- 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:
parent
432cc66984
commit
03b59864df
|
@ -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) &&
|
||||
|
|
Loading…
Reference in New Issue