From 30fc12c61857d9f242953e49b97118c976170d13 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Fri, 2 Dec 2011 21:57:45 +0000 Subject: Fix constant value eval and declaration and initialization of array elements --- pp2cc.py | 145 ++++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 98 insertions(+), 47 deletions(-) (limited to 'pp2cc.py') diff --git a/pp2cc.py b/pp2cc.py index d3aac94..9de64dd 100755 --- a/pp2cc.py +++ b/pp2cc.py @@ -950,13 +950,17 @@ class Parse(object): return lines def parseDecl(self, linked_node): lines = [] - size = 1 + in_function = linked_node.getFunctionNode() is not None + size = 0 linked_type = LinkedNode(linked_node.node.type, linked_node) name = linked_node.node.name if linked_type.type == "ArrayDecl": if linked_type.node.dim is not None: - size = self.determineConstValue(LinkedNode(linked_type.node.dim, - linked_node)) + linked_dim_node = LinkedNode(linked_type.node.dim, linked_node) + try: + size = self.determineConstValue(linked_dim_node) + except RuntimeError as errmsg: + self.logger.error(errmsg, linked_node=linked_dim_node) else: size = None node_init = linked_node.node.init @@ -987,6 +991,10 @@ class Parse(object): self.logger.error("Unknown declaration type '{}'".format(linked_type.type), linked_node=linked_node) + # increment size here because the array dimension calculation does not + # take the pointer into account + size += 1 + try: linked_node.variables.declName(name, size) # address of variable split up in register and displacement @@ -994,52 +1002,92 @@ class Parse(object): except RuntimeError as errmsg: self.logger.error(errmsg, linked_node=linked_node) + # initialize pointer address of array + if linked_type.type == "ArrayDecl" and not in_function: + reg_array = self.registers.next_free() + # store the address of the first array element in the pointer + self.globalInit.append(self.asm.binary_op("LOAD", reg_array, var_reg)) + # in this particular case, it happens that the array values are + # next to the pointer to the array + self.globalInit.append(self.asm.binary_op("ADD", reg_array, 1)) + # store address of the first array element in the array pointer + self.globalInit.append(self.asm.binary_op("STOR", reg_array, "[" + + var_reg + "+" + var_disp + "]")) # if the declaration also has a definition if linked_node.node.init: init_vals = [] linked_init = LinkedNode(linked_node.node.init, linked_node) if (linked_type.type == "ArrayDecl" and linked_init.type == "ExprList"): - reg_value = "R0" - # contains the address of the first array element - reg_array = "R1" - # store the address of the first array element in the pointer - init_vals.append(self.asm.binary_op("LOAD", reg_array, var_reg)) - # in this particular case, it happens that the array values are - # next to the pointer to the array - init_vals.append(self.asm.binary_op("ADD", reg_array, 1)) - # store address of the first array element in the array pointer - init_vals.append(self.asm.binary_op("STOR", reg_array, - "[" + var_reg + "+" + - var_disp + "]")) + # next available register for storing the value + reg_value = self.registers.next_free(reg_array) array_index = 0 for array_elm in linked_init.node.exprs: linked_arrelm = LinkedNode(array_elm, linked_init) - # only constant expressions are allowed in array init - init_val = self.determineConstValue(linked_arrelm) - - # store the array element in the array instead of the - # pointer itself - init_vals.append(self.asm.binary_op("LOAD", reg_value, - init_val)) - # save the value to the array's base address + index - init_vals.append(self.asm.binary_op("STOR", reg_value, - "[" + reg_array + "+" + - str(array_index) + "]")) + try: + # only constant expressions are allowed in array init + init_val = str(self.determineConstValue(linked_arrelm)) + if in_function: + init_vals.append(self.asm.binary_op("LOAD", + reg_value, init_val)) + else: + # +1 because the first element is reserved for pointer + self.varNames[var_disp][array_index + 1] = init_val + except RuntimeError as errmsg: + # only functions are allowed to have non-constant + # expressions + if not in_function: + self.logger.error(errmsg, linked_node=linked_arrelm) + + init_vals.append(self.asm.push(reg_array)) + init_val = self.parseExpression(array_elm, linked_init) + # if the result register has changed, update + res_reg = self.registers.find_register(init_val, fatal=True) + init_vals += init_val + + # swap registers if the result would be overwritten + if res_reg == reg_array: + reg_value, reg_array = reg_array, res_value + init_vals.append(self.asm.pull(reg_array)) + + # store the array element in the array instead of the + # pointer itself + init_vals.append(self.asm.binary_op("LOAD", reg_value, + init_val)) + if in_function: + # save the value to the array's base address + index + init_vals.append(self.asm.binary_op("STOR", reg_value, + "[" + reg_array + "+" + str(array_index) + "]")) + array_index += 1 # ignore elements which do not fit in the allocated space if array_index > size: break + if init_vals: + init_vals = pre_init + init_vals else: - init_vals = self.parseExpression(linked_node.node.init, + try: + init_val = str(self.determineConstValue(linked_init)) + if in_function: + init_vals.append(self.asm.binary_op("LOAD", result_reg, + init_val)) + else: + self.varNames[var_disp][0] = init_val + except RuntimeError as errmsg: + # only constant expressions are allowed in global init + if not in_function: + self.logger.error(errmsg, linked_node=linked_init) + + init_vals = self.parseExpression(linked_node.node.init, linked_node) - result_reg = self.registers.find_register(init_vals) - init_vals.append(self.asm.binary_op("STOR", result_reg, - "[" + var_reg + "+" + - var_disp + "]")) + result_reg = self.registers.find_register(init_vals) + if in_function: + init_vals.append(self.asm.binary_op("STOR", result_reg, + "[" + var_reg + "+" + + var_disp + "]")) # if global context (i.e. not in a function) - if linked_node.getFunctionNode() is None: + if not in_function: self.globalInit += init_vals else: lines += init_vals @@ -1187,8 +1235,8 @@ class Parse(object): self.asm.level = linked_node.level lines = [] if linked_node.isTypeStatement(): - lines.append(self.asm.format_line("; " + linked_node.type + " " + - linked_node.getLocation())) + #lines.append(self.asm.format_line("; " + linked_node.type + " " + + # linked_node.getLocation())) if hasattr(self, "parse" + linked_node.type): lines += getattr(self, "parse" + linked_node.type)(linked_node) # add for support post increment and decrement @@ -1207,8 +1255,8 @@ class Parse(object): self.asm.level = linked_node.level lines = [] - lines.append(self.asm.format_line("; " + linked_node.type + " " + - linked_node.getLocation())) + #lines.append(self.asm.format_line("; " + linked_node.type + " " + + # linked_node.getLocation())) if linked_node.type in ("ID", "Constant", "UnaryOp", "FuncCall", "Cast", "BinaryOp", "TernaryOp", "Assignment", "ExprList", "ArrayRef"): lines += getattr(self, "parse" + linked_node.type)(linked_node) @@ -1238,9 +1286,12 @@ class Parse(object): if linked_node.type == "Constant": if node.type != "int": - self.logger.error("Unsupported constant type '{}'".format(node.type), - linked_node=linked_node) + raise RuntimeError("Unsupported constant type '{}'".format(node.type)) value = self.convertStrToInteger(self.convertInteger(node.value)) + elif linked_node.type == "Cast": + self.logger.warning("Found a type cast, but these are unsupported", + linked_node=linked_node) + value = self.determineConstValue(LinkedNode(node.expr, linked_node)) elif linked_node.type == "UnaryOp": op = node.op operators = { @@ -1250,10 +1301,10 @@ class Parse(object): "~": "invert" } if op not in operators: - self.logger.error("Operator '{}' is not supported".format(op), - linked_node=linked_node) + raise RuntimeError("Operator '{}' is not supported".format(op)) else: - operand = self.determineConstValue(node.expr) + operand = self.determineConstValue(LinkedNode(node.expr, + linked_node)) if op == "-": # negating a value in PP2 is flipping the WORDSIZE-th bit value = operand ^ msb @@ -1285,11 +1336,12 @@ class Parse(object): ">>": "rshift" } if op not in operators: - self.logger.error("Operator '{}' is not supported".format(op), - linked_node=linked_node) + raise RuntimeError("Operator '{}' is not supported".format(op)) else: - operand1 = self.determineConstValue(node.left) - operand2 = self.determineConstValue(node.right) + operand1 = self.determineConstValue(LinkedNode(node.left, + linked_node)) + operand2 = self.determineConstValue(LinkedNode(node.right, + linked_node)) if op == "-": # ensure that the result of substraction is positive by # setting the (WORDSIZE+1)-nth bit on the first operand @@ -1309,8 +1361,7 @@ class Parse(object): else: value = int(getattr(operator, op)(operand1, operand2)) else: - self.logger.error("Unsupported node type '{}'".format(linked_node.type), - linked_node=linked_node) + raise RuntimeError("Unsupported node type '{}'".format(linked_node.type)) # The PP2 can only count in 18-bit, therefore AND the result. Note that # overflow may occur for large numbes. This is a non-issue for unary + # - ~ (and ! because it results in 0 or 1). For binary comparison -- cgit v1.2.1