From 3f3b501c58b2de70ea69b92525e344e960775aa0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 5 Dec 2012 19:47:22 +0900 Subject: [PATCH] Move flowvar/deflabel from symbol_t to def_t. With the need to handle aliasing in the optimizer, it has become apparent that having the flow data attached to symbols is not nearly as useful as having it attached to defs (which are views of the actual variables). This also involves a bit of a cleanup of operand types: op_pointer and op_alias are gone (this seems to greatly simplify the optimizer) There is a bit of a problem with enums in switch statements, but this might actually be a sign that something is not quite right in the switch code (other than enums not being recognized as ints for jump table optimization). --- tools/qfcc/include/def.h | 2 + tools/qfcc/include/statements.h | 13 ++- tools/qfcc/include/symtab.h | 2 - tools/qfcc/source/dags.c | 82 ++++++------------ tools/qfcc/source/emit.c | 40 ++------- tools/qfcc/source/flow.c | 74 ++++++---------- tools/qfcc/source/statements.c | 147 ++++++++++++++++++-------------- 7 files changed, 149 insertions(+), 211 deletions(-) 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