!ir_instr_op(in, 1, func, false))
{
delete in;
+ delete out;
return nullptr;
}
self->m_instr.push_back(in);
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;
* 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<std::unique_ptr<ir_value>> locals;
+ std::vector<size_t> sizes;
+ std::vector<size_t> positions;
+ std::vector<bool> unique;
};
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)
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;
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;
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;
}
bool ir_function_allocate_locals(ir_function *self)
{
- bool retval = true;
size_t pos;
bool opt_gt = OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS);
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)
{
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)
{
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 */
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;
}
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 */
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
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");
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();
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);
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;
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);
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;
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);
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;
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);
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;
{
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;
ir_value *ep;
prog_section_statement_t stmt;
- numparams = vec_size(self->m_params);
+ numparams = self->m_params.size();
if (!numparams)
return true;
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;
if (!name || name[0] == '#' || OPTS_FLAG(SINGLE_VECTOR_DEFS))
return;
- def.type = TYPE_FLOAT;
+ def.type = type;
len = strlen(name);
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;
}
}
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:
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;
}
}
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());
}
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);