- Structure handling fixes.

- Fix for asm statements with multiple results.


git-svn-id: svn://svn.coreboot.org/coreboot/trunk@942 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Eric Biederman 2003-07-12 01:21:31 +00:00
parent a3c708b5d2
commit e058a1e418
2 changed files with 72 additions and 19 deletions

View File

@ -74,6 +74,7 @@ TESTS=\
simple_test54.c \ simple_test54.c \
simple_test55.c \ simple_test55.c \
simple_test56.c \ simple_test56.c \
simple_test59.c \
raminit_test.c \ raminit_test.c \
raminit_test2.c \ raminit_test2.c \
raminit_test3.c \ raminit_test3.c \
@ -95,10 +96,10 @@ FAIL_OUT:=$(patsubst %.c, tests/%.out, $(FAIL_TESTS))
$(TEST_ASM): %.S: %.c romcc $(TEST_ASM): %.S: %.c romcc
export ALLOC_CHECK_=2; ./romcc -O2 -mcpu=k8 -o $@ $< > $*.debug export ALLOC_CHECK_=2; ./romcc -O -mcpu=k8 -o $@ $< > $*.debug
$(FAIL_OUT): %.out: %.c romcc $(FAIL_OUT): %.out: %.c romcc
export ALLOC_CHECK_=2; if ./romcc -O2 -o $*.S $< > $*.debug 2> $@ ; then exit 1 ; else exit 0 ; fi export ALLOC_CHECK_=2; if ./romcc -O -o $*.S $< > $*.debug 2> $@ ; then exit 1 ; else exit 0 ; fi
$(TEST_OBJ): %.o: %.S $(TEST_OBJ): %.o: %.S
as $< -o $@ as $< -o $@

View File

