- A few more fixes to get pointers to structures working correctly.
authorEric Biederman <ebiederm@xmission.com>
Tue, 24 Jun 2003 14:27:37 +0000 (14:27 +0000)
committerEric Biederman <ebiederm@xmission.com>
Tue, 24 Jun 2003 14:27:37 +0000 (14:27 +0000)
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@901 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1

util/romcc/romcc.c

index af9c5552c6fe73019b99b35b4ec7ce7b9e81df1b..feebdbdab45dc5c7ba6fcec2f2e1c7e85e6ae5e6 100644 (file)
@@ -3932,6 +3932,15 @@ static size_t align_of(struct compile_state *state, struct type *type)
        return align;
 }
 
+static size_t needed_padding(size_t offset, size_t align)
+{
+        size_t padding;
+       padding = 0;
+       if (offset % align) {
+               padding = align - (offset % align);
+       }
+       return padding;
+}
 static size_t size_of(struct compile_state *state, struct type *type)
 {
        size_t size;
@@ -3961,16 +3970,16 @@ static size_t size_of(struct compile_state *state, struct type *type)
        case TYPE_PRODUCT:
        {
                size_t align, pad;
-               size = size_of(state, type->left);
-               while((type->right->type & TYPE_MASK) == TYPE_PRODUCT) {
-                       type = type->right;
+               size = 0;
+               while((type->type & TYPE_MASK) == TYPE_PRODUCT) {
                        align = align_of(state, type->left);
-                       pad = align - (size % align);
+                       pad = needed_padding(size, align);
                        size = size + pad + size_of(state, type->left);
+                       type = type->right;
                }
-               align = align_of(state, type->right);
-               pad = align - (size % align);
-               size = size + pad + sizeof(type->right);
+               align = align_of(state, type);
+               pad = needed_padding(size, align);
+               size = size + pad + sizeof(type);
                break;
        }
        case TYPE_OVERLAP:
@@ -4001,26 +4010,26 @@ static size_t size_of(struct compile_state *state, struct type *type)
 static size_t field_offset(struct compile_state *state, 
        struct type *type, struct hash_entry *field)
 {
-       size_t size, align, pad;
+       size_t size, align;
        if ((type->type & TYPE_MASK) != TYPE_STRUCT) {
                internal_error(state, 0, "field_offset only works on structures");
        }
        size = 0;
        type = type->left;
        while((type->type & TYPE_MASK) == TYPE_PRODUCT) {
+               align = align_of(state, type->left);
+               size += needed_padding(size, align);
                if (type->left->field_ident == field) {
                        type = type->left;
                        break;
                }
                size += size_of(state, type->left);
                type = type->right;
-               align = align_of(state, type);
-               pad = align - (size % align);
-               size += pad;
        }
+       align = align_of(state, type);
+       size += needed_padding(size, align);
        if (type->field_ident != field) {
-               internal_error(state, 0, "field_offset: member %s not present",
-                       field->name);
+               error(state, 0, "member %s not present", field->name);
        }
        return size;
 }
@@ -4040,8 +4049,34 @@ static struct type *field_type(struct compile_state *state,
                type = type->right;
        }
        if (type->field_ident != field) {
-               internal_error(state, 0, "field_type: member %s not present", 
-                       field->name);
+               error(state, 0, "member %s not present", field->name);
+       }
+       return type;
+}
+
+static struct type *next_field(struct compile_state *state,
+       struct type *type, struct type *prev_member) 
+{
+       if ((type->type & TYPE_MASK) != TYPE_STRUCT) {
+               internal_error(state, 0, "next_field only works on structures");
+       }
+       type = type->left;
+       while((type->type & TYPE_MASK) == TYPE_PRODUCT) {
+               if (!prev_member) {
+                       type = type->left;
+                       break;
+               }
+               if (type->left == prev_member) {
+                       prev_member = 0;
+               }
+               type = type->right;
+       }
+       if (type == prev_member) {
+               prev_member = 0;
+       }
+       if (prev_member) {
+               internal_error(state, 0, "prev_member %s not present", 
+                       prev_member->field_ident->name);
        }
        return type;
 }
@@ -4494,17 +4529,7 @@ static struct triple *deref_field(
                error(state, 0, "request for member %s in something not a struct or union",
                        field->name);
        }
-       member = type->left;
-       while((member->type & TYPE_MASK) == TYPE_PRODUCT) {
-               if (member->left->field_ident == field) {
-                       member = member->left;
-                       break;
-               }
-               member = member->right;
-       }
-       if (member->field_ident != field) {
-               error(state, 0, "%s is not a member", field->name);
-       }
+       member = field_type(state, type, field);
        if ((type->type & STOR_MASK) == STOR_PERM) {
                /* Do the pointer arithmetic to get a deref the field */
                ulong_t offset;
@@ -4514,8 +4539,7 @@ static struct triple *deref_field(
        }
        else {
                /* Find the variable for the field I want. */
-               result = triple(state, OP_DOT, 
-                       field_type(state, type, field), expr, 0);
+               result = triple(state, OP_DOT, member, expr, 0);
                result->u.field = field;
        }
        return result;
@@ -4797,9 +4821,6 @@ 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)
 {
@@ -5156,9 +5177,12 @@ static struct triple *flatten(
                        struct triple *base;
                        base = RHS(ptr, 0);
                        if (base->op == OP_DEREF) {
+                               struct triple *left;
                                ulong_t offset;
                                offset = field_offset(state, base->type, ptr->u.field);
-                               ptr = mk_add_expr(state, RHS(base, 0), 
+                               left = RHS(base, 0);
+                               ptr = triple(state, OP_ADD, left->type, 
+                                       read_expr(state, left),
                                        int_const(state, &ulong_type, offset));
                                free_triple(state, base);
                        }
@@ -8815,28 +8839,14 @@ static struct field_info designator(struct compile_state *state, struct type *ty
                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);
                        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;
+                       info.offset = field_offset(state, type, field);
+                       info.type   = field_type(state, type, field);
                        break;
                }
                default:
@@ -8866,6 +8876,9 @@ static struct triple *initializer(
                }
                info.offset = 0;
                info.type = type->left;
+               if ((type->type & TYPE_MASK) == TYPE_STRUCT) {
+                       info.type = next_field(state, type, 0);
+               }
                if (type->elements == ELEMENT_COUNT_UNSPECIFIED) {
                        max_offset = 0;
                } else {
@@ -8889,9 +8902,6 @@ static struct triple *initializer(
                                error(state, 0, "element beyond bounds");
                        }
                        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) &&
@@ -8920,8 +8930,6 @@ static struct triple *initializer(
                                *((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);
@@ -8930,8 +8938,10 @@ static struct triple *initializer(
                                comma = 1;
                        }
                        info.offset += value_size;
-                       if ((info.type->type & TYPE_MASK) == TYPE_PRODUCT) {
-                               info.type = info.type->right;
+                       if ((type->type & TYPE_MASK) == TYPE_STRUCT) {
+                               info.type = next_field(state, type, info.type);
+                               info.offset = field_offset(state, type, 
+                                       info.type->field_ident);
                        }
                } while(comma && (peek(state) != TOK_RBRACE));
                if ((type->elements == ELEMENT_COUNT_UNSPECIFIED) &&