From a557445e0536cfb1788e29528fd32ef4beae71b9 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sat, 22 Aug 2015 13:56:17 -0700 Subject: [PATCH] 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. --- artiq/compiler/embedding.py | 4 +-- artiq/compiler/ir.py | 10 +++--- .../compiler/transforms/artiq_ir_generator.py | 34 +++++++++---------- .../compiler/transforms/llvm_ir_generator.py | 12 +++---- artiq/compiler/validators/local_access.py | 9 +++-- 5 files changed, 36 insertions(+), 33 deletions(-) diff --git a/artiq/compiler/embedding.py b/artiq/compiler/embedding.py index ec1b629e3..afbce7820 100644 --- a/artiq/compiler/embedding.py +++ b/artiq/compiler/embedding.py @@ -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 diff --git a/artiq/compiler/ir.py b/artiq/compiler/ir.py index 90d5ef1a1..1861d110e 100644 --- a/artiq/compiler/ir.py +++ b/artiq/compiler/ir.py @@ -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 diff --git a/artiq/compiler/transforms/artiq_ir_generator.py b/artiq/compiler/transforms/artiq_ir_generator.py index 6b38f6af2..fd1be222f 100644 --- a/artiq/compiler/transforms/artiq_ir_generator.py +++ b/artiq/compiler/transforms/artiq_ir_generator.py @@ -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), diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index 2956020c8..0c1d8d5ec 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -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 diff --git a/artiq/compiler/validators/local_access.py b/artiq/compiler/validators/local_access.py index 156a26e05..f3429140e 100644 --- a/artiq/compiler/validators/local_access.py +++ b/artiq/compiler/validators/local_access.py @@ -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,