LocalAccessValidator: assume variables with "$" in name are internal.

Internal variables are assumed to be scoped correctly
(including not being accessed uninitialized).

This was changed from "." because artiq.compiler.embedding uses
"." in module prefix of function names.
This commit is contained in:
whitequark 2015-08-22 13:56:17 -07:00
parent 0e26cfb66e
commit a557445e05
5 changed files with 36 additions and 33 deletions

View File

@ -366,11 +366,11 @@ class Stitcher:
if syscall is None:
function_type = types.TRPCFunction(arg_types, optarg_types, ret_type,
service=self._map(function))
function_name = "__rpc_{}__".format(function_type.service)
function_name = "rpc${}".format(function_type.service)
else:
function_type = types.TCFunction(arg_types, ret_type,
name=syscall)
function_name = "__ffi_{}__".format(function_type.name)
function_name = "ffi${}".format(function_type.name)
self.globals[function_name] = function_type
self.functions[function] = function_name

View File

@ -465,7 +465,7 @@ class TEnvironment(types.TMono):
def __init__(self, vars, outer=None):
if outer is not None:
assert isinstance(outer, TEnvironment)
env = OrderedDict({".outer": outer})
env = OrderedDict({"$outer": outer})
env.update(vars)
else:
env = OrderedDict(vars)
@ -475,14 +475,14 @@ class TEnvironment(types.TMono):
def type_of(self, name):
if name in self.params:
return self.params[name].find()
elif ".outer" in self.params:
return self.params[".outer"].type_of(name)
elif "$outer" in self.params:
return self.params["$outer"].type_of(name)
else:
assert False
def outermost(self):
if ".outer" in self.params:
return self.params[".outer"].outermost()
if "$outer" in self.params:
return self.params["$outer"].outermost()
else:
return self

View File