@ -4002,7 +4002,7 @@ static size_t size_of(struct compile_state *state, struct type *type)
} }
align = align_of(state, type); align = align_of(state, type);
pad = needed_padding(size, align); pad = needed_padding(size, align);
size = size + pad + sizeof(type); size = size + pad + size_of(state, type);
break; break;
} }
case TYPE_OVERLAP: case TYPE_OVERLAP:
@ -4021,8 +4021,15 @@ static size_t size_of(struct compile_state *state, struct type *type)
} }
break; break;
case TYPE_STRUCT: case TYPE_STRUCT:
{
size_t align, pad;
size = size_of(state, type->left); size = size_of(state, type->left);
/* Pad structures so their size is a multiples of their alignment */
align = align_of(state, type);
pad = needed_padding(size, align);
size = size + pad;
break; break;
}
default: default:
internal_error(state, 0, "sizeof not yet defined for type\n"); internal_error(state, 0, "sizeof not yet defined for type\n");
break; break;
@ -4617,7 +4624,7 @@ static struct triple *read_expr(struct compile_state *state, struct triple *def)
return triple(state, op, def->type, def, 0); return triple(state, op, def->type, def, 0);
} }
static void write_compatible(struct compile_state *state, int is_write_compatible(struct compile_state *state,
struct type *dest, struct type *rval) struct type *dest, struct type *rval)
{ {
int compatible = 0; int compatible = 0;
@ -4642,11 +4649,31 @@ static void write_compatible(struct compile_state *state,
(dest->type_ident == rval->type_ident)) { (dest->type_ident == rval->type_ident)) {
compatible = 1; compatible = 1;
} }
if (!compatible) { return compatible;
}
static void write_compatible(struct compile_state *state,
struct type *dest, struct type *rval)
{
if (!is_write_compatible(state, dest, rval)) {
error(state, 0, "Incompatible types in assignment"); error(state, 0, "Incompatible types in assignment");
} }
} }
static int is_init_compatible(struct compile_state *state,
struct type *dest, struct type *rval)
{
int compatible = 0;
if (is_write_compatible(state, dest, rval)) {
compatible = 1;
}
else if (equiv_types(dest, rval)) {
compatible = 1;
}
return compatible;
}
static struct triple *write_expr( static struct triple *write_expr(
struct compile_state *state, struct triple *dest, struct triple *rval) struct compile_state *state, struct triple *dest, struct triple *rval)
{ {
@ -5430,6 +5457,15 @@ static struct triple *mk_subscript_expr(
return mk_deref_expr(state, mk_add_expr(state, left, right)); return mk_deref_expr(state, mk_add_expr(state, left, right));
} }
static struct triple *mk_cast_expr(
struct compile_state *state, struct type *type, struct triple *expr)
{
struct triple *def;
def = read_expr(state, expr);
def = triple(state, OP_COPY, type, def, 0);
return def;
}
/* /*
* Compile time evaluation * Compile time evaluation
* =========================== * ===========================
@ -7333,8 +7369,7 @@ static struct triple *cast_expr(struct compile_state *state)
eat(state, TOK_LPAREN); eat(state, TOK_LPAREN);
type = type_name(state); type = type_name(state);
eat(state, TOK_RPAREN); eat(state, TOK_RPAREN);
def = read_expr(state, cast_expr(state)); def = mk_cast_expr(state, type, cast_expr(state));
def = triple(state, OP_COPY, type, def, 0);
} }
else { else {
def = unary_expr(state); def = unary_expr(state);
@ -8182,7 +8217,6 @@ static void asm_statement(struct compile_state *state, struct triple *first)
error(state, 0, "Maximum clobber limit exceeded."); error(state, 0, "Maximum clobber limit exceeded.");
} }
clobber = string_constant(state); clobber = string_constant(state);
eat(state, TOK_RPAREN);
clob_param[clobbers].constraint = clobber; clob_param[clobbers].constraint = clobber;
if (peek(state) == TOK_COMMA) { if (peek(state) == TOK_COMMA) {
@ -8250,21 +8284,22 @@ static void asm_statement(struct compile_state *state, struct triple *first)
RHS(def, i) = read_expr(state,in_param[i].expr); RHS(def, i) = read_expr(state,in_param[i].expr);
} }
flatten(state, first, def); flatten(state, first, def);
for(i = 0; i < out; i++) { for(i = 0; i < (out + clobbers); i++) {
struct type *type;
struct triple *piece; struct triple *piece;
piece = triple(state, OP_PIECE, out_param[i].expr->type, def, 0); type = (i < out)? out_param[i].expr->type : &void_type;
piece->u.cval = i; piece = triple(state, OP_PIECE, type, def, 0);
LHS(def, i) = piece;
flatten(state, first,
write_expr(state, out_param[i].expr, piece));
}
for(; i - out < clobbers; i++) {
struct triple *piece;
piece = triple(state, OP_PIECE, &void_type, def, 0);
piece->u.cval = i; piece->u.cval = i;
LHS(def, i) = piece; LHS(def, i) = piece;
flatten(state, first, piece); flatten(state, first, piece);
} }
/* And write the helpers to their destinations */
for(i = 0; i < out; i++) {
struct triple *piece;
piece = LHS(def, i);
flatten(state, first,
write_expr(state, out_param[i].expr, piece));
}
} }
@ -8627,7 +8662,9 @@ static struct type *struct_or_union_specifier(
struct_type = new_type(TYPE_STRUCT | spec, struct_type, 0); struct_type = new_type(TYPE_STRUCT | spec, struct_type, 0);
struct_type->type_ident = ident; struct_type->type_ident = ident;
struct_type->elements = elements; struct_type->elements = elements;
symbol(state, ident, &ident->sym_struct, 0, struct_type); if (ident) {
symbol(state, ident, &ident->sym_struct, 0, struct_type);
}
} }
if (ident && ident->sym_struct) { if (ident && ident->sym_struct) {
struct_type = clone_type(spec, ident->sym_struct->type); struct_type = clone_type(spec, ident->sym_struct->type);
@ -9015,8 +9052,23 @@ static struct triple *initializer(
struct compile_state *state, struct type *type) struct compile_state *state, struct type *type)
{ {
struct triple *result; struct triple *result;
#warning "FIXME handle string pointer initializers "
#warning "FIXME more consistent initializer handling (where should eval_const_expr go?"
if (peek(state) != TOK_LBRACE) { if (peek(state) != TOK_LBRACE) {
result = assignment_expr(state); result = assignment_expr(state);
if (((type->type & TYPE_MASK) == TYPE_ARRAY) &&
(type->elements == ELEMENT_COUNT_UNSPECIFIED) &&
((result->type->type & TYPE_MASK) == TYPE_ARRAY) &&
(result->type->elements != ELEMENT_COUNT_UNSPECIFIED) &&
(equiv_types(type->left, result->type->left))) {
type->elements = result->type->elements;
}
if (!is_init_compatible(state, type, result->type)) {
error(state, 0, "Incompatible types in initializer");
}
if (!equiv_types(type, result->type)) {
result = mk_cast_expr(state, type, result);
}
} }
else { else {
int comma; int comma;