mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-09 00:14:10 -08:00
Add IR parser of binary operations and phi functions
This commit is contained in:
parent
6148d7a943
commit
f6308c1782
|
@ -23,6 +23,8 @@ import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.teavm.model.BasicBlock;
|
import org.teavm.model.BasicBlock;
|
||||||
|
import org.teavm.model.Incoming;
|
||||||
|
import org.teavm.model.Phi;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.TextLocation;
|
import org.teavm.model.TextLocation;
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
|
@ -30,11 +32,14 @@ import org.teavm.model.instructions.ArrayElementType;
|
||||||
import org.teavm.model.instructions.AssignInstruction;
|
import org.teavm.model.instructions.AssignInstruction;
|
||||||
import org.teavm.model.instructions.BinaryBranchingCondition;
|
import org.teavm.model.instructions.BinaryBranchingCondition;
|
||||||
import org.teavm.model.instructions.BinaryBranchingInstruction;
|
import org.teavm.model.instructions.BinaryBranchingInstruction;
|
||||||
|
import org.teavm.model.instructions.BinaryInstruction;
|
||||||
|
import org.teavm.model.instructions.BinaryOperation;
|
||||||
import org.teavm.model.instructions.BranchingCondition;
|
import org.teavm.model.instructions.BranchingCondition;
|
||||||
import org.teavm.model.instructions.BranchingInstruction;
|
import org.teavm.model.instructions.BranchingInstruction;
|
||||||
import org.teavm.model.instructions.EmptyInstruction;
|
import org.teavm.model.instructions.EmptyInstruction;
|
||||||
import org.teavm.model.instructions.ExitInstruction;
|
import org.teavm.model.instructions.ExitInstruction;
|
||||||
import org.teavm.model.instructions.JumpInstruction;
|
import org.teavm.model.instructions.JumpInstruction;
|
||||||
|
import org.teavm.model.instructions.NumericOperandType;
|
||||||
import org.teavm.model.instructions.PutElementInstruction;
|
import org.teavm.model.instructions.PutElementInstruction;
|
||||||
|
|
||||||
public class ListingParser {
|
public class ListingParser {
|
||||||
|
@ -244,6 +249,19 @@ public class ListingParser {
|
||||||
parseAssignmentVariable(block, receiver, variable);
|
parseAssignmentVariable(block, receiver, variable);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case IDENTIFIER: {
|
||||||
|
String keyword = (String) lexer.getTokenValue();
|
||||||
|
switch (keyword) {
|
||||||
|
case "phi":
|
||||||
|
lexer.nextToken();
|
||||||
|
parsePhi(block, receiver);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unexpected();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
unexpected();
|
unexpected();
|
||||||
}
|
}
|
||||||
|
@ -261,11 +279,69 @@ public class ListingParser {
|
||||||
block.getInstructions().add(insn);
|
block.getInstructions().add(insn);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ADD:
|
||||||
|
parseBinary(block, receiver, variable, BinaryOperation.ADD);
|
||||||
|
break;
|
||||||
|
case SUBTRACT:
|
||||||
|
parseBinary(block, receiver, variable, BinaryOperation.SUBTRACT);
|
||||||
|
break;
|
||||||
|
case MULTIPLY:
|
||||||
|
parseBinary(block, receiver, variable, BinaryOperation.MULTIPLY);
|
||||||
|
break;
|
||||||
|
case DIVIDE:
|
||||||
|
parseBinary(block, receiver, variable, BinaryOperation.DIVIDE);
|
||||||
|
break;
|
||||||
|
case REMAINDER:
|
||||||
|
parseBinary(block, receiver, variable, BinaryOperation.MODULO);
|
||||||
|
break;
|
||||||
|
case AND:
|
||||||
|
parseBinary(block, receiver, variable, BinaryOperation.AND);
|
||||||
|
break;
|
||||||
|
case OR:
|
||||||
|
parseBinary(block, receiver, variable, BinaryOperation.OR);
|
||||||
|
break;
|
||||||
|
case XOR:
|
||||||
|
parseBinary(block, receiver, variable, BinaryOperation.XOR);
|
||||||
|
break;
|
||||||
|
case SHIFT_LEFT:
|
||||||
|
parseBinary(block, receiver, variable, BinaryOperation.SHIFT_LEFT);
|
||||||
|
break;
|
||||||
|
case SHIFT_RIGHT:
|
||||||
|
parseBinary(block, receiver, variable, BinaryOperation.SHIFT_RIGHT);
|
||||||
|
break;
|
||||||
|
case SHIFT_RIGHT_UNSIGNED:
|
||||||
|
parseBinary(block, receiver, variable, BinaryOperation.SHIFT_RIGHT_UNSIGNED);
|
||||||
|
break;
|
||||||
|
case IDENTIFIER:
|
||||||
|
switch ((String) lexer.getTokenValue()) {
|
||||||
|
case "compareTo":
|
||||||
|
parseBinary(block, receiver, variable, BinaryOperation.COMPARE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unexpected();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
unexpected();
|
unexpected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void parseBinary(BasicBlock block, Variable receiver, Variable first, BinaryOperation operation)
|
||||||
|
throws IOException, ListingParseException {
|
||||||
|
lexer.nextToken();
|
||||||
|
Variable second = expectVariable();
|
||||||
|
expectKeyword("as");
|
||||||
|
NumericOperandType type = expectNumericType();
|
||||||
|
|
||||||
|
BinaryInstruction instruction = new BinaryInstruction(operation, type);
|
||||||
|
instruction.setFirstOperand(first);
|
||||||
|
instruction.setSecondOperand(second);
|
||||||
|
instruction.setReceiver(receiver);
|
||||||
|
|
||||||
|
block.getInstructions().add(instruction);
|
||||||
|
}
|
||||||
|
|
||||||
private void parseArrayAssignment(BasicBlock block, Variable array) throws IOException, ListingParseException {
|
private void parseArrayAssignment(BasicBlock block, Variable array) throws IOException, ListingParseException {
|
||||||
Variable index = expectVariable();
|
Variable index = expectVariable();
|
||||||
expect(ListingToken.RIGHT_SQUARE_BRACKET);
|
expect(ListingToken.RIGHT_SQUARE_BRACKET);
|
||||||
|
@ -284,6 +360,30 @@ public class ListingParser {
|
||||||
block.getInstructions().add(insn);
|
block.getInstructions().add(insn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void parsePhi(BasicBlock block, Variable receiver) throws IOException, ListingParseException {
|
||||||
|
int phiStart = lexer.getIndex();
|
||||||
|
|
||||||
|
Phi phi = new Phi();
|
||||||
|
while (true) {
|
||||||
|
Incoming incoming = new Incoming();
|
||||||
|
incoming.setValue(expectVariable());
|
||||||
|
expectKeyword("from");
|
||||||
|
incoming.setSource(expectBlock());
|
||||||
|
phi.getIncomings().add(incoming);
|
||||||
|
|
||||||
|
if (lexer.getToken() != ListingToken.COMMA) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lexer.nextToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!block.getInstructions().isEmpty() || block.getExceptionVariable() != null) {
|
||||||
|
throw new ListingParseException("Phi must be first instruction in block", phiStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
block.getPhis().add(phi);
|
||||||
|
}
|
||||||
|
|
||||||
private void parseIf(BasicBlock block) throws IOException, ListingParseException {
|
private void parseIf(BasicBlock block) throws IOException, ListingParseException {
|
||||||
Variable first = expectVariable();
|
Variable first = expectVariable();
|
||||||
|
|
||||||
|
@ -405,6 +505,30 @@ public class ListingParser {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private NumericOperandType expectNumericType() throws IOException, ListingParseException {
|
||||||
|
expect(ListingToken.IDENTIFIER);
|
||||||
|
NumericOperandType type;
|
||||||
|
switch ((String) lexer.getTokenValue()) {
|
||||||
|
case "int":
|
||||||
|
type = NumericOperandType.INT;
|
||||||
|
break;
|
||||||
|
case "long":
|
||||||
|
type = NumericOperandType.LONG;
|
||||||
|
break;
|
||||||
|
case "float":
|
||||||
|
type = NumericOperandType.FLOAT;
|
||||||
|
break;
|
||||||
|
case "double":
|
||||||
|
type = NumericOperandType.DOUBLE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ListingParseException("Unknown numeric type: " + lexer.getTokenValue(),
|
||||||
|
lexer.getTokenStart());
|
||||||
|
}
|
||||||
|
lexer.nextToken();
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
private Variable expectVariable() throws IOException, ListingParseException {
|
private Variable expectVariable() throws IOException, ListingParseException {
|
||||||
expect(ListingToken.VARIABLE);
|
expect(ListingToken.VARIABLE);
|
||||||
String variableName = (String) lexer.getTokenValue();
|
String variableName = (String) lexer.getTokenValue();
|
||||||
|
|
|
@ -41,6 +41,13 @@ public class ParserTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void phi() throws Exception {
|
||||||
|
Program program = runTest("phi");
|
||||||
|
Assert.assertEquals(4, program.basicBlockCount());
|
||||||
|
Assert.assertEquals(2, program.basicBlockAt(3).getPhis().size());
|
||||||
|
}
|
||||||
|
|
||||||
private Program runTest(String name) throws IOException {
|
private Program runTest(String name) throws IOException {
|
||||||
ClassLoader classLoader = ParserTest.class.getClassLoader();
|
ClassLoader classLoader = ParserTest.class.getClassLoader();
|
||||||
String path = "model/text/" + name + ".txt";
|
String path = "model/text/" + name + ".txt";
|
||||||
|
|
11
core/src/test/resources/model/text/phi.txt
Normal file
11
core/src/test/resources/model/text/phi.txt
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
$test
|
||||||
|
if @param == 0 then goto $whenzero else goto $whennonzero
|
||||||
|
$whenzero
|
||||||
|
goto $joint
|
||||||
|
$whennonzero
|
||||||
|
goto $joint
|
||||||
|
$joint
|
||||||
|
@u := phi @a from $whenzero, @b from $whennonzero
|
||||||
|
@v := phi @x from $whenzero, @y from $whennonzero
|
||||||
|
@result := @u + @v as int
|
||||||
|
return @result
|
Loading…
Reference in New Issue
Block a user