Handle closure effects appropriately in LocalAccessValidator.

This commit is contained in:
whitequark 2015-07-23 03:15:36 +03:00
parent acb8810e62
commit 9db199cad9
5 changed files with 16 additions and 15 deletions

View File

@ -32,8 +32,6 @@ class Module:
monomorphism_validator.visit(self.typedtree) monomorphism_validator.visit(self.typedtree)
escape_validator.visit(self.typedtree) escape_validator.visit(self.typedtree)
self.artiq_ir = artiq_ir_generator.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) dead_code_eliminator.process(self.artiq_ir)
local_access_validator.process(self.artiq_ir) local_access_validator.process(self.artiq_ir)
self.llvm_ir = llvm_ir_generator.process(self.artiq_ir) self.llvm_ir = llvm_ir_generator.process(self.artiq_ir)

View File

@ -42,7 +42,7 @@ class Printer(algorithm.Visitor):
":{}".format(self.type_printer.name(node.type))) ":{}".format(self.type_printer.name(node.type)))
def main(): def main():
if sys.argv[1] == "+mono": if len(sys.argv) > 1 and sys.argv[1] == "+mono":
del sys.argv[1] del sys.argv[1]
monomorphize = True monomorphize = True
else: else:

View File

@ -17,8 +17,9 @@ class LLVMIRGenerator:
self.fixups = [] self.fixups = []
def llty_of_type(self, typ, bare=False, for_return=False): def llty_of_type(self, typ, bare=False, for_return=False):
typ = typ.find()
if types.is_tuple(typ): 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): elif types.is_function(typ):
envarg = ll.IntType(8).as_pointer() envarg = ll.IntType(8).as_pointer()
llty = ll.FunctionType(args=[envarg] + llty = ll.FunctionType(args=[envarg] +

View File

@ -97,16 +97,18 @@ class LocalAccessValidator:
self._uninitialized_access(insn, var_name, self._uninitialized_access(insn, var_name,
pred_at_fault(env, var_name)) pred_at_fault(env, var_name))
if isinstance(insn, ir.Closure): # Creating a closure has no side effects. However, using a closure does.
env = insn.environment() for operand in insn.operands:
# Make sure this environment has any interesting variables. if isinstance(operand, ir.Closure):
if env in block_state: env = operand.environment()
for var_name in block_state[env]: # Make sure this environment has any interesting variables.
if not block_state[env][var_name]: if env in block_state:
# A closure would capture this variable while it is not always for var_name in block_state[env]:
# initialized. Note that this check is transitive. if not block_state[env][var_name]:
self._uninitialized_access(insn, var_name, # A closure would capture this variable while it is not always
pred_at_fault(env, var_name)) # initialized. Note that this check is transitive.
self._uninitialized_access(operand, var_name,
pred_at_fault(env, var_name))
# Save the state. # Save the state.
state[block] = block_state state[block] = block_state

View File

@ -20,7 +20,7 @@ else:
-t -t
# CHECK-L: ${LINE:+1}: error: variable 't' can be captured in a closure uninitialized # 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 # CHECK-L: ${LINE:+1}: error: variable 't' can be captured in a closure uninitialized
def f(): def f():