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;
}
/* See which operands are read and write operands */
ir_op_read_write(instr->opcode, &read, &write);
- if (instr->opcode == INSTR_MUL_VF)
- {
- /* the float source will get an additional lifetime */
- tempbool = ir_value_life_merge(instr->_ops[2], instr->eid+1);
- *changed = *changed || tempbool;
- }
- else if (instr->opcode == INSTR_MUL_FV)
- {
- /* the float source will get an additional lifetime */
- tempbool = ir_value_life_merge(instr->_ops[1], instr->eid+1);
- *changed = *changed || tempbool;
- }
-
/* Go through the 3 main operands
* writes first, then reads
*/
}
}
+ if (instr->opcode == INSTR_MUL_VF)
+ {
+ value = instr->_ops[2];
+ /* the float source will get an additional lifetime */
+ if (ir_value_life_merge(value, instr->eid+1))
+ *changed = true;
+ if (value->memberof && ir_value_life_merge(value->memberof, instr->eid+1))
+ *changed = true;
+ }
+ else if (instr->opcode == INSTR_MUL_FV)
+ {
+ value = instr->_ops[1];
+ /* the float source will get an additional lifetime */
+ if (ir_value_life_merge(value, instr->eid+1))
+ *changed = true;
+ if (value->memberof && ir_value_life_merge(value->memberof, instr->eid+1))
+ *changed = true;
+ }
+
for (o = 0; o < 3; ++o)
{
if (!instr->_ops[o]) /* no such operand */
*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)
size_t stidx;
size_t i;
-tailcall:
block->generated = true;
block->code_start = vec_size(code_statements);
for (i = 0; i < vec_size(block->instr); ++i)
/* for uncoditional jumps, if the target hasn't been generated
* yet, we generate them right here.
*/
- if (!target->generated) {
- block = target;
- goto tailcall;
- }
+ if (!target->generated)
+ return gen_blocks_recursive(func, target);
/* otherwise we generate a jump instruction */
stmt.opcode = INSTR_GOTO;
code_push_statement(&stmt, instr->context.line);
}
if (!ontrue->generated) {
- if (onfalse->generated) {
- block = ontrue;
- goto tailcall;
- }
+ if (onfalse->generated)
+ return gen_blocks_recursive(func, ontrue);
}
if (!onfalse->generated) {
- if (ontrue->generated) {
- block = onfalse;
- goto tailcall;
- }
+ if (ontrue->generated)
+ return gen_blocks_recursive(func, onfalse);
}
/* neither ontrue nor onfalse exist */
stmt.opcode = INSTR_IFNOT;
code_pop_statement();
}
/* if not, generate now */
- block = onfalse;
- goto tailcall;
+ return gen_blocks_recursive(func, onfalse);
}
if ( (instr->opcode >= INSTR_CALL0 && instr->opcode <= INSTR_CALL8)
pushdef = true;
if (OPTS_OPTIMIZATION(OPTIM_STRIP_CONSTANT_NAMES) &&
+ !(global->flags & IR_FLAG_INCLUDE_DEF) &&
(global->name[0] == '#' || global->cvq == CV_CONST))
{
pushdef = false;
oprintf("endmodule %s\n", b->name);
}
+static const char *storenames[] = {
+ "[global]", "[local]", "[param]", "[value]", "[return]"
+};
+
void ir_function_dump(ir_function *f, char *ind,
int (*oprintf)(const char*, ...))
{
attr = "unique ";
else if (v->locked)
attr = "locked ";
- oprintf("%s\t%s: %s %s%s@%i ", ind, v->name, type_name[v->vtype],
+ oprintf("%s\t%s: %s %s %s%s@%i ", ind, v->name, type_name[v->vtype],
+ storenames[v->store],
attr, (v->callparam ? "callparam " : ""),
(int)v->code.local);
+ if (!v->life)
+ oprintf("[null]");
for (l = 0; l < vec_size(v->life); ++l) {
oprintf("[%i,%i] ", v->life[l].start, v->life[l].end);
}
ir_value *vm = v->members[m];
if (!vm)
continue;
- if (vm->unique_life && vm->locked)
- attr = "unique,locked ";
- else if (vm->unique_life)
- attr = "unique ";
- else if (vm->locked)
- attr = "locked ";
- oprintf("%s\t%s: %s@%i ", ind, vm->name, attr, (int)vm->code.local);
+ oprintf("%s\t%s: @%i ", ind, vm->name, (int)vm->code.local);
for (l = 0; l < vec_size(vm->life); ++l) {
oprintf("[%i,%i] ", vm->life[l].start, vm->life[l].end);
}
attr = "unique ";
else if (v->locked)
attr = "locked ";
- oprintf("%s\t%s: %s %s%s@%i ", ind, v->name, type_name[v->vtype],
+ oprintf("%s\t%s: %s %s %s%s@%i ", ind, v->name, type_name[v->vtype],
+ storenames[v->store],
attr, (v->callparam ? "callparam " : ""),
(int)v->code.local);
+ if (!v->life)
+ oprintf("[null]");
for (l = 0; l < vec_size(v->life); ++l) {
oprintf("[%i,%i] ", v->life[l].start, v->life[l].end);
}