From f8c1ccfac7fc22ba7d316a5b25ee58cd4d26a031 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Wed, 30 Nov 2011 21:14:48 +0000 Subject: Support for array reference (both assignment and rvalue), update README --- README | 26 ++++++++++++++++---------- pp2cc.py | 30 ++++++++++++++++++++++++------ 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/README b/README index 096545f..9521338 100644 --- a/README +++ b/README @@ -53,8 +53,8 @@ A7.3 Postfix Expressions - unsupported function calls - supported, result is stored in register R0 (for int functions) Other types (void) are not checked when using their value. If an undefined function is used, it'll still try to branch to the label - Parameters are not supported. -A7.4 Unary Operators - supported: ++ -- + - ~ ! Unsupported: sizeof & * + Parameters are not supported. Pointers to functions are unsupported +A7.4 Unary Operators - supported: ++ -- + - ~ ! & * Unsupported: sizeof A7.5 Casts - unsupported and ignored A7.6-A7.7, A7.9-7.13 - supported: * / % + - < > <= >= == != & ^ | Left to right A7.8 Shift - << >> is supported, if the second operand is negative, no shift @@ -64,7 +64,7 @@ Example in bits assuming 4-bit words: 1000 (-8) >> 2 becomes 0010 (2), 0110 (6) A7.14-A7.15 Logical AND && and OR || are supported. Result is indeed 0 or 1 A7.16 Conditional operator ? : - supported A7.17 Assignment - supported: = Unsupported: *= /= %= += -= <<= >>= &= ^= |= - Supported for variable names only, pointers are not yet supported + Supported for variable names only, pointers and array references A7.18 Comma - supported A7.19 Constant expressions - not checked @@ -76,24 +76,30 @@ A8.2 Type specifiers - unsupported, everything is assumed to be int. void in A8.3 Structure and union declarations - unsupported A8.4 Enumerations - unsupported A8.5 Declarators - pointers and qualifiers are ignored, only a direct name is - supported -A8.6 Meaning of declarators - pointer is supported, array is not, function is - supported without parameters and assumed to be an int function -A8.7 Initialization - Supported for an expression resulting in an int + supported. An array can be declared without initialization as in: + int a[2]; +A8.6 Meaning of declarators - pointer and arrays are supported, function is + supported without parameters and assumed to be an int function. +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. + A8.8 Type names - not verified A8.9 Typedef - won't be supported as we have int only A8.10 Type equivalence - not supported as everything is an int A9 Statements -A9.1 Labeled statements - not supported +A9.1 Labeled statements - supported A9.2 Expression statement - supported by parser A9.3 Compound statement - supported A9.4 Selection statements - if and if/else are supported. switch is also supported including fallthrough and case/ default labels support A9.5 Iteration statements - while, do/while and for are supported. A missing second expression in the for is equivalent to a non-zero constant -A9.6 Jump statements - goto is unsupported. continue and break are supported. - return is supported with and without value. The function result is +A9.6 Jump statements - goto, continue and break are supported. return is + supported with and without value. The function result is undefined for the second case A10 External Declarations diff --git a/pp2cc.py b/pp2cc.py index 11ff592..6e6e614 100755 --- a/pp2cc.py +++ b/pp2cc.py @@ -1131,8 +1131,12 @@ class Parse(object): linked_lval = LinkedNode(node.lvalue, linked_node) # this lvalue may be an expression if there is an indirection - if isinstance(node.lvalue, c_ast.UnaryOp) and node.lvalue.op == "*": - lvalue = self.parseExpression(linked_lval.node.expr, linked_lval) + if (linked_lval.type == "UnaryOp" and node.lvalue.op == "*" or + linked_lval.type == "ArrayRef"): + if linked_lval.type == "UnaryOp": + lvalue = self.parseExpression(linked_lval.node.expr, linked_lval) + else: + lvalue = self.parseExpression(linked_lval.node, linked_node) lvalue_result_reg = self.registers.find_register(lvalue) for line in lvalue: # if the right value register is modified, we need to pull @@ -1186,14 +1190,24 @@ class Parse(object): linked_type = LinkedNode(linked_node.node.type, linked_node) var_name = linked_node.variables.declName(linked_node.node.name, 1) if linked_type.type == "ArrayDecl": - size = self.determineConstValue(LinkedNode(linked_type.node.dim, + if linked_type.node.dim is not None: + size = self.determineConstValue(LinkedNode(linked_type.node.dim, linked_node)) + else: + size = None node_init = linked_node.node.init + # determine the array dimension based on the initializer if node_init and isinstance(node_init, c_ast.ExprList): real_size = len(node_init.exprs) - if real_size > size: + if size is None: + size = real_size + elif real_size > size: self.logger.warning("excess elements in array initializer", linked_node=linked_node) + # it's an error if the array dimension is unavailable, e.g.: + # int a[]; + if size is None: + raise RuntimeError("Array size missing in '{}'".format(var_name)) var_array = linked_node.variables.declName(var_name, size, prefix="arr") elif linked_type.type == "PtrDecl": @@ -1332,8 +1346,12 @@ class Parse(object): else: lines += index_expr - lines.append(self.asm.binary_op("LOAD", name_reg, - "[" + name_reg + "+" + index_reg + "]")) + if (linked_node.parent and linked_node.parent.type == "Assignment" and + linked_node.parent.node.lvalue is linked_node.node): + lines.append(self.asm.binary_op("ADD", name_reg, index_reg)) + else: + lines.append(self.asm.binary_op("LOAD", name_reg, + "[" + name_reg + "+" + index_reg + "]")) return lines def parseLabel(self, linked_node): lines = [] -- cgit v1.2.1