From 20416d5ae946d4defbfea66c53e58761cf885b73 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Thu, 1 Dec 2011 18:28:36 +0000 Subject: WIP for func parameter support and local (automatic) variables --- Variables.py | 91 +++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 69 insertions(+), 22 deletions(-) (limited to 'Variables.py') diff --git a/Variables.py b/Variables.py index 1d37f0f..338cfdf 100644 --- a/Variables.py +++ b/Variables.py @@ -19,42 +19,89 @@ __maintainer__ = "Peter Wu" __email__ = "uwretep@gmail.com" class Variables(object): - def __init__(self, defined_names, parent_variables): + def __init__(self, parent_variables, defined_names, function=None): """A scope for holding variable names Keywords arguments: - defined_names -- A list of defined variables to which additional - variables might be appended parent_variables -- the parent Variables object. If None, it's a global variable scope + defined_names -- A list of defined variables to which additional + variables might be appended + function -- The function object used for allocating memory. If not set, + the variables object will ask the parent_variables object for it """ - self.local_vars = {} - self.defined_names = defined_names self.parent_variables = parent_variables + self.function = function + # if there is a parent_variables object, it must be a function + if self.parent_variables: + # key: name, value: address n relative to BP (n >= 1) + self.local_vars = {} + self.param_vars = [] + if not self.function: + self.function = self.parent_variables.function + else: + # key: name of var, value: label of var + self.global_vars = {} + self.defined_names = defined_names def uniqName(self, name): - """Returns an unique variable name""" + """Returns an unique global variable name for assembly""" uniq_name = name i = 0 while uniq_name in self.defined_names: uniq_name = name + "_" + str(i) i += 1 return uniq_name - def getName(self, name): - """Gets the name of a declared variable as it appears in the @DATA - section""" - if name in self.local_vars: - return self.local_vars[name] + def getAddress(self, name): + """Gets the address for a variable as a tuple containing a register and + displacement + + To get the address of the variable, add the register value and + displacement + """ + # first try the local scope + if self.function: + if name in self.local_vars: + # XXX don't hardcode R5 + return ("R5", str(self.local_vars[name])) + try: + return ("R5", str(-self.param_vars.index(name))) + except ValueError: + pass + else: + # lookup in global vars + if name in self.global_vars: + return ("GB", self.global_vars[name]) + # lookup in the parent if self.parent_variables: - return self.parent_variables.getName(name) + return self.parent_variables.getAddress(name) raise RuntimeError("Use of undefined variable '{}'".format(name)) - def declName(self, name, size=1, prefix="var"): - """Declares a variable in the nearest scope and returns the label - name""" - if name in self.local_vars: + def declName(self, name, size=1, is_param=False): + """Declares a variable in the nearest scope + + Keyword arguments: + name -- The symbolic name of the variable + size -- The size of the memory to be allocated in words (default 1) + is_param -- Whether the name is a function parameter or not + """ + already_defined = False + if self.function: + already_defined = name in self.local_vars or name in self.param_vars + else: + already_defined = name in self.global_vars + if already_defined: raise RuntimeError("Redeclaration of variable '{}'".format(name)) - # global variables are prefixed "var_", locals with "varl_" - var_name = prefix + ("l_" if self.parent_variables else "_") + name - var_name = self.uniqName(var_name) - self.local_vars[name] = var_name - self.defined_names[var_name] = size - return var_name + + if self.function: + # parameters do not need a special allocation because the callee + # pushes it into the stack + if is_param: + self.param_vars.append(name) + else: + self.local_vars[name] = self.function.allocStack(size) + elif is_param: + raise RuntimeError("Parameter '{}' declared in global context".format(name)) + else: + # global variables are prefixed "var_" + var_name = "var_" + name + self.global_vars[name] = var_name + self.defined_names[var_name] = size -- cgit v1.2.1