- 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:
parent
a3c708b5d2
commit
e058a1e418
|
@ -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 $@
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue