forked from M-Labs/artiq
Fix ARTIQ IR generation for variables declared global.
This commit is contained in:
parent
21eafefd28
commit
5ad02d5282
|
@ -426,6 +426,12 @@ class TEnvironment(types.TMono):
|
||||||
else:
|
else:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
def outermost(self):
|
||||||
|
if ".outer" in self.params:
|
||||||
|
return self.params[".outer"].outermost()
|
||||||
|
else:
|
||||||
|
return self
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Add a new binding, ensuring hygiene.
|
Add a new binding, ensuring hygiene.
|
||||||
|
|
||||||
|
@ -487,7 +493,7 @@ class GetLocal(Instruction):
|
||||||
:param var_name: (string) local variable name
|
:param var_name: (string) local variable name
|
||||||
"""
|
"""
|
||||||
def __init__(self, env, var_name, name=""):
|
def __init__(self, env, var_name, name=""):
|
||||||
assert isinstance(env, Alloc)
|
assert isinstance(env, Value)
|
||||||
assert isinstance(env.type, TEnvironment)
|
assert isinstance(env.type, TEnvironment)
|
||||||
assert isinstance(var_name, str)
|
assert isinstance(var_name, str)
|
||||||
super().__init__([env], env.type.type_of(var_name), name)
|
super().__init__([env], env.type.type_of(var_name), name)
|
||||||
|
@ -513,7 +519,7 @@ class SetLocal(Instruction):
|
||||||
:param value: (:class:`Value`) value to assign
|
:param value: (:class:`Value`) value to assign
|
||||||
"""
|
"""
|
||||||
def __init__(self, env, var_name, value, name=""):
|
def __init__(self, env, var_name, value, name=""):
|
||||||
assert isinstance(env, Alloc)
|
assert isinstance(env, Value)
|
||||||
assert isinstance(env.type, TEnvironment)
|
assert isinstance(env.type, TEnvironment)
|
||||||
assert isinstance(var_name, str)
|
assert isinstance(var_name, str)
|
||||||
assert env.type.type_of(var_name) == value.type
|
assert env.type.type_of(var_name) == value.type
|
||||||
|
|
|
@ -151,7 +151,11 @@ class LocalExtractor(algorithm.Visitor):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.global_.add(name)
|
self.global_.add(name)
|
||||||
if name in self.env_stack[1]:
|
if len(self.env_stack) == 1:
|
||||||
|
self._assignable(name) # already in global scope
|
||||||
|
else:
|
||||||
|
if name not in self.env_stack[1]:
|
||||||
|
self.env_stack[1][name] = types.TVar()
|
||||||
self.typing_env[name] = self.env_stack[1][name]
|
self.typing_env[name] = self.env_stack[1][name]
|
||||||
|
|
||||||
def visit_Nonlocal(self, node):
|
def visit_Nonlocal(self, node):
|
||||||
|
|
|
@ -35,6 +35,8 @@ class IRGenerator(algorithm.Visitor):
|
||||||
source range of the node being currently visited
|
source range of the node being currently visited
|
||||||
:ivar current_function: (:class:`ir.Function` or None)
|
:ivar current_function: (:class:`ir.Function` or None)
|
||||||
module, def or lambda currently being translated
|
module, def or lambda currently being translated
|
||||||
|
:ivar current_globals: (set of string)
|
||||||
|
set of variables that will be resolved in global scope
|
||||||
:ivar current_block: (:class:`ir.BasicBlock`)
|
:ivar current_block: (:class:`ir.BasicBlock`)
|
||||||
basic block to which any new instruction will be appended
|
basic block to which any new instruction will be appended
|
||||||
:ivar current_env: (:class:`ir.Environment`)
|
:ivar current_env: (:class:`ir.Environment`)
|
||||||
|
@ -65,6 +67,7 @@ class IRGenerator(algorithm.Visitor):
|
||||||
self.name = [module_name]
|
self.name = [module_name]
|
||||||
self.current_loc = None
|
self.current_loc = None
|
||||||
self.current_function = None
|
self.current_function = None
|
||||||
|
self.current_globals = set()
|
||||||
self.current_block = None
|
self.current_block = None
|
||||||
self.current_env = None
|
self.current_env = None
|
||||||
self.current_private_env = None
|
self.current_private_env = None
|
||||||
|
@ -179,7 +182,13 @@ class IRGenerator(algorithm.Visitor):
|
||||||
entry = self.add_block()
|
entry = self.add_block()
|
||||||
old_block, self.current_block = self.current_block, entry
|
old_block, self.current_block = self.current_block, entry
|
||||||
|
|
||||||
env_type = ir.TEnvironment(node.typing_env, self.current_env.type)
|
old_globals, self.current_globals = self.current_globals, node.globals_in_scope
|
||||||
|
|
||||||
|
env_without_globals = \
|
||||||
|
{var: node.typing_env[var]
|
||||||
|
for var in node.typing_env
|
||||||
|
if var not in node.globals_in_scope}
|
||||||
|
env_type = ir.TEnvironment(env_without_globals, self.current_env.type)
|
||||||
env = self.append(ir.Alloc([], env_type, name="env"))
|
env = self.append(ir.Alloc([], env_type, name="env"))
|
||||||
old_env, self.current_env = self.current_env, env
|
old_env, self.current_env = self.current_env, env
|
||||||
|
|
||||||
|
@ -201,22 +210,25 @@ class IRGenerator(algorithm.Visitor):
|
||||||
if is_lambda:
|
if is_lambda:
|
||||||
self.terminate(ir.Return(result))
|
self.terminate(ir.Return(result))
|
||||||
elif builtins.is_none(typ.ret):
|
elif builtins.is_none(typ.ret):
|
||||||
self.terminate(ir.Return(ir.Constant(None, builtins.TNone())))
|
if not self.current_block.is_terminated():
|
||||||
|
self.current_block.append(ir.Return(ir.Constant(None, builtins.TNone())))
|
||||||
else:
|
else:
|
||||||
self.terminate(ir.Unreachable())
|
if not self.current_block.is_terminated():
|
||||||
|
self.current_block.append(ir.Unreachable())
|
||||||
|
|
||||||
return func
|
return func
|
||||||
finally:
|
finally:
|
||||||
self.name = old_name
|
self.name = old_name
|
||||||
self.current_function = old_func
|
self.current_function = old_func
|
||||||
self.current_block = old_block
|
self.current_block = old_block
|
||||||
|
self.current_globals = old_globals
|
||||||
self.current_env = old_env
|
self.current_env = old_env
|
||||||
if not is_lambda:
|
if not is_lambda:
|
||||||
self.current_private_env = old_priv_env
|
self.current_private_env = old_priv_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.append(ir.SetLocal(self.current_env, node.name, func))
|
self._set_local(node.name, func)
|
||||||
|
|
||||||
def visit_Return(self, node):
|
def visit_Return(self, node):
|
||||||
if node.value is None:
|
if node.value is None:
|
||||||
|
@ -465,7 +477,7 @@ class IRGenerator(algorithm.Visitor):
|
||||||
|
|
||||||
if handler_node.name is not None:
|
if handler_node.name is not None:
|
||||||
exn = self.append(ir.Builtin("exncast", [landingpad], handler_node.name_type))
|
exn = self.append(ir.Builtin("exncast", [landingpad], handler_node.name_type))
|
||||||
self.append(ir.SetLocal(self.current_env, handler_node.name, exn))
|
self._set_local(handler_node.name, exn)
|
||||||
self.visit(handler_node.body)
|
self.visit(handler_node.body)
|
||||||
|
|
||||||
if any(node.finalbody):
|
if any(node.finalbody):
|
||||||
|
@ -545,12 +557,24 @@ class IRGenerator(algorithm.Visitor):
|
||||||
def visit_NameConstantT(self, node):
|
def visit_NameConstantT(self, node):
|
||||||
return ir.Constant(node.value, node.type)
|
return ir.Constant(node.value, node.type)
|
||||||
|
|
||||||
|
def _env_for(self, name):
|
||||||
|
if name in self.current_globals:
|
||||||
|
return self.append(ir.Builtin("globalenv", [self.current_env],
|
||||||
|
self.current_env.type.outermost()))
|
||||||
|
else:
|
||||||
|
return self.current_env
|
||||||
|
|
||||||
|
def _get_local(self, name):
|
||||||
|
return self.append(ir.GetLocal(self._env_for(name), name, name="local." + name))
|
||||||
|
|
||||||
|
def _set_local(self, name, value):
|
||||||
|
self.append(ir.SetLocal(self._env_for(name), name, value))
|
||||||
|
|
||||||
def visit_NameT(self, node):
|
def visit_NameT(self, node):
|
||||||
if self.current_assign is None:
|
if self.current_assign is None:
|
||||||
return self.append(ir.GetLocal(self.current_env, node.id,
|
return self._get_local(node.id)
|
||||||
name="{}.{}".format(self.current_env.name, node.id)))
|
|
||||||
else:
|
else:
|
||||||
self.append(ir.SetLocal(self.current_env, node.id, self.current_assign))
|
return self._set_local(node.id, self.current_assign)
|
||||||
|
|
||||||
def visit_AttributeT(self, node):
|
def visit_AttributeT(self, node):
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Reference in New Issue