Add IR parser of different simple instructions

This commit is contained in:
Alexey Andreev 2016-12-03 21:55:04 +03:00
parent 2b94a8b05c
commit 6084491119
5 changed files with 220 additions and 16 deletions

View File

@ -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

View File

@ -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();

View File

@ -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";

View File

@ -0,0 +1,5 @@
$block
@a := new java.lang.String
@b := newArray `Ljava/lang/String;` [@size]
@c := newArray I [@h, @w]
return

View 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