mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-31 12:24:10 -08:00
C: fix behaviour of nested try/catch statements
This commit is contained in:
parent
73bd139b7e
commit
220537d984
|
@ -151,6 +151,8 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
|||
private ObjectIntMap<IdentifiedStatement> labelMap = new ObjectIntHashMap<>();
|
||||
private Set<IdentifiedStatement> usedAsBreakTarget = new HashSet<>();
|
||||
private Set<IdentifiedStatement> usedAsContinueTarget = new HashSet<>();
|
||||
private Map<IdentifiedStatement, Integer> tryDepthByStatements = new HashMap<>();
|
||||
private int tryDepth;
|
||||
|
||||
static {
|
||||
BUFFER_TYPES.put(ByteBuffer.class.getName(), "int8_t");
|
||||
|
@ -1197,8 +1199,7 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
|||
IdentifiedStatement oldDefaultBreakTarget = defaultBreakTarget;
|
||||
defaultBreakTarget = statement;
|
||||
|
||||
int statementId = labelMap.size() + 1;
|
||||
labelMap.put(statement, statementId);
|
||||
int statementId = registerIdentifiedStatement(statement);
|
||||
|
||||
pushLocation(statement.getValue().getLocation());
|
||||
writer.print("switch (");
|
||||
|
@ -1243,8 +1244,7 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
|||
defaultBreakTarget = statement;
|
||||
defaultContinueTarget = statement;
|
||||
|
||||
int statementId = labelMap.size() + 1;
|
||||
labelMap.put(statement, statementId);
|
||||
int statementId = registerIdentifiedStatement(statement);
|
||||
|
||||
writer.print("while (");
|
||||
if (statement.getCondition() != null) {
|
||||
|
@ -1276,8 +1276,7 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(BlockStatement statement) {
|
||||
int statementId = labelMap.size() + 1;
|
||||
labelMap.put(statement, statementId);
|
||||
int statementId = registerIdentifiedStatement(statement);
|
||||
|
||||
visitMany(statement.getBody());
|
||||
|
||||
|
@ -1293,8 +1292,7 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
|||
if (target == null) {
|
||||
target = defaultBreakTarget;
|
||||
}
|
||||
int id = labelMap.get(target);
|
||||
writer.println("goto teavm_label_" + id + ";");
|
||||
jumpToTarget(target, "teavm_label_");
|
||||
usedAsBreakTarget.add(target);
|
||||
popLocation(statement.getLocation());
|
||||
}
|
||||
|
@ -1306,12 +1304,28 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
|||
if (target == null) {
|
||||
target = defaultContinueTarget;
|
||||
}
|
||||
int id = labelMap.get(target);
|
||||
writer.println("goto teavm_cnt_" + id + ";");
|
||||
jumpToTarget(target, "teavm_cnt_");
|
||||
usedAsContinueTarget.add(target);
|
||||
popLocation(statement.getLocation());
|
||||
}
|
||||
|
||||
private int registerIdentifiedStatement(IdentifiedStatement statement) {
|
||||
tryDepthByStatements.put(statement, tryDepth);
|
||||
int statementId = labelMap.size() + 1;
|
||||
labelMap.put(statement, statementId);
|
||||
return statementId;
|
||||
}
|
||||
|
||||
private void jumpToTarget(IdentifiedStatement target, String prefix) {
|
||||
int targetDepth = tryDepthByStatements.get(target);
|
||||
while (targetDepth < tryDepth) {
|
||||
targetDepth++;
|
||||
writer.println("TEAVM_RESTORE_JUMP_BUFFER;");
|
||||
}
|
||||
int id = labelMap.get(target);
|
||||
writer.println("goto " + prefix + id + ";");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ReturnStatement statement) {
|
||||
pushLocation(statement.getLocation());
|
||||
|
@ -1398,7 +1412,10 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
|||
}
|
||||
|
||||
writer.println("TEAVM_TRY").indent();
|
||||
tryDepth++;
|
||||
visitMany(statement.getProtectedBody());
|
||||
tryDepth--;
|
||||
handlers.subList(firstId, handlers.size()).clear();
|
||||
writer.outdent().println("TEAVM_CATCH").indent();
|
||||
|
||||
for (int i = tryCatchStatements.size() - 1; i >= 0; --i) {
|
||||
|
@ -1421,8 +1438,6 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
|||
writer.outdent().println("}");
|
||||
}
|
||||
|
||||
handlers.subList(firstId, handlers.size()).clear();
|
||||
|
||||
writer.outdent().println("TEAVM_END_TRY");
|
||||
}
|
||||
|
||||
|
|
|
@ -108,13 +108,17 @@ public final class ExceptionHandling {
|
|||
while (handler != null) {
|
||||
if (handler.exceptionClass == null || handler.exceptionClass.isSupertypeOf.apply(exceptionClass)) {
|
||||
handlerId = handler.id;
|
||||
ShadowStack.setExceptionHandlerId(stackFrame, handler.id);
|
||||
if (!isJumpSupported()) {
|
||||
ShadowStack.setExceptionHandlerId(stackFrame, handlerId);
|
||||
}
|
||||
break stackLoop;
|
||||
}
|
||||
handler = handler.next;
|
||||
}
|
||||
|
||||
ShadowStack.setExceptionHandlerId(stackFrame, callSiteId - 1);
|
||||
if (!isJumpSupported()) {
|
||||
ShadowStack.setExceptionHandlerId(stackFrame, callSiteId - 1);
|
||||
}
|
||||
}
|
||||
stackFrame = ShadowStack.getNextStackFrame(stackFrame);
|
||||
}
|
||||
|
|
|
@ -10,21 +10,25 @@
|
|||
|
||||
#if TEAVM_USE_SETJMP
|
||||
#define TEAVM_JUMP_SUPPORTED 1
|
||||
|
||||
#define TEAVM_RESTORE_JUMP_BUFFER \
|
||||
teavm_shadowStack.header.jmpTarget = teavm_shadowStack.header.jmpTarget->previous
|
||||
|
||||
#define TEAVM_TRY \
|
||||
do { \
|
||||
jmp_buf teavm_tryBuffer; \
|
||||
jmp_buf* teavm_oldTryBuffer = teavm_shadowStack.header.jmpTarget; \
|
||||
teavm_shadowStack.header.jmpTarget = &teavm_tryBuffer; \
|
||||
int teavm_exceptionHandler = setjmp(teavm_tryBuffer); \
|
||||
TeaVM_LongjmpDesc teavm_longJmpdesc; \
|
||||
teavm_longJmpdesc.previous = teavm_shadowStack.header.jmpTarget; \
|
||||
teavm_shadowStack.header.jmpTarget = &teavm_longJmpdesc; \
|
||||
int teavm_exceptionHandler = setjmp(teavm_longJmpdesc.buffer); \
|
||||
if (teavm_exceptionHandler == 0) {
|
||||
#define TEAVM_CATCH \
|
||||
teavm_shadowStack.header.jmpTarget = teavm_oldTryBuffer; \
|
||||
TEAVM_RESTORE_JUMP_BUFFER; \
|
||||
} else { \
|
||||
teavm_shadowStack.header.jmpTarget = teavm_oldTryBuffer; \
|
||||
TEAVM_RESTORE_JUMP_BUFFER; \
|
||||
switch (teavm_exceptionHandler) {
|
||||
#define TEAVM_END_TRY \
|
||||
default: \
|
||||
longjmp(*teavm_oldTryBuffer, teavm_exceptionHandler); \
|
||||
longjmp(teavm_shadowStack.header.jmpTarget->buffer, teavm_exceptionHandler); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
|
@ -32,7 +36,7 @@
|
|||
|
||||
#define TEAVM_JUMP_TO_FRAME(frame, id) \
|
||||
teavm_stackTop = (TeaVM_StackFrame*) (frame); \
|
||||
longjmp(*teavm_stackTop->jmpTarget, id)
|
||||
longjmp(teavm_stackTop->jmpTarget->buffer, id)
|
||||
|
||||
|
||||
#if TEAVM_UNIX
|
||||
|
|
|
@ -35,13 +35,20 @@ typedef struct TeaVM_CallSite {
|
|||
TeaVM_CallSiteLocation* location;
|
||||
} TeaVM_CallSite;
|
||||
|
||||
#if TEAVM_USE_SETJMP
|
||||
typedef struct TeaVM_LongjmpDesc {
|
||||
jmp_buf buffer;
|
||||
struct TeaVM_LongjmpDesc* previous;
|
||||
} TeaVM_LongjmpDesc;
|
||||
#endif
|
||||
|
||||
typedef struct TeaVM_StackFrame {
|
||||
struct TeaVM_StackFrame* next;
|
||||
#if TEAVM_INCREMENTAL
|
||||
TeaVM_CallSite* callSites;
|
||||
#endif
|
||||
#if TEAVM_USE_SETJMP
|
||||
jmp_buf* jmpTarget;
|
||||
TeaVM_LongjmpDesc* jmpTarget;
|
||||
#endif
|
||||
int32_t size;
|
||||
int32_t callSiteId;
|
||||
|
|
Loading…
Reference in New Issue
Block a user