X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=ir.c;h=f32f9d49492c2ae3efa4b58ec3d3df44e78a42f0;hb=ddfd44e2a40ed78310b893740f86cedf8771d7c9;hp=fbf07bc9552756642ea269677413920b0730a1f7;hpb=8270f37d3cc5e0c87685dd7284caf1f66481bb6b;p=xonotic%2Fgmqcc.git diff --git a/ir.c b/ir.c index fbf07bc..f32f9d4 100644 --- a/ir.c +++ b/ir.c @@ -59,6 +59,21 @@ uint16_t type_store_instr[TYPE_COUNT] = { INSTR_STORE_V, /* variant, should never be accessed */ }; +uint16_t type_storep_instr[TYPE_COUNT] = { + INSTR_STOREP_F, /* should use I when having integer support */ + INSTR_STOREP_S, + INSTR_STOREP_F, + INSTR_STOREP_V, + INSTR_STOREP_ENT, + INSTR_STOREP_FLD, + INSTR_STOREP_FNC, + INSTR_STOREP_ENT, /* should use I */ +#if 0 + INSTR_STOREP_ENT, /* integer type */ +#endif + INSTR_STOREP_V, /* variant, should never be accessed */ +}; + MEM_VEC_FUNCTIONS(ir_value_vector, ir_value*, v) /*********************************************************************** @@ -296,14 +311,21 @@ ir_value* ir_function_get_local(ir_function *self, const char *name) return NULL; } -ir_value* ir_function_create_local(ir_function *self, const char *name, int vtype) +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) { return NULL; } - ve = ir_value_var(name, store_local, vtype); + if (param && + self->locals_count && + self->locals[self->locals_count-1]->store != store_param) { + printf("cannot add parameters after adding locals\n"); + return NULL; + } + + ve = ir_value_var(name, (param ? store_param : store_local), vtype); if (!ir_function_locals_add(self, ve)) { ir_value_delete(ve); return NULL; @@ -830,46 +852,14 @@ bool ir_block_create_store(ir_block *self, ir_value *target, ir_value *what) else vtype = target->vtype; - switch (vtype) { - case TYPE_FLOAT: #if 0 - if (what->vtype == TYPE_INTEGER) - op = INSTR_CONV_ITOF; - else -#endif - op = INSTR_STORE_F; - break; - case TYPE_VECTOR: - op = INSTR_STORE_V; - break; - case TYPE_ENTITY: - op = INSTR_STORE_ENT; - break; - case TYPE_STRING: - op = INSTR_STORE_S; - break; - case TYPE_FIELD: - op = INSTR_STORE_FLD; - break; -#if 0 - case TYPE_INTEGER: - if (what->vtype == TYPE_INTEGER) - op = INSTR_CONV_FTOI; - else - op = INSTR_STORE_I; - break; + if (vtype == TYPE_FLOAT && what->vtype == TYPE_INTEGER) + op = INSTR_CONV_ITOF; + else if (vtype == TYPE_INTEGER && what->vtype == TYPE_FLOAT) + op = INSTR_CONV_FTOI; #endif - case TYPE_POINTER: -#if 0 - op = INSTR_STORE_I; -#else - op = INSTR_STORE_ENT; -#endif - break; - default: - /* Unknown type */ - return false; - } + op = type_store_instr[vtype]; + return ir_block_create_store_op(self, op, target, what); } @@ -886,38 +876,8 @@ bool ir_block_create_storep(ir_block *self, ir_value *target, ir_value *what) */ vtype = what->vtype; - switch (vtype) { - case TYPE_FLOAT: - op = INSTR_STOREP_F; - break; - case TYPE_VECTOR: - op = INSTR_STOREP_V; - break; - case TYPE_ENTITY: - op = INSTR_STOREP_ENT; - break; - case TYPE_STRING: - op = INSTR_STOREP_S; - break; - case TYPE_FIELD: - op = INSTR_STOREP_FLD; - break; -#if 0 - case TYPE_INTEGER: - op = INSTR_STOREP_I; - break; -#endif - case TYPE_POINTER: -#if 0 - op = INSTR_STOREP_I; -#else - op = INSTR_STOREP_ENT; -#endif - break; - default: - /* Unknown type */ - return false; - } + op = type_storep_instr[vtype]; + return ir_block_create_store_op(self, op, target, what); } @@ -1209,6 +1169,39 @@ ir_value* ir_block_create_binop(ir_block *self, return ir_block_create_general_instr(self, label, opcode, left, right, ot); } +ir_value* ir_block_create_unary(ir_block *self, + const char *label, int opcode, + ir_value *operand) +{ + int ot = TYPE_FLOAT; + switch (opcode) { + case INSTR_NOT_F: + case INSTR_NOT_V: + case INSTR_NOT_S: + case INSTR_NOT_ENT: + case INSTR_NOT_FNC: +#if 0 + case INSTR_NOT_I: +#endif + ot = TYPE_FLOAT; + break; + /* QC doesn't have other unary operations. We expect extensions to fill + * the above list, otherwise we assume out-type = in-type, eg for an + * unary minus + */ + default: + ot = operand->vtype; + break; + }; + if (ot == TYPE_VOID) { + /* The AST or parser were supposed to check this! */ + return NULL; + } + + /* let's use the general instruction creator and pass NULL for OPB */ + return ir_block_create_general_instr(self, label, opcode, operand, NULL, ot); +} + ir_value* ir_block_create_general_instr(ir_block *self, const char *label, int op, ir_value *a, ir_value *b, int outype) { @@ -1504,7 +1497,7 @@ static bool ir_block_naive_phi(ir_block *self) if (v->writes[w]->_ops[0] == v) v->writes[w]->_ops[0] = instr->_ops[0]; - if (old->store != store_value && old->store != store_local) + if (old->store != store_value && old->store != store_local && old->store != store_param) { /* If it originally wrote to a global we need to store the value * there as welli @@ -1884,8 +1877,11 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change value = instr->_ops[o]; /* We only care about locals */ + /* we also calculate parameter liferanges so that locals + * can take up parameter slots */ if (value->store != store_value && - value->store != store_local) + value->store != store_local && + value->store != store_param) continue; /* read operands */ @@ -2291,10 +2287,8 @@ tailcall: stmt.o1.u1 = stmt.o3.u1; stmt.o3.u1 = 0; } - else if ((stmt.opcode >= INSTR_STORE_F && - stmt.opcode <= INSTR_STORE_FNC) || - (stmt.opcode >= INSTR_NOT_F && - stmt.opcode <= INSTR_NOT_FNC)) + else if (stmt.opcode >= INSTR_STORE_F && + stmt.opcode <= INSTR_STORE_FNC) { /* 2-operand instructions with A -> B */ stmt.o2.u1 = stmt.o3.u1; @@ -2408,6 +2402,7 @@ static bool gen_global_function(ir_builder *ir, ir_value *global) static bool ir_builder_gen_global(ir_builder *self, ir_value *global) { + size_t i; int32_t *iptr; prog_section_def def; @@ -2487,8 +2482,8 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global) case TYPE_VARIANT: /* assume biggest type */ global->code.globaladdr = code_globals_add(0); - code_globals_add(0); - code_globals_add(0); + for (i = 1; i < type_sizeof[TYPE_VARIANT]; ++i) + code_globals_add(0); return true; default: /* refuse to create 'void' type or any other fancy business. */ @@ -2558,6 +2553,10 @@ void ir_function_dump(ir_function *f, char *ind, int (*oprintf)(const char*, ...)) { size_t i; + if (f->builtin != 0) { + oprintf("%sfunction %s = builtin %i\n", ind, f->name, -f->builtin); + return; + } oprintf("%sfunction %s\n", ind, f->name); strncat(ind, "\t", IND_BUFSZ); if (f->locals_count)