X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;ds=sidebyside;f=ir.c;h=1f9a80db3d213436fce94ad993f45dd46d1ab31b;hb=04dca17cffcf250a6f561b8624fe053b96e37f86;hp=74cb1cb7cf90c51eeb479133756c31c1b5541fb1;hpb=f6e5396f9f160d93f4eb92ff9f206e64b6b0c001;p=xonotic%2Fgmqcc.git diff --git a/ir.c b/ir.c index 74cb1cb..1f9a80d 100644 --- a/ir.c +++ b/ir.c @@ -138,7 +138,7 @@ static bool irwarning(lex_ctx ctx, int warntype, const char *fmt, ...) va_list ap; int lvl = LVL_WARNING; - if (!OPTS_WARN(warntype)) + if (warntype && !OPTS_WARN(warntype)) return false; if (opts_werror) @@ -426,10 +426,12 @@ ir_value* ir_function_get_local(ir_function *self, const char *name) ir_value* ir_function_create_local(ir_function *self, const char *name, int vtype, bool param) { - ir_value *ve = ir_function_get_local(self, name); - if (ve) { + ir_value *ve; + + /* + if (ir_function_get_local(self, name)) return NULL; - } + */ if (param && self->locals_count && @@ -460,7 +462,7 @@ ir_block* ir_block_new(ir_function* owner, const char *name) memset(self, 0, sizeof(*self)); self->label = NULL; - if (!ir_block_set_label(self, name)) { + if (name && !ir_block_set_label(self, name)) { mem_d(self); return NULL; } @@ -489,7 +491,7 @@ MEM_VEC_FUNCTIONS_ALL(ir_block, ir_value*, living) void ir_block_delete(ir_block* self) { size_t i; - mem_d(self->label); + if (self->label) mem_d(self->label); for (i = 0; i != self->instr_count; ++i) ir_instr_delete(self->instr[i]); MEM_VECTOR_CLEAR(self, instr); @@ -628,7 +630,11 @@ ir_value* ir_value_var(const char *name, int storetype, int vtype) self->context.file = "<@no context>"; self->context.line = 0; self->name = NULL; - ir_value_set_name(self, name); + if (name && !ir_value_set_name(self, name)) { + irerror(self->context, "out of memory"); + mem_d(self); + return NULL; + } memset(&self->constval, 0, sizeof(self->constval)); memset(&self->code, 0, sizeof(self->code)); @@ -721,11 +727,12 @@ void ir_value_delete(ir_value* self) mem_d(self); } -void ir_value_set_name(ir_value *self, const char *name) +bool ir_value_set_name(ir_value *self, const char *name) { if (self->name) mem_d((void*)self->name); self->name = util_strdup(name); + return !!self->name; } bool ir_value_set_float(ir_value *self, float f) @@ -917,14 +924,14 @@ bool ir_value_life_merge_into(ir_value *self, const ir_value *other) } if (life->start < entry->start && - life->end >= entry->start) + life->end+1 >= entry->start) { /* starts earlier and overlaps */ entry->start = life->start; } - if (life->end > entry->end && - life->start-1 <= entry->end) + if (life->end > entry->end && + life->start <= entry->end+1) { /* ends later and overlaps */ entry->end = life->end; @@ -1812,6 +1819,7 @@ bool ir_function_calculate_liferanges(ir_function *self) { if (self->blocks[i]->is_return) { + self->blocks[i]->living_count = 0; if (!ir_block_life_propagate(self->blocks[i], NULL, &changed)) return false; } @@ -2108,6 +2116,19 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change /* See which operands are read and write operands */ ir_op_read_write(instr->opcode, &read, &write); + if (instr->opcode == INSTR_MUL_VF) + { + /* the float source will get an additional lifetime */ + tempbool = ir_value_life_merge(instr->_ops[2], instr->eid+1); + *changed = *changed || tempbool; + } + else if (instr->opcode == INSTR_MUL_FV) + { + /* the float source will get an additional lifetime */ + tempbool = ir_value_life_merge(instr->_ops[1], instr->eid+1); + *changed = *changed || tempbool; + } + /* Go through the 3 main operands */ for (o = 0; o < 3; ++o) { @@ -2215,7 +2236,7 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change * * Breaking conventions is annoying... */ -static bool ir_builder_gen_global(ir_builder *self, ir_value *global); +static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool islocal); static bool gen_global_field(ir_value *global) { @@ -2557,11 +2578,10 @@ static bool gen_global_function(ir_builder *ir, ir_value *global) } fun.firstlocal = code_globals_elements; - fun.locals = irfun->allocated_locals + irfun->locals_count; local_var_end = fun.firstlocal; for (i = 0; i < irfun->locals_count; ++i) { - if (!ir_builder_gen_global(ir, irfun->locals[i])) { + if (!ir_builder_gen_global(ir, irfun->locals[i], true)) { irerror(irfun->locals[i]->context, "Failed to generate local %s", irfun->locals[i]->name); return false; } @@ -2582,6 +2602,8 @@ static bool gen_global_function(ir_builder *ir, ir_value *global) code_globals_add(0); } + fun.locals = code_globals_elements - fun.firstlocal; + if (irfun->builtin) fun.entry = irfun->builtin; else { @@ -2622,7 +2644,7 @@ static bool gen_global_function_code(ir_builder *ir, ir_value *global) return true; } -static bool ir_builder_gen_global(ir_builder *self, ir_value *global) +static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool islocal) { size_t i; int32_t *iptr; @@ -2650,8 +2672,9 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global) /* I'd argue setting it to 0 is sufficient, but maybe some depend on knowing how far * the system fields actually go? Though the engine knows this anyway... * Maybe this could be an -foption + * fteqcc creates data for end_sys_* - of size 1, so let's do the same */ - ir_value_code_setaddr(global, def.offset); + ir_value_code_setaddr(global, code_globals_add(0)); /* Add the def */ if (code_defs_add(def) < 0) return false; @@ -2668,33 +2691,35 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global) /* fall through */ case TYPE_FLOAT: { - if (code_defs_add(def) < 0) - return false; - if (global->isconst) { iptr = (int32_t*)&global->constval.vfloat; ir_value_code_setaddr(global, code_globals_add(*iptr)); - } else + } else { ir_value_code_setaddr(global, code_globals_add(0)); + if (!islocal) + def.type |= DEF_SAVEGLOBAL; + } + if (code_defs_add(def) < 0) + return false; return global->code.globaladdr >= 0; } case TYPE_STRING: { - if (code_defs_add(def) < 0) - return false; if (global->isconst) ir_value_code_setaddr(global, code_globals_add(code_cachedstring(global->constval.vstring))); - else + else { ir_value_code_setaddr(global, code_globals_add(0)); + if (!islocal) + def.type |= DEF_SAVEGLOBAL; + } + if (code_defs_add(def) < 0) + return false; return global->code.globaladdr >= 0; } case TYPE_VECTOR: { size_t d; - if (code_defs_add(def) < 0) - return false; - if (global->isconst) { iptr = (int32_t*)&global->constval.vvec; ir_value_code_setaddr(global, code_globals_add(iptr[0])); @@ -2714,20 +2739,30 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global) if (code_globals_add(0) < 0) return false; } + if (!islocal) + def.type |= DEF_SAVEGLOBAL; } + + if (code_defs_add(def) < 0) + return false; return global->code.globaladdr >= 0; } case TYPE_FUNCTION: - if (code_defs_add(def) < 0) - return false; if (!global->isconst) { ir_value_code_setaddr(global, code_globals_add(0)); - return global->code.globaladdr >= 0; + if (global->code.globaladdr < 0) + return false; } else { ir_value_code_setaddr(global, code_globals_elements); code_globals_add(code_functions_elements); - return gen_global_function(self, global); + if (!gen_global_function(self, global)) + return false; + if (!islocal) + def.type |= DEF_SAVEGLOBAL; } + if (code_defs_add(def) < 0) + return false; + return true; case TYPE_VARIANT: /* assume biggest type */ ir_value_code_setaddr(global, code_globals_add(0)); @@ -2819,7 +2854,7 @@ bool ir_builder_generate(ir_builder *self, const char *filename) for (i = 0; i < self->globals_count; ++i) { - if (!ir_builder_gen_global(self, self->globals[i])) { + if (!ir_builder_gen_global(self, self->globals[i], false)) { return false; } } @@ -2921,6 +2956,25 @@ void ir_function_dump(ir_function *f, char *ind, oprintf("\n"); } } + oprintf("%sliferanges:\n", ind); + for (i = 0; i < f->locals_count; ++i) { + size_t l; + ir_value *v = f->locals[i]; + oprintf("%s\t%s: unique ", ind, v->name); + for (l = 0; l < v->life_count; ++l) { + oprintf("[%i,%i] ", v->life[l].start, v->life[l].end); + } + oprintf("\n"); + } + for (i = 0; i < f->values_count; ++i) { + size_t l; + ir_value *v = f->values[i]; + oprintf("%s\t%s: @%i ", ind, v->name, (int)v->code.local); + for (l = 0; l < v->life_count; ++l) { + oprintf("[%i,%i] ", v->life[l].start, v->life[l].end); + } + oprintf("\n"); + } if (f->blocks_count) { oprintf("%slife passes (check): %i\n", ind, (int)f->run_id); @@ -3009,6 +3063,12 @@ void ir_instr_dump(ir_instr *in, char *ind, } if (in->bops[1]) oprintf("%s[%s]", comma, in->bops[1]->label); + if (in->params_count) { + oprintf("\tparams: "); + for (i = 0; i != in->params_count; ++i) { + oprintf("%s, ", in->params[i]->name); + } + } oprintf("\n"); ind[strlen(ind)-1] = 0; } @@ -3022,7 +3082,7 @@ void ir_value_dump(ir_value* v, int (*oprintf)(const char*, ...)) oprintf("(void)"); break; case TYPE_FUNCTION: - oprintf("(function)"); + oprintf("fn:%s", v->name); break; case TYPE_FLOAT: oprintf("%g", v->constval.vfloat); @@ -3054,10 +3114,10 @@ void ir_value_dump(ir_value* v, int (*oprintf)(const char*, ...)) } } -void ir_value_dump_life(ir_value *self, int (*oprintf)(const char*,...)) +void ir_value_dump_life(const ir_value *self, int (*oprintf)(const char*,...)) { size_t i; - oprintf("Life of %s:\n", self->name); + oprintf("Life of %12s:", self->name); for (i = 0; i < self->life_count; ++i) { oprintf(" + [%i, %i]\n", self->life[i].start, self->life[i].end);