diff options
Diffstat (limited to 'util/romcc/romcc.c')
-rw-r--r-- | util/romcc/romcc.c | 92 |
1 files changed, 51 insertions, 41 deletions
diff --git a/util/romcc/romcc.c b/util/romcc/romcc.c index feebdbdab4..ea949989c2 100644 --- a/util/romcc/romcc.c +++ b/util/romcc/romcc.c @@ -751,7 +751,6 @@ struct compile_state { const char *label_prefix; const char *ofilename; FILE *output; - struct triple *vars; struct file_state *file; struct occurance *last_occurance; const char *function; @@ -4010,25 +4009,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) { + struct type *member; 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); + member = type->left; + while((member->type & TYPE_MASK) == TYPE_PRODUCT) { + align = align_of(state, member->left); size += needed_padding(size, align); - if (type->left->field_ident == field) { - type = type->left; + if (member->left->field_ident == field) { + member = member->left; break; } - size += size_of(state, type->left); - type = type->right; + size += size_of(state, member->left); + member = member->right; } - align = align_of(state, type); + align = align_of(state, member); size += needed_padding(size, align); - if (type->field_ident != field) { + if (member->field_ident != field) { error(state, 0, "member %s not present", field->name); } return size; @@ -4037,48 +4037,50 @@ static size_t field_offset(struct compile_state *state, static struct type *field_type(struct compile_state *state, struct type *type, struct hash_entry *field) { + struct type *member; if ((type->type & TYPE_MASK) != TYPE_STRUCT) { internal_error(state, 0, "field_type only works on structures"); } - type = type->left; - while((type->type & TYPE_MASK) == TYPE_PRODUCT) { - if (type->left->field_ident == field) { - type = type->left; + member = type->left; + while((member->type & TYPE_MASK) == TYPE_PRODUCT) { + if (member->left->field_ident == field) { + member = member->left; break; } - type = type->right; + member = member->right; } - if (type->field_ident != field) { + if (member->field_ident != field) { error(state, 0, "member %s not present", field->name); } - return type; + return member; } static struct type *next_field(struct compile_state *state, struct type *type, struct type *prev_member) { + struct type *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) { + member = type->left; + while((member->type & TYPE_MASK) == TYPE_PRODUCT) { if (!prev_member) { - type = type->left; + member = member->left; break; } - if (type->left == prev_member) { + if (member->left == prev_member) { prev_member = 0; } - type = type->right; + member = member->right; } - if (type == prev_member) { + if (member == 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 member; } static struct triple *struct_field(struct compile_state *state, @@ -4477,6 +4479,8 @@ static struct triple *do_mk_addr_expr(struct compile_state *state, struct triple *result; clvalue(state, expr); + type = new_type(TYPE_POINTER | (type->type & QUAL_MASK), type, 0); + result = 0; if (expr->op == OP_ADECL) { error(state, expr, "address of auto variables not supported"); @@ -4497,13 +4501,7 @@ static struct triple *do_mk_addr_expr(struct compile_state *state, static struct triple *mk_addr_expr( struct compile_state *state, struct triple *expr, ulong_t offset) { - struct type *type; - - type = new_type( - TYPE_POINTER | (expr->type->type & QUAL_MASK), - expr->type, 0); - - return do_mk_addr_expr(state, expr, type, offset); + return do_mk_addr_expr(state, expr, expr->type, offset); } static struct triple *mk_deref_expr( @@ -4515,6 +4513,21 @@ static struct triple *mk_deref_expr( return triple(state, OP_DEREF, base_type, expr, 0); } +static struct triple *array_to_pointer(struct compile_state *state, struct triple *def) +{ + if ((def->type->type & TYPE_MASK) == TYPE_ARRAY) { + struct type *type; + struct triple *addrconst; + type = new_type( + TYPE_POINTER | (def->type->type & QUAL_MASK), + def->type->left, 0); + addrconst = triple(state, OP_ADDRCONST, type, 0, 0); + MISC(addrconst, 0) = def; + def = addrconst; + } + return def; +} + static struct triple *deref_field( struct compile_state *state, struct triple *expr, struct hash_entry *field) { @@ -4555,16 +4568,10 @@ static struct triple *read_expr(struct compile_state *state, struct triple *def) return def; } /* Tranform an array to a pointer to the first element */ + #warning "CHECK_ME is this the right place to transform arrays to pointers?" if ((def->type->type & TYPE_MASK) == TYPE_ARRAY) { - struct type *type; - struct triple *result; - type = new_type( - TYPE_POINTER | (def->type->type & QUAL_MASK), - def->type->left, 0); - result = triple(state, OP_ADDRCONST, type, 0, 0); - MISC(result, 0) = def; - return result; + return array_to_pointer(state, def); } if (is_in_reg(state, def)) { op = OP_READ; @@ -8441,14 +8448,14 @@ static struct type *struct_or_union_specifier( } if (!ident || (peek(state) == TOK_LBRACE)) { ulong_t elements; + struct type **next; elements = 0; eat(state, TOK_LBRACE); + next = &struct_type; do { struct type *base_type; - struct type **next; int done; base_type = specifier_qualifier_list(state); - next = &struct_type; do { struct type *type; struct hash_entry *fident; @@ -9107,6 +9114,9 @@ static struct triple *do_decl(struct compile_state *state, default: internal_error(state, 0, "Undefined storage class"); } + if ((type->type & TYPE_MASK) == TYPE_FUNCTION) { + error(state, 0, "Function prototypes not supported"); + } if (ident && ((type->type & STOR_MASK) == STOR_STATIC) && ((type->type & QUAL_CONST) == 0)) { |