mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-10 08:54:11 -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;
|
return VOID;
|
||||||
case 'L':
|
case 'L':
|
||||||
if (!string.endsWith(";")) {
|
if (!string.endsWith(";")) {
|
||||||
throw new IllegalArgumentException("Wrong type descriptor");
|
return null;
|
||||||
}
|
}
|
||||||
return object(string.substring(1, string.length() - 1).replace('/', '.'));
|
return object(string.substring(1, string.length() - 1).replace('/', '.'));
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -78,14 +78,17 @@ public class ListingBuilder {
|
||||||
sb.append(prefix).append(" ").append(insnSb).append("\n");
|
sb.append(prefix).append(" ").append(insnSb).append("\n");
|
||||||
}
|
}
|
||||||
for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) {
|
for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) {
|
||||||
sb.append(prefix).append(" catch ").append(tryCatch.getExceptionType())
|
sb.append(prefix).append(" catch ");
|
||||||
.append(" -> $").append(tryCatch.getHandler().getIndex());
|
if (tryCatch.getExceptionType() != null) {
|
||||||
|
InstructionStringifier.escapeStringLiteral(tryCatch.getExceptionType(), sb);
|
||||||
|
}
|
||||||
|
sb.append(" goto $").append(tryCatch.getHandler().getIndex());
|
||||||
sb.append("\n");
|
sb.append("\n");
|
||||||
for (TryCatchJointReader joint : tryCatch.readJoints()) {
|
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())
|
sb.append(joint.readSourceVariables().stream().map(sourceVar -> "@" + sourceVar.getIndex())
|
||||||
.collect(Collectors.joining(", ")));
|
.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.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.TryCatchBlock;
|
||||||
|
import org.teavm.model.TryCatchJoint;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
import org.teavm.model.instructions.ArrayElementType;
|
import org.teavm.model.instructions.ArrayElementType;
|
||||||
|
@ -88,6 +90,7 @@ public class ListingParser {
|
||||||
private Set<String> declaredBlocks = new HashSet<>();
|
private Set<String> declaredBlocks = new HashSet<>();
|
||||||
private TextLocation currentLocation;
|
private TextLocation currentLocation;
|
||||||
private BasicBlock currentBlock;
|
private BasicBlock currentBlock;
|
||||||
|
private TryCatchBlock currentTryCatch;
|
||||||
|
|
||||||
public Program parse(Reader reader) throws IOException, ListingParseException {
|
public Program parse(Reader reader) throws IOException, ListingParseException {
|
||||||
try {
|
try {
|
||||||
|
@ -173,6 +176,7 @@ public class ListingParser {
|
||||||
b.setLabel(k);
|
b.setLabel(k);
|
||||||
return b;
|
return b;
|
||||||
});
|
});
|
||||||
|
currentTryCatch = null;
|
||||||
|
|
||||||
currentLocation = null;
|
currentLocation = null;
|
||||||
do {
|
do {
|
||||||
|
@ -268,6 +272,11 @@ public class ListingParser {
|
||||||
parseSwitch();
|
parseSwitch();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "catch": {
|
||||||
|
lexer.nextToken();
|
||||||
|
parseCatch();
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
unexpected();
|
unexpected();
|
||||||
break;
|
break;
|
||||||
|
@ -344,6 +353,10 @@ public class ListingParser {
|
||||||
lexer.nextToken();
|
lexer.nextToken();
|
||||||
parsePhi(receiver);
|
parsePhi(receiver);
|
||||||
break;
|
break;
|
||||||
|
case "ephi":
|
||||||
|
lexer.nextToken();
|
||||||
|
parseExceptionPhi(receiver);
|
||||||
|
break;
|
||||||
case "classOf":
|
case "classOf":
|
||||||
lexer.nextToken();
|
lexer.nextToken();
|
||||||
parseClassLiteral(receiver);
|
parseClassLiteral(receiver);
|
||||||
|
@ -402,6 +415,15 @@ public class ListingParser {
|
||||||
parseFieldGet(receiver);
|
parseFieldGet(receiver);
|
||||||
break;
|
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:
|
default:
|
||||||
unexpected();
|
unexpected();
|
||||||
break;
|
break;
|
||||||
|
@ -563,6 +585,24 @@ public class ListingParser {
|
||||||
currentBlock.getPhis().add(phi);
|
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 {
|
private void parseClassLiteral(Variable receiver) throws IOException, ListingParseException {
|
||||||
ValueType type = expectValueType();
|
ValueType type = expectValueType();
|
||||||
ClassConstantInstruction insn = new ClassConstantInstruction();
|
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 {
|
private void parseCast(Variable receiver) throws IOException, ListingParseException {
|
||||||
lexer.nextToken();
|
lexer.nextToken();
|
||||||
Variable value = expectVariable();
|
Variable value = expectVariable();
|
||||||
|
@ -1109,7 +1161,8 @@ public class ListingParser {
|
||||||
throw new ListingParseException("Unexpected token " + lexer.getToken(), lexer.getTokenStart());
|
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);
|
instruction.setLocation(currentLocation);
|
||||||
currentBlock.getInstructions().add(instruction);
|
currentBlock.getInstructions().add(instruction);
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,6 +146,11 @@ public class ParserTest {
|
||||||
runTest("switchInsn");
|
runTest("switchInsn");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void exceptions() throws Exception {
|
||||||
|
runTest("exceptions");
|
||||||
|
}
|
||||||
|
|
||||||
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";
|
||||||
|
|
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