forked from M-Labs/artiq
Add an explicit ARTIQ IR instruction to create a closure.
This commit is contained in:
parent
5ad02d5282
commit
8e1cc8d985
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user