- 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;
}
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) &&