self->nil = ir_value_var("nil", store_value, TYPE_NIL);
self->nil->cvq = CV_CONST;
+ self->reserved_va_count = NULL;
+
return self;
}
return ve;
}
+ir_value* ir_builder_get_va_count(ir_builder *self)
+{
+ if (self->reserved_va_count)
+ return self->reserved_va_count;
+ return (self->reserved_va_count = ir_builder_create_global(self, "reserved:va_count", TYPE_FLOAT));
+}
+
ir_value* ir_builder_get_field(ir_builder *self, const char *name)
{
return (ir_value*)util_htget(self->htfields, name);
self->values = NULL;
self->locals = NULL;
+ self->max_varargs = NULL;
+
self->code_function_def = -1;
self->allocated_locals = 0;
self->globaltemps = 0;
self->fieldtype = TYPE_VOID;
self->outtype = TYPE_VOID;
self->store = storetype;
+ self->flags = 0;
self->reads = NULL;
self->writes = NULL;
/* each block now gets an additional "entry" instruction id
* we can use to avoid point-life issues
*/
+ self->blocks[i]->entry_id = instruction_id;
++instruction_id;
self->blocks[i]->eid = i;
for (i = 0; i < vec_size(self->locals); ++i)
{
v = self->locals[i];
- if (!OPTS_OPTIMIZATION(OPTIM_LOCAL_TEMPS)) {
+ if ((self->flags & IR_FLAG_MASK_NO_LOCAL_TEMPS) || !OPTS_OPTIMIZATION(OPTIM_LOCAL_TEMPS)) {
v->locked = true;
v->unique_life = true;
}
*changed = *changed || tempbool;
}
/* the "entry" instruction ID */
- tempbool = ir_block_living_add_instr(self, instr->eid-1);
+ tempbool = ir_block_living_add_instr(self, self->entry_id);
*changed = *changed || tempbool;
if (self->run_id == self->owner->run_id)
return true;
}
+static bool gen_function_varargs_copy(ir_function *self)
+{
+ size_t i, ext, numparams, maxparams;
+
+ ir_builder *ir = self->owner;
+ ir_value *ep;
+ prog_section_statement stmt;
+
+ numparams = vec_size(self->params);
+ if (!numparams)
+ return true;
+
+ stmt.opcode = INSTR_STORE_V;
+ stmt.o3.s1 = 0;
+ maxparams = numparams + self->max_varargs;
+ for (i = numparams; i < maxparams; ++i) {
+ if (i <= 8) {
+ stmt.o1.u1 = OFS_PARM0 + 3*i;
+ stmt.o2.u1 = ir_value_code_addr(self->locals[i]);
+ code_push_statement(&stmt, self->context.line);
+ continue;
+ }
+ ext = i - 8;
+ if (ext >= vec_size(ir->extparams))
+ ir_gen_extparam(ir);
+
+ ep = ir->extparams[ext];
+
+ stmt.o1.u1 = ir_value_code_addr(ep);
+ stmt.o2.u1 = ir_value_code_addr(self->locals[i]);
+ code_push_statement(&stmt, self->context.line);
+ }
+
+ return true;
+}
+
static bool gen_function_locals(ir_builder *ir, ir_value *global)
{
prog_section_function *def;
irerror(irfun->context, "Failed to generate extparam-copy code for function %s", irfun->name);
return false;
}
+ if (irfun->max_varargs && !gen_function_varargs_copy(irfun)) {
+ irerror(irfun->context, "Failed to generate vararg-copy code for function %s", irfun->name);
+ return false;
+ }
if (!gen_function_code(irfun)) {
irerror(irfun->context, "Failed to generate code for function %s", irfun->name);
return false;
pushdef = true;
if (OPTS_OPTIMIZATION(OPTIM_STRIP_CONSTANT_NAMES) &&
+ !(global->flags & IR_FLAG_INCLUDE_DEF) &&
(global->name[0] == '#' || global->cvq == CV_CONST))
{
pushdef = false;