X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=ir.c;h=7af697961edc9902d79b1d95243244e6111fee7d;hb=74cb075665a8e389cd4a5492bef158bb2f59de85;hp=0dc785a0d4b565d6008df65e2ac13b9f75ddcc3f;hpb=5d884bcb456d0a4727ef590b25aa9bbffd55dfd3;p=xonotic%2Fgmqcc.git diff --git a/ir.c b/ir.c index 0dc785a..7af6979 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) @@ -166,6 +166,8 @@ ir_builder* ir_builder_new(const char *modulename) MEM_VECTOR_INIT(self, functions); MEM_VECTOR_INIT(self, globals); MEM_VECTOR_INIT(self, fields); + MEM_VECTOR_INIT(self, filenames); + MEM_VECTOR_INIT(self, filestrings); self->name = NULL; if (!ir_builder_set_name(self, modulename)) { mem_d(self); @@ -175,9 +177,11 @@ ir_builder* ir_builder_new(const char *modulename) return self; } -MEM_VEC_FUNCTIONS(ir_builder, ir_value*, globals) -MEM_VEC_FUNCTIONS(ir_builder, ir_value*, fields) +MEM_VEC_FUNCTIONS(ir_builder, ir_value*, globals) +MEM_VEC_FUNCTIONS(ir_builder, ir_value*, fields) MEM_VEC_FUNCTIONS(ir_builder, ir_function*, functions) +MEM_VEC_FUNCTIONS(ir_builder, const char*, filenames) +MEM_VEC_FUNCTIONS(ir_builder, qcint, filestrings) void ir_builder_delete(ir_builder* self) { @@ -195,6 +199,8 @@ void ir_builder_delete(ir_builder* self) ir_value_delete(self->fields[i]); } MEM_VECTOR_CLEAR(self, fields); + MEM_VECTOR_CLEAR(self, filenames); + MEM_VECTOR_CLEAR(self, filestrings); mem_d(self); } @@ -426,10 +432,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 +468,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 +497,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 +636,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 +733,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 +930,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; @@ -2109,6 +2122,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) { @@ -2216,7 +2242,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) { @@ -2529,6 +2555,27 @@ static bool gen_function_code(ir_function *self) return true; } +static qcint ir_builder_filestring(ir_builder *ir, const char *filename) +{ + /* NOTE: filename pointers are copied, we never strdup them, + * thus we can use pointer-comparison to find the string. + */ + size_t i; + qcint str; + + for (i = 0; i < ir->filenames_count; ++i) { + if (ir->filenames[i] == filename) + return ir->filestrings[i]; + } + + str = code_genstring(filename); + if (!ir_builder_filenames_add(ir, filename)) + return 0; + if (!ir_builder_filestrings_add(ir, str)) + ir->filenames_count--; + return str; +} + static bool gen_global_function(ir_builder *ir, ir_value *global) { prog_section_function fun; @@ -2546,7 +2593,7 @@ static bool gen_global_function(ir_builder *ir, ir_value *global) irfun = global->constval.vfunc; fun.name = global->code.name; - fun.file = code_cachedstring(global->context.file); + fun.file = ir_builder_filestring(ir, global->context.file); fun.profile = 0; /* always 0 */ fun.nargs = irfun->params_count; @@ -2558,11 +2605,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; } @@ -2583,6 +2629,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 { @@ -2623,7 +2671,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; @@ -2651,8 +2699,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; @@ -2669,33 +2718,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 + ir_value_code_setaddr(global, code_globals_add(code_genstring(global->constval.vstring))); + 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])); @@ -2715,20 +2766,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)); @@ -2820,7 +2881,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; } } @@ -2926,7 +2987,7 @@ void ir_function_dump(ir_function *f, char *ind, for (i = 0; i < f->locals_count; ++i) { size_t l; ir_value *v = f->locals[i]; - oprintf("%s\t%s: ", ind, v->name); + 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); } @@ -2935,7 +2996,7 @@ void ir_function_dump(ir_function *f, char *ind, 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->life_count); + 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); } @@ -3080,10 +3141,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);