X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=ir.cpp;h=0f7989f328e2f8501f4158e73751cd28742548b7;hp=f3a4dca13b0b089838ddae273223308e33cb5dc2;hb=2d4a054440e9fdf12edc202188ae4ea2e4ce90b5;hpb=95d232ca7285b49ce1bdccbe81c2c444c68e1c4d diff --git a/ir.cpp b/ir.cpp index f3a4dca..0f7989f 100644 --- a/ir.cpp +++ b/ir.cpp @@ -1474,6 +1474,7 @@ ir_instr* ir_block_create_call(ir_block *self, lex_ctx_t ctx, const char *label, !ir_instr_op(in, 1, func, false)) { delete in; + delete out; return nullptr; } self->m_instr.push_back(in); @@ -1643,7 +1644,7 @@ ir_value* ir_block_create_unary(ir_block *self, lex_ctx_t ctx, case VINSTR_NEG_F: return ir_block_create_general_instr(self, ctx, label, INSTR_SUB_F, nullptr, operand, ot); case VINSTR_NEG_V: - return ir_block_create_general_instr(self, ctx, label, INSTR_SUB_V, nullptr, operand, TYPE_VECTOR); + return ir_block_create_general_instr(self, ctx, label, INSTR_SUB_V, self->m_owner->m_owner->m_nil, operand, TYPE_VECTOR); default: ot = operand->m_vtype; @@ -1836,10 +1837,10 @@ void ir_function_enumerate(ir_function *self) * This is the counterpart to register-allocation in register machines. */ struct function_allocator { - ir_value **locals; - size_t *sizes; - size_t *positions; - bool *unique; + std::vector> locals; + std::vector sizes; + std::vector positions; + std::vector unique; }; static bool function_allocator_alloc(function_allocator *alloc, ir_value *var) @@ -1847,7 +1848,7 @@ static bool function_allocator_alloc(function_allocator *alloc, ir_value *var) ir_value *slot; size_t vsize = var->size(); - var->m_code.local = vec_size(alloc->locals); + var->m_code.local = alloc->locals.size(); slot = new ir_value("reg", store_global, var->m_vtype); if (!slot) @@ -1856,9 +1857,9 @@ static bool function_allocator_alloc(function_allocator *alloc, ir_value *var) if (!slot->mergeLife(var)) goto localerror; - vec_push(alloc->locals, slot); - vec_push(alloc->sizes, vsize); - vec_push(alloc->unique, var->m_unique_life); + alloc->locals.emplace_back(slot); + alloc->sizes.push_back(vsize); + alloc->unique.push_back(var->m_unique_life); return true; @@ -1870,23 +1871,22 @@ localerror: static bool ir_function_allocator_assign(ir_function *self, function_allocator *alloc, ir_value *v) { size_t a; - ir_value *slot; if (v->m_unique_life) return function_allocator_alloc(alloc, v); - for (a = 0; a < vec_size(alloc->locals); ++a) + for (a = 0; a < alloc->locals.size(); ++a) { /* if it's reserved for a unique liferange: skip */ if (alloc->unique[a]) continue; - slot = alloc->locals[a]; + ir_value *slot = alloc->locals[a].get(); /* never resize parameters * will be required later when overlapping temps + locals */ - if (a < vec_size(self->m_params) && + if (a < self->m_params.size() && alloc->sizes[a] < v->size()) { continue; @@ -1905,7 +1905,7 @@ static bool ir_function_allocator_assign(ir_function *self, function_allocator * v->m_code.local = a; return true; } - if (a >= vec_size(alloc->locals)) { + if (a >= alloc->locals.size()) { if (!function_allocator_alloc(alloc, v)) return false; } @@ -1914,7 +1914,6 @@ static bool ir_function_allocator_assign(ir_function *self, function_allocator * bool ir_function_allocate_locals(ir_function *self) { - bool retval = true; size_t pos; bool opt_gt = OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS); @@ -1923,15 +1922,6 @@ bool ir_function_allocate_locals(ir_function *self) if (self->m_locals.empty() && self->m_values.empty()) return true; - globalloc.locals = nullptr; - globalloc.sizes = nullptr; - globalloc.positions = nullptr; - globalloc.unique = nullptr; - lockalloc.locals = nullptr; - lockalloc.sizes = nullptr; - lockalloc.positions = nullptr; - lockalloc.unique = nullptr; - size_t i; for (i = 0; i < self->m_locals.size(); ++i) { @@ -1940,12 +1930,12 @@ bool ir_function_allocate_locals(ir_function *self) v->m_locked = true; v->m_unique_life = true; } - else if (i >= vec_size(self->m_params)) + else if (i >= self->m_params.size()) break; else v->m_locked = true; /* lock parameters locals */ if (!function_allocator_alloc((v->m_locked || !opt_gt ? &lockalloc : &globalloc), v)) - goto error; + return false; } for (; i < self->m_locals.size(); ++i) { @@ -1953,7 +1943,7 @@ bool ir_function_allocate_locals(ir_function *self) if (v->m_life.empty()) continue; if (!ir_function_allocator_assign(self, (v->m_locked || !opt_gt ? &lockalloc : &globalloc), v)) - goto error; + return false; } /* Allocate a slot for any value that still exists */ @@ -1979,7 +1969,7 @@ bool ir_function_allocate_locals(ir_function *self) ir_instr *call = v->m_reads[0]; if (!vec_ir_value_find(call->m_params, v, ¶m)) { irerror(call->m_context, "internal error: unlocked parameter %s not found", v->m_name.c_str()); - goto error; + return false; } ++opts_optimizationcount[OPTIM_CALL_STORES]; v->m_callparam = true; @@ -2013,33 +2003,33 @@ bool ir_function_allocate_locals(ir_function *self) } if (!ir_function_allocator_assign(self, (v->m_locked || !opt_gt ? &lockalloc : &globalloc), v)) - goto error; + return false; } - if (!lockalloc.sizes && !globalloc.sizes) { - goto cleanup; - } - vec_push(lockalloc.positions, 0); - vec_push(globalloc.positions, 0); + if (lockalloc.sizes.empty() && globalloc.sizes.empty()) + return true; + + lockalloc.positions.push_back(0); + globalloc.positions.push_back(0); /* Adjust slot positions based on sizes */ - if (lockalloc.sizes) { - pos = (vec_size(lockalloc.sizes) ? lockalloc.positions[0] : 0); - for (i = 1; i < vec_size(lockalloc.sizes); ++i) + if (!lockalloc.sizes.empty()) { + pos = (lockalloc.sizes.size() ? lockalloc.positions[0] : 0); + for (i = 1; i < lockalloc.sizes.size(); ++i) { pos = lockalloc.positions[i-1] + lockalloc.sizes[i-1]; - vec_push(lockalloc.positions, pos); + lockalloc.positions.push_back(pos); } - self->m_allocated_locals = pos + vec_last(lockalloc.sizes); + self->m_allocated_locals = pos + lockalloc.sizes.back(); } - if (globalloc.sizes) { - pos = (vec_size(globalloc.sizes) ? globalloc.positions[0] : 0); - for (i = 1; i < vec_size(globalloc.sizes); ++i) + if (!globalloc.sizes.empty()) { + pos = (globalloc.sizes.size() ? globalloc.positions[0] : 0); + for (i = 1; i < globalloc.sizes.size(); ++i) { pos = globalloc.positions[i-1] + globalloc.sizes[i-1]; - vec_push(globalloc.positions, pos); + globalloc.positions.push_back(pos); } - self->m_globaltemps = pos + vec_last(globalloc.sizes); + self->m_globaltemps = pos + globalloc.sizes.back(); } /* Locals need to know their new position */ @@ -2057,24 +2047,7 @@ bool ir_function_allocate_locals(ir_function *self) value->m_code.local = globalloc.positions[value->m_code.local]; } - goto cleanup; - -error: - retval = false; -cleanup: - for (i = 0; i < vec_size(lockalloc.locals); ++i) - delete lockalloc.locals[i]; - for (i = 0; i < vec_size(globalloc.locals); ++i) - delete globalloc.locals[i]; - vec_free(globalloc.unique); - vec_free(globalloc.locals); - vec_free(globalloc.sizes); - vec_free(globalloc.positions); - vec_free(lockalloc.unique); - vec_free(lockalloc.locals); - vec_free(lockalloc.sizes); - vec_free(lockalloc.positions); - return retval; + return true; } /* Get information about which operand @@ -2342,7 +2315,7 @@ static bool ir_block_life_propagate(ir_block *self, bool *changed) bool ir_function_calculate_liferanges(ir_function *self) { /* parameters live at 0 */ - for (size_t i = 0; i < vec_size(self->m_params); ++i) + for (size_t i = 0; i < self->m_params.size(); ++i) if (!self->m_locals[i].get()->setAlive(0)) compile_error(self->m_context, "internal error: failed value-life merging"); @@ -2542,7 +2515,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc stmt.opcode = INSTR_BITOR; stmt.o1.s1 = instr->_m_ops[1]->codeAddress(); stmt.o2.s1 = instr->_m_ops[2]->codeAddress(); - stmt.o3.s1 = instr->_m_ops[0]->codeAddress(); + stmt.o3.s1 = func->m_owner->m_vinstr_temp[1]->codeAddress(); code_push_statement(code, &stmt, instr->m_context); stmt.opcode = INSTR_BITAND; stmt.o1.s1 = instr->_m_ops[1]->codeAddress(); @@ -2550,7 +2523,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc stmt.o3.s1 = func->m_owner->m_vinstr_temp[0]->codeAddress(); code_push_statement(code, &stmt, instr->m_context); stmt.opcode = INSTR_SUB_F; - stmt.o1.s1 = instr->_m_ops[0]->codeAddress(); + stmt.o1.s1 = func->m_owner->m_vinstr_temp[1]->codeAddress(); stmt.o2.s1 = func->m_owner->m_vinstr_temp[0]->codeAddress(); stmt.o3.s1 = instr->_m_ops[0]->codeAddress(); code_push_statement(code, &stmt, instr->m_context); @@ -2602,7 +2575,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc stmt.opcode = INSTR_BITOR; stmt.o1.s1 = instr->_m_ops[1]->codeAddress() + j; stmt.o2.s1 = instr->_m_ops[2]->codeAddress() + j; - stmt.o3.s1 = instr->_m_ops[0]->codeAddress() + j; + stmt.o3.s1 = func->m_owner->m_vinstr_temp[1]->codeAddress() + j; code_push_statement(code, &stmt, instr->m_context); stmt.opcode = INSTR_BITAND; stmt.o1.s1 = instr->_m_ops[1]->codeAddress() + j; @@ -2611,7 +2584,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc code_push_statement(code, &stmt, instr->m_context); } stmt.opcode = INSTR_SUB_V; - stmt.o1.s1 = instr->_m_ops[0]->codeAddress(); + stmt.o1.s1 = func->m_owner->m_vinstr_temp[1]->codeAddress(); stmt.o2.s1 = func->m_owner->m_vinstr_temp[0]->codeAddress(); stmt.o3.s1 = instr->_m_ops[0]->codeAddress(); code_push_statement(code, &stmt, instr->m_context); @@ -2659,7 +2632,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc stmt.opcode = INSTR_BITOR; stmt.o1.s1 = instr->_m_ops[1]->codeAddress() + j; stmt.o2.s1 = instr->_m_ops[2]->codeAddress(); - stmt.o3.s1 = instr->_m_ops[0]->codeAddress() + j; + stmt.o3.s1 = func->m_owner->m_vinstr_temp[1]->codeAddress() + j; code_push_statement(code, &stmt, instr->m_context); stmt.opcode = INSTR_BITAND; stmt.o1.s1 = instr->_m_ops[1]->codeAddress() + j; @@ -2668,7 +2641,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc code_push_statement(code, &stmt, instr->m_context); } stmt.opcode = INSTR_SUB_V; - stmt.o1.s1 = instr->_m_ops[0]->codeAddress(); + stmt.o1.s1 = func->m_owner->m_vinstr_temp[1]->codeAddress(); stmt.o2.s1 = func->m_owner->m_vinstr_temp[0]->codeAddress(); stmt.o3.s1 = instr->_m_ops[0]->codeAddress(); code_push_statement(code, &stmt, instr->m_context); @@ -2682,7 +2655,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc for (j = 0; j < 3; ++j) { stmt.o1.s1 = instr->_m_ops[1]->codeAddress() + (j + 1) % 3; stmt.o2.s1 = instr->_m_ops[2]->codeAddress() + (j + 2) % 3; - stmt.o3.s1 = instr->_m_ops[0]->codeAddress() + j; + stmt.o3.s1 = func->m_owner->m_vinstr_temp[1]->codeAddress() + j; code_push_statement(code, &stmt, instr->m_context); stmt.o1.s1 = instr->_m_ops[1]->codeAddress() + (j + 2) % 3; stmt.o2.s1 = instr->_m_ops[2]->codeAddress() + (j + 1) % 3; @@ -2690,7 +2663,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc code_push_statement(code, &stmt, instr->m_context); } stmt.opcode = INSTR_SUB_V; - stmt.o1.s1 = instr->_m_ops[0]->codeAddress(); + stmt.o1.s1 = func->m_owner->m_vinstr_temp[1]->codeAddress(); stmt.o2.s1 = func->m_owner->m_vinstr_temp[0]->codeAddress(); stmt.o3.s1 = instr->_m_ops[0]->codeAddress(); code_push_statement(code, &stmt, instr->m_context); @@ -3030,7 +3003,7 @@ bool ir_builder::generateGlobalFunction(ir_value *global) fun.name = global->m_code.name; fun.file = filestring(global->m_context.file); fun.profile = 0; /* always 0 */ - fun.nargs = vec_size(irfun->m_params); + fun.nargs = irfun->m_params.size(); if (fun.nargs > 8) fun.nargs = 8; @@ -3095,7 +3068,7 @@ static bool gen_function_extparam_copy(code_t *code, ir_function *self) { ir_builder *ir = self->m_owner; - size_t numparams = vec_size(self->m_params); + size_t numparams = self->m_params.size(); if (!numparams) return true; @@ -3131,7 +3104,7 @@ static bool gen_function_varargs_copy(code_t *code, ir_function *self) ir_value *ep; prog_section_statement_t stmt; - numparams = vec_size(self->m_params); + numparams = self->m_params.size(); if (!numparams) return true; @@ -3267,7 +3240,7 @@ bool ir_builder::generateGlobalFunctionCode(ir_value *global) return true; } -static void gen_vector_defs(code_t *code, prog_section_def_t def, const char *name) +static void gen_vector_defs(code_t *code, prog_section_def_t def, const char *name, int type) { char *component; size_t len, i; @@ -3275,7 +3248,7 @@ static void gen_vector_defs(code_t *code, prog_section_def_t def, const char *na if (!name || name[0] == '#' || OPTS_FLAG(SINGLE_VECTOR_DEFS)) return; - def.type = TYPE_FLOAT; + def.type = type; len = strlen(name); @@ -3375,9 +3348,9 @@ bool ir_builder::generateGlobal(ir_value *global, bool islocal) def.offset = global->codeAddress(); m_code->defs.push_back(def); if (global->m_vtype == TYPE_VECTOR) - gen_vector_defs(m_code.get(), def, global->m_name.c_str()); + gen_vector_defs(m_code.get(), def, global->m_name.c_str(), TYPE_FLOAT); else if (global->m_vtype == TYPE_FIELD && global->m_fieldtype == TYPE_VECTOR) - gen_vector_defs(m_code.get(), def, global->m_name.c_str()); + gen_vector_defs(m_code.get(), def, global->m_name.c_str(), TYPE_FIELD); return true; } } @@ -3419,7 +3392,7 @@ bool ir_builder::generateGlobal(ir_value *global, bool islocal) if (pushdef) { m_code->defs.push_back(def); if (global->m_fieldtype == TYPE_VECTOR) - gen_vector_defs(m_code.get(), def, global->m_name.c_str()); + gen_vector_defs(m_code.get(), def, global->m_name.c_str(), TYPE_FIELD); } return gen_global_field(m_code.get(), global); case TYPE_ENTITY: @@ -3485,7 +3458,7 @@ bool ir_builder::generateGlobal(ir_value *global, bool islocal) if (pushdef) { m_code->defs.push_back(def); def.type &= ~DEF_SAVEGLOBAL; - gen_vector_defs(m_code.get(), def, global->m_name.c_str()); + gen_vector_defs(m_code.get(), def, global->m_name.c_str(), TYPE_FLOAT); } return global->m_code.globaladdr >= 0; } @@ -3588,7 +3561,7 @@ static bool ir_builder_gen_field(ir_builder *self, ir_value *field) } if (field->m_fieldtype == TYPE_VECTOR) { - gen_vector_defs (self->m_code.get(), def, field->m_name.c_str()); + gen_vector_defs (self->m_code.get(), def, field->m_name.c_str(), TYPE_FIELD); gen_vector_fields(self->m_code.get(), fld, field->m_name.c_str()); } @@ -4081,10 +4054,11 @@ void ir_value::dump(int (*oprintf)(const char*, ...)) const oprintf("fn:%s", m_name.c_str()); break; case TYPE_FLOAT: - oprintf("%g", m_constval.vfloat); + // %.9g is lossless for IEEE single precision. + oprintf("%.9g", m_constval.vfloat); break; case TYPE_VECTOR: - oprintf("'%g %g %g'", + oprintf("'%.9g %.9g %.9g'", m_constval.vvec.x, m_constval.vvec.y, m_constval.vvec.z);