3, /* TYPE_VARIANT */
};
+MEM_VEC_FUNCTIONS(ir_value_vector, ir_value*, v)
+
/***********************************************************************
*IR Builder
*/
self->bops[0] = NULL;
self->bops[1] = NULL;
MEM_VECTOR_INIT(self, phi);
+ MEM_VECTOR_INIT(self, params);
self->eid = 0;
return self;
}
MEM_VEC_FUNCTIONS(ir_instr, ir_phi_entry_t, phi)
+MEM_VEC_FUNCTIONS(ir_instr, ir_value*, params)
void ir_instr_delete(ir_instr *self)
{
for (i = 0; i < self->phi_count; ++i) {
size_t idx;
if (ir_value_writes_find(self->phi[i].value, self, &idx))
- if (ir_value_writes_remove(self->phi[i].value, idx)) GMQCC_SUPRESS_EMPTY_BODY;
+ if (ir_value_writes_remove(self->phi[i].value, idx)) GMQCC_SUPPRESS_EMPTY_BODY;
if (ir_value_reads_find(self->phi[i].value, self, &idx))
- if (ir_value_reads_remove (self->phi[i].value, idx)) GMQCC_SUPRESS_EMPTY_BODY;
+ if (ir_value_reads_remove (self->phi[i].value, idx)) GMQCC_SUPPRESS_EMPTY_BODY;
}
MEM_VECTOR_CLEAR(self, phi);
- if (ir_instr_op(self, 0, NULL, false)) GMQCC_SUPRESS_EMPTY_BODY;
- if (ir_instr_op(self, 1, NULL, false)) GMQCC_SUPRESS_EMPTY_BODY;
- if (ir_instr_op(self, 2, NULL, false)) GMQCC_SUPRESS_EMPTY_BODY;
+ for (i = 0; i < self->params_count; ++i) {
+ size_t idx;
+ if (ir_value_writes_find(self->params[i], self, &idx))
+ if (ir_value_writes_remove(self->params[i], idx)) GMQCC_SUPPRESS_EMPTY_BODY;
+ if (ir_value_reads_find(self->params[i], self, &idx))
+ if (ir_value_reads_remove (self->params[i], idx)) GMQCC_SUPPRESS_EMPTY_BODY;
+ }
+ MEM_VECTOR_CLEAR(self, params);
+ if (ir_instr_op(self, 0, NULL, false)) GMQCC_SUPPRESS_EMPTY_BODY;
+ if (ir_instr_op(self, 1, NULL, false)) GMQCC_SUPPRESS_EMPTY_BODY;
+ if (ir_instr_op(self, 2, NULL, false)) GMQCC_SUPPRESS_EMPTY_BODY;
mem_d(self);
}
self = (ir_value*)mem_a(sizeof(*self));
self->vtype = vtype;
self->fieldtype = TYPE_VOID;
+ self->outtype = TYPE_VOID;
self->store = storetype;
MEM_VECTOR_INIT(self, reads);
MEM_VECTOR_INIT(self, writes);
return ir_instr_phi_add(self, pe);
}
+/* call related code */
+ir_instr* ir_block_create_call(ir_block *self, const char *label, ir_value *func, int ot)
+{
+ ir_value *out;
+ ir_instr *in;
+ in = ir_instr_new(self, INSTR_CALL0);
+ if (!in)
+ return NULL;
+ out = ir_value_out(self->owner, label, store_value, ot);
+ if (!out) {
+ ir_instr_delete(in);
+ return NULL;
+ }
+ if (!ir_instr_op(in, 0, out, true) ||
+ !ir_instr_op(in, 1, func, false) ||
+ !ir_block_instr_add(self, in))
+ {
+ ir_instr_delete(in);
+ ir_value_delete(out);
+ return NULL;
+ }
+ return in;
+}
+
+ir_value* ir_call_value(ir_instr *self)
+{
+ return self->_ops[0];
+}
+
+bool ir_call_param(ir_instr* self, ir_value *v)
+{
+ if (!ir_instr_params_add(self, v))
+ return false;
+ if (!ir_value_reads_add(v, self)) {
+ if (!ir_instr_params_remove(self, self->params_count-1))
+ GMQCC_SUPPRESS_EMPTY_BODY;
+ return false;
+ }
+ return true;
+}
+
/* binary op related code */
ir_value* ir_block_create_binop(ir_block *self,
}
if (instr->opcode >= INSTR_CALL0 && instr->opcode <= INSTR_CALL8) {
+ /* Trivial call translation:
+ * copy all params to OFS_PARM*
+ *
+ * NOTES on how to do it better without much trouble:
+ * -) The liferanges!
+ * Simply check the liferange of all parameters for
+ * other CALLs. For each param with no CALL in its
+ * liferange, we can store it in an OFS_PARM at
+ * generation already. This would even include later
+ * reuse.... probably... :)
+ */
printf("TODO: call instruction\n");
return false;
}