@ -141,7 +141,7 @@ class ARTIQIRGenerator(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
@ -181,7 +181,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
for arg_name, default_node in zip(typ.optargs, node.args.defaults):
default = self.visit(default_node)
env_default_name = \
self.current_env.type.add("default." + arg_name, default.type)
self.current_env.type.add("default$" + arg_name, default.type)
self.append(ir.SetLocal(self.current_env, env_default_name, default))
defaults.append(env_default_name)
@ -217,11 +217,11 @@ class ARTIQIRGenerator(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))
self.append(ir.SetLocal(env, "$outer", env_arg))
for index, arg_name in enumerate(typ.args):
self.append(ir.SetLocal(env, arg_name, args[index]))
for index, (arg_name, env_default_name) in enumerate(zip(typ.optargs, defaults)):
@ -267,7 +267,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
if self.return_target is None:
self.append(ir.Return(return_value))
else:
self.append(ir.SetLocal(self.current_private_env, ".return", return_value))
self.append(ir.SetLocal(self.current_private_env, "$return", return_value))
self.append(ir.Branch(self.return_target))
def visit_Expr(self, node):
@ -516,30 +516,30 @@ class ARTIQIRGenerator(algorithm.Visitor):
if any(node.finalbody):
# k for continuation
final_state = self.append(ir.Alloc([], ir.TEnvironment({ ".k": ir.TBasicBlock() })))
final_state = self.append(ir.Alloc([], ir.TEnvironment({ "$k": ir.TBasicBlock() })))
final_targets = []
if self.break_target is not None:
break_proxy = self.add_block("try.break")
old_break, self.break_target = self.break_target, break_proxy
break_proxy.append(ir.SetLocal(final_state, ".k", old_break))
break_proxy.append(ir.SetLocal(final_state, "$k", old_break))
final_targets.append(old_break)
if self.continue_target is not None:
continue_proxy = self.add_block("try.continue")
old_continue, self.continue_target = self.continue_target, continue_proxy
continue_proxy.append(ir.SetLocal(final_state, ".k", old_continue))
continue_proxy.append(ir.SetLocal(final_state, "$k", old_continue))
final_targets.append(old_continue)
return_proxy = self.add_block("try.return")
old_return, self.return_target = self.return_target, return_proxy
if old_return is not None:
return_proxy.append(ir.SetLocal(final_state, ".k", old_return))
return_proxy.append(ir.SetLocal(final_state, "$k", old_return))
final_targets.append(old_return)
else:
return_action = self.add_block("try.doreturn")
value = return_action.append(ir.GetLocal(self.current_private_env, ".return"))
value = return_action.append(ir.GetLocal(self.current_private_env, "$return"))
return_action.append(ir.Return(value))
return_proxy.append(ir.SetLocal(final_state, ".k", return_action))
return_proxy.append(ir.SetLocal(final_state, "$k", return_action))
final_targets.append(return_action)
body = self.add_block("try.body")
@ -607,19 +607,19 @@ class ARTIQIRGenerator(algorithm.Visitor):
return_proxy.append(ir.Branch(finalizer))
if not body.is_terminated():
body.append(ir.SetLocal(final_state, ".k", tail))
body.append(ir.SetLocal(final_state, "$k", tail))
body.append(ir.Branch(finalizer))
cleanup.append(ir.SetLocal(final_state, ".k", reraise))
cleanup.append(ir.SetLocal(final_state, "$k", reraise))
cleanup.append(ir.Branch(finalizer))
for handler, post_handler in handlers:
if not post_handler.is_terminated():
post_handler.append(ir.SetLocal(final_state, ".k", tail))
post_handler.append(ir.SetLocal(final_state, "$k", tail))
post_handler.append(ir.Branch(finalizer))
if not post_finalizer.is_terminated():
dest = post_finalizer.append(ir.GetLocal(final_state, ".k"))
dest = post_finalizer.append(ir.GetLocal(final_state, "$k"))
post_finalizer.append(ir.IndirectBranch(dest, final_targets))
else:
if not body.is_terminated():
@ -961,7 +961,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
env = self.append(ir.Alloc([], env_type, name="env.gen"))
old_env, self.current_env = self.current_env, env
self.append(ir.SetLocal(env, ".outer", old_env))
self.append(ir.SetLocal(env, "$outer", old_env))
def body_gen(index):
elt = self.iterable_get(iterable, index)
@ -1483,7 +1483,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
for (subexpr, name) in self.current_assert_subexprs]):
return # don't display the same subexpression twice
name = self.current_assert_env.type.add(".subexpr", ir.TOption(node.type))
name = self.current_assert_env.type.add("$subexpr", ir.TOption(node.type))
value_opt = self.append(ir.Alloc([value], ir.TOption(node.type)),
loc=node.loc)
self.append(ir.SetLocal(self.current_assert_env, name, value_opt),

View File

@ -495,10 +495,10 @@ class LLVMIRGenerator:
var_index = list(env_ty.params.keys()).index(var_name)
return self.llbuilder.gep(llenv, [self.llindex(0), self.llindex(var_index)])
else:
outer_index = list(env_ty.params.keys()).index(".outer")
outer_index = list(env_ty.params.keys()).index("$outer")
llptr = self.llbuilder.gep(llenv, [self.llindex(0), self.llindex(outer_index)])
llouterenv = self.llbuilder.load(llptr)
return self.llptr_to_var(llouterenv, env_ty.params[".outer"], var_name)
return self.llptr_to_var(llouterenv, env_ty.params["$outer"], var_name)
def process_GetLocal(self, insn):
env = insn.environment()
@ -519,7 +519,7 @@ class LLVMIRGenerator:
if llptr.type.pointee != llvalue.type:
# The environment argument is an i8*, so that all closures can
# unify with each other regardless of environment type or size.
# We fixup the type on assignment into the ".outer" slot.
# We fixup the type on assignment into the "$outer" slot.
assert isinstance(insn.value(), ir.EnvironmentArgument)
llvalue = self.llbuilder.bitcast(llvalue, llptr.type.pointee)
return self.llbuilder.store(llvalue, llptr)
@ -740,11 +740,11 @@ class LLVMIRGenerator:
name=insn.name)
elif insn.op == "globalenv":
def get_outer(llenv, env_ty):
if ".outer" in env_ty.params:
outer_index = list(env_ty.params.keys()).index(".outer")
if "$outer" in env_ty.params:
outer_index = list(env_ty.params.keys()).index("$outer")
llptr = self.llbuilder.gep(llenv, [self.llindex(0), self.llindex(outer_index)])
llouterenv = self.llbuilder.load(llptr)
return self.llptr_to_var(llouterenv, env_ty.params[".outer"], var_name)
return self.llptr_to_var(llouterenv, env_ty.params["$outer"], var_name)
else:
return llenv

View File

@ -7,6 +7,9 @@ from functools import reduce
from pythonparser import diagnostic
from .. import ir, analyses
def is_special_variable(name):
return "$" in name
class LocalAccessValidator:
def __init__(self, engine):
self.engine = engine
@ -85,8 +88,8 @@ class LocalAccessValidator:
return None
set_local_in_this_frame = False
if isinstance(insn, (ir.SetLocal, ir.GetLocal)) and \
"." not in insn.var_name:
if (isinstance(insn, (ir.SetLocal, ir.GetLocal)) and
not is_special_variable(insn.var_name)):
env, var_name = insn.environment(), insn.var_name
# Make sure that the variable is defined in the scope of this function.
@ -124,7 +127,7 @@ class LocalAccessValidator:
# Make sure this environment has any interesting variables.
if env in block_state:
for var_name in block_state[env]:
if not block_state[env][var_name]:
if not block_state[env][var_name] and not is_special_variable(var_name):
# A closure would capture this variable while it is not always
# initialized. Note that this check is transitive.
self._uninitialized_access(closure, var_name,