Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 7c77dd317aa7
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: a83e7e224819
Choose a head ref
  • 2 commits
  • 9 files changed
  • 1 contributor

Commits on Jul 27, 2015

  1. Copy the full SHA
    90be44c View commit details
  2. Add tests for exceptional control flow.

    whitequark committed Jul 27, 2015
    Copy the full SHA
    a83e7e2 View commit details
5 changes: 3 additions & 2 deletions artiq/compiler/ir.py
Original file line number Diff line number Diff line change
@@ -292,7 +292,7 @@ def remove_from_parent(self):

def erase(self):
# self.instructions is updated while iterating
for insn in list(self.instructions):
for insn in reversed(self.instructions):
insn.erase()
self.remove_from_parent()
# Check this after erasing instructions in case the block
@@ -997,7 +997,8 @@ def value(self):
return self.operands[0]

def exception_target(self):
return self.operands[1]
if len(self.operands) > 1:
return self.operands[1]

class Invoke(Terminator):
"""
22 changes: 11 additions & 11 deletions artiq/compiler/transforms/artiq_ir_generator.py
Original file line number Diff line number Diff line change
@@ -546,13 +546,13 @@ def visit_Try(self, node):
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 @@ def visit_Try(self, node):
# 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 @@ def visit_Try(self, node):
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

4 changes: 4 additions & 0 deletions artiq/compiler/transforms/dead_code_eliminator.py
Original file line number Diff line number Diff line change
@@ -25,6 +25,10 @@ def remove_block(self, block):
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

13 changes: 13 additions & 0 deletions lit-test/test/exceptions/catch_all.py
Original file line number Diff line number Diff line change
@@ -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])
15 changes: 15 additions & 0 deletions lit-test/test/exceptions/catch_multi.py
Original file line number Diff line number Diff line change
@@ -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])
15 changes: 15 additions & 0 deletions lit-test/test/exceptions/catch_outer.py
Original file line number Diff line number Diff line change
@@ -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")
File renamed without changes.
64 changes: 64 additions & 0 deletions lit-test/test/integration/finally.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# RUN: %python -m artiq.compiler.testbench.jit %s
# RUN: %python %s
# REQUIRES: exceptions

def f():
while True:
try:
print("f-try")
break
finally:
print("f-finally")
print("f-out")

# CHECK-L: f-try
# CHECK-L: f-finally
# CHECK-L: f-out
f()

def g():
x = True
while x:
try:
print("g-try")
x = False
continue
finally:
print("g-finally")
print("g-out")

# CHECK-L: g-try
# CHECK-L: g-finally
# CHECK-L: g-out
g()

def h():
try:
print("h-try")
return 10
finally:
print("h-finally")
print("h-out")
return 20

# CHECK-L: h-try
# CHECK-L: h-finally
# CHECK-NOT-L: h-out
# CHECK-L: h 10
print("h", h())

def i():
try:
print("i-try")
return 10
finally:
print("i-finally")
return 30
print("i-out")
return 20

# CHECK-L: i-try
# CHECK-L: i-finally
# CHECK-NOT-L: i-out
# CHECK-L: i 30
print("i", i())
22 changes: 11 additions & 11 deletions soc/runtime/artiq_personality.c
Original file line number Diff line number Diff line change
@@ -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;
}