diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index e282210c7..69b9ba0a6 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -76,6 +76,7 @@ extern storage_class_t current_storage; def_t *new_def (const char *name, struct type_s *type, struct defspace_s *space, storage_class_t storage); def_t *alias_def (def_t *def, struct type_s *type); +def_t *temp_def (etype_t type, int size); void free_def (def_t *def); void def_to_ddef (def_t *def, ddef_t *ddef, int aux); diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index d4b5da79a..86c07fe45 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -44,6 +44,7 @@ typedef struct operand_s { struct operand_s *next; op_type_e op_type; etype_t type; ///< possibly override symbol's type + int size; ///< for structures union { struct symbol_s *symbol; struct ex_value_s *value; diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 86575535a..55d5ed455 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -53,6 +53,7 @@ static __attribute__ ((used)) const char rcsid[] = #include "diagnostic.h" #include "emit.h" #include "expr.h" +#include "function.h" #include "options.h" #include "reloc.h" #include "strpool.h" @@ -142,12 +143,33 @@ alias_def (def_t *def, type_t *type) def_t *alias; ALLOC (16384, def_t, defs, alias); + alias->return_addr = __builtin_return_address (0); alias->offset = def->offset; alias->type = type; alias->alias = def; return alias; } +def_t * +temp_def (etype_t type, int size) +{ + def_t *temp; + defspace_t *space = current_func->symtab->space; + + ALLOC (16384, def_t, defs, temp); + temp->return_addr = __builtin_return_address (0); + temp->name = save_string (va (".tmp%d", current_func->temp_num++)); + temp->type = ev_types[type]; + temp->file = pr.source_file; + temp->line = pr.source_line; + set_storage_bits (temp, st_local); + temp->offset = defspace_alloc_loc (space, size); + temp->space = space; + *space->def_tail = temp; + space->def_tail = &temp->next; + return temp; +} + void free_def (def_t *def) { diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 2b074bed0..7651dff50 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -109,13 +109,8 @@ get_operand_def (expr_t *expr, operand_t *op) zero_def.type = &type_short; return &zero_def; //FIXME case op_temp: - if (!op->o.def) { - const char *temp_name; - - temp_name = va (".tmp%d", current_func->temp_num++); - op->o.def = new_def (temp_name, ev_types[op->type], - current_func->symtab->space, st_local); - } + if (!op->o.def) + op->o.def = temp_def (op->type, op->size); return op->o.def; case op_pointer: def = op->o.pointer->def; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 87e92b5f9..a240d02b0 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -217,6 +217,16 @@ free_sblock (sblock_t *sblock) free_sblocks = sblock; } +static operand_t * +temp_operand (type_t *type) +{ + operand_t *op = new_operand (op_temp); + + op->type = low_level_type (type); + op->size = type_size (type); + return op; +} + static operand_t * short_operand (short short_val) { @@ -486,8 +496,7 @@ lea_statement (operand_t *pointer, operand_t *offset, expr_t *e) statement_t *s = new_statement ("&", e); s->opa = pointer; s->opb = offset; - s->opc = new_operand (op_temp); - s->opc->type = ev_pointer; + s->opc = temp_operand (&type_pointer); return s; } @@ -496,8 +505,7 @@ address_statement (operand_t *value, expr_t *e) { statement_t *s = new_statement ("&", e); s->opa = value; - s->opc = new_operand (op_temp); - s->opc->type = ev_pointer; + s->opc = temp_operand (&type_pointer); return s; } @@ -519,10 +527,8 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) operand_t *offs = 0; sblock = statement_subexpr (sblock, e->e.expr.e1, &ptr); sblock = statement_subexpr (sblock, e->e.expr.e2, &offs); - if (!*op) { - *op = new_operand (op_temp); - (*op)->type = low_level_type (type); - } + if (!*op) + *op = temp_operand (type); if (low_level_type (type) == ev_void) { operand_t *src_addr; operand_t *dst_addr; @@ -591,10 +597,8 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) s = new_statement (opcode, e); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb); - if (!*op) { - *op = new_operand (op_temp); - (*op)->type = low_level_type (e->e.expr.type); - } + if (!*op) + *op = temp_operand (e->e.expr.type); s->opc = *op; sblock_add_statement (sblock, s); break; @@ -621,10 +625,8 @@ expr_cast (sblock_t *sblock, expr_t *e, operand_t **op) sblock = statement_subexpr (sblock, e->e.expr.e1, &src); if ((src->type == ev_integer && type->type == ev_float) || (src->type == ev_float && type->type == ev_integer)) { - if (!*op) { - (*op) = new_operand (op_temp); - (*op)->type = low_level_type (e->e.expr.type); - } + if (!*op) + *op = temp_operand (e->e.expr.type); s = new_statement ("=", e); s->opa = src; s->opc = *op; @@ -681,10 +683,8 @@ expr_uexpr (sblock_t *sblock, expr_t *e, operand_t **op) internal_error (e, "ice ice baby"); s = new_statement (opcode, e); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); - if (!*op) { - *op = new_operand (op_temp); - (*op)->type = low_level_type (e->e.expr.type); - } + if (!*op) + *op = temp_operand (e->e.expr.type); s->opc = *op; sblock_add_statement (sblock, s); } @@ -703,10 +703,8 @@ expr_symbol (sblock_t *sblock, expr_t *e, operand_t **op) static sblock_t * expr_temp (sblock_t *sblock, expr_t *e, operand_t **op) { - if (!e->e.temp.op) { - e->e.temp.op = new_operand (op_temp); - e->e.temp.op->type = low_level_type (e->e.temp.type); - } + if (!e->e.temp.op) + e->e.temp.op = temp_operand (e->e.temp.type); *op = e->e.temp.op; return sblock; }