From 2939d4f0f3bb2a20bd34f954ec3f31a07b05ed56 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 27 Jul 2015 12:36:21 +0300 Subject: [PATCH] Add tests for finally clause and reraising. --- artiq/compiler/ir.py | 50 ++++++++++---- .../compiler/transforms/artiq_ir_generator.py | 47 ++++++++------ .../transforms/dead_code_eliminator.py | 8 +-- artiq/compiler/transforms/inferencer.py | 15 +++-- .../compiler/transforms/llvm_ir_generator.py | 24 +++++-- lit-test/test/exceptions/catch.py | 3 +- lit-test/test/exceptions/catch_all.py | 3 +- lit-test/test/exceptions/catch_multi.py | 3 +- lit-test/test/exceptions/catch_outer.py | 3 +- lit-test/test/exceptions/finally.py | 21 ++++++ lit-test/test/exceptions/finally_catch.py | 17 +++++ lit-test/test/exceptions/finally_raise.py | 23 +++++++ lit-test/test/exceptions/finally_squash.py | 21 ++++++ lit-test/test/exceptions/reraise.py | 16 +++++ lit-test/test/exceptions/reraise_update.py | 16 +++++ lit-test/test/exceptions/uncaught.py | 5 +- lit-test/test/integration/finally.py | 12 ++++ soc/runtime/artiq_personality.c | 65 +++++++++++++------ soc/runtime/artiq_personality.h | 9 ++- t.py | 0 20 files changed, 285 insertions(+), 76 deletions(-) create mode 100644 lit-test/test/exceptions/finally.py create mode 100644 lit-test/test/exceptions/finally_catch.py create mode 100644 lit-test/test/exceptions/finally_raise.py create mode 100644 lit-test/test/exceptions/finally_squash.py create mode 100644 lit-test/test/exceptions/reraise.py create mode 100644 lit-test/test/exceptions/reraise_update.py create mode 100644 t.py diff --git a/artiq/compiler/ir.py b/artiq/compiler/ir.py index 3a00c7335..7cb73ed30 100644 --- a/artiq/compiler/ir.py +++ b/artiq/compiler/ir.py @@ -979,15 +979,14 @@ class Raise(Terminator): """ :param value: (:class:`Value`) exception value - :param exn: (:class:`BasicBlock`) exceptional target + :param exn: (:class:`BasicBlock` or None) exceptional target """ - def __init__(self, value, exn=None, name=""): + def __init__(self, value=None, exn=None, name=""): assert isinstance(value, Value) + operands = [value] if exn is not None: assert isinstance(exn, BasicBlock) - operands = [value, exn] - else: - operands = [value] + operands.append(exn) super().__init__(operands, builtins.TNone(), name) def opcode(self): @@ -1000,6 +999,28 @@ class Raise(Terminator): if len(self.operands) > 1: return self.operands[1] +class Reraise(Terminator): + """ + A reraise instruction. + """ + + """ + :param exn: (:class:`BasicBlock` or None) exceptional target + """ + def __init__(self, exn=None, name=""): + operands = [] + if exn is not None: + assert isinstance(exn, BasicBlock) + operands.append(exn) + super().__init__(operands, builtins.TNone(), name) + + def opcode(self): + return "reraise" + + def exception_target(self): + if len(self.operands) > 0: + return self.operands[0] + class Invoke(Terminator): """ A function call operation that supports exception handling. @@ -1051,12 +1072,18 @@ class LandingPad(Terminator): exception types corresponding to the basic block operands """ - def __init__(self, name=""): - super().__init__([], builtins.TException(), name) + def __init__(self, cleanup, name=""): + super().__init__([cleanup], builtins.TException(), name) self.types = [] + def opcode(self): + return "landingpad" + + def cleanup(self): + return self.operands[0] + def clauses(self): - return zip(self.operands, self.types) + return zip(self.operands[1:], self.types) def add_clause(self, target, typ): assert isinstance(target, BasicBlock) @@ -1065,14 +1092,11 @@ class LandingPad(Terminator): self.types.append(typ.find() if typ is not None else None) target.uses.add(self) - def opcode(self): - return "landingpad" - def _operands_as_string(self): table = [] - for typ, target in zip(self.types, self.operands): + for target, typ in self.clauses(): if typ is None: table.append("... => {}".format(target.as_operand())) else: table.append("{} => {}".format(types.TypePrinter().name(typ), target.as_operand())) - return "[{}]".format(", ".join(table)) + return "cleanup {}, [{}]".format(self.cleanup().as_operand(), ", ".join(table)) diff --git a/artiq/compiler/transforms/artiq_ir_generator.py b/artiq/compiler/transforms/artiq_ir_generator.py index ef3c44166..8c649a25b 100644 --- a/artiq/compiler/transforms/artiq_ir_generator.py +++ b/artiq/compiler/transforms/artiq_ir_generator.py @@ -466,23 +466,29 @@ class ARTIQIRGenerator(algorithm.Visitor): self.append(ir.Branch(self.continue_target)) def raise_exn(self, exn): - loc_file = ir.Constant(self.current_loc.source_buffer.name, builtins.TStr()) - loc_line = ir.Constant(self.current_loc.line(), builtins.TInt(types.TValue(32))) - loc_column = ir.Constant(self.current_loc.column(), builtins.TInt(types.TValue(32))) - self.append(ir.SetAttr(exn, "__file__", loc_file)) - self.append(ir.SetAttr(exn, "__line__", loc_line)) - self.append(ir.SetAttr(exn, "__col__", loc_column)) - if self.unwind_target: - self.append(ir.Raise(exn, self.unwind_target)) + if exn is not None: + loc_file = ir.Constant(self.current_loc.source_buffer.name, builtins.TStr()) + loc_line = ir.Constant(self.current_loc.line(), builtins.TInt(types.TValue(32))) + loc_column = ir.Constant(self.current_loc.column(), builtins.TInt(types.TValue(32))) + self.append(ir.SetAttr(exn, "__file__", loc_file)) + self.append(ir.SetAttr(exn, "__line__", loc_line)) + self.append(ir.SetAttr(exn, "__col__", loc_column)) + + if self.unwind_target is not None: + self.append(ir.Raise(exn, self.unwind_target)) + else: + self.append(ir.Raise(exn)) else: - self.append(ir.Raise(exn)) + if self.unwind_target is not None: + self.append(ir.Reraise(self.unwind_target)) + else: + self.append(ir.Reraise()) def visit_Raise(self, node): self.raise_exn(self.visit(node.exc)) def visit_Try(self, node): dispatcher = self.add_block("try.dispatch") - landingpad = dispatcher.append(ir.LandingPad()) if any(node.finalbody): # k for continuation @@ -532,8 +538,10 @@ class ARTIQIRGenerator(algorithm.Visitor): self.continue_target = old_continue self.return_target = old_return + cleanup = self.add_block('handler.cleanup') + landingpad = dispatcher.append(ir.LandingPad(cleanup)) + handlers = [] - has_catchall = False for handler_node in node.handlers: exn_type = handler_node.name_type.find() if handler_node.filter is not None and \ @@ -543,7 +551,6 @@ class ARTIQIRGenerator(algorithm.Visitor): else: handler = self.add_block("handler.catchall") landingpad.add_clause(handler, None) - has_catchall = True self.current_block = handler if handler_node.name is not None: @@ -561,9 +568,13 @@ class ARTIQIRGenerator(algorithm.Visitor): self.visit(node.finalbody) post_finalizer = self.current_block + reraise = self.add_block('try.reraise') + reraise.append(ir.Reraise(self.unwind_target)) + self.current_block = tail = self.add_block("try.tail") if any(node.finalbody): final_targets.append(tail) + final_targets.append(reraise) if self.break_target: break_proxy.append(ir.Branch(finalizer)) @@ -575,17 +586,13 @@ class ARTIQIRGenerator(algorithm.Visitor): body.append(ir.SetLocal(final_state, ".k", tail)) body.append(ir.Branch(finalizer)) - if not has_catchall: - # Add a catch-all handler so that finally would have a chance - # to execute. - handler = self.add_block("handler.catchall") - landingpad.add_clause(handler, None) - handlers.append((handler, handler)) + cleanup.append(ir.SetLocal(final_state, ".k", reraise)) + cleanup.append(ir.Branch(finalizer)) for handler, post_handler in handlers: if not post_handler.is_terminated(): post_handler.append(ir.SetLocal(final_state, ".k", tail)) - post_handler.append(ir.Branch(tail)) + post_handler.append(ir.Branch(finalizer)) if not post_finalizer.is_terminated(): dest = post_finalizer.append(ir.GetLocal(final_state, ".k")) @@ -594,6 +601,8 @@ class ARTIQIRGenerator(algorithm.Visitor): if not body.is_terminated(): body.append(ir.Branch(tail)) + cleanup.append(ir.Reraise(self.unwind_target)) + for handler, post_handler in handlers: if not post_handler.is_terminated(): post_handler.append(ir.Branch(tail)) diff --git a/artiq/compiler/transforms/dead_code_eliminator.py b/artiq/compiler/transforms/dead_code_eliminator.py index 003b8561c..1159dc0ca 100644 --- a/artiq/compiler/transforms/dead_code_eliminator.py +++ b/artiq/compiler/transforms/dead_code_eliminator.py @@ -15,7 +15,9 @@ class DeadCodeEliminator: def process_function(self, func): for block in func.basic_blocks: - if not any(block.predecessors()) and block != func.entry(): + if not any(block.predecessors()) and \ + not any([isinstance(use, ir.SetLocal) for use in block.uses]) and \ + block != func.entry(): self.remove_block(block) def remove_block(self, block): @@ -25,10 +27,6 @@ class DeadCodeEliminator: use.remove_incoming_block(block) if not any(use.operands): self.remove_instruction(use) - elif isinstance(use, ir.SetLocal): - # Setting the target for `finally` resumption, e.g. - # setlocal(.k) %v.4, label %try.doreturn - use.erase() else: assert False diff --git a/artiq/compiler/transforms/inferencer.py b/artiq/compiler/transforms/inferencer.py index 15604e5b8..57aa9247d 100644 --- a/artiq/compiler/transforms/inferencer.py +++ b/artiq/compiler/transforms/inferencer.py @@ -956,13 +956,14 @@ class Inferencer(algorithm.Visitor): def visit_Raise(self, node): self.generic_visit(node) - exc_type = node.exc.type - if not types.is_var(exc_type) and not builtins.is_exception(exc_type): - diag = diagnostic.Diagnostic("error", - "cannot raise a value of type {type}, which is not an exception", - {"type": types.TypePrinter().name(exc_type)}, - node.exc.loc) - self.engine.process(diag) + if node.exc is not None: + exc_type = node.exc.type + if not types.is_var(exc_type) and not builtins.is_exception(exc_type): + diag = diagnostic.Diagnostic("error", + "cannot raise a value of type {type}, which is not an exception", + {"type": types.TypePrinter().name(exc_type)}, + node.exc.loc) + self.engine.process(diag) def visit_Assert(self, node): self.generic_visit(node) diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index 965ddad8c..8c1eca73b 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -137,13 +137,19 @@ class LLVMIRGenerator: llty = ll.FunctionType(ll.DoubleType(), [ll.DoubleType(), ll.DoubleType()]) elif name == "printf": llty = ll.FunctionType(ll.VoidType(), [ll.IntType(8).as_pointer()], var_arg=True) - elif name == "__artiq_raise": - llty = ll.FunctionType(ll.VoidType(), [self.llty_of_type(builtins.TException())]) elif name == "__artiq_personality": llty = ll.FunctionType(ll.IntType(32), [], var_arg=True) + elif name == "__artiq_raise": + llty = ll.FunctionType(ll.VoidType(), [self.llty_of_type(builtins.TException())]) + elif name == "__artiq_reraise": + llty = ll.FunctionType(ll.VoidType(), []) else: assert False - return ll.Function(self.llmodule, llty, name) + + llfun = ll.Function(self.llmodule, llty, name) + if name in ("__artiq_raise", "__artiq_reraise", "llvm.trap"): + llfun.attributes.add("noreturn") + return llfun def map(self, value): if isinstance(value, (ir.Argument, ir.Instruction, ir.BasicBlock)): @@ -599,12 +605,20 @@ class LLVMIRGenerator: llinsn.attributes.add('noreturn') return llinsn + def process_Reraise(self, insn): + llinsn = self.llbuilder.call(self.llbuiltin("__artiq_reraise"), [], + name=insn.name) + llinsn.attributes.add('noreturn') + self.llbuilder.unreachable() + return llinsn + def process_LandingPad(self, insn): # Layout on return from landing pad: {%_Unwind_Exception*, %Exception*} lllandingpadty = ll.LiteralStructType([ll.IntType(8).as_pointer(), ll.IntType(8).as_pointer()]) lllandingpad = self.llbuilder.landingpad(lllandingpadty, - self.llbuiltin("__artiq_personality")) + self.llbuiltin("__artiq_personality"), + cleanup=True) llrawexn = self.llbuilder.extract_value(lllandingpad, 1) llexn = self.llbuilder.bitcast(llrawexn, self.llty_of_type(insn.type)) llexnnameptr = self.llbuilder.gep(llexn, [self.llindex(0), self.llindex(0)]) @@ -627,7 +641,7 @@ class LLVMIRGenerator: self.llbuilder.branch(self.map(target)) if self.llbuilder.basic_block.terminator is None: - self.llbuilder.resume(lllandingpad) + self.llbuilder.branch(self.map(insn.cleanup())) return llexn diff --git a/lit-test/test/exceptions/catch.py b/lit-test/test/exceptions/catch.py index 4d2730859..d6c2866c1 100644 --- a/lit-test/test/exceptions/catch.py +++ b/lit-test/test/exceptions/catch.py @@ -1,4 +1,5 @@ -# RUN: %python -m artiq.compiler.testbench.jit %s +# RUN: %python -m artiq.compiler.testbench.jit %s >%t +# RUN: OutputCheck %s --file-to-check=%t # REQUIRES: exceptions try: diff --git a/lit-test/test/exceptions/catch_all.py b/lit-test/test/exceptions/catch_all.py index 21d8f9581..1417f5f31 100644 --- a/lit-test/test/exceptions/catch_all.py +++ b/lit-test/test/exceptions/catch_all.py @@ -1,4 +1,5 @@ -# RUN: %python -m artiq.compiler.testbench.jit %s +# RUN: %python -m artiq.compiler.testbench.jit %s >%t +# RUN: OutputCheck %s --file-to-check=%t # REQUIRES: exceptions def catch(f): diff --git a/lit-test/test/exceptions/catch_multi.py b/lit-test/test/exceptions/catch_multi.py index fc836e9a0..472086660 100644 --- a/lit-test/test/exceptions/catch_multi.py +++ b/lit-test/test/exceptions/catch_multi.py @@ -1,4 +1,5 @@ -# RUN: %python -m artiq.compiler.testbench.jit %s +# RUN: %python -m artiq.compiler.testbench.jit %s >%t +# RUN: OutputCheck %s --file-to-check=%t # REQUIRES: exceptions def catch(f): diff --git a/lit-test/test/exceptions/catch_outer.py b/lit-test/test/exceptions/catch_outer.py index 0011f5c1b..de7253eaf 100644 --- a/lit-test/test/exceptions/catch_outer.py +++ b/lit-test/test/exceptions/catch_outer.py @@ -1,4 +1,5 @@ -# RUN: %python -m artiq.compiler.testbench.jit %s +# RUN: %python -m artiq.compiler.testbench.jit %s >%t +# RUN: OutputCheck %s --file-to-check=%t # REQUIRES: exceptions def f(): diff --git a/lit-test/test/exceptions/finally.py b/lit-test/test/exceptions/finally.py new file mode 100644 index 000000000..17304fc15 --- /dev/null +++ b/lit-test/test/exceptions/finally.py @@ -0,0 +1,21 @@ +# RUN: %python -m artiq.compiler.testbench.jit %s >%t +# RUN: OutputCheck %s --file-to-check=%t +# REQUIRES: exceptions + +def f(): + try: + 1/0 + finally: + print("f-fin") + print("f-out") + +def g(): + try: + f() + except: + print("g-except") + +# CHECK-L: f-fin +# CHECK-NOT-L: f-out +# CHECK-L: g-except +g() diff --git a/lit-test/test/exceptions/finally_catch.py b/lit-test/test/exceptions/finally_catch.py new file mode 100644 index 000000000..23bc39730 --- /dev/null +++ b/lit-test/test/exceptions/finally_catch.py @@ -0,0 +1,17 @@ +# RUN: %python -m artiq.compiler.testbench.jit %s >%t +# RUN: OutputCheck %s --file-to-check=%t +# REQUIRES: exceptions + +def f(): + try: + 1/0 + except: + print("f-except") + finally: + print("f-fin") + print("f-out") + +# CHECK-L: f-except +# CHECK-L: f-fin +# CHECK-L: f-out +f() diff --git a/lit-test/test/exceptions/finally_raise.py b/lit-test/test/exceptions/finally_raise.py new file mode 100644 index 000000000..02c41ea7e --- /dev/null +++ b/lit-test/test/exceptions/finally_raise.py @@ -0,0 +1,23 @@ +# RUN: %python -m artiq.compiler.testbench.jit %s >%t +# RUN: OutputCheck %s --file-to-check=%t +# REQUIRES: exceptions + +def f(): + try: + 1/0 + finally: + print("f-fin") + raise ValueError() + +def g(): + try: + f() + except ZeroDivisionError: + print("g-except-zde") + except ValueError: + print("g-except-ve") + +# CHECK-L: f-fin +# CHECK-L: g-except-ve +# CHECK-NOT-L: g-except-zde +g() diff --git a/lit-test/test/exceptions/finally_squash.py b/lit-test/test/exceptions/finally_squash.py new file mode 100644 index 000000000..8c7b58fc3 --- /dev/null +++ b/lit-test/test/exceptions/finally_squash.py @@ -0,0 +1,21 @@ +# RUN: %python -m artiq.compiler.testbench.jit %s >%t +# RUN: OutputCheck %s --file-to-check=%t +# REQUIRES: exceptions + +def f(): + try: + 1/0 + finally: + print("f-fin") + return + +def g(): + try: + f() + except: + print("g-except") + +# CHECK-L: f-fin +# CHECK-NOT-L: f-out +# CHECK-NOT-L: g-except +g() diff --git a/lit-test/test/exceptions/reraise.py b/lit-test/test/exceptions/reraise.py new file mode 100644 index 000000000..2a02b523d --- /dev/null +++ b/lit-test/test/exceptions/reraise.py @@ -0,0 +1,16 @@ +# RUN: %not %python -m artiq.compiler.testbench.jit %s >%t +# RUN: OutputCheck %s --file-to-check=%t +# REQUIRES: exceptions + +def f(): + # CHECK-L: Uncaught ZeroDivisionError + # CHECK-L: at input.py:${LINE:+1}: + 1/0 + +def g(): + try: + f() + except: + raise + +g() diff --git a/lit-test/test/exceptions/reraise_update.py b/lit-test/test/exceptions/reraise_update.py new file mode 100644 index 000000000..891e7685d --- /dev/null +++ b/lit-test/test/exceptions/reraise_update.py @@ -0,0 +1,16 @@ +# RUN: %not %python -m artiq.compiler.testbench.jit %s >%t +# RUN: OutputCheck %s --file-to-check=%t +# REQUIRES: exceptions + +def f(): + 1/0 + +def g(): + try: + f() + except Exception as e: + # CHECK-L: Uncaught ZeroDivisionError + # CHECK-L: at input.py:${LINE:+1}: + raise e + +g() diff --git a/lit-test/test/exceptions/uncaught.py b/lit-test/test/exceptions/uncaught.py index 4e056e025..6044f8bf2 100644 --- a/lit-test/test/exceptions/uncaught.py +++ b/lit-test/test/exceptions/uncaught.py @@ -1,6 +1,7 @@ -# RUN: %not %python -m artiq.compiler.testbench.jit %s +# RUN: %not %python -m artiq.compiler.testbench.jit %s >%t +# RUN: OutputCheck %s --file-to-check=%t # REQUIRES: exceptions # CHECK-L: Uncaught ZeroDivisionError: cannot divide by zero (0, 0, 0) -# CHECK-L: at input.py:${LINE:+1}:0 +# CHECK-L: at input.py:${LINE:+1}: 1/0 diff --git a/lit-test/test/integration/finally.py b/lit-test/test/integration/finally.py index 376051e66..fab1fe93d 100644 --- a/lit-test/test/integration/finally.py +++ b/lit-test/test/integration/finally.py @@ -62,3 +62,15 @@ def i(): # CHECK-NOT-L: i-out # CHECK-L: i 30 print("i", i()) + +def j(): + try: + print("j-try") + finally: + print("j-finally") + print("j-out") + +# CHECK-L: j-try +# CHECK-L: j-finally +# CHECK-L: j-out +print("j", j()) diff --git a/soc/runtime/artiq_personality.c b/soc/runtime/artiq_personality.c index b7bbad460..a8c19cfd0 100644 --- a/soc/runtime/artiq_personality.c +++ b/soc/runtime/artiq_personality.c @@ -8,8 +8,8 @@ /* Logging */ #ifndef NDEBUG -#define EH_LOG0(fmt) fprintf(stderr, "__artiq_personality: " fmt "\n") -#define EH_LOG(fmt, ...) fprintf(stderr, "__artiq_personality: " fmt "\n", __VA_ARGS__) +#define EH_LOG0(fmt) fprintf(stderr, "%s: " fmt "\n", __func__) +#define EH_LOG(fmt, ...) fprintf(stderr, "%s: " fmt "\n", __func__, __VA_ARGS__) #else #define EH_LOG0(fmt) #define EH_LOG(fmt, ...) @@ -17,7 +17,7 @@ #define EH_FAIL(err) \ do { \ - fprintf(stderr, "__artiq_personality fatal: %s\n", err); \ + fprintf(stderr, "%s fatal: %s\n", __func__, err); \ abort(); \ } while(0) @@ -195,37 +195,61 @@ static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) { } -/* Raising and catching */ +/* Raising */ #define ARTIQ_EXCEPTION_CLASS 0x4152545141525451LL // 'ARTQARTQ' +static void __artiq_cleanup(_Unwind_Reason_Code reason, struct _Unwind_Exception *exc); + struct artiq_raised_exception { struct _Unwind_Exception unwind; struct artiq_exception artiq; + int handled; }; +static struct artiq_raised_exception inflight; + +void __artiq_raise(struct artiq_exception *artiq_exn) { + EH_LOG("===> raise (name=%s)", artiq_exn->name); + + memmove(&inflight.artiq, artiq_exn, sizeof(struct artiq_exception)); + inflight.unwind.exception_class = ARTIQ_EXCEPTION_CLASS; + inflight.unwind.exception_cleanup = &__artiq_cleanup; + inflight.handled = 0; + + _Unwind_Reason_Code result = _Unwind_RaiseException(&inflight.unwind); + EH_ASSERT((result == _URC_END_OF_STACK) && + "Unexpected error during unwinding"); + + // If we're here, there are no handlers, only cleanups. + __artiq_terminate(&inflight.artiq); +} + +void __artiq_reraise() { + if(inflight.handled) { + EH_LOG0("===> reraise"); + __artiq_raise(&inflight.artiq); + } else { + EH_LOG0("===> resume"); + EH_ASSERT((inflight.artiq.typeinfo != 0) && + "Need an exception to reraise"); + _Unwind_Resume(&inflight.unwind); + abort(); + } +} + +/* Catching */ + +// The code below does not refer to the `inflight` global. + static void __artiq_cleanup(_Unwind_Reason_Code reason, struct _Unwind_Exception *exc) { + EH_LOG0("===> cleanup"); struct artiq_raised_exception *inflight = (struct artiq_raised_exception*) exc; // The in-flight exception is statically allocated, so we don't need to free it. // But, we clear it to mark it as processed. memset(&inflight->artiq, 0, sizeof(struct artiq_exception)); } -void __artiq_raise(struct artiq_exception *artiq_exn) { - static struct artiq_raised_exception inflight; - memcpy(&inflight.artiq, artiq_exn, sizeof(struct artiq_exception)); - inflight.unwind.exception_class = ARTIQ_EXCEPTION_CLASS; - inflight.unwind.exception_cleanup = &__artiq_cleanup; - - _Unwind_Reason_Code result = _Unwind_RaiseException(&inflight.unwind); - if(result == _URC_END_OF_STACK) { - __artiq_terminate(&inflight.artiq); - } else { - fprintf(stderr, "__artiq_raise: unexpected error (%d)\n", result); - abort(); - } -} - _Unwind_Reason_Code __artiq_personality( int version, _Unwind_Action actions, uint64_t exceptionClass, struct _Unwind_Exception *exceptionObject, struct _Unwind_Context *context) { @@ -345,6 +369,9 @@ _Unwind_Reason_Code __artiq_personality( if(!(actions & _UA_SEARCH_PHASE)) { EH_LOG0("=> jumping to landing pad"); + if(actions & _UA_HANDLER_FRAME) + inflight->handled = 1; + _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), (uintptr_t)exceptionObject); _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), diff --git a/soc/runtime/artiq_personality.h b/soc/runtime/artiq_personality.h index 45b0ef9f1..2e3fc0f45 100644 --- a/soc/runtime/artiq_personality.h +++ b/soc/runtime/artiq_personality.h @@ -19,10 +19,15 @@ struct artiq_exception { extern "C" { #endif -void __artiq_terminate(struct artiq_exception *artiq_exn) +/* Provided by the runtime */ +void __artiq_raise(struct artiq_exception *artiq_exn) + __attribute__((noreturn)); +void __artiq_reraise() __attribute__((noreturn)); -void __artiq_raise(struct artiq_exception *artiq_exn); +/* Called by the runtime */ +void __artiq_terminate(struct artiq_exception *artiq_exn) + __attribute__((noreturn)); #ifdef __cplusplus } diff --git a/t.py b/t.py new file mode 100644 index 000000000..e69de29bb