- Fix handling of structures stored in memory
authorEric Biederman <ebiederm@xmission.com>
Tue, 24 Jun 2003 12:34:45 +0000 (12:34 +0000)
committerEric Biederman <ebiederm@xmission.com>
Tue, 24 Jun 2003 12:34:45 +0000 (12:34 +0000)
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@899 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1

util/romcc/romcc.c

index 1f5c91af821dd99a2242c85d5cbf9e1ac785c2f1..af9c5552c6fe73019b99b35b4ec7ce7b9e81df1b 100644 (file)
@@ -957,10 +957,13 @@ static void loc(FILE *fp, struct compile_state *state, struct triple *triple)
 {
        int col;
        if (triple) {
+               struct occurance *spot;
+               spot = triple->occurance;
+               while(spot->parent) {
+                       spot = spot->parent;
+               }
                fprintf(fp, "%s:%d.%d: ", 
-                       triple->occurance->filename, 
-                       triple->occurance->line, 
-                       triple->occurance->col);
+                       spot->filename, spot->line, spot->col);
                return;
        }
        if (!state->file) {
@@ -4007,10 +4010,11 @@ static size_t field_offset(struct compile_state *state,
        while((type->type & TYPE_MASK) == TYPE_PRODUCT) {
                if (type->left->field_ident == field) {
                        type = type->left;
+                       break;
                }
                size += size_of(state, type->left);
                type = type->right;
-               align = align_of(state, type->left);
+               align = align_of(state, type);
                pad = align - (size % align);
                size += pad;
        }
@@ -4379,16 +4383,13 @@ static int is_lvalue(struct compile_state *state, struct triple *def)
        if (!is_stable(state, def)) {
                return 0;
        }
-       if (def->type->type & QUAL_CONST) {
-               ret = 0;
-       }
-       else if (def->op == OP_DOT) {
+       if (def->op == OP_DOT) {
                ret = is_lvalue(state, RHS(def, 0));
        }
        return ret;
 }
 
-static void lvalue(struct compile_state *state, struct triple *def)
+static void clvalue(struct compile_state *state, struct triple *def)
 {
        if (!def) {
                internal_error(state, def, "nothing where lvalue expected?");
@@ -4397,6 +4398,13 @@ static void lvalue(struct compile_state *state, struct triple *def)
                error(state, def, "lvalue expected");
        }
 }
+static void lvalue(struct compile_state *state, struct triple *def)
+{
+       clvalue(state, def);
+       if (def->type->type & QUAL_CONST) {
+               error(state, def, "modifable lvalue expected");
+       }
+}
 
 static int is_pointer(struct triple *def)
 {
@@ -4432,7 +4440,7 @@ static struct triple *do_mk_addr_expr(struct compile_state *state,
        struct triple *expr, struct type *type, ulong_t offset)
 {
        struct triple *result;
-       lvalue(state, expr);
+       clvalue(state, expr);
 
        result = 0;
        if (expr->op == OP_ADECL) {
@@ -4469,10 +4477,6 @@ static struct triple *mk_deref_expr(
        struct type *base_type;
        pointer(state, expr);
        base_type = expr->type->left;
-       if (!TYPE_PTR(base_type->type) && !TYPE_ARITHMETIC(base_type->type)) {
-               error(state, 0, 
-                       "Only pointer and arithmetic values can be dereferenced");
-       }
        return triple(state, OP_DEREF, base_type, expr, 0);
 }
 
@@ -4593,6 +4597,9 @@ static struct triple *write_expr(
        if (!is_lvalue(state, dest)) {
                internal_error(state, 0, "writing to a non lvalue?");
        }
+       if (dest->type->type & QUAL_CONST) {
+               internal_error(state, 0, "modifable lvalue expexted");
+       }
 
        write_compatible(state, dest->type, rval->type);
 
@@ -4790,6 +4797,9 @@ static int expr_depth(struct compile_state *state, struct triple *ins)
 static struct triple *flatten(
        struct compile_state *state, struct triple *first, struct triple *ptr);
 
+static struct triple *mk_add_expr(
+       struct compile_state *state, struct triple *left, struct triple *right);
+
 static struct triple *flatten_generic(
        struct compile_state *state, struct triple *first, struct triple *ptr)
 {
@@ -5145,8 +5155,15 @@ static struct triple *flatten(
                {
                        struct triple *base;
                        base = RHS(ptr, 0);
-                       base = flatten(state, first, base);
-                       if (base->op == OP_VAL_VEC) {
+                       if (base->op == OP_DEREF) {
+                               ulong_t offset;
+                               offset = field_offset(state, base->type, ptr->u.field);
+                               ptr = mk_add_expr(state, RHS(base, 0), 
+                                       int_const(state, &ulong_type, offset));
+                               free_triple(state, base);
+                       }
+                       else if (base->op == OP_VAL_VEC) {
+                               base = flatten(state, first, base);
                                ptr = struct_field(state, base, ptr->u.field);
                        }
                        break;
@@ -5694,13 +5711,13 @@ static void flatten_structures(struct compile_state *state)
        do {
                ins->id &= ~TRIPLE_FLAG_FLATTENED;
                if ((ins->type->type & TYPE_MASK) == TYPE_STRUCT) {
-                       internal_error(state, 0, "STRUCT_TYPE remains?");
+                       internal_error(state, ins, "STRUCT_TYPE remains?");
                }
                if (ins->op == OP_DOT) {
-                       internal_error(state, 0, "OP_DOT remains?");
+                       internal_error(state, ins, "OP_DOT remains?");
                }
                if (ins->op == OP_VAL_VEC) {
-                       internal_error(state, 0, "OP_VAL_VEC remains?");
+                       internal_error(state, ins, "OP_VAL_VEC remains?");
                }
                ins = ins->next;
        } while(ins != first);
@@ -7432,25 +7449,31 @@ static struct triple *eval_const_expr(
        struct compile_state *state, struct triple *expr)
 {
        struct triple *def;
-       struct triple *head, *ptr;
-       head = label(state); /* dummy initial triple */
-       flatten(state, head, expr);
-       for(ptr = head->next; ptr != head; ptr = ptr->next) {
-               simplify(state, ptr);
-       }
-       /* Remove the constant value the tail of the list */
-       def = head->prev;
-       def->prev->next = def->next;
-       def->next->prev = def->prev;
-       def->next = def->prev = def;
-       if (!is_const(def)) {
-               internal_error(state, 0, "Not a constant expression");
-       }
-       /* Free the intermediate expressions */
-       while(head->next != head) {
-               release_triple(state, head->next);
+       if (is_const(expr)) {
+               def = expr;
+       } 
+       else {
+               /* If we don't start out as a constant simplify into one */
+               struct triple *head, *ptr;
+               head = label(state); /* dummy initial triple */
+               flatten(state, head, expr);
+               for(ptr = head->next; ptr != head; ptr = ptr->next) {
+                       simplify(state, ptr);
+               }
+               /* Remove the constant value the tail of the list */
+               def = head->prev;
+               def->prev->next = def->next;
+               def->next->prev = def->prev;
+               def->next = def->prev = def;
+               if (!is_const(def)) {
+                       error(state, 0, "Not a constant expression");
+               }
+               /* Free the intermediate expressions */
+               while(head->next != head) {
+                       release_triple(state, head->next);
+               }
+               free_triple(state, head);
        }
-       free_triple(state, head);
        return def;
 }
 
@@ -8364,7 +8387,7 @@ static struct type *struct_declarator(
 #endif
 
 static struct type *struct_or_union_specifier(
-       struct compile_state *state, unsigned int specifiers)
+       struct compile_state *state, unsigned int spec)
 {
        struct type *struct_type;
        struct hash_entry *ident;
@@ -8424,13 +8447,13 @@ static struct type *struct_or_union_specifier(
                        eat(state, TOK_SEMI);
                } while(peek(state) != TOK_RBRACE);
                eat(state, TOK_RBRACE);
-               struct_type = new_type(TYPE_STRUCT, struct_type, 0);
+               struct_type = new_type(TYPE_STRUCT | spec, struct_type, 0);
                struct_type->type_ident = ident;
                struct_type->elements = elements;
                symbol(state, ident, &ident->sym_struct, 0, struct_type);
        }
        if (ident && ident->sym_struct) {
-               struct_type = ident->sym_struct->type;
+               struct_type = clone_type(spec,  ident->sym_struct->type);
        }
        else if (ident && !ident->sym_struct) {
                error(state, 0, "struct %s undeclared", ident->name);
@@ -8762,34 +8785,67 @@ static struct type *decl_specifiers(struct compile_state *state)
        return type;
 }
 
-static unsigned designator(struct compile_state *state)
+struct field_info {
+       struct type *type;
+       size_t offset;
+};
+
+static struct field_info designator(struct compile_state *state, struct type *type)
 {
        int tok;
-       unsigned index;
-       index = -1U;
+       struct field_info info;
+       info.offset = ~0U;
+       info.type = 0;
        do {
                switch(peek(state)) {
                case TOK_LBRACKET:
                {
                        struct triple *value;
+                       if ((type->type & TYPE_MASK) != TYPE_ARRAY) {
+                               error(state, 0, "Array designator not in array initializer");
+                       }
                        eat(state, TOK_LBRACKET);
                        value = constant_expr(state);
                        eat(state, TOK_RBRACKET);
-                       index = value->u.cval;
+
+                       info.type = type->left;
+                       info.offset = value->u.cval * size_of(state, info.type);
                        break;
                }
                case TOK_DOT:
+               {
+                       struct hash_entry *field;
+                       struct type *member;
+                       if ((type->type & TYPE_MASK) != TYPE_STRUCT) {
+                               error(state, 0, "Struct designator not in struct initializer");
+                       }
                        eat(state, TOK_DOT);
                        eat(state, TOK_IDENT);
-                       error(state, 0, "Struct Designators not currently supported");
+                       field = state->token[0].ident;
+                       info.offset = 0;
+                       member = type->left;
+                       while((member->type & TYPE_MASK) == TYPE_PRODUCT) {
+                               if (member->left->field_ident == field) {
+                                       member = member->left;
+                                       break;
+                               }
+                               info.offset += size_of(state, member->left);
+                               member = member->right;
+                       }
+                       if (member->field_ident != field) {
+                               error(state, 0, "%s is not a member", 
+                                       field->name);
+                       }
+                       info.type = member;
                        break;
+               }
                default:
                        error(state, 0, "Invalid designator");
                }
                tok = peek(state);
        } while((tok == TOK_LBRACKET) || (tok == TOK_DOT));
        eat(state, TOK_EQ);
-       return index;
+       return info;
 }
 
 static struct triple *initializer(
@@ -8801,74 +8857,87 @@ static struct triple *initializer(
        }
        else {
                int comma;
-               unsigned index, max_index;
+               size_t max_offset;
+               struct field_info info;
                void *buf;
-               max_index = index = 0;
-               if ((type->type & TYPE_MASK) == TYPE_ARRAY) {
-                       max_index = type->elements;
-                       if (type->elements == ELEMENT_COUNT_UNSPECIFIED) {
-                               type->elements = 0;
-                       }
+               if (((type->type & TYPE_MASK) != TYPE_ARRAY) &&
+                       ((type->type & TYPE_MASK) != TYPE_STRUCT)) {
+                       internal_error(state, 0, "unknown initializer type");
+               }
+               info.offset = 0;
+               info.type = type->left;
+               if (type->elements == ELEMENT_COUNT_UNSPECIFIED) {
+                       max_offset = 0;
                } else {
-                       error(state, 0, "Struct initializers not currently supported");
+                       max_offset = size_of(state, type);
                }
-               buf = xcmalloc(size_of(state, type), "initializer");
+               buf = xcmalloc(max_offset, "initializer");
                eat(state, TOK_LBRACE);
                do {
                        struct triple *value;
                        struct type *value_type;
                        size_t value_size;
+                       void *dest;
                        int tok;
                        comma = 0;
                        tok = peek(state);
                        if ((tok == TOK_LBRACKET) || (tok == TOK_DOT)) {
-                               index = designator(state);
+                               info = designator(state, type);
                        }
-                       if ((max_index != ELEMENT_COUNT_UNSPECIFIED) &&
-                               (index > max_index)) {
+                       if ((type->elements != ELEMENT_COUNT_UNSPECIFIED) &&
+                               (info.offset >= max_offset)) {
                                error(state, 0, "element beyond bounds");
                        }
-                       value_type = 0;
-                       if ((type->type & TYPE_MASK) == TYPE_ARRAY) {
+                       value_type = info.type;
+                       if ((value_type->type & TYPE_MASK) == TYPE_PRODUCT) {
                                value_type = type->left;
                        }
                        value = eval_const_expr(state, initializer(state, value_type));
                        value_size = size_of(state, value_type);
                        if (((type->type & TYPE_MASK) == TYPE_ARRAY) &&
-                               (max_index == ELEMENT_COUNT_UNSPECIFIED) &&
-                               (type->elements <= index)) {
+                               (type->elements == ELEMENT_COUNT_UNSPECIFIED) &&
+                               (max_offset <= info.offset)) {
                                void *old_buf;
                                size_t old_size;
                                old_buf = buf;
-                               old_size = size_of(state, type);
-                               type->elements = index + 1;
-                               buf = xmalloc(size_of(state, type), "initializer");
+                               old_size = max_offset;
+                               max_offset = info.offset + value_size;
+                               buf = xmalloc(max_offset, "initializer");
                                memcpy(buf, old_buf, old_size);
                                xfree(old_buf);
                        }
+                       dest = ((char *)buf) + info.offset;
                        if (value->op == OP_BLOBCONST) {
-                               memcpy((char *)buf + index * value_size, value->u.blob, value_size);
+                               memcpy(dest, value->u.blob, value_size);
                        }
                        else if ((value->op == OP_INTCONST) && (value_size == 1)) {
-                               *(((uint8_t *)buf) + index) = value->u.cval & 0xff;
+                               *((uint8_t *)dest) = value->u.cval & 0xff;
                        }
                        else if ((value->op == OP_INTCONST) && (value_size == 2)) {
-                               *(((uint16_t *)buf) + index) = value->u.cval & 0xffff;
+                               *((uint16_t *)dest) = value->u.cval & 0xffff;
                        }
                        else if ((value->op == OP_INTCONST) && (value_size == 4)) {
-                               *(((uint32_t *)buf) + index) = value->u.cval & 0xffffffff;
+                               *((uint32_t *)dest) = value->u.cval & 0xffffffff;
                        }
                        else {
                                fprintf(stderr, "%d %d\n",
                                        value->op, value_size);
                                internal_error(state, 0, "unhandled constant initializer");
                        }
+                       free_triple(state, value);
                        if (peek(state) == TOK_COMMA) {
                                eat(state, TOK_COMMA);
                                comma = 1;
                        }
-                       index += 1;
+                       info.offset += value_size;
+                       if ((info.type->type & TYPE_MASK) == TYPE_PRODUCT) {
+                               info.type = info.type->right;
+                       }
                } while(comma && (peek(state) != TOK_RBRACE));
+               if ((type->elements == ELEMENT_COUNT_UNSPECIFIED) &&
+                       ((type->type & TYPE_MASK) == TYPE_ARRAY)) {
+                       type->elements = max_offset / size_of(state, type->left);
+               }
                eat(state, TOK_RBRACE);
                result = triple(state, OP_BLOBCONST, type, 0, 0);
                result->u.blob = buf;
@@ -9028,7 +9097,8 @@ static struct triple *do_decl(struct compile_state *state,
        default:
                internal_error(state, 0, "Undefined storage class");
        }
-       if (((type->type & STOR_MASK) == STOR_STATIC) &&
+       if (ident && 
+               ((type->type & STOR_MASK) == STOR_STATIC) &&
                ((type->type & QUAL_CONST) == 0)) {
                error(state, 0, "non const static variables not supported");
        }