From a83e7e224819f4a1235c80531fec7b95211dbc70 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 27 Jul 2015 10:13:57 +0300 Subject: [PATCH] Add tests for exceptional control flow. --- .../compiler/transforms/artiq_ir_generator.py | 22 +++++++++---------- lit-test/test/exceptions/catch_all.py | 13 +++++++++++ lit-test/test/exceptions/catch_multi.py | 15 +++++++++++++ lit-test/test/exceptions/catch_outer.py | 15 +++++++++++++ .../test/exceptions/{raise.py => uncaught.py} | 0 soc/runtime/artiq_personality.c | 22 +++++++++---------- 6 files changed, 65 insertions(+), 22 deletions(-) create mode 100644 lit-test/test/exceptions/catch_all.py create mode 100644 lit-test/test/exceptions/catch_multi.py create mode 100644 lit-test/test/exceptions/catch_outer.py rename lit-test/test/exceptions/{raise.py => uncaught.py} (100%) diff --git a/artiq/compiler/transforms/artiq_ir_generator.py b/artiq/compiler/transforms/artiq_ir_generator.py index 54b1efecf..ef3c44166 100644 --- a/artiq/compiler/transforms/artiq_ir_generator.py +++ b/artiq/compiler/transforms/artiq_ir_generator.py @@ -546,13 +546,13 @@ class ARTIQIRGenerator(algorithm.Visitor): has_catchall = True self.current_block = handler - handlers.append(handler) - if handler_node.name is not None: exn = self.append(ir.Builtin("exncast", [landingpad], handler_node.name_type)) self._set_local(handler_node.name, exn) - self.visit(handler_node.body) + post_handler = self.current_block + + handlers.append((handler, post_handler)) if any(node.finalbody): finalizer = self.add_block("finally") @@ -580,12 +580,12 @@ class ARTIQIRGenerator(algorithm.Visitor): # to execute. handler = self.add_block("handler.catchall") landingpad.add_clause(handler, None) - handlers.append(handler) + handlers.append((handler, handler)) - for handler in handlers: - if not handler.is_terminated(): - handler.append(ir.SetLocal(final_state, ".k", tail)) - handler.append(ir.Branch(tail)) + 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)) if not post_finalizer.is_terminated(): dest = post_finalizer.append(ir.GetLocal(final_state, ".k")) @@ -594,9 +594,9 @@ class ARTIQIRGenerator(algorithm.Visitor): if not body.is_terminated(): body.append(ir.Branch(tail)) - for handler in handlers: - if not handler.is_terminated(): - handler.append(ir.Branch(tail)) + for handler, post_handler in handlers: + if not post_handler.is_terminated(): + post_handler.append(ir.Branch(tail)) # TODO: With diff --git a/lit-test/test/exceptions/catch_all.py b/lit-test/test/exceptions/catch_all.py new file mode 100644 index 000000000..21d8f9581 --- /dev/null +++ b/lit-test/test/exceptions/catch_all.py @@ -0,0 +1,13 @@ +# RUN: %python -m artiq.compiler.testbench.jit %s +# REQUIRES: exceptions + +def catch(f): + try: + f() + except Exception as e: + print(e) + +# CHECK-L: ZeroDivisionError +catch(lambda: 1/0) +# CHECK-L: IndexError +catch(lambda: [1.0][10]) diff --git a/lit-test/test/exceptions/catch_multi.py b/lit-test/test/exceptions/catch_multi.py new file mode 100644 index 000000000..fc836e9a0 --- /dev/null +++ b/lit-test/test/exceptions/catch_multi.py @@ -0,0 +1,15 @@ +# RUN: %python -m artiq.compiler.testbench.jit %s +# REQUIRES: exceptions + +def catch(f): + try: + f() + except ZeroDivisionError as zde: + print(zde) + except IndexError as ie: + print(ie) + +# CHECK-L: ZeroDivisionError +catch(lambda: 1/0) +# CHECK-L: IndexError +catch(lambda: [1.0][10]) diff --git a/lit-test/test/exceptions/catch_outer.py b/lit-test/test/exceptions/catch_outer.py new file mode 100644 index 000000000..0011f5c1b --- /dev/null +++ b/lit-test/test/exceptions/catch_outer.py @@ -0,0 +1,15 @@ +# RUN: %python -m artiq.compiler.testbench.jit %s +# REQUIRES: exceptions + +def f(): + try: + 1/0 + except ValueError: + # CHECK-NOT-L: FAIL + print("FAIL") + +try: + f() +except ZeroDivisionError: + # CHECK-L: OK + print("OK") diff --git a/lit-test/test/exceptions/raise.py b/lit-test/test/exceptions/uncaught.py similarity index 100% rename from lit-test/test/exceptions/raise.py rename to lit-test/test/exceptions/uncaught.py diff --git a/soc/runtime/artiq_personality.c b/soc/runtime/artiq_personality.c index 7057bde17..b7bbad460 100644 --- a/soc/runtime/artiq_personality.c +++ b/soc/runtime/artiq_personality.c @@ -229,7 +229,7 @@ void __artiq_raise(struct artiq_exception *artiq_exn) { _Unwind_Reason_Code __artiq_personality( int version, _Unwind_Action actions, uint64_t exceptionClass, struct _Unwind_Exception *exceptionObject, struct _Unwind_Context *context) { - EH_LOG("entry (actions =%s%s%s%s; class=%08lx; object=%p, context=%p)", + EH_LOG("===> entry (actions =%s%s%s%s; class=%08lx; object=%p, context=%p)", (actions & _UA_SEARCH_PHASE ? " search" : ""), (actions & _UA_CLEANUP_PHASE ? " cleanup" : ""), (actions & _UA_HANDLER_FRAME ? " handler" : ""), @@ -240,7 +240,7 @@ _Unwind_Reason_Code __artiq_personality( struct artiq_raised_exception *inflight = (struct artiq_raised_exception*)exceptionObject; - EH_LOG("exception name=%s", + EH_LOG("=> exception name=%s", inflight->artiq.name); // Get a pointer to LSDA. If there's no LSDA, this function doesn't @@ -259,7 +259,7 @@ _Unwind_Reason_Code __artiq_personality( uintptr_t funcStart = _Unwind_GetRegionStart(context); uintptr_t pcOffset = pc - funcStart; - EH_LOG("pc=%p (%p+%p)", (void*)pc, (void*)funcStart, (void*)pcOffset); + EH_LOG("=> pc=%p (%p+%p)", (void*)pc, (void*)funcStart, (void*)pcOffset); // Parse LSDA header. uint8_t lpStartEncoding = *lsda++; @@ -286,7 +286,7 @@ _Unwind_Reason_Code __artiq_personality( const uint8_t *actionTableStart = callSiteTableEnd; const uint8_t *callSitePtr = callSiteTableStart; - while (callSitePtr < callSiteTableEnd) { + while(callSitePtr < callSiteTableEnd) { uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding); uintptr_t length = readEncodedPointer(&callSitePtr, @@ -303,8 +303,8 @@ _Unwind_Reason_Code __artiq_personality( continue; } - if ((start <= pcOffset) && (pcOffset < (start + length))) { - EH_LOG0("call site matches pc"); + if((start <= pcOffset) && (pcOffset < (start + length))) { + EH_LOG0("=> call site matches pc"); int exceptionMatched = 0; if(actionValue) { @@ -329,7 +329,7 @@ _Unwind_Reason_Code __artiq_personality( encodingSize, typeInfoPtrPtr, (void*)typeInfoPtr); EH_LOG("typeInfo=%s", (char*)typeInfoPtr); - if(inflight->artiq.typeinfo == typeInfoPtr) { + if(typeInfoPtr == 0 || inflight->artiq.typeinfo == typeInfoPtr) { EH_LOG0("matching action found"); exceptionMatched = 1; break; @@ -342,8 +342,8 @@ _Unwind_Reason_Code __artiq_personality( } } - if (!(actions & _UA_SEARCH_PHASE)) { - EH_LOG0("jumping to landing pad"); + if(!(actions & _UA_SEARCH_PHASE)) { + EH_LOG0("=> jumping to landing pad"); _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), (uintptr_t)exceptionObject); @@ -353,11 +353,11 @@ _Unwind_Reason_Code __artiq_personality( return _URC_INSTALL_CONTEXT; } else if(exceptionMatched) { - EH_LOG0("handler found"); + EH_LOG0("=> handler found"); return _URC_HANDLER_FOUND; } else { - EH_LOG0("handler not found"); + EH_LOG0("=> handler not found"); return _URC_CONTINUE_UNWIND; }