- A few more fixes to get pointers to structures working correctly.

git-svn-id: svn://svn.coreboot.org/coreboot/trunk@901 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Eric Biederman 2003-06-24 14:27:37 +00:00
parent 432cc66984
commit 03b59864df
1 changed files with 65 additions and 55 deletions

View File

@ -3932,6 +3932,15 @@ static size_t align_of(struct compile_state *state, struct type *type)
return align; 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) static size_t size_of(struct compile_state *state, struct type *type)
{ {
size_t size; size_t size;
@ -3961,16 +3970,16 @@ static size_t size_of(struct compile_state *state, struct type *type)
case TYPE_PRODUCT: case TYPE_PRODUCT:
{ {
size_t align, pad; size_t align, pad;
size = size_of(state, type->left); size = 0;
while((type->right->type & TYPE_MASK) == TYPE_PRODUCT) { while((type->type & TYPE_MASK) == TYPE_PRODUCT) {
type = type->right;
align = align_of(state, type->left); align = align_of(state, type->left);
pad = align - (size % align); pad = needed_padding(size, align);
size = size + pad + size_of(state, type->left); size = size + pad + size_of(state, type->left);
type = type->right;
} }
align = align_of(state, type->right); align = align_of(state, type);
pad = align - (size % align); pad = needed_padding(size, align);
size = size + pad + sizeof(type->right); size = size + pad + sizeof(type);
break; break;
} }
case TYPE_OVERLAP: 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, static size_t field_offset(struct compile_state *state,
struct type *type, struct hash_entry *field) struct type *type, struct hash_entry *field)
{ {
size_t size, align, pad; size_t size, align;
if ((type->type & TYPE_MASK) != TYPE_STRUCT) { if ((type->type & TYPE_MASK) != TYPE_STRUCT) {
internal_error(state, 0, "field_offset only works on structures"); internal_error(state, 0, "field_offset only works on structures");
} }
size = 0; size = 0;
type = type->left; type = type->left;
while((type->type & TYPE_MASK) == TYPE_PRODUCT) { while((type->type & TYPE_MASK) == TYPE_PRODUCT) {
align = align_of(state, type->left);
size += needed_padding(size, align);
if (type->left->field_ident == field) { if (type->left->field_ident == field) {
type = type->left; type = type->left;
break; break;
} }
size += size_of(state, type->left); size += size_of(state, type->left);
type = type->right; 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) { if (type->field_ident != field) {
internal_error(state, 0, "field_offset: member %s not present", error(state, 0, "member %s not present", field->name);
field->name);
} }
return size; return size;
} }
@ -4040,8 +4049,34 @@ static struct type *field_type(struct compile_state *state,
type = type->right; type = type->right;
} }
if (type->field_ident != field) { if (type->field_ident != field) {
internal_error(state, 0, "field_type: member %s not present", error(state, 0, "member %s not present", field->name);
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; 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", error(state, 0, "request for member %s in something not a struct or union",
field->name); field->name);
} }
member = type->left; member = field_type(state, type, field);
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);
}
if ((type->type & STOR_MASK) == STOR_PERM) { if ((type->type & STOR_MASK) == STOR_PERM) {
/* Do the pointer arithmetic to get a deref the field */ /* Do the pointer arithmetic to get a deref the field */
ulong_t offset; ulong_t offset;
@ -4514,8 +4539,7 @@ static struct triple *deref_field(
} }
else { else {
/* Find the variable for the field I want. */ /* Find the variable for the field I want. */
result = triple(state, OP_DOT, result = triple(state, OP_DOT, member, expr, 0);
field_type(state, type, field), expr, 0);
result->u.field = field; result->u.field = field;
} }
return result; return result;
@ -4797,9 +4821,6 @@ static int expr_depth(struct compile_state *state, struct triple *ins)
static struct triple *flatten( static struct triple *flatten(
struct compile_state *state, struct triple *first, struct triple *ptr); 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( static struct triple *flatten_generic(
struct compile_state *state, struct triple *first, struct triple *ptr) struct compile_state *state, struct triple *first, struct triple *ptr)
{ {
@ -5156,9 +5177,12 @@ static struct triple *flatten(
struct triple *base; struct triple *base;
base = RHS(ptr, 0); base = RHS(ptr, 0);
if (base->op == OP_DEREF) { if (base->op == OP_DEREF) {
struct triple *left;
ulong_t offset; ulong_t offset;
offset = field_offset(state, base->type, ptr->u.field); 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)); int_const(state, &ulong_type, offset));
free_triple(state, base); free_triple(state, base);
} }
@ -8815,28 +8839,14 @@ static struct field_info designator(struct compile_state *state, struct type *ty
case TOK_DOT: case TOK_DOT:
{ {
struct hash_entry *field; struct hash_entry *field;
struct type *member;
if ((type->type & TYPE_MASK) != TYPE_STRUCT) { if ((type->type & TYPE_MASK) != TYPE_STRUCT) {
error(state, 0, "Struct designator not in struct initializer"); error(state, 0, "Struct designator not in struct initializer");
} }
eat(state, TOK_DOT); eat(state, TOK_DOT);
eat(state, TOK_IDENT); eat(state, TOK_IDENT);
field = state->token[0].ident; field = state->token[0].ident;
info.offset = 0; info.offset = field_offset(state, type, field);
member = type->left; info.type = field_type(state, type, field);
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; break;
} }
default: default:
@ -8866,6 +8876,9 @@ static struct triple *initializer(
} }
info.offset = 0; info.offset = 0;
info.type = type->left; info.type = type->left;
if ((type->type & TYPE_MASK) == TYPE_STRUCT) {
info.type = next_field(state, type, 0);
}
if (type->elements == ELEMENT_COUNT_UNSPECIFIED) { if (type->elements == ELEMENT_COUNT_UNSPECIFIED) {
max_offset = 0; max_offset = 0;
} else { } else {
@ -8889,9 +8902,6 @@ static struct triple *initializer(
error(state, 0, "element beyond bounds"); error(state, 0, "element beyond bounds");
} }
value_type = info.type; 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 = eval_const_expr(state, initializer(state, value_type));
value_size = size_of(state, value_type); value_size = size_of(state, value_type);
if (((type->type & TYPE_MASK) == TYPE_ARRAY) && if (((type->type & TYPE_MASK) == TYPE_ARRAY) &&
@ -8920,8 +8930,6 @@ static struct triple *initializer(
*((uint32_t *)dest) = value->u.cval & 0xffffffff; *((uint32_t *)dest) = value->u.cval & 0xffffffff;
} }
else { else {
fprintf(stderr, "%d %d\n",
value->op, value_size);
internal_error(state, 0, "unhandled constant initializer"); internal_error(state, 0, "unhandled constant initializer");
} }
free_triple(state, value); free_triple(state, value);
@ -8930,8 +8938,10 @@ static struct triple *initializer(
comma = 1; comma = 1;
} }
info.offset += value_size; info.offset += value_size;
if ((info.type->type & TYPE_MASK) == TYPE_PRODUCT) { if ((type->type & TYPE_MASK) == TYPE_STRUCT) {
info.type = info.type->right; info.type = next_field(state, type, info.type);
info.offset = field_offset(state, type,
info.type->field_ident);
} }
} while(comma && (peek(state) != TOK_RBRACE)); } while(comma && (peek(state) != TOK_RBRACE));
if ((type->elements == ELEMENT_COUNT_UNSPECIFIED) && if ((type->elements == ELEMENT_COUNT_UNSPECIFIED) &&