mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Add IR parser of catch blocks
This commit is contained in:
parent
6883b59fc3
commit
7ca6a4d64e
|
@ -321,7 +321,7 @@ public abstract class ValueType {
|
|||
return VOID;
|
||||
case 'L':
|
||||
if (!string.endsWith(";")) {
|
||||
throw new IllegalArgumentException("Wrong type descriptor");
|
||||
return null;
|
||||
}
|
||||
return object(string.substring(1, string.length() - 1).replace('/', '.'));
|
||||
default:
|
||||
|
|
|
@ -78,14 +78,17 @@ public class ListingBuilder {
|
|||
sb.append(prefix).append(" ").append(insnSb).append("\n");
|
||||
}
|
||||
for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) {
|
||||
sb.append(prefix).append(" catch ").append(tryCatch.getExceptionType())
|
||||
.append(" -> $").append(tryCatch.getHandler().getIndex());
|
||||
sb.append(prefix).append(" catch ");
|
||||
if (tryCatch.getExceptionType() != null) {
|
||||
InstructionStringifier.escapeStringLiteral(tryCatch.getExceptionType(), sb);
|
||||
}
|
||||
sb.append(" goto $").append(tryCatch.getHandler().getIndex());
|
||||
sb.append("\n");
|
||||
for (TryCatchJointReader joint : tryCatch.readJoints()) {
|
||||
sb.append(" @").append(joint.getReceiver().getIndex()).append(" := e-phi(");
|
||||
sb.append(" @").append(joint.getReceiver().getIndex()).append(" := ephi ");
|
||||
sb.append(joint.readSourceVariables().stream().map(sourceVar -> "@" + sourceVar.getIndex())
|
||||
.collect(Collectors.joining(", ")));
|
||||
sb.append(")\n");
|
||||
sb.append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ import org.teavm.model.MethodReference;
|
|||
import org.teavm.model.Phi;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.TextLocation;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.TryCatchJoint;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.ArrayElementType;
|
||||
|
@ -88,6 +90,7 @@ public class ListingParser {
|
|||
private Set<String> declaredBlocks = new HashSet<>();
|
||||
private TextLocation currentLocation;
|
||||
private BasicBlock currentBlock;
|
||||
private TryCatchBlock currentTryCatch;
|
||||
|
||||
public Program parse(Reader reader) throws IOException, ListingParseException {
|
||||
try {
|
||||
|
@ -173,6 +176,7 @@ public class ListingParser {
|
|||
b.setLabel(k);
|
||||
return b;
|
||||
});
|
||||
currentTryCatch = null;
|
||||
|
||||
currentLocation = null;
|
||||
do {
|
||||
|
@ -268,6 +272,11 @@ public class ListingParser {
|
|||
parseSwitch();
|
||||
break;
|
||||
}
|
||||
case "catch": {
|
||||
lexer.nextToken();
|
||||
parseCatch();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
unexpected();
|
||||
break;
|
||||
|
@ -344,6 +353,10 @@ public class ListingParser {
|
|||
lexer.nextToken();
|
||||
parsePhi(receiver);
|
||||
break;
|
||||
case "ephi":
|
||||
lexer.nextToken();
|
||||
parseExceptionPhi(receiver);
|
||||
break;
|
||||
case "classOf":
|
||||
lexer.nextToken();
|
||||
parseClassLiteral(receiver);
|
||||
|
@ -402,6 +415,15 @@ public class ListingParser {
|
|||
parseFieldGet(receiver);
|
||||
break;
|
||||
}
|
||||
case "exception": {
|
||||
lexer.nextToken();
|
||||
if (!currentBlock.getInstructions().isEmpty() || currentBlock.getExceptionVariable() != null) {
|
||||
throw new ListingParseException("Exception can be read as a first instruction",
|
||||
lexer.getTokenStart());
|
||||
}
|
||||
currentBlock.setExceptionVariable(receiver);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
unexpected();
|
||||
break;
|
||||
|
@ -563,6 +585,24 @@ public class ListingParser {
|
|||
currentBlock.getPhis().add(phi);
|
||||
}
|
||||
|
||||
private void parseExceptionPhi(Variable receiver) throws IOException, ListingParseException {
|
||||
int phiStart = lexer.getIndex();
|
||||
|
||||
TryCatchJoint joint = new TryCatchJoint();
|
||||
joint.setReceiver(receiver);
|
||||
joint.getSourceVariables().add(expectVariable());
|
||||
while (lexer.getToken() == ListingToken.COMMA) {
|
||||
lexer.nextToken();
|
||||
joint.getSourceVariables().add(expectVariable());
|
||||
}
|
||||
|
||||
if (currentTryCatch == null) {
|
||||
throw new ListingParseException("Exception phi must appear right after catch block", phiStart);
|
||||
}
|
||||
|
||||
currentTryCatch.getJoints().add(joint);
|
||||
}
|
||||
|
||||
private void parseClassLiteral(Variable receiver) throws IOException, ListingParseException {
|
||||
ValueType type = expectValueType();
|
||||
ClassConstantInstruction insn = new ClassConstantInstruction();
|
||||
|
@ -736,6 +776,18 @@ public class ListingParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void parseCatch() throws IOException, ListingParseException {
|
||||
TryCatchBlock tryCatch = new TryCatchBlock();
|
||||
if (lexer.getToken() == ListingToken.IDENTIFIER) {
|
||||
tryCatch.setExceptionType((String) lexer.getTokenValue());
|
||||
lexer.nextToken();
|
||||
}
|
||||
expectKeyword("goto");
|
||||
tryCatch.setHandler(expectBlock());
|
||||
currentTryCatch = tryCatch;
|
||||
currentBlock.getTryCatchBlocks().add(tryCatch);
|
||||
}
|
||||
|
||||
private void parseCast(Variable receiver) throws IOException, ListingParseException {
|
||||
lexer.nextToken();
|
||||
Variable value = expectVariable();
|
||||
|
@ -1109,7 +1161,8 @@ public class ListingParser {
|
|||
throw new ListingParseException("Unexpected token " + lexer.getToken(), lexer.getTokenStart());
|
||||
}
|
||||
|
||||
private void addInstruction(Instruction instruction) {
|
||||
private void addInstruction(Instruction instruction) throws ListingParseException {
|
||||
currentTryCatch = null;
|
||||
instruction.setLocation(currentLocation);
|
||||
currentBlock.getInstructions().add(instruction);
|
||||
}
|
||||
|
|
|
@ -146,6 +146,11 @@ public class ParserTest {
|
|||
runTest("switchInsn");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exceptions() throws Exception {
|
||||
runTest("exceptions");
|
||||
}
|
||||
|
||||
private Program runTest(String name) throws IOException {
|
||||
ClassLoader classLoader = ParserTest.class.getClassLoader();
|
||||
String path = "model/text/" + name + ".txt";
|
||||
|
|
14
core/src/test/resources/model/text/exceptions.txt
Normal file
14
core/src/test/resources/model/text/exceptions.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
$start
|
||||
@a_1 := 0
|
||||
invokeStatic `foo.Bar.baz()I`
|
||||
@a_2 := 1
|
||||
invokeStatic `foo.Bar.baz()I`
|
||||
@a_3 := 2
|
||||
return @a_3
|
||||
catch java.lang.Exception goto $handler
|
||||
@a_h := ephi @a_1, @a_2, @a_3
|
||||
$handler
|
||||
@e := exception
|
||||
@out := field `java.lang.String.out` as `Ljava/io/PrintStream;`
|
||||
invokeVirtual `java.io.PrintStream.println(Ljava/lang/Object;)V` @out, @e
|
||||
return @a_h
|
Loading…
Reference in New Issue
Block a user