transforms.artiq_ir_generator: split out finally→reraise control flow.

This makes it accessible to introspect by local access validator,
making some previously rejected code valid.

Fixes #331.
This commit is contained in:
whitequark 2016-06-22 00:56:39 +00:00
parent f2ae24da39
commit 77d47c2fdd
2 changed files with 31 additions and 5 deletions

View File

@ -690,6 +690,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
handlers.append((handler, post_handler)) handlers.append((handler, post_handler))
if any(node.finalbody): if any(node.finalbody):
# Finalize and continue after try statement.
self.final_branch = old_final_branch self.final_branch = old_final_branch
finalizer = self.add_block("finally") finalizer = self.add_block("finally")
@ -698,13 +699,17 @@ class ARTIQIRGenerator(algorithm.Visitor):
self.visit(node.finalbody) self.visit(node.finalbody)
post_finalizer = self.current_block post_finalizer = self.current_block
reraise = self.add_block('try.reraise') # Finalize and reraise. Separate from previous case to expose flow
reraise.append(ir.Reraise(self.unwind_target)) # 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") self.current_block = tail = self.add_block("try.tail")
if any(node.finalbody): if any(node.finalbody):
final_targets.append(tail) final_targets.append(tail)
final_targets.append(reraise)
for block in final_paths: for block in final_paths:
block.append(ir.Branch(finalizer)) block.append(ir.Branch(finalizer))
@ -713,8 +718,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
body.append(ir.SetLocal(final_state, "$cont", tail)) body.append(ir.SetLocal(final_state, "$cont", tail))
body.append(ir.Branch(finalizer)) body.append(ir.Branch(finalizer))
cleanup.append(ir.SetLocal(final_state, "$cont", reraise)) cleanup.append(ir.Branch(finalizer_reraise))
cleanup.append(ir.Branch(finalizer))
for handler, post_handler in handlers: for handler, post_handler in handlers:
if not post_handler.is_terminated(): if not post_handler.is_terminated():

View File

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