From cbb589740133d53224fcd66c4c2decf43a7eca6e Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Sat, 3 Dec 2011 13:55:31 +0000 Subject: Support multiple declarations in the global scope --- README | 3 ++- Variables.py | 21 ++++++++++++++++++++- pp2cc.py | 16 +++++++++++++--- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/README b/README index 29b6dff..6adfb4a 100644 --- a/README +++ b/README @@ -100,7 +100,8 @@ A8.7 Initialization - Supported for an expression resulting in an int, arrays may be initialized with a list of expressions yielding a constant value, e.g. int a[2]={3,1+2};int b[]={2}; in If the number of initializers are larger than the dimension, the excess elements are - discarded. + discarded. Multi-dimensional arrays are not supported at + initialization. A8.8 Type names - not verified A8.9 Typedef - won't be supported as we have int only diff --git a/Variables.py b/Variables.py index 617113f..89c8501 100644 --- a/Variables.py +++ b/Variables.py @@ -84,7 +84,10 @@ class GlobalVariables(Variables): defined in assembly """ self.defined_names = defined_names + # key: variable name, value: name as it appears in assembly self.global_vars = {} + # a list of variable names which are declared and defined + self.global_vars_defined = [] def _uniqName(self, name): """Returns an unique global variable name for assembly""" uniq_name = name @@ -93,6 +96,12 @@ class GlobalVariables(Variables): uniq_name = name + "_" + str(i) i += 1 return uniq_name + def isDeclared(self, name): + """Returns True if the global variable is declared, False otherwise""" + return name in self.global_vars + def isDefined(self, name): + """Returns True if the global variable is defined, False otherwise""" + return name in self.global_vars_defined def getAddress(self, name): """Gets the address for a variable as a tuple containing a register and displacement @@ -100,7 +109,7 @@ class GlobalVariables(Variables): To get the address of the variable, add the register value and displacement """ - if name in self.global_vars: + if self.isDeclared(name): return ("GB", self.global_vars[name]) raise RuntimeError("Use of undefined variable '{}'".format(name)) def declName(self, name, size=1, is_param=False, is_static=False): @@ -138,3 +147,13 @@ class GlobalVariables(Variables): else: # insert size items, initialized with 0 self.defined_names[var_name] = ["0"] * size + def defName(self, name): + """Marks a variable name as defined + + Variables may be declared multiple times in the globa scope, but not + defined multiple times + """ + assert self.isDeclared(name), "Definition of undeclared '{}'".format(name) + if self.isDefined(name): + raise RuntimeError("Redefinition of '{}'".format(name)) + self.global_vars_defined.append(name) diff --git a/pp2cc.py b/pp2cc.py index 03a57a1..190f10a 100755 --- a/pp2cc.py +++ b/pp2cc.py @@ -988,7 +988,7 @@ class Parse(object): if not linked_type.node.type.names[0] in ("int", "void"): self.logger.warning("Only void and int types are supported", linked_node) elif linked_type.type == "FuncDecl": - # a function declaration does not accept an initializaer, but it's + # a function declaration does not accept an initializer, but it's # still special because it has params return self.parseStatement(linked_type.node, linked_node) else: @@ -1000,8 +1000,11 @@ class Parse(object): size += 1 try: - is_static = "static" in linked_node.node.storage - linked_node.variables.declName(name, size, is_static=is_static) + # global variables may be declared multiple times, local variables + # are not allowed for that + if in_function or not linked_node.variables.isDeclared(name): + is_static = "static" in linked_node.node.storage + linked_node.variables.declName(name, size, is_static=is_static) # address of variable split up in register and displacement var_reg, var_disp = linked_node.variables.getAddress(name) except RuntimeError as errmsg: @@ -1020,6 +1023,13 @@ class Parse(object): var_reg + "+" + var_disp + "]")) # if the declaration also has a definition if linked_node.node.init: + # global variables needs to be marked as defined + if not in_function: + try: + linked_node.variables.defName(name) + except RuntimeError as errmsg: + self.logger.error(errmsg, linked_node=linked_node) + init_vals = [] linked_init = LinkedNode(linked_node.node.init, linked_node) if (linked_type.type == "ArrayDecl" and -- cgit v1.2.1