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