3, /* TYPE_VARIANT */
};
+uint16_t type_store_instr[TYPE_COUNT] = {
+ INSTR_STORE_F, /* should use I when having integer support */
+ INSTR_STORE_S,
+ INSTR_STORE_F,
+ INSTR_STORE_V,
+ INSTR_STORE_ENT,
+ INSTR_STORE_FLD,
+ INSTR_STORE_FNC,
+ INSTR_STORE_ENT, /* should use I */
+#if 0
+ INSTR_STORE_ENT, /* integer type */
+#endif
+ INSTR_STORE_V, /* variant, should never be accessed */
+};
+
+uint16_t type_storep_instr[TYPE_COUNT] = {
+ INSTR_STOREP_F, /* should use I when having integer support */
+ INSTR_STOREP_S,
+ INSTR_STOREP_F,
+ INSTR_STOREP_V,
+ INSTR_STOREP_ENT,
+ INSTR_STOREP_FLD,
+ INSTR_STOREP_FNC,
+ INSTR_STOREP_ENT, /* should use I */
+#if 0
+ INSTR_STOREP_ENT, /* integer type */
+#endif
+ INSTR_STOREP_V, /* variant, should never be accessed */
+};
+
MEM_VEC_FUNCTIONS(ir_value_vector, ir_value*, v)
/***********************************************************************
self->context.line = 0;
self->outtype = outtype;
self->value = NULL;
+ self->builtin = 0;
MEM_VECTOR_INIT(self, params);
MEM_VECTOR_INIT(self, blocks);
MEM_VECTOR_INIT(self, values);
MEM_VEC_FUNCTIONS(ir_function, ir_value*, values)
MEM_VEC_FUNCTIONS(ir_function, ir_block*, blocks)
MEM_VEC_FUNCTIONS(ir_function, ir_value*, locals)
+MEM_VEC_FUNCTIONS(ir_function, int, params)
bool ir_function_set_name(ir_function *self, const char *name)
{
bool ir_function_finalize(ir_function *self)
{
+ if (self->builtin)
+ return true;
+
if (!ir_function_naive_phi(self))
return false;
return NULL;
}
-ir_value* ir_function_create_local(ir_function *self, const char *name, int vtype)
+ir_value* ir_function_create_local(ir_function *self, const char *name, int vtype, bool param)
{
ir_value *ve = ir_function_get_local(self, name);
if (ve) {
return NULL;
}
- ve = ir_value_var(name, store_local, vtype);
+ if (param &&
+ self->locals_count &&
+ self->locals[self->locals_count-1]->store != store_param) {
+ printf("cannot add parameters after adding locals\n");
+ return NULL;
+ }
+
+ ve = ir_value_var(name, (param ? store_param : store_local), vtype);
if (!ir_function_locals_add(self, ve)) {
ir_value_delete(ve);
return NULL;
return true;
}
+bool ir_value_set_func(ir_value *self, int f)
+{
+ if (self->vtype != TYPE_FUNCTION)
+ return false;
+ self->constval.vint = f;
+ self->isconst = true;
+ return true;
+}
+
bool ir_value_set_vector(ir_value *self, vector v)
{
if (self->vtype != TYPE_VECTOR)
else
vtype = target->vtype;
- switch (vtype) {
- case TYPE_FLOAT:
#if 0
- if (what->vtype == TYPE_INTEGER)
- op = INSTR_CONV_ITOF;
- else
+ if (vtype == TYPE_FLOAT && what->vtype == TYPE_INTEGER)
+ op = INSTR_CONV_ITOF;
+ else if (vtype == TYPE_INTEGER && what->vtype == TYPE_FLOAT)
+ op = INSTR_CONV_FTOI;
#endif
- op = INSTR_STORE_F;
- break;
- case TYPE_VECTOR:
- op = INSTR_STORE_V;
- break;
- case TYPE_ENTITY:
- op = INSTR_STORE_ENT;
- break;
- case TYPE_STRING:
- op = INSTR_STORE_S;
- break;
- case TYPE_FIELD:
- op = INSTR_STORE_FLD;
- break;
-#if 0
- case TYPE_INTEGER:
- if (what->vtype == TYPE_INTEGER)
- op = INSTR_CONV_FTOI;
- else
- op = INSTR_STORE_I;
- break;
-#endif
- case TYPE_POINTER:
-#if 0
- op = INSTR_STORE_I;
-#else
- op = INSTR_STORE_ENT;
-#endif
- break;
- default:
- /* Unknown type */
- return false;
- }
+ op = type_store_instr[vtype];
+
return ir_block_create_store_op(self, op, target, what);
}
*/
vtype = what->vtype;
- switch (vtype) {
- case TYPE_FLOAT:
- op = INSTR_STOREP_F;
- break;
- case TYPE_VECTOR:
- op = INSTR_STOREP_V;
- break;
- case TYPE_ENTITY:
- op = INSTR_STOREP_ENT;
- break;
- case TYPE_STRING:
- op = INSTR_STOREP_S;
- break;
- case TYPE_FIELD:
- op = INSTR_STOREP_FLD;
- break;
-#if 0
- case TYPE_INTEGER:
- op = INSTR_STOREP_I;
- break;
-#endif
- case TYPE_POINTER:
-#if 0
- op = INSTR_STOREP_I;
-#else
- op = INSTR_STOREP_ENT;
-#endif
- break;
- default:
- /* Unknown type */
- return false;
- }
+ op = type_storep_instr[vtype];
+
return ir_block_create_store_op(self, op, target, what);
}
if (v->writes[w]->_ops[0] == v)
v->writes[w]->_ops[0] = instr->_ops[0];
- if (old->store != store_value && old->store != store_local)
+ if (old->store != store_value && old->store != store_local && old->store != store_param)
{
/* If it originally wrote to a global we need to store the value
* there as welli
function_allocator alloc;
+ if (!self->locals_count)
+ return true;
+
MEM_VECTOR_INIT(&alloc, locals);
MEM_VECTOR_INIT(&alloc, sizes);
MEM_VECTOR_INIT(&alloc, positions);
value = instr->_ops[o];
/* We only care about locals */
+ /* we also calculate parameter liferanges so that locals
+ * can take up parameter slots */
if (value->store != store_value &&
- value->store != store_local)
+ value->store != store_local &&
+ value->store != store_param)
continue;
/* read operands */
* generation already. This would even include later
* reuse.... probably... :)
*/
- printf("TODO: call instruction\n");
- return false;
+ size_t p;
+ ir_value *retvalue;
+
+ for (p = 0; p < instr->params_count; ++p)
+ {
+ ir_value *param = instr->params[p];
+
+ stmt.opcode = INSTR_STORE_F;
+ stmt.o3.u1 = 0;
+
+ stmt.opcode = type_store_instr[param->vtype];
+ stmt.o1.u1 = param->code.globaladdr;
+ stmt.o2.u1 = OFS_PARM0 + 3 * p;
+ if (code_statements_add(stmt) < 0)
+ return false;
+ }
+ stmt.opcode = INSTR_CALL0 + instr->params_count;
+ if (stmt.opcode > INSTR_CALL8)
+ stmt.opcode = INSTR_CALL8;
+ stmt.o1.u1 = instr->_ops[1]->code.globaladdr;
+ stmt.o2.u1 = 0;
+ stmt.o3.u1 = 0;
+ if (code_statements_add(stmt) < 0)
+ return false;
+
+ retvalue = instr->_ops[0];
+ if (retvalue && retvalue->store != store_return && retvalue->life_count)
+ {
+ /* not to be kept in OFS_RETURN */
+ stmt.opcode = type_store_instr[retvalue->vtype];
+ stmt.o1.u1 = OFS_RETURN;
+ stmt.o2.u1 = retvalue->code.globaladdr;
+ stmt.o3.u1 = 0;
+ if (code_statements_add(stmt) < 0)
+ return false;
+ }
+ continue;
}
if (instr->opcode == INSTR_STATE) {
static bool gen_function_code(ir_function *self)
{
ir_block *block;
+ prog_section_statement stmt;
/* Starting from entry point, we generate blocks "as they come"
* for now. Dead blocks will not be translated obviously.
printf("failed to generate blocks for '%s'\n", self->name);
return false;
}
+
+ /* otherwise code_write crashes since it debug-prints functions until AINSTR_END */
+ stmt.opcode = AINSTR_END;
+ stmt.o1.u1 = 0;
+ stmt.o2.u1 = 0;
+ stmt.o3.u1 = 0;
+ if (code_statements_add(stmt) < 0)
+ return false;
return true;
}
size_t i;
size_t local_var_end;
- if (!global->isconst ||
- !global->constval.vfunc)
+ if (!global->isconst || (!global->constval.vfunc))
{
printf("Invalid state of function-global: not constant: %s\n", global->name);
return false;
for (i = 0;i < 8; ++i) {
if (i >= fun.nargs)
fun.argsize[i] = 0;
- else if (irfun->params[i] == TYPE_VECTOR)
- fun.argsize[i] = 3;
else
- fun.argsize[i] = 1;
+ fun.argsize[i] = type_sizeof[irfun->params[i]];
}
fun.firstlocal = code_globals_elements;
code_globals_add(0);
}
- fun.entry = code_statements_elements;
- if (!gen_function_code(irfun)) {
- printf("Failed to generate code for function %s\n", irfun->name);
- return false;
+ if (irfun->builtin)
+ fun.entry = irfun->builtin;
+ else {
+ fun.entry = code_statements_elements;
+ if (!gen_function_code(irfun)) {
+ printf("Failed to generate code for function %s\n", irfun->name);
+ return false;
+ }
}
return (code_functions_add(fun) >= 0);
}
case TYPE_VECTOR:
{
+ size_t d;
if (code_defs_add(def) < 0)
return false;
if (global->isconst) {
iptr = (int32_t*)&global->constval.vvec;
global->code.globaladdr = code_globals_add(iptr[0]);
- if (code_globals_add(iptr[1]) < 0 || code_globals_add(iptr[2]) < 0)
+ if (global->code.globaladdr < 0)
return false;
+ for (d = 1; d < type_sizeof[global->vtype]; ++d)
+ {
+ if (code_globals_add(iptr[d]) < 0)
+ return false;
+ }
} else {
global->code.globaladdr = code_globals_add(0);
- if (code_globals_add(0) < 0 || code_globals_add(0) < 0)
+ if (global->code.globaladdr < 0)
return false;
+ for (d = 1; d < type_sizeof[global->vtype]; ++d)
+ {
+ if (code_globals_add(0) < 0)
+ return false;
+ }
}
return global->code.globaladdr >= 0;
}
case TYPE_FUNCTION:
if (code_defs_add(def) < 0)
return false;
+ global->code.globaladdr = code_globals_elements;
code_globals_add(code_functions_elements);
return gen_global_function(self, global);
case TYPE_VARIANT:
int (*oprintf)(const char*, ...))
{
size_t i;
+ if (f->builtin != 0) {
+ oprintf("%sfunction %s = builtin %i\n", ind, f->name, -f->builtin);
+ return;
+ }
oprintf("%sfunction %s\n", ind, f->name);
strncat(ind, "\t", IND_BUFSZ);
if (f->locals_count)