mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-09 00:14:10 -08:00
Add IR parser of different simple instructions
This commit is contained in:
parent
2b94a8b05c
commit
6084491119
|
@ -314,7 +314,7 @@ class InstructionStringifier implements InstructionReader {
|
|||
|
||||
@Override
|
||||
public void createArray(VariableReader receiver, ValueType itemType, List<? extends VariableReader> dimensions) {
|
||||
sb.append("@").append(receiver.getIndex()).append(" := new ");
|
||||
sb.append("@").append(receiver.getIndex()).append(" := newArray ");
|
||||
escapeIdentifierIfNeeded(itemType.toString(), sb);
|
||||
sb.append("[");
|
||||
|
||||
|
@ -329,9 +329,8 @@ class InstructionStringifier implements InstructionReader {
|
|||
|
||||
@Override
|
||||
public void create(VariableReader receiver, String type) {
|
||||
sb.append("@").append(receiver.getIndex()).append(" := new ");
|
||||
sb.append("@").append(receiver.getIndex()).append(" := newArray ");
|
||||
escapeIdentifierIfNeeded(type, sb);
|
||||
sb.append("");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.teavm.model.TextLocation;
|
|||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.ArrayElementType;
|
||||
import org.teavm.model.instructions.ArrayLengthInstruction;
|
||||
import org.teavm.model.instructions.AssignInstruction;
|
||||
import org.teavm.model.instructions.BinaryBranchingCondition;
|
||||
import org.teavm.model.instructions.BinaryBranchingInstruction;
|
||||
|
@ -46,19 +47,31 @@ import org.teavm.model.instructions.CastIntegerDirection;
|
|||
import org.teavm.model.instructions.CastIntegerInstruction;
|
||||
import org.teavm.model.instructions.CastNumberInstruction;
|
||||
import org.teavm.model.instructions.ClassConstantInstruction;
|
||||
import org.teavm.model.instructions.CloneArrayInstruction;
|
||||
import org.teavm.model.instructions.ConstructArrayInstruction;
|
||||
import org.teavm.model.instructions.ConstructInstruction;
|
||||
import org.teavm.model.instructions.ConstructMultiArrayInstruction;
|
||||
import org.teavm.model.instructions.DoubleConstantInstruction;
|
||||
import org.teavm.model.instructions.EmptyInstruction;
|
||||
import org.teavm.model.instructions.ExitInstruction;
|
||||
import org.teavm.model.instructions.FloatConstantInstruction;
|
||||
import org.teavm.model.instructions.InitClassInstruction;
|
||||
import org.teavm.model.instructions.IntegerConstantInstruction;
|
||||
import org.teavm.model.instructions.IntegerSubtype;
|
||||
import org.teavm.model.instructions.InvocationType;
|
||||
import org.teavm.model.instructions.InvokeInstruction;
|
||||
import org.teavm.model.instructions.IsInstanceInstruction;
|
||||
import org.teavm.model.instructions.JumpInstruction;
|
||||
import org.teavm.model.instructions.LongConstantInstruction;
|
||||
import org.teavm.model.instructions.MonitorEnterInstruction;
|
||||
import org.teavm.model.instructions.MonitorExitInstruction;
|
||||
import org.teavm.model.instructions.NegateInstruction;
|
||||
import org.teavm.model.instructions.NullCheckInstruction;
|
||||
import org.teavm.model.instructions.NumericOperandType;
|
||||
import org.teavm.model.instructions.PutElementInstruction;
|
||||
import org.teavm.model.instructions.RaiseInstruction;
|
||||
import org.teavm.model.instructions.StringConstantInstruction;
|
||||
import org.teavm.model.instructions.UnwrapArrayInstruction;
|
||||
|
||||
public class ListingParser {
|
||||
private Program program;
|
||||
|
@ -200,6 +213,14 @@ public class ListingParser {
|
|||
block.getInstructions().add(insn);
|
||||
break;
|
||||
}
|
||||
case "throw": {
|
||||
lexer.nextToken();
|
||||
RaiseInstruction insn = new RaiseInstruction();
|
||||
insn.setLocation(currentLocation);
|
||||
insn.setException(expectVariable());
|
||||
block.getInstructions().add(insn);
|
||||
break;
|
||||
}
|
||||
case "if": {
|
||||
lexer.nextToken();
|
||||
parseIf(block);
|
||||
|
@ -211,6 +232,32 @@ public class ListingParser {
|
|||
parseInvoke(block, null);
|
||||
break;
|
||||
}
|
||||
case "initClass": {
|
||||
lexer.nextToken();
|
||||
InitClassInstruction insn = new InitClassInstruction();
|
||||
expect(ListingToken.IDENTIFIER);
|
||||
insn.setClassName((String) lexer.getTokenValue());
|
||||
lexer.nextToken();
|
||||
insn.setLocation(currentLocation);
|
||||
block.getInstructions().add(insn);
|
||||
break;
|
||||
}
|
||||
case "monitorEnter": {
|
||||
lexer.nextToken();
|
||||
MonitorEnterInstruction insn = new MonitorEnterInstruction();
|
||||
insn.setObjectRef(expectVariable());
|
||||
insn.setLocation(currentLocation);
|
||||
block.getInstructions().add(insn);
|
||||
break;
|
||||
}
|
||||
case "monitorExit": {
|
||||
lexer.nextToken();
|
||||
MonitorExitInstruction insn = new MonitorExitInstruction();
|
||||
insn.setObjectRef(expectVariable());
|
||||
insn.setLocation(currentLocation);
|
||||
block.getInstructions().add(insn);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
unexpected();
|
||||
break;
|
||||
|
@ -299,6 +346,51 @@ public class ListingParser {
|
|||
case "cast":
|
||||
parseCast(block, receiver);
|
||||
break;
|
||||
case "new":
|
||||
parseNew(block, receiver);
|
||||
break;
|
||||
case "newArray":
|
||||
parseNewArray(block, receiver);
|
||||
break;
|
||||
case "nullCheck": {
|
||||
lexer.nextToken();
|
||||
NullCheckInstruction insn = new NullCheckInstruction();
|
||||
insn.setReceiver(receiver);
|
||||
insn.setValue(expectVariable());
|
||||
insn.setLocation(currentLocation);
|
||||
block.getInstructions().add(insn);
|
||||
break;
|
||||
}
|
||||
case "data": {
|
||||
lexer.nextToken();
|
||||
Variable value = expectVariable();
|
||||
expectKeyword("as");
|
||||
ArrayElementType type = expectArrayType();
|
||||
UnwrapArrayInstruction insn = new UnwrapArrayInstruction(type);
|
||||
insn.setArray(value);
|
||||
insn.setReceiver(receiver);
|
||||
insn.setLocation(currentLocation);
|
||||
block.getInstructions().add(insn);
|
||||
break;
|
||||
}
|
||||
case "lengthOf": {
|
||||
lexer.nextToken();
|
||||
ArrayLengthInstruction insn = new ArrayLengthInstruction();
|
||||
insn.setArray(expectVariable());
|
||||
insn.setReceiver(receiver);
|
||||
insn.setLocation(currentLocation);
|
||||
block.getInstructions().add(insn);
|
||||
break;
|
||||
}
|
||||
case "clone": {
|
||||
lexer.nextToken();
|
||||
CloneArrayInstruction insn = new CloneArrayInstruction();
|
||||
insn.setArray(expectVariable());
|
||||
insn.setReceiver(receiver);
|
||||
insn.setLocation(currentLocation);
|
||||
block.getInstructions().add(insn);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
unexpected();
|
||||
break;
|
||||
|
@ -325,6 +417,10 @@ public class ListingParser {
|
|||
parseStringConstant(block, receiver);
|
||||
break;
|
||||
}
|
||||
case SUBTRACT: {
|
||||
parseNegate(block, receiver);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
unexpected();
|
||||
}
|
||||
|
@ -380,6 +476,17 @@ public class ListingParser {
|
|||
case "compareTo":
|
||||
parseBinary(block, receiver, variable, BinaryOperation.COMPARE);
|
||||
break;
|
||||
case "instanceOf": {
|
||||
lexer.nextToken();
|
||||
ValueType type = expectValueType();
|
||||
IsInstanceInstruction insn = new IsInstanceInstruction();
|
||||
insn.setValue(variable);
|
||||
insn.setReceiver(receiver);
|
||||
insn.setType(type);
|
||||
insn.setLocation(currentLocation);
|
||||
block.getInstructions().add(insn);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
unexpected();
|
||||
break;
|
||||
|
@ -450,13 +557,7 @@ public class ListingParser {
|
|||
}
|
||||
|
||||
private void parseClassLiteral(BasicBlock block, Variable receiver) throws IOException, ListingParseException {
|
||||
expect(ListingToken.IDENTIFIER);
|
||||
String typeString = (String) lexer.getTokenValue();
|
||||
ValueType type = ValueType.parseIfPossible(typeString);
|
||||
if (type == null) {
|
||||
throw new ListingParseException("Unparseable type: " + typeString, lexer.getTokenStart());
|
||||
}
|
||||
lexer.nextToken();
|
||||
ValueType type = expectValueType();
|
||||
|
||||
ClassConstantInstruction insn = new ClassConstantInstruction();
|
||||
insn.setReceiver(receiver);
|
||||
|
@ -510,6 +611,18 @@ public class ListingParser {
|
|||
lexer.nextToken();
|
||||
}
|
||||
|
||||
private void parseNegate(BasicBlock block, Variable receiver) throws IOException, ListingParseException {
|
||||
lexer.nextToken();
|
||||
Variable value = expectVariable();
|
||||
expectKeyword("as");
|
||||
NumericOperandType type = expectNumericType();
|
||||
NegateInstruction insn = new NegateInstruction(type);
|
||||
insn.setReceiver(receiver);
|
||||
insn.setOperand(value);
|
||||
insn.setLocation(currentLocation);
|
||||
block.getInstructions().add(insn);
|
||||
}
|
||||
|
||||
private void parseInvoke(BasicBlock block, Variable receiver) throws IOException, ListingParseException {
|
||||
InvokeInstruction insn = new InvokeInstruction();
|
||||
insn.setReceiver(receiver);
|
||||
|
@ -665,12 +778,7 @@ public class ListingParser {
|
|||
private void parseObjectCast(BasicBlock block, Variable receiver, Variable value)
|
||||
throws IOException, ListingParseException {
|
||||
lexer.nextToken();
|
||||
expect(ListingToken.IDENTIFIER);
|
||||
ValueType type = ValueType.parseIfPossible((String) lexer.getTokenValue());
|
||||
if (type == null) {
|
||||
throw new ListingParseException("Unparseable type", lexer.getTokenStart());
|
||||
}
|
||||
lexer.nextToken();
|
||||
ValueType type = expectValueType();
|
||||
|
||||
CastInstruction insn = new CastInstruction();
|
||||
insn.setReceiver(receiver);
|
||||
|
@ -680,6 +788,48 @@ public class ListingParser {
|
|||
block.getInstructions().add(insn);
|
||||
}
|
||||
|
||||
private void parseNew(BasicBlock block, Variable receiver) throws IOException, ListingParseException {
|
||||
lexer.nextToken();
|
||||
expect(ListingToken.IDENTIFIER);
|
||||
String type = (String) lexer.getTokenValue();
|
||||
lexer.nextToken();
|
||||
|
||||
ConstructInstruction insn = new ConstructInstruction();
|
||||
insn.setReceiver(receiver);
|
||||
insn.setType(type);
|
||||
insn.setLocation(currentLocation);
|
||||
block.getInstructions().add(insn);
|
||||
}
|
||||
|
||||
private void parseNewArray(BasicBlock block, Variable receiver) throws IOException, ListingParseException {
|
||||
lexer.nextToken();
|
||||
ValueType type = expectValueType();
|
||||
List<Variable> dimensions = new ArrayList<>();
|
||||
expect(ListingToken.LEFT_SQUARE_BRACKET);
|
||||
do {
|
||||
lexer.nextToken();
|
||||
dimensions.add(expectVariable());
|
||||
} while (lexer.getToken() == ListingToken.COMMA);
|
||||
expect(ListingToken.RIGHT_SQUARE_BRACKET);
|
||||
lexer.nextToken();
|
||||
|
||||
if (dimensions.size() == 1) {
|
||||
ConstructArrayInstruction insn = new ConstructArrayInstruction();
|
||||
insn.setReceiver(receiver);
|
||||
insn.setItemType(type);
|
||||
insn.setSize(dimensions.get(0));
|
||||
insn.setLocation(currentLocation);
|
||||
block.getInstructions().add(insn);
|
||||
} else {
|
||||
ConstructMultiArrayInstruction insn = new ConstructMultiArrayInstruction();
|
||||
insn.setReceiver(receiver);
|
||||
insn.setItemType(type);
|
||||
insn.getDimensions().addAll(dimensions);
|
||||
insn.setLocation(currentLocation);
|
||||
block.getInstructions().add(insn);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseIf(BasicBlock block) throws IOException, ListingParseException {
|
||||
Variable first = expectVariable();
|
||||
|
||||
|
@ -825,6 +975,16 @@ public class ListingParser {
|
|||
return type;
|
||||
}
|
||||
|
||||
private ValueType expectValueType() throws IOException, ListingParseException {
|
||||
expect(ListingToken.IDENTIFIER);
|
||||
ValueType type = ValueType.parseIfPossible((String) lexer.getTokenValue());
|
||||
if (type == null) {
|
||||
throw new ListingParseException("Unparseable type", lexer.getTokenStart());
|
||||
}
|
||||
lexer.nextToken();
|
||||
return type;
|
||||
}
|
||||
|
||||
private Variable expectVariable() throws IOException, ListingParseException {
|
||||
expect(ListingToken.VARIABLE);
|
||||
String variableName = (String) lexer.getTokenValue();
|
||||
|
|
|
@ -30,6 +30,9 @@ import org.teavm.model.instructions.CastInstruction;
|
|||
import org.teavm.model.instructions.CastIntegerInstruction;
|
||||
import org.teavm.model.instructions.CastNumberInstruction;
|
||||
import org.teavm.model.instructions.ClassConstantInstruction;
|
||||
import org.teavm.model.instructions.ConstructArrayInstruction;
|
||||
import org.teavm.model.instructions.ConstructInstruction;
|
||||
import org.teavm.model.instructions.ConstructMultiArrayInstruction;
|
||||
import org.teavm.model.instructions.DoubleConstantInstruction;
|
||||
import org.teavm.model.instructions.FloatConstantInstruction;
|
||||
import org.teavm.model.instructions.IntegerConstantInstruction;
|
||||
|
@ -117,6 +120,22 @@ public class ParserTest {
|
|||
assertTrue(block.getInstructions().get(3) instanceof CastNumberInstruction);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void operations() throws Exception {
|
||||
runTest("operations");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void create() throws Exception {
|
||||
Program program = runTest("create");
|
||||
assertEquals(1, program.basicBlockCount());
|
||||
|
||||
BasicBlock block = program.basicBlockAt(0);
|
||||
assertTrue(block.getInstructions().get(0) instanceof ConstructInstruction);
|
||||
assertTrue(block.getInstructions().get(1) instanceof ConstructArrayInstruction);
|
||||
assertTrue(block.getInstructions().get(2) instanceof ConstructMultiArrayInstruction);
|
||||
}
|
||||
|
||||
private Program runTest(String name) throws IOException {
|
||||
ClassLoader classLoader = ParserTest.class.getClassLoader();
|
||||
String path = "model/text/" + name + ".txt";
|
||||
|
|
5
core/src/test/resources/model/text/create.txt
Normal file
5
core/src/test/resources/model/text/create.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
$block
|
||||
@a := new java.lang.String
|
||||
@b := newArray `Ljava/lang/String;` [@size]
|
||||
@c := newArray I [@h, @w]
|
||||
return
|
21
core/src/test/resources/model/text/operations.txt
Normal file
21
core/src/test/resources/model/text/operations.txt
Normal file
|
@ -0,0 +1,21 @@
|
|||
$block
|
||||
@r1 := @a + @b as int
|
||||
@r2 := @c - @d as long
|
||||
@r3 := @e * @f as float
|
||||
@r4 := @g % @h as double
|
||||
@r5 := @a compareTo @b as int
|
||||
@r6 := @a >> @b as int
|
||||
@r7 := @a >>> @b as int
|
||||
@r8 := @a & @b as int
|
||||
@r8 := @a | @b as int
|
||||
@r8 := @a ^ @b as int
|
||||
@r9 := -@a as int
|
||||
@r10 := @i instanceOf `[J`
|
||||
initClass java.lang.Math
|
||||
monitorEnter @i
|
||||
@r11 := nullCheck @i
|
||||
@r12 := data @i as long
|
||||
@r13 := lengthOf @i
|
||||
@r14 := clone @i
|
||||
monitorExit @i
|
||||
throw @exception
|
Loading…
Reference in New Issue
Block a user