Skip to content

Commit

Permalink
LocalAccessValidator: assume variables with "$" in name are internal.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
whitequark committed Aug 22, 2015
1 parent 0e26cfb commit a557445
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 33 deletions.
4 changes: 2 additions & 2 deletions artiq/compiler/embedding.py
Expand Up @@ -366,11 +366,11 @@ def _quote_foreign_function(self, function, loc, syscall):
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
Expand Down
10 changes: 5 additions & 5 deletions artiq/compiler/ir.py
Expand Up @@ -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)
Expand All @@ -475,14 +475,14 @@ def __init__(self, vars, outer=None):
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

Expand Down
34 changes: 17 additions & 17 deletions artiq/compiler/transforms/artiq_ir_generator.py
Expand Up @@ -141,7 +141,7 @@ def visit_ModuleT(self, node):
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

Expand Down Expand Up @@ -181,7 +181,7 @@ def visit_function(self, node, is_lambda, is_internal):
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)

Expand Down Expand Up @@ -217,11 +217,11 @@ def visit_function(self, node, is_lambda, is_internal):
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)):
Expand Down Expand Up @@ -267,7 +267,7 @@ def visit_Return(self, node):
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):
Expand Down Expand Up @@ -516,30 +516,30 @@ def visit_Try(self, node):

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")
Expand Down Expand Up @@ -607,19 +607,19 @@ def visit_Try(self, node):
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():
Expand Down Expand Up @@ -961,7 +961,7 @@ def visit_ListCompT(self, node):
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)
Expand Down Expand Up @@ -1483,7 +1483,7 @@ def instrument_assert(self, node, value):
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),
Expand Down
12 changes: 6 additions & 6 deletions artiq/compiler/transforms/llvm_ir_generator.py
Expand Up @@ -495,10 +495,10 @@ def llptr_to_var(self, llenv, env_ty, var_name, var_type=None):
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()
Expand All @@ -519,7 +519,7 @@ def process_SetLocal(self, insn):
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)
Expand Down Expand Up @@ -740,11 +740,11 @@ def process_Builtin(self, insn):
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

Expand Down
9 changes: 6 additions & 3 deletions artiq/compiler/validators/local_access.py
Expand Up @@ -7,6 +7,9 @@
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
Expand Down Expand Up @@ -85,8 +88,8 @@ def pred_at_fault(env, var_name):
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.
Expand Down Expand Up @@ -124,7 +127,7 @@ def pred_at_fault(env, var_name):
# 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,
Expand Down

0 comments on commit a557445

Please sign in to comment.