Add tests for exceptional control flow.

This commit is contained in:
whitequark 2015-07-27 10:13:57 +03:00
parent 90be44c596
commit a83e7e2248
6 changed files with 65 additions and 22 deletions

View File

@ -546,13 +546,13 @@ class ARTIQIRGenerator(algorithm.Visitor):
has_catchall = True has_catchall = True
self.current_block = handler self.current_block = handler
handlers.append(handler)
if handler_node.name is not None: if handler_node.name is not None:
exn = self.append(ir.Builtin("exncast", [landingpad], handler_node.name_type)) exn = self.append(ir.Builtin("exncast", [landingpad], handler_node.name_type))
self._set_local(handler_node.name, exn) self._set_local(handler_node.name, exn)
self.visit(handler_node.body) self.visit(handler_node.body)
post_handler = self.current_block
handlers.append((handler, post_handler))
if any(node.finalbody): if any(node.finalbody):
finalizer = self.add_block("finally") finalizer = self.add_block("finally")
@ -580,12 +580,12 @@ class ARTIQIRGenerator(algorithm.Visitor):
# to execute. # to execute.
handler = self.add_block("handler.catchall") handler = self.add_block("handler.catchall")
landingpad.add_clause(handler, None) landingpad.add_clause(handler, None)
handlers.append(handler) handlers.append((handler, handler))
for handler in handlers: for handler, post_handler in handlers:
if not handler.is_terminated(): if not post_handler.is_terminated():
handler.append(ir.SetLocal(final_state, ".k", tail)) post_handler.append(ir.SetLocal(final_state, ".k", tail))
handler.append(ir.Branch(tail)) post_handler.append(ir.Branch(tail))
if not post_finalizer.is_terminated(): if not post_finalizer.is_terminated():
dest = post_finalizer.append(ir.GetLocal(final_state, ".k")) dest = post_finalizer.append(ir.GetLocal(final_state, ".k"))
@ -594,9 +594,9 @@ class ARTIQIRGenerator(algorithm.Visitor):
if not body.is_terminated(): if not body.is_terminated():
body.append(ir.Branch(tail)) body.append(ir.Branch(tail))
for handler in handlers: for handler, post_handler in handlers:
if not handler.is_terminated(): if not post_handler.is_terminated():
handler.append(ir.Branch(tail)) post_handler.append(ir.Branch(tail))
# TODO: With # TODO: With

View File

@ -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])

View File

@ -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])

View File

@ -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")

View File

@ -229,7 +229,7 @@ void __artiq_raise(struct artiq_exception *artiq_exn) {
_Unwind_Reason_Code __artiq_personality( _Unwind_Reason_Code __artiq_personality(
int version, _Unwind_Action actions, uint64_t exceptionClass, int version, _Unwind_Action actions, uint64_t exceptionClass,
struct _Unwind_Exception *exceptionObject, struct _Unwind_Context *context) { 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_SEARCH_PHASE ? " search" : ""),
(actions & _UA_CLEANUP_PHASE ? " cleanup" : ""), (actions & _UA_CLEANUP_PHASE ? " cleanup" : ""),
(actions & _UA_HANDLER_FRAME ? " handler" : ""), (actions & _UA_HANDLER_FRAME ? " handler" : ""),
@ -240,7 +240,7 @@ _Unwind_Reason_Code __artiq_personality(
struct artiq_raised_exception *inflight = struct artiq_raised_exception *inflight =
(struct artiq_raised_exception*)exceptionObject; (struct artiq_raised_exception*)exceptionObject;
EH_LOG("exception name=%s", EH_LOG("=> exception name=%s",
inflight->artiq.name); inflight->artiq.name);
// Get a pointer to LSDA. If there's no LSDA, this function doesn't // 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 funcStart = _Unwind_GetRegionStart(context);
uintptr_t pcOffset = pc - funcStart; 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. // Parse LSDA header.
uint8_t lpStartEncoding = *lsda++; uint8_t lpStartEncoding = *lsda++;
@ -304,7 +304,7 @@ _Unwind_Reason_Code __artiq_personality(
} }
if((start <= pcOffset) && (pcOffset < (start + length))) { if((start <= pcOffset) && (pcOffset < (start + length))) {
EH_LOG0("call site matches pc"); EH_LOG0("=> call site matches pc");
int exceptionMatched = 0; int exceptionMatched = 0;
if(actionValue) { if(actionValue) {
@ -329,7 +329,7 @@ _Unwind_Reason_Code __artiq_personality(
encodingSize, typeInfoPtrPtr, (void*)typeInfoPtr); encodingSize, typeInfoPtrPtr, (void*)typeInfoPtr);
EH_LOG("typeInfo=%s", (char*)typeInfoPtr); EH_LOG("typeInfo=%s", (char*)typeInfoPtr);
if(inflight->artiq.typeinfo == typeInfoPtr) { if(typeInfoPtr == 0 || inflight->artiq.typeinfo == typeInfoPtr) {
EH_LOG0("matching action found"); EH_LOG0("matching action found");
exceptionMatched = 1; exceptionMatched = 1;
break; break;
@ -343,7 +343,7 @@ _Unwind_Reason_Code __artiq_personality(
} }
if(!(actions & _UA_SEARCH_PHASE)) { if(!(actions & _UA_SEARCH_PHASE)) {
EH_LOG0("jumping to landing pad"); EH_LOG0("=> jumping to landing pad");
_Unwind_SetGR(context, __builtin_eh_return_data_regno(0), _Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
(uintptr_t)exceptionObject); (uintptr_t)exceptionObject);
@ -353,11 +353,11 @@ _Unwind_Reason_Code __artiq_personality(
return _URC_INSTALL_CONTEXT; return _URC_INSTALL_CONTEXT;
} else if(exceptionMatched) { } else if(exceptionMatched) {
EH_LOG0("handler found"); EH_LOG0("=> handler found");
return _URC_HANDLER_FOUND; return _URC_HANDLER_FOUND;
} else { } else {
EH_LOG0("handler not found"); EH_LOG0("=> handler not found");
return _URC_CONTINUE_UNWIND; return _URC_CONTINUE_UNWIND;
} }