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):
|
def __str__(self):
|
||||||
return self.as_operand()
|
return self.as_operand()
|
||||||
|
|
||||||
class Function(Value):
|
class Function:
|
||||||
"""
|
"""
|
||||||
A function containing SSA IR.
|
A function containing SSA IR.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, typ, name, arguments):
|
def __init__(self, typ, name, arguments):
|
||||||
super().__init__(typ)
|
self.type, self.name = typ, name
|
||||||
self.name = name
|
|
||||||
self.names, self.arguments, self.basic_blocks = set(), [], []
|
self.names, self.arguments, self.basic_blocks = set(), [], []
|
||||||
self.set_arguments(arguments)
|
self.set_arguments(arguments)
|
||||||
|
|
||||||
|
@ -389,10 +388,6 @@ class Function(Value):
|
||||||
return [block for block in self.basic_blocks
|
return [block for block in self.basic_blocks
|
||||||
if block.is_terminated() and successor in block.successors()]
|
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):
|
def __str__(self):
|
||||||
printer = types.TypePrinter()
|
printer = types.TypePrinter()
|
||||||
lines = []
|
lines = []
|
||||||
|
@ -766,6 +761,30 @@ class Builtin(Instruction):
|
||||||
def opcode(self):
|
def opcode(self):
|
||||||
return "builtin({})".format(self.op)
|
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):
|
class Call(Instruction):
|
||||||
"""
|
"""
|
||||||
A function call operation.
|
A function call operation.
|
||||||
|
@ -776,7 +795,6 @@ class Call(Instruction):
|
||||||
:param args: (list of :class:`Value`) function arguments
|
:param args: (list of :class:`Value`) function arguments
|
||||||
"""
|
"""
|
||||||
def __init__(self, func, args, name=""):
|
def __init__(self, func, args, name=""):
|
||||||
print(func)
|
|
||||||
assert isinstance(func, Value)
|
assert isinstance(func, Value)
|
||||||
for arg in args: assert isinstance(arg, Value)
|
for arg in args: assert isinstance(arg, Value)
|
||||||
super().__init__([func] + args, func.type.ret, name)
|
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"))
|
env = self.append(ir.Alloc([], ir.TEnvironment(node.typing_env), name="env"))
|
||||||
old_env, self.current_env = self.current_env, 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
|
old_priv_env, self.current_private_env = self.current_private_env, priv_env
|
||||||
|
|
||||||
self.generic_visit(node)
|
self.generic_visit(node)
|
||||||
|
@ -193,7 +194,8 @@ class IRGenerator(algorithm.Visitor):
|
||||||
old_env, self.current_env = self.current_env, env
|
old_env, self.current_env = self.current_env, env
|
||||||
|
|
||||||
if not is_lambda:
|
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
|
old_priv_env, self.current_private_env = self.current_private_env, priv_env
|
||||||
|
|
||||||
self.append(ir.SetLocal(env, ".outer", env_arg))
|
self.append(ir.SetLocal(env, ".outer", env_arg))
|
||||||
|
@ -215,8 +217,6 @@ class IRGenerator(algorithm.Visitor):
|
||||||
else:
|
else:
|
||||||
if not self.current_block.is_terminated():
|
if not self.current_block.is_terminated():
|
||||||
self.current_block.append(ir.Unreachable())
|
self.current_block.append(ir.Unreachable())
|
||||||
|
|
||||||
return func
|
|
||||||
finally:
|
finally:
|
||||||
self.name = old_name
|
self.name = old_name
|
||||||
self.current_function = old_func
|
self.current_function = old_func
|
||||||
|
@ -226,6 +226,8 @@ class IRGenerator(algorithm.Visitor):
|
||||||
if not is_lambda:
|
if not is_lambda:
|
||||||
self.current_private_env = old_priv_env
|
self.current_private_env = old_priv_env
|
||||||
|
|
||||||
|
return self.append(ir.Closure(func, self.current_env))
|
||||||
|
|
||||||
def visit_FunctionDefT(self, node):
|
def visit_FunctionDefT(self, node):
|
||||||
func = self.visit_function(node, is_lambda=False)
|
func = self.visit_function(node, is_lambda=False)
|
||||||
self._set_local(node.name, func)
|
self._set_local(node.name, func)
|
||||||
|
|
Loading…
Reference in New Issue