diff --git a/artiq/compiler/ir.py b/artiq/compiler/ir.py index 86af6062c..cc8fda5cc 100644 --- a/artiq/compiler/ir.py +++ b/artiq/compiler/ir.py @@ -344,14 +344,13 @@ class Argument(NamedValue): def __str__(self): return self.as_operand() -class Function(Value): +class Function: """ A function containing SSA IR. """ def __init__(self, typ, name, arguments): - super().__init__(typ) - self.name = name + self.type, self.name = typ, name self.names, self.arguments, self.basic_blocks = set(), [], [] self.set_arguments(arguments) @@ -389,10 +388,6 @@ class Function(Value): return [block for block in self.basic_blocks if block.is_terminated() and successor in block.successors()] - def as_operand(self): - return "{} @{}".format(types.TypePrinter().name(self.type), - escape_name(self.name)) - def __str__(self): printer = types.TypePrinter() lines = [] @@ -766,6 +761,30 @@ class Builtin(Instruction): def opcode(self): return "builtin({})".format(self.op) +class Closure(Instruction): + """ + A closure creation operation. + + :ivar target_function: (:class:`Function`) function to invoke + """ + + """ + :param func: (:class:`Function`) function + :param env: (:class:`Value`) outer environment + """ + def __init__(self, func, env, name=""): + assert isinstance(func, Function) + assert isinstance(env, Value) + assert is_environment(env.type) + super().__init__([env], func.type, name) + self.target_function = func + + def opcode(self): + return "closure({})".format(self.target_function.name) + + def get_environment(self): + return self.operands[0] + class Call(Instruction): """ A function call operation. @@ -776,7 +795,6 @@ class Call(Instruction): :param args: (list of :class:`Value`) function arguments """ def __init__(self, func, args, name=""): - print(func) assert isinstance(func, Value) for arg in args: assert isinstance(arg, Value) super().__init__([func] + args, func.type.ret, name) diff --git a/artiq/compiler/transforms/ir_generator.py b/artiq/compiler/transforms/ir_generator.py index 834aed7ff..3edb90160 100644 --- a/artiq/compiler/transforms/ir_generator.py +++ b/artiq/compiler/transforms/ir_generator.py @@ -131,7 +131,8 @@ class IRGenerator(algorithm.Visitor): env = self.append(ir.Alloc([], ir.TEnvironment(node.typing_env), name="env")) old_env, self.current_env = self.current_env, env - priv_env = self.append(ir.Alloc([], ir.TEnvironment({ ".return": typ.ret }))) + priv_env = self.append(ir.Alloc([], ir.TEnvironment({ ".return": typ.ret }), + name="privenv")) old_priv_env, self.current_private_env = self.current_private_env, priv_env self.generic_visit(node) @@ -193,7 +194,8 @@ class IRGenerator(algorithm.Visitor): old_env, self.current_env = self.current_env, env if not is_lambda: - priv_env = self.append(ir.Alloc([], ir.TEnvironment({ ".return": typ.ret }))) + priv_env = self.append(ir.Alloc([], ir.TEnvironment({ ".return": typ.ret }), + name="privenv")) old_priv_env, self.current_private_env = self.current_private_env, priv_env self.append(ir.SetLocal(env, ".outer", env_arg)) @@ -215,8 +217,6 @@ class IRGenerator(algorithm.Visitor): else: if not self.current_block.is_terminated(): self.current_block.append(ir.Unreachable()) - - return func finally: self.name = old_name self.current_function = old_func @@ -226,6 +226,8 @@ class IRGenerator(algorithm.Visitor): if not is_lambda: self.current_private_env = old_priv_env + return self.append(ir.Closure(func, self.current_env)) + def visit_FunctionDefT(self, node): func = self.visit_function(node, is_lambda=False) self._set_local(node.name, func)