X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;ds=sidebyside;f=ir.c;h=b977817fbee886279d1a8a4c7e16ee9d3aaa5a13;hb=18b27d5cf62b72716f7640af263935ab1fad9b03;hp=cab06582870363241c99c782266647a05db784d0;hpb=390ac0d871f65a169fe7d30d82fe7e69bf9c90d4;p=xonotic%2Fgmqcc.git diff --git a/ir.c b/ir.c index cab0658..b977817 100644 --- a/ir.c +++ b/ir.c @@ -171,6 +171,28 @@ uint16_t type_ne_instr[TYPE_COUNT] = { AINSTR_END, /* array */ }; +uint16_t type_not_instr[TYPE_COUNT] = { + INSTR_NOT_F, /* should use I when having integer support */ + INSTR_NOT_S, + INSTR_NOT_F, + INSTR_NOT_V, + INSTR_NOT_ENT, + INSTR_NOT_ENT, + INSTR_NOT_FNC, + INSTR_NOT_ENT, /* should use I */ +#if 0 + INSTR_NOT_I, /* integer type */ +#else + INSTR_NOT_F, +#endif + + INSTR_NOT_V, /* variant, should never be accessed */ + + AINSTR_END, /* struct */ + AINSTR_END, /* union */ + AINSTR_END, /* array */ +}; + static void irerror(lex_ctx ctx, const char *msg, ...) { va_list ap; @@ -262,6 +284,9 @@ ir_builder* ir_builder_new(const char *modulename) self->extparams = NULL; self->filenames = NULL; self->filestrings = NULL; + self->htglobals = util_htnew(IR_HT_SIZE); + self->htfields = util_htnew(IR_HT_SIZE); + self->htfunctions = util_htnew(IR_HT_SIZE); self->str_immediate = 0; self->name = NULL; @@ -276,6 +301,9 @@ ir_builder* ir_builder_new(const char *modulename) void ir_builder_delete(ir_builder* self) { size_t i; + util_htdel(self->htglobals); + util_htdel(self->htfields); + util_htdel(self->htfunctions); mem_d((void*)self->name); for (i = 0; i != vec_size(self->functions); ++i) { ir_function_delete_quick(self->functions[i]); @@ -308,12 +336,7 @@ bool ir_builder_set_name(ir_builder *self, const char *name) ir_function* ir_builder_get_function(ir_builder *self, const char *name) { - size_t i; - for (i = 0; i < vec_size(self->functions); ++i) { - if (!strcmp(name, self->functions[i]->name)) - return self->functions[i]; - } - return NULL; + return (ir_function*)util_htget(self->htfunctions, name); } ir_function* ir_builder_create_function(ir_builder *self, const char *name, int outtype) @@ -330,6 +353,7 @@ ir_function* ir_builder_create_function(ir_builder *self, const char *name, int return NULL; } vec_push(self->functions, fn); + util_htset(self->htfunctions, name, fn); fn->value = ir_builder_create_global(self, fn->name, TYPE_FUNCTION); if (!fn->value) { @@ -347,12 +371,7 @@ ir_function* ir_builder_create_function(ir_builder *self, const char *name, int ir_value* ir_builder_get_global(ir_builder *self, const char *name) { - size_t i; - for (i = 0; i < vec_size(self->globals); ++i) { - if (!strcmp(self->globals[i]->name, name)) - return self->globals[i]; - } - return NULL; + return (ir_value*)util_htget(self->htglobals, name); } ir_value* ir_builder_create_global(ir_builder *self, const char *name, int vtype) @@ -369,17 +388,13 @@ ir_value* ir_builder_create_global(ir_builder *self, const char *name, int vtype ve = ir_value_var(name, store_global, vtype); vec_push(self->globals, ve); + util_htset(self->htglobals, name, ve); return ve; } ir_value* ir_builder_get_field(ir_builder *self, const char *name) { - size_t i; - for (i = 0; i < vec_size(self->fields); ++i) { - if (!strcmp(self->fields[i]->name, name)) - return self->fields[i]; - } - return NULL; + return (ir_value*)util_htget(self->htfields, name); } @@ -393,6 +408,7 @@ ir_value* ir_builder_create_field(ir_builder *self, const char *name, int vtype) ve = ir_value_var(name, store_global, TYPE_FIELD); ve->fieldtype = vtype; vec_push(self->fields, ve); + util_htset(self->htfields, name, ve); return ve; } @@ -520,31 +536,15 @@ bool ir_function_finalize(ir_function *self) if (!ir_function_calculate_liferanges(self)) return false; - if (!ir_function_allocate_locals(self)) return false; return true; } -ir_value* ir_function_get_local(ir_function *self, const char *name) -{ - size_t i; - for (i = 0; i < vec_size(self->locals); ++i) { - if (!strcmp(self->locals[i]->name, name)) - return self->locals[i]; - } - return NULL; -} - ir_value* ir_function_create_local(ir_function *self, const char *name, int vtype, bool param) { ir_value *ve; - /* - if (ir_function_get_local(self, name)) - return NULL; - */ - if (param && vec_size(self->locals) && self->locals[vec_size(self->locals)-1]->store != store_param) { @@ -654,6 +654,8 @@ ir_instr* ir_instr_new(ir_block* owner, int op) self->params = NULL; self->eid = 0; + + self->likely = true; return self; } @@ -1768,6 +1770,7 @@ bool ir_function_naive_phi(ir_function *self) return true; } +#if 0 static bool ir_naive_phi_emit_store(ir_block *block, size_t iid, ir_value *old, ir_value *what) { ir_instr *instr; @@ -1785,10 +1788,11 @@ static bool ir_naive_phi_emit_store(ir_block *block, size_t iid, ir_value *old, return true; } +#endif static bool ir_block_naive_phi(ir_block *self) { - size_t i, p, w; + size_t i, p; /*, w;*/ /* FIXME: optionally, create_phi can add the phis * to a list so we don't need to loop through blocks * - anyway: "don't optimize YET" @@ -1812,7 +1816,8 @@ static bool ir_block_naive_phi(ir_block *self) vec_size(v->writes) == 1) { /* replace the value */ - ir_instr_op(v->writes[0], 0, instr->_ops[0], true); + if (!ir_instr_op(v->writes[0], 0, instr->_ops[0], true)) + return false; } else { @@ -2144,6 +2149,9 @@ static bool ir_block_living_add_instr(ir_block *self, size_t eid) static bool ir_block_life_prop_previous(ir_block* self, ir_block *prev, bool *changed) { size_t i; + + (void)changed; + /* values which have been read in a previous iteration are now * in the "living" array even if the previous block doesn't use them. * So we have to remove whatever does not exist in the previous block. @@ -2498,6 +2506,13 @@ tailcall: } /* neither ontrue nor onfalse exist */ stmt.opcode = INSTR_IFNOT; + if (!instr->likely) { + /* Honor the likelyhood hint */ + ir_block *tmp = onfalse; + stmt.opcode = INSTR_IF; + onfalse = ontrue; + ontrue = tmp; + } stidx = vec_size(code_statements); vec_push(code_statements, stmt); /* on false we jump, so add ontrue-path */ @@ -2509,6 +2524,16 @@ tailcall: if (onfalse->generated) { /* fixup the jump address */ code_statements[stidx].o2.s1 = (onfalse->code_start) - (stidx); + stmt.opcode = vec_last(code_statements).opcode; + if (stmt.opcode == INSTR_GOTO || + stmt.opcode == INSTR_IF || + stmt.opcode == INSTR_IFNOT || + stmt.opcode == INSTR_RETURN || + stmt.opcode == INSTR_DONE) + { + /* no use jumping from here */ + return true; + } /* may have been generated in the previous recursive call */ stmt.opcode = INSTR_GOTO; stmt.o1.s1 = (onfalse->code_start) - vec_size(code_statements); @@ -2557,20 +2582,20 @@ tailcall: stmt.o2.u1 = OFS_PARM0 + 3 * p; vec_push(code_statements, stmt); } - /* No whandle extparams */ + /* Now handle extparams */ first = vec_size(instr->params); for (; p < first; ++p) { ir_builder *ir = func->owner; ir_value *param = instr->params[p]; - ir_value *target; + ir_value *targetparam; if (p-8 >= vec_size(ir->extparams)) { irerror(instr->context, "Not enough extparam-globals have been created"); return false; } - target = ir->extparams[p-8]; + targetparam = ir->extparams[p-8]; stmt.opcode = INSTR_STORE_F; stmt.o3.u1 = 0; @@ -2580,7 +2605,7 @@ tailcall: else stmt.opcode = type_store_instr[param->vtype]; stmt.o1.u1 = ir_value_code_addr(param); - stmt.o2.u1 = ir_value_code_addr(target); + stmt.o2.u1 = ir_value_code_addr(targetparam); vec_push(code_statements, stmt); } @@ -2828,6 +2853,8 @@ static bool gen_global_function_code(ir_builder *ir, ir_value *global) prog_section_function *fundef; ir_function *irfun; + (void)ir; + irfun = global->constval.vfunc; if (!irfun) { irwarning(global->context, WARN_IMPLICIT_FUNCTION_POINTER, @@ -3002,8 +3029,10 @@ static bool ir_builder_gen_field(ir_builder *self, ir_value *field) prog_section_def def; prog_section_field fld; - def.type = field->vtype; - def.offset = vec_size(code_globals); + (void)self; + + def.type = (uint16_t)field->vtype; + def.offset = (uint16_t)vec_size(code_globals); /* create a global named the same as the field */ if (opts_standard == COMPILER_GMQCC) { @@ -3091,6 +3120,11 @@ bool ir_builder_generate(ir_builder *self, const char *filename) } } + if (vec_size(code_globals) >= 65536) { + irerror(vec_last(self->globals)->context, "This progs file would require more globals than the metadata can handle. Bailing out."); + return false; + } + /* DP errors if the last instruction is not an INSTR_DONE * and for debugging purposes we add an additional AINSTR_END * to the end of functions, so here it goes: @@ -3119,7 +3153,7 @@ bool ir_builder_generate(ir_builder *self, const char *filename) const char *qc_opname(int op) { if (op < 0) return ""; - if (op < ( sizeof(asm_instr) / sizeof(asm_instr[0]) )) + if (op < (int)( sizeof(asm_instr) / sizeof(asm_instr[0]) )) return asm_instr[op].m; switch (op) { case VINSTR_PHI: return "PHI"; @@ -3215,8 +3249,7 @@ void ir_block_dump(ir_block* b, char *ind, ind[strlen(ind)-1] = 0; } -void dump_phi(ir_instr *in, char *ind, - int (*oprintf)(const char*, ...)) +void dump_phi(ir_instr *in, int (*oprintf)(const char*, ...)) { size_t i; oprintf("%s <- phi ", in->_ops[0]->name); @@ -3237,7 +3270,7 @@ void ir_instr_dump(ir_instr *in, char *ind, oprintf("%s (%i) ", ind, (int)in->eid); if (in->opcode == VINSTR_PHI) { - dump_phi(in, ind, oprintf); + dump_phi(in, oprintf); return; } @@ -3286,6 +3319,26 @@ void ir_instr_dump(ir_instr *in, char *ind, ind[strlen(ind)-1] = 0; } +void ir_value_dump_string(const char *str, int (*oprintf)(const char*, ...)) +{ + oprintf("\""); + for (; *str; ++str) { + switch (*str) { + case '\n': oprintf("\\n"); break; + case '\r': oprintf("\\r"); break; + case '\t': oprintf("\\t"); break; + case '\v': oprintf("\\v"); break; + case '\f': oprintf("\\f"); break; + case '\b': oprintf("\\b"); break; + case '\a': oprintf("\\a"); break; + case '\\': oprintf("\\\\"); break; + case '"': oprintf("\\\""); break; + default: oprintf("%c", *str); break; + } + } + oprintf("\""); +} + void ir_value_dump(ir_value* v, int (*oprintf)(const char*, ...)) { if (v->isconst) { @@ -3310,7 +3363,7 @@ void ir_value_dump(ir_value* v, int (*oprintf)(const char*, ...)) oprintf("(entity)"); break; case TYPE_STRING: - oprintf("\"%s\"", v->constval.vstring); + ir_value_dump_string(v->constval.vstring, oprintf); break; #if 0 case TYPE_INTEGER: