- 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;
|
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) &&
|
||||||
|
|
Loading…
Reference in New Issue