AINSTR_END, /* array */
};
+uint16_t type_not_instr[TYPE_COUNT] = {
+ INSTR_NOT_F, /* should use I when having integer support */
+ INSTR_NOT_S,
+ INSTR_NOT_F,
+ INSTR_NOT_V,
+ INSTR_NOT_ENT,
+ INSTR_NOT_ENT,
+ INSTR_NOT_FNC,
+ INSTR_NOT_ENT, /* should use I */
+#if 0
+ INSTR_NOT_I, /* integer type */
+#else
+ INSTR_NOT_F,
+#endif
+
+ INSTR_NOT_V, /* variant, should never be accessed */
+
+ AINSTR_END, /* struct */
+ AINSTR_END, /* union */
+ AINSTR_END, /* array */
+};
+
static void irerror(lex_ctx ctx, const char *msg, ...)
{
va_list ap;
self->extparams = NULL;
self->filenames = NULL;
self->filestrings = NULL;
+ self->htglobals = util_htnew(IR_HT_SIZE);
+ self->htfields = util_htnew(IR_HT_SIZE);
+ self->htfunctions = util_htnew(IR_HT_SIZE);
self->str_immediate = 0;
self->name = NULL;
void ir_builder_delete(ir_builder* self)
{
size_t i;
+ util_htdel(self->htglobals);
+ util_htdel(self->htfields);
+ util_htdel(self->htfunctions);
mem_d((void*)self->name);
for (i = 0; i != vec_size(self->functions); ++i) {
ir_function_delete_quick(self->functions[i]);
ir_function* ir_builder_get_function(ir_builder *self, const char *name)
{
- size_t i;
- for (i = 0; i < vec_size(self->functions); ++i) {
- if (!strcmp(name, self->functions[i]->name))
- return self->functions[i];
- }
- return NULL;
+ return (ir_function*)util_htget(self->htfunctions, name);
}
ir_function* ir_builder_create_function(ir_builder *self, const char *name, int outtype)
return NULL;
}
vec_push(self->functions, fn);
+ util_htset(self->htfunctions, name, fn);
fn->value = ir_builder_create_global(self, fn->name, TYPE_FUNCTION);
if (!fn->value) {
ir_value* ir_builder_get_global(ir_builder *self, const char *name)
{
- size_t i;
- for (i = 0; i < vec_size(self->globals); ++i) {
- if (!strcmp(self->globals[i]->name, name))
- return self->globals[i];
- }
- return NULL;
+ return (ir_value*)util_htget(self->htglobals, name);
}
ir_value* ir_builder_create_global(ir_builder *self, const char *name, int vtype)
ve = ir_value_var(name, store_global, vtype);
vec_push(self->globals, ve);
+ util_htset(self->htglobals, name, ve);
return ve;
}
ir_value* ir_builder_get_field(ir_builder *self, const char *name)
{
- size_t i;
- for (i = 0; i < vec_size(self->fields); ++i) {
- if (!strcmp(self->fields[i]->name, name))
- return self->fields[i];
- }
- return NULL;
+ return (ir_value*)util_htget(self->htfields, name);
}
ve = ir_value_var(name, store_global, TYPE_FIELD);
ve->fieldtype = vtype;
vec_push(self->fields, ve);
+ util_htset(self->htfields, name, ve);
return ve;
}
if (!ir_function_calculate_liferanges(self))
return false;
-
if (!ir_function_allocate_locals(self))
return false;
return true;
}
-ir_value* ir_function_get_local(ir_function *self, const char *name)
-{
- size_t i;
- for (i = 0; i < vec_size(self->locals); ++i) {
- if (!strcmp(self->locals[i]->name, name))
- return self->locals[i];
- }
- return NULL;
-}
-
ir_value* ir_function_create_local(ir_function *self, const char *name, int vtype, bool param)
{
ir_value *ve;
- /*
- if (ir_function_get_local(self, name))
- return NULL;
- */
-
if (param &&
vec_size(self->locals) &&
self->locals[vec_size(self->locals)-1]->store != store_param) {
self->params = NULL;
self->eid = 0;
+
+ self->likely = true;
return self;
}
return true;
}
+#if 0
static bool ir_naive_phi_emit_store(ir_block *block, size_t iid, ir_value *old, ir_value *what)
{
ir_instr *instr;
return true;
}
+#endif
static bool ir_block_naive_phi(ir_block *self)
{
- size_t i, p, w;
+ size_t i, p; /*, w;*/
/* FIXME: optionally, create_phi can add the phis
* to a list so we don't need to loop through blocks
* - anyway: "don't optimize YET"
for (p = 0; p < vec_size(instr->phi); ++p)
{
+ ir_value *v = instr->phi[p].value;
+ ir_block *b = instr->phi[p].from;
+
+ if (v->store == store_value &&
+ vec_size(v->reads) == 1 &&
+ vec_size(v->writes) == 1)
+ {
+ /* replace the value */
+ if (!ir_instr_op(v->writes[0], 0, instr->_ops[0], true))
+ return false;
+ }
+ else
+ {
+ /* force a move instruction */
+ ir_instr *prevjump = vec_last(b->instr);
+ vec_pop(b->instr);
+ b->final = false;
+ instr->_ops[0]->store = store_global;
+ if (!ir_block_create_store(b, instr->_ops[0], v))
+ return false;
+ instr->_ops[0]->store = store_value;
+ vec_push(b->instr, prevjump);
+ b->final = true;
+ }
+
+#if 0
ir_value *v = instr->phi[p].value;
for (w = 0; w < vec_size(v->writes); ++w) {
ir_value *old;
}
}
}
+#endif
}
ir_instr_delete(instr);
}
static bool ir_block_life_prop_previous(ir_block* self, ir_block *prev, bool *changed)
{
size_t i;
+
+ (void)changed;
+
/* values which have been read in a previous iteration are now
* in the "living" array even if the previous block doesn't use them.
* So we have to remove whatever does not exist in the previous block.
}
/* neither ontrue nor onfalse exist */
stmt.opcode = INSTR_IFNOT;
+ if (!instr->likely) {
+ /* Honor the likelyhood hint */
+ ir_block *tmp = onfalse;
+ stmt.opcode = INSTR_IF;
+ onfalse = ontrue;
+ ontrue = tmp;
+ }
stidx = vec_size(code_statements);
vec_push(code_statements, stmt);
/* on false we jump, so add ontrue-path */
if (onfalse->generated) {
/* fixup the jump address */
code_statements[stidx].o2.s1 = (onfalse->code_start) - (stidx);
+ stmt.opcode = vec_last(code_statements).opcode;
+ if (stmt.opcode == INSTR_GOTO ||
+ stmt.opcode == INSTR_IF ||
+ stmt.opcode == INSTR_IFNOT ||
+ stmt.opcode == INSTR_RETURN ||
+ stmt.opcode == INSTR_DONE)
+ {
+ /* no use jumping from here */
+ return true;
+ }
/* may have been generated in the previous recursive call */
stmt.opcode = INSTR_GOTO;
stmt.o1.s1 = (onfalse->code_start) - vec_size(code_statements);
stmt.o2.u1 = OFS_PARM0 + 3 * p;
vec_push(code_statements, stmt);
}
- /* No whandle extparams */
+ /* Now handle extparams */
first = vec_size(instr->params);
for (; p < first; ++p)
{
ir_builder *ir = func->owner;
ir_value *param = instr->params[p];
- ir_value *target;
+ ir_value *targetparam;
if (p-8 >= vec_size(ir->extparams)) {
irerror(instr->context, "Not enough extparam-globals have been created");
return false;
}
- target = ir->extparams[p-8];
+ targetparam = ir->extparams[p-8];
stmt.opcode = INSTR_STORE_F;
stmt.o3.u1 = 0;
else
stmt.opcode = type_store_instr[param->vtype];
stmt.o1.u1 = ir_value_code_addr(param);
- stmt.o2.u1 = ir_value_code_addr(target);
+ stmt.o2.u1 = ir_value_code_addr(targetparam);
vec_push(code_statements, stmt);
}
prog_section_function *fundef;
ir_function *irfun;
+ (void)ir;
+
irfun = global->constval.vfunc;
if (!irfun) {
irwarning(global->context, WARN_IMPLICIT_FUNCTION_POINTER,
prog_section_def def;
prog_section_field fld;
- def.type = field->vtype;
- def.offset = vec_size(code_globals);
+ (void)self;
+
+ def.type = (uint16_t)field->vtype;
+ def.offset = (uint16_t)vec_size(code_globals);
/* create a global named the same as the field */
if (opts_standard == COMPILER_GMQCC) {
}
}
+ if (vec_size(code_globals) >= 65536) {
+ irerror(vec_last(self->globals)->context, "This progs file would require more globals than the metadata can handle. Bailing out.");
+ return false;
+ }
+
/* DP errors if the last instruction is not an INSTR_DONE
* and for debugging purposes we add an additional AINSTR_END
* to the end of functions, so here it goes:
const char *qc_opname(int op)
{
if (op < 0) return "<INVALID>";
- if (op < ( sizeof(asm_instr) / sizeof(asm_instr[0]) ))
+ if (op < (int)( sizeof(asm_instr) / sizeof(asm_instr[0]) ))
return asm_instr[op].m;
switch (op) {
case VINSTR_PHI: return "PHI";
ind[strlen(ind)-1] = 0;
}
-void dump_phi(ir_instr *in, char *ind,
- int (*oprintf)(const char*, ...))
+void dump_phi(ir_instr *in, int (*oprintf)(const char*, ...))
{
size_t i;
oprintf("%s <- phi ", in->_ops[0]->name);
oprintf("%s (%i) ", ind, (int)in->eid);
if (in->opcode == VINSTR_PHI) {
- dump_phi(in, ind, oprintf);
+ dump_phi(in, oprintf);
return;
}
ind[strlen(ind)-1] = 0;
}
+void ir_value_dump_string(const char *str, int (*oprintf)(const char*, ...))
+{
+ oprintf("\"");
+ for (; *str; ++str) {
+ switch (*str) {
+ case '\n': oprintf("\\n"); break;
+ case '\r': oprintf("\\r"); break;
+ case '\t': oprintf("\\t"); break;
+ case '\v': oprintf("\\v"); break;
+ case '\f': oprintf("\\f"); break;
+ case '\b': oprintf("\\b"); break;
+ case '\a': oprintf("\\a"); break;
+ case '\\': oprintf("\\\\"); break;
+ case '"': oprintf("\\\""); break;
+ default: oprintf("%c", *str); break;
+ }
+ }
+ oprintf("\"");
+}
+
void ir_value_dump(ir_value* v, int (*oprintf)(const char*, ...))
{
if (v->isconst) {
oprintf("(entity)");
break;
case TYPE_STRING:
- oprintf("\"%s\"", v->constval.vstring);
+ ir_value_dump_string(v->constval.vstring, oprintf);
break;
#if 0
case TYPE_INTEGER: