Skip to content

Commit

Permalink
transforms.artiq_ir_generator: split out finally→reraise control flow.
Browse files Browse the repository at this point in the history
This makes it accessible to introspect by local access validator,
making some previously rejected code valid.

Fixes #331.
whitequark committed Jun 22, 2016
1 parent f2ae24d commit 77d47c2
Showing 2 changed files with 31 additions and 5 deletions.
14 changes: 9 additions & 5 deletions artiq/compiler/transforms/artiq_ir_generator.py
Original file line number Diff line number Diff line change
@@ -690,6 +690,7 @@ def final_branch(target, block):
handlers.append((handler, post_handler))

if any(node.finalbody):
# Finalize and continue after try statement.
self.final_branch = old_final_branch

finalizer = self.add_block("finally")
@@ -698,13 +699,17 @@ def final_branch(target, block):
self.visit(node.finalbody)
post_finalizer = self.current_block

reraise = self.add_block('try.reraise')
reraise.append(ir.Reraise(self.unwind_target))
# Finalize and reraise. Separate from previous case to expose flow
# to LocalAccessValidator.
finalizer_reraise = self.add_block("finally.reraise")
self.current_block = finalizer_reraise

self.visit(node.finalbody)
self.terminate(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)

for block in final_paths:
block.append(ir.Branch(finalizer))
@@ -713,8 +718,7 @@ def final_branch(target, block):
body.append(ir.SetLocal(final_state, "$cont", tail))
body.append(ir.Branch(finalizer))

cleanup.append(ir.SetLocal(final_state, "$cont", reraise))
cleanup.append(ir.Branch(finalizer))
cleanup.append(ir.Branch(finalizer_reraise))

for handler, post_handler in handlers:
if not post_handler.is_terminated():
22 changes: 22 additions & 0 deletions artiq/test/lit/exceptions/finally_reraise.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# RUN: %python -m artiq.compiler.testbench.jit %s >%t
# RUN: OutputCheck %s --file-to-check=%t
# REQUIRES: exceptions

x = 1

def doit():
try:
if x > 0:
raise ZeroDivisionError
r = 0
finally:
print('final')
return r

try:
doit()
except ZeroDivisionError:
print('caught')

# CHECK-L: final
# CHECK-L: caught

0 comments on commit 77d47c2

Please sign in to comment.