From 9db199cad9751b70734d654142dff92847c23ebd Mon Sep 17 00:00:00 2001 From: whitequark Date: Thu, 23 Jul 2015 03:15:36 +0300 Subject: [PATCH] Handle closure effects appropriately in LocalAccessValidator. --- artiq/compiler/module.py | 2 -- artiq/compiler/testbench/inferencer.py | 2 +- .../compiler/transforms/llvm_ir_generator.py | 3 ++- artiq/compiler/validators/local_access.py | 22 ++++++++++--------- lit-test/compiler/local_access/invalid.py | 2 +- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/artiq/compiler/module.py b/artiq/compiler/module.py index 80e44acd3..38bccda92 100644 --- a/artiq/compiler/module.py +++ b/artiq/compiler/module.py @@ -32,8 +32,6 @@ class Module: monomorphism_validator.visit(self.typedtree) escape_validator.visit(self.typedtree) self.artiq_ir = artiq_ir_generator.visit(self.typedtree) - print(self.artiq_ir[0]) - print(self.artiq_ir[1]) dead_code_eliminator.process(self.artiq_ir) local_access_validator.process(self.artiq_ir) self.llvm_ir = llvm_ir_generator.process(self.artiq_ir) diff --git a/artiq/compiler/testbench/inferencer.py b/artiq/compiler/testbench/inferencer.py index 64a24b39d..e6e73ea60 100644 --- a/artiq/compiler/testbench/inferencer.py +++ b/artiq/compiler/testbench/inferencer.py @@ -42,7 +42,7 @@ class Printer(algorithm.Visitor): ":{}".format(self.type_printer.name(node.type))) def main(): - if sys.argv[1] == "+mono": + if len(sys.argv) > 1 and sys.argv[1] == "+mono": del sys.argv[1] monomorphize = True else: diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index 8749d3348..de7a75307 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -17,8 +17,9 @@ class LLVMIRGenerator: self.fixups = [] def llty_of_type(self, typ, bare=False, for_return=False): + typ = typ.find() if types.is_tuple(typ): - return ll.LiteralStructType([self.llty_of_type(eltty) for eltty in typ.find().elts]) + return ll.LiteralStructType([self.llty_of_type(eltty) for eltty in typ.elts]) elif types.is_function(typ): envarg = ll.IntType(8).as_pointer() llty = ll.FunctionType(args=[envarg] + diff --git a/artiq/compiler/validators/local_access.py b/artiq/compiler/validators/local_access.py index 57fd8486c..fb68b54d4 100644 --- a/artiq/compiler/validators/local_access.py +++ b/artiq/compiler/validators/local_access.py @@ -97,16 +97,18 @@ class LocalAccessValidator: self._uninitialized_access(insn, var_name, pred_at_fault(env, var_name)) - if isinstance(insn, ir.Closure): - env = insn.environment() - # Make sure this environment has any interesting variables. - if env in block_state: - for var_name in block_state[env]: - if not block_state[env][var_name]: - # A closure would capture this variable while it is not always - # initialized. Note that this check is transitive. - self._uninitialized_access(insn, var_name, - pred_at_fault(env, var_name)) + # Creating a closure has no side effects. However, using a closure does. + for operand in insn.operands: + if isinstance(operand, ir.Closure): + env = operand.environment() + # Make sure this environment has any interesting variables. + if env in block_state: + for var_name in block_state[env]: + if not block_state[env][var_name]: + # A closure would capture this variable while it is not always + # initialized. Note that this check is transitive. + self._uninitialized_access(operand, var_name, + pred_at_fault(env, var_name)) # Save the state. state[block] = block_state diff --git a/lit-test/compiler/local_access/invalid.py b/lit-test/compiler/local_access/invalid.py index 789285d51..c67272eef 100644 --- a/lit-test/compiler/local_access/invalid.py +++ b/lit-test/compiler/local_access/invalid.py @@ -20,7 +20,7 @@ else: -t # CHECK-L: ${LINE:+1}: error: variable 't' can be captured in a closure uninitialized -lambda: t +l = lambda: t # CHECK-L: ${LINE:+1}: error: variable 't' can be captured in a closure uninitialized def f():