diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index 5b74397ac..a8005ba11 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -65,6 +65,8 @@ typedef struct def_s { struct def_s *alias; ///< real def which this def aliases struct reloc_s *relocs; ///< for relocations struct expr_s *initializer;///< initialer expression + struct daglabel_s *daglabel;///< daglabel for this def + struct flowvar_s *flowvar; ///< flowvar for this def unsigned offset_reloc:1; ///< use *_def_ofs relocs unsigned initialized:1; ///< the def has been initialized diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index f401fb909..a24b17741 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -33,12 +33,10 @@ #include "QF/pr_comp.h" typedef enum { - op_symbol, + op_def, op_value, op_label, op_temp, - op_pointer, - op_alias, } op_type_e; typedef struct { @@ -46,20 +44,20 @@ typedef struct { struct type_s *type; struct flowvar_s *flowvar; struct daglabel_s *daglabel; + struct operand_s *alias; int users; } tempop_t; typedef struct operand_s { struct operand_s *next; op_type_e op_type; - etype_t type; ///< possibly override symbol's type + etype_t type; ///< possibly override def's type int size; ///< for structures union { - struct symbol_s *symbol; + struct def_s *def; struct ex_value_s *value; struct ex_label_s *label; tempop_t tempop; - struct operand_s *alias; } o; } operand_t; @@ -108,7 +106,8 @@ typedef struct sblock_s { struct expr_s; struct type_s; -operand_t *alias_operand (operand_t *op, etype_t type); +const char *optype_str (op_type_e type); + operand_t *temp_operand (struct type_s *type); sblock_t *new_sblock (void); statement_t *new_statement (st_type_t type, const char *opcode, diff --git a/tools/qfcc/include/symtab.h b/tools/qfcc/include/symtab.h index c8c831203..0a89a39e7 100644 --- a/tools/qfcc/include/symtab.h +++ b/tools/qfcc/include/symtab.h @@ -64,8 +64,6 @@ typedef struct symbol_s { sy_type_e sy_type; ///< symbol type struct type_s *type; ///< type of object to which symbol refers struct param_s *params; ///< the parameters if a function - struct flowvar_s *flowvar; - struct daglabel_s *daglabel;///< dag label for this symbol union { int offset; ///< sy_var (in a struct/union) struct def_s *def; ///< sy_var diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index ca68ceb5d..b3493b34b 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -65,13 +65,11 @@ flush_daglabels (void) operand_t *op; if ((op = daglabel_chain->op)) { - while (op->op_type == op_alias) - op = op->o.alias; - if (op->op_type == op_symbol) - op->o.symbol->daglabel = 0; + if (op->op_type == op_def) + op->o.def->daglabel = 0; else if (op->op_type == op_temp) op->o.tempop.daglabel = 0; - else if (op->op_type == op_value || op->op_type == op_pointer) + else if (op->op_type == op_value) op->o.value->daglabel = 0; else if (op->op_type == op_label) op->o.label->daglabel = 0; @@ -146,14 +144,12 @@ opcode_label (dag_t *dag, const char *opcode, expr_t *expr) static daglabel_t * operand_label (dag_t *dag, operand_t *op) { - symbol_t *sym = 0; + def_t *def = 0; ex_value_t *val = 0; daglabel_t *label; if (!op) return 0; - while (op->op_type == op_alias) - op = op->o.alias; if (op->op_type == op_temp) { if (op->o.tempop.daglabel) @@ -161,14 +157,14 @@ operand_label (dag_t *dag, operand_t *op) label = new_label (dag); label->op = op; op->o.tempop.daglabel = label; - } else if (op->op_type == op_symbol) { - sym = op->o.symbol; - if (sym->daglabel) - return sym->daglabel; + } else if (op->op_type == op_def) { + def = op->o.def; + if (def->daglabel) + return def->daglabel; label = new_label (dag); label->op = op; - sym->daglabel = label; - } else if (op->op_type == op_value || op->op_type == op_pointer) { + def->daglabel = label; + } else if (op->op_type == op_value) { val = op->o.value; if (val->daglabel) return val->daglabel; @@ -207,23 +203,19 @@ leaf_node (dag_t *dag, operand_t *op, expr_t *expr) static dagnode_t * dag_node (operand_t *op) { - symbol_t *sym; + def_t *def; dagnode_t *node = 0; if (!op) return 0; - while (op->op_type == op_alias) - op = op->o.alias; - if (op->op_type == op_symbol) { - sym = op->o.symbol; - //if (sym->sy_type == sy_const) - // return 0; - if (sym->daglabel) - node = sym->daglabel->dagnode; + if (op->op_type == op_def) { + def = op->o.def; + if (def->daglabel) + node = def->daglabel->dagnode; } else if (op->op_type == op_temp) { if (op->o.tempop.daglabel) node = op->o.tempop.daglabel->dagnode; - } else if (op->op_type == op_value || op->op_type == op_pointer) { + } else if (op->op_type == op_value) { if (op->o.value->daglabel) node = op->o.value->daglabel->dagnode; } else if (op->op_type == op_label) { @@ -337,19 +329,13 @@ dagnode_set_edges (dagnode_t *n) static int op_is_identifier (operand_t *op) { - while (op->op_type == op_alias) - op = op->o.alias; if (op->op_type == op_label) return 0; if (op->op_type == op_value) return 0; - if (op->op_type == op_pointer) - return 1; if (op->op_type == op_temp) return 1; - if (op->op_type != op_symbol) - return 0; - if (op->o.symbol->sy_type != sy_var) + if (op->op_type != op_def) return 0; return 1; } @@ -569,10 +555,11 @@ build_statement (const char *opcode, operand_t **operands, expr_t *expr) for (i = 0; i < 3; i++) { if ((op = operands[i])) { - while (op->op_type == op_alias) - op = op->o.alias; - if (op->op_type == op_temp) + if (op->op_type == op_temp) { + while (op->o.tempop.alias) + op = op->o.tempop.alias; op->o.tempop.users++; + } } } st->opa = operands[0]; @@ -614,13 +601,6 @@ dag_calc_node_costs (dagnode_t *dagnode) } } #endif -static operand_t * -fix_op_type (operand_t *op, etype_t type) -{ - if (op && op->op_type != op_label && op->type != type) - op = alias_operand (op, type); - return op; -} static operand_t * generate_assignments (dag_t *dag, sblock_t *block, operand_t *src, @@ -631,15 +611,12 @@ generate_assignments (dag_t *dag, sblock_t *block, operand_t *src, operand_t *operands[3] = {0, 0, 0}; daglabel_t *var; - operands[0] = fix_op_type (src, type); + operands[0] = src; for ( ; var_iter; var_iter = set_next (var_iter)) { var = dag->labels[var_iter->member]; - operands[1] = fix_op_type (var->op, type); - if (!dst) { + operands[1] = var->op; + if (!dst) dst = operands[1]; - while (dst->op_type == op_alias) - dst = dst->o.alias; - } st = build_statement ("=", operands, var->expr); sblock_add_statement (block, st); @@ -653,9 +630,6 @@ make_operand (dag_t *dag, sblock_t *block, const dagnode_t *dagnode, int index) operand_t *op; op = dagnode->children[index]->value; - while (op->op_type == op_alias) - op = op->o.alias; - op = fix_op_type (op, dagnode->types[index]); return op; } @@ -676,9 +650,9 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode) dst = dagnode->label->op; if ((var_iter = set_first (dagnode->identifiers))) { type = dst->type; - if (dst->op_type == op_symbol - && !strcmp (dst->o.symbol->name, ".return")) - type = dag->flownode->return_type.in; + //if (dst->op_type == op_def + // && !strcmp (dst->o.def->name, ".return")) + // type = dag->flownode->return_type.in; dst = generate_assignments (dag, block, dst, var_iter, type); } break; @@ -692,7 +666,7 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode) } else { daglabel_t *var = dag->labels[var_iter->member]; - operands[2] = fix_op_type (var->op, type); + operands[2] = var->op; var_iter = set_next (var_iter); } dst = operands[2]; diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index c873c7716..7d00b6715 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -79,28 +79,11 @@ get_value_def (ex_value_t *value, etype_t type) static def_t * get_operand_def (expr_t *expr, operand_t *op) { - def_t *def; - if (!op) return 0; switch (op->op_type) { - case op_symbol: - switch (op->o.symbol->sy_type) { - case sy_var: - if (op->type != op->o.symbol->type->type) - return alias_def (op->o.symbol->s.def, - ev_types[op->type], 0); - return op->o.symbol->s.def; - case sy_func: - return op->o.symbol->s.func->def; - case sy_const: - return get_value_def (op->o.symbol->s.value, op->type); - case sy_type: - case sy_expr: - case sy_class: - internal_error (expr, "invalid operand type"); - } - break; + case op_def: + return op->o.def; case op_value: return get_value_def (op->o.value, op->type); case op_label: @@ -108,22 +91,11 @@ get_operand_def (expr_t *expr, operand_t *op) zero_def.type = &type_short; return &zero_def; //FIXME case op_temp: + while (op->o.tempop.alias) + op = op->o.tempop.alias; if (!op->o.tempop.def) op->o.tempop.def = temp_def (op->type, op->size); return op->o.tempop.def; - case op_pointer: - def = op->o.value->v.pointer.def; - if (op->o.value->v.pointer.val || op->type != def->type->type) { - def = alias_def (def, ev_types[op->type], - op->o.value->v.pointer.val); - } - return def; - case op_alias: - def = get_operand_def (expr, op->o.alias); - if (def->alias) - def = def->alias; - def = alias_def (def, ev_types[op->type], 0); - return def; } return 0; } @@ -172,10 +144,10 @@ add_statement_op_ref (operand_t *op, dstatement_t *st, int field) static void use_tempop (operand_t *op, expr_t *expr) { - while (op && op->op_type == op_alias) - op = op->o.alias; if (!op || op->op_type != op_temp) return; + while (op->o.tempop.alias) + op = op->o.tempop.alias; if (--op->o.tempop.users == 0) free_temp_def (op->o.tempop.def); if (op->o.tempop.users <= -1) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 280917253..05646442a 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -64,15 +64,15 @@ static struct { const char *name; operand_t op; } flow_params[] = { - {".return", {0, op_symbol}}, - {".param_0", {0, op_symbol}}, - {".param_1", {0, op_symbol}}, - {".param_2", {0, op_symbol}}, - {".param_3", {0, op_symbol}}, - {".param_4", {0, op_symbol}}, - {".param_5", {0, op_symbol}}, - {".param_6", {0, op_symbol}}, - {".param_7", {0, op_symbol}}, + {".return", {0, op_def}}, + {".param_0", {0, op_def}}, + {".param_1", {0, op_def}}, + {".param_2", {0, op_def}}, + {".param_3", {0, op_def}}, + {".param_4", {0, op_def}}, + {".param_5", {0, op_def}}, + {".param_6", {0, op_def}}, + {".param_7", {0, op_def}}, }; static const int num_flow_params = sizeof(flow_params)/sizeof(flow_params[0]); @@ -156,36 +156,27 @@ flowvar_get_def (flowvar_t *var) { operand_t *op = var->op; - while (op->op_type == op_alias) - op = op->o.alias; switch (op->op_type) { - case op_symbol: - return op->o.symbol->s.def; + case op_def: + return op->o.def; case op_value: case op_label: return 0; case op_temp: return op->o.tempop.def; - case op_pointer: - return op->o.value->v.pointer.def; - case op_alias: - internal_error (0, "oops, blue pill"); } + internal_error (0, "oops, blue pill"); return 0; } static int flowvar_is_global (flowvar_t *var) { - symbol_t *sym; def_t *def; - if (var->op->op_type != op_symbol) + if (var->op->op_type != op_def) return 0; - sym = var->op->o.symbol; - if (sym->sy_type != sy_var) - return 0; - def = sym->s.def; + def = var->op->o.def; if (def->local) return 0; return 1; @@ -194,15 +185,11 @@ flowvar_is_global (flowvar_t *var) static int flowvar_is_param (flowvar_t *var) { - symbol_t *sym; def_t *def; - if (var->op->op_type != op_symbol) + if (var->op->op_type != op_def) return 0; - sym = var->op->o.symbol; - if (sym->sy_type != sy_var) - return 0; - def = sym->s.def; + def = var->op->o.def; if (!def->local) return 0; if (!def->param) @@ -213,15 +200,11 @@ flowvar_is_param (flowvar_t *var) static int flowvar_is_initialized (flowvar_t *var) { - symbol_t *sym; def_t *def; - if (var->op->op_type != op_symbol) + if (var->op->op_type != op_def) return 0; - sym = var->op->o.symbol; - if (sym->sy_type != sy_var) - return 0; - def = sym->s.def; + def = var->op->o.def; return def->initialized; } @@ -231,18 +214,15 @@ flow_get_var (operand_t *op) if (!op) return 0; - while (op->op_type == op_alias) - op = op->o.alias; - if (op->op_type == op_temp) { if (!op->o.tempop.flowvar) op->o.tempop.flowvar = new_flowvar (); return op->o.tempop.flowvar; } - if (op->op_type == op_symbol && op->o.symbol->sy_type == sy_var) { - if (!op->o.symbol->flowvar) - op->o.symbol->flowvar = new_flowvar (); - return op->o.symbol->flowvar; + if (op->op_type == op_def) { + if (!op->o.def->flowvar) + op->o.def->flowvar = new_flowvar (); + return op->o.def->flowvar; } //FIXME functions? (some are variable) values? return 0; @@ -283,8 +263,6 @@ add_operand (function_t *func, operand_t *op) if (!op) return; - while (op->op_type == op_alias) - op = op->o.alias; if (op->op_type == op_label) return; @@ -319,7 +297,7 @@ flow_build_vars (function_t *func) // first, count .return and .param_[0-7] as they are always needed for (i = 0; i < num_flow_params; i++) { - flow_params[i].op.o.symbol = param_symbol (flow_params[i].name); + flow_params[i].op.o.def = param_symbol (flow_params[i].name)->s.def; num_vars += count_operand (&flow_params[i].op); } // then run through the statements in the function looking for accessed @@ -561,10 +539,8 @@ get_function_type (operand_t *op) type_t *type = &type_void; //FIXME fuction type casts? - while (op->op_type == op_alias) - op = op->o.alias; - if (op->op_type == op_symbol) { - type = op->o.symbol->type; + if (op->op_type == op_def) { + type = op->o.def->type; if (type->type != ev_func) internal_error (0, "not a function symbol"); type = type->t.func.type; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 8cc6c15b4..62fb30171 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -55,16 +55,29 @@ #include "type.h" #include "qc-parse.h" +static const char *op_type_names[] = { + "op_def", + "op_value", + "op_label", + "op_temp", +}; + +const char * +optype_str (op_type_e type) +{ + if (type < 0 || type > op_temp) + return ""; + return op_type_names[type]; +} + const char * operand_string (operand_t *op) { - type_t *type; - if (!op) return ""; switch (op->op_type) { - case op_symbol: - return op->o.symbol->name; + case op_def: + return op->o.def->name; case op_value: switch (op->o.value->type) { case ev_string: @@ -108,20 +121,9 @@ operand_string (operand_t *op) case op_label: return op->o.label->name; case op_temp: + while (op->o.tempop.alias) + op = op->o.tempop.alias; return va ("", op, op->o.tempop.users); - case op_pointer: - type = op->o.value->v.pointer.type; - if (op->o.value->v.pointer.def) - return va ("(%s)[%d]<%s>", - type ? pr_type_name[type->type] : "???", - op->o.value->v.pointer.val, - op->o.value->v.pointer.def->name); - else - return va ("(%s)[%d]", - type ? pr_type_name[type->type] : "???", - op->o.value->v.pointer.val); - case op_alias: - return operand_string (op->o.alias);//FIXME better output } return ("??"); } @@ -130,9 +132,9 @@ static void print_operand (operand_t *op) { switch (op->op_type) { - case op_symbol: + case op_def: printf ("(%s) ", pr_type_name[op->type]); - printf ("%s", op->o.symbol->name); + printf ("%s", op->o.def->name); break; case op_value: printf ("(%s) ", pr_type_name[op->type]); @@ -187,15 +189,6 @@ print_operand (operand_t *op) if (op->o.tempop.def) printf (" %s", op->o.tempop.def->name); break; - case op_pointer: - printf ("ptr (%s)[%d]", - pr_type_name[op->o.value->v.pointer.type->type], - op->o.value->v.pointer.val); - break; - case op_alias: - printf ("alias %s ", pr_type_name[op->type]); - print_operand (op->o.alias); - break; } } @@ -259,14 +252,6 @@ new_operand (op_type_e op) static void __attribute__((unused)) //FIXME free_operand (operand_t *op) { - if (op->next) { - //FIXME this should be an error, but due to the way operands are used, - //it can happen. - debug (0, "free_operand: double free"); - return; - } - if (op->op_type == op_alias) - free_operand (op->o.alias); FREE (operands, op); } @@ -304,16 +289,6 @@ temp_operand (type_t *type) return op; } -operand_t * -alias_operand (operand_t *op, etype_t type) -{ - operand_t *alias = new_operand (op_alias); - alias->type = type; - alias->size = pr_type_size[type]; - alias->o.alias = op; - return alias; -} - static operand_t * short_operand (short short_val) { @@ -433,7 +408,7 @@ statement_get_targetlist (statement_t *s) } else if (statement_is_goto (s)) { count = 1; } else if (statement_is_jumpb (s)) { - table = s->opa->o.alias->o.symbol->s.def; //FIXME check!!! + table = s->opa->o.def; count = table->type->t.array.size; } target_list = malloc ((count + 1) * sizeof (sblock_t *)); @@ -709,9 +684,11 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) e = deref->e.expr.e1; if (e->type == ex_uexpr && e->e.expr.op == '&' && e->e.expr.e1->type == ex_symbol) { - *op = new_operand (op_symbol); + if (e->e.expr.e1->e.symbol->sy_type != sy_var) + internal_error (e, "address of non-var"); + *op = new_operand (op_def); (*op)->type = low_level_type (type); - (*op)->o.symbol = e->e.expr.e1->e.symbol; + (*op)->o.def = e->e.expr.e1->e.symbol->s.def; } else if (e->type == ex_expr && e->e.expr.op == '&') { statement_t *s; operand_t *ptr = 0; @@ -746,9 +723,10 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) sblock_add_statement (sblock, s); } } else if (e->type == ex_value && e->e.value->type == ev_pointer) { - *op = new_operand (op_pointer); - (*op)->type = low_level_type (e->e.value->v.pointer.type); - (*op)->o.value = e->e.value; + ex_pointer_t *ptr = &e->e.value->v.pointer; + *op = new_operand (op_def); + (*op)->type = low_level_type (ptr->type); + (*op)->o.def = alias_def (ptr->def, ptr->type, ptr->val); } else { statement_t *s; operand_t *ptr = 0; @@ -813,12 +791,33 @@ static sblock_t * expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) { operand_t *aop = 0; + def_t *def; sblock = statement_subexpr (sblock, e->e.expr.e1, &aop); - while (aop->op_type == op_alias) - aop = aop->o.alias; - *op = new_operand (op_alias); - (*op)->type = low_level_type (e->e.expr.type); - (*op)->o.alias = aop; + if (aop->op_type == op_temp) { + while (aop->o.tempop.alias) { + aop = aop->o.tempop.alias; + if (aop->op_type != op_temp) + internal_error (e, "temp alias of non-temp var"); + } + *op = new_operand (op_temp); + (*op)->type = low_level_type (e->e.expr.type); + (*op)->o.tempop.alias = aop; + } else if (aop->op_type == op_def) { + def = aop->o.def; + while (def->alias) + def = def->alias; + *op = new_operand (op_def); + (*op)->type = low_level_type (e->e.expr.type); + (*op)->o.def = alias_def (def, ev_types[(*op)->type], 0); + } else if (aop->op_type == op_value && aop->o.value->type == ev_pointer) { + ex_pointer_t *ptr = &aop->o.value->v.pointer; + *op = new_operand (op_def); + (*op)->type = low_level_type (ptr->type); + (*op)->o.def = alias_def (ptr->def, ptr->type, ptr->val); + } else { + internal_error (e, "invalid alias target: %s: %s", + optype_str (aop->op_type), operand_string (aop)); + } return sblock; } @@ -901,9 +900,24 @@ expr_uexpr (sblock_t *sblock, expr_t *e, operand_t **op) static sblock_t * expr_symbol (sblock_t *sblock, expr_t *e, operand_t **op) { - *op = new_operand (op_symbol); - (*op)->type = low_level_type (e->e.symbol->type); - (*op)->o.symbol = e->e.symbol; + symbol_t *sym = e->e.symbol; + + if (sym->sy_type == sy_var) { + *op = new_operand (op_def); + (*op)->type = low_level_type (sym->type); + (*op)->o.def = sym->s.def; + } else if (sym->sy_type == sy_const) { + *op = new_operand (op_value); + (*op)->type = sym->s.value->type; + (*op)->o.value = sym->s.value; + } else if (sym->sy_type == sy_func) { + *op = new_operand (op_def); + (*op)->type = ev_func; + (*op)->o.def = sym->s.func->def; + } else { + internal_error (e, "unexpected symbol type: %s", + symtype_str(sym->sy_type)); + } return sblock; } @@ -1463,6 +1477,7 @@ check_final_block (sblock_t *sblock) { statement_t *s; symbol_t *return_symbol = 0; + def_t *return_def = 0; operand_t *return_operand = 0; const char *return_opcode = ""; @@ -1482,12 +1497,13 @@ check_final_block (sblock_t *sblock) if (options.traditional || options.code.progsversion == PROG_ID_VERSION) { return_symbol = make_symbol (".return", &type_param, pr.symtab->space, sc_extern); + return_def = return_symbol->s.def; return_opcode = ""; } if (return_symbol) { - return_operand = new_operand (op_symbol); + return_operand = new_operand (op_def); return_operand->type = ev_void; - return_operand->o.symbol = return_symbol; + return_operand->o.def = return_def; } s = new_statement (st_func, return_opcode, 0); s->opa = return_operand; @@ -1529,10 +1545,11 @@ count_temp (operand_t *op) { if (!op) return; - while (op->op_type == op_alias) - op = op->o.alias; - if (op->op_type == op_temp) + if (op->op_type == op_temp) { + while (op->o.tempop.alias) + op = op->o.tempop.alias; op->o.tempop.users++; + } } void