static void ir_function_delete(ir_function*);
static void ir_function_dump(ir_function*, char *ind, int (*oprintf)(const char*,...));
-static ir_value* ir_block_create_general_instr(ir_block *self, lex_ctx, const char *label,
+static ir_value* ir_block_create_general_instr(ir_block *self, lex_ctx_t, const char *label,
int op, ir_value *a, ir_value *b, int outype);
static void ir_block_delete(ir_block*);
static ir_block* ir_block_new(struct ir_function_s *owner, const char *label);
-static bool GMQCC_WARN ir_block_create_store(ir_block*, lex_ctx, ir_value *target, ir_value *what);
+static bool GMQCC_WARN ir_block_create_store(ir_block*, lex_ctx_t, ir_value *target, ir_value *what);
static bool ir_block_set_label(ir_block*, const char *label);
static void ir_block_dump(ir_block*, char *ind, int (*oprintf)(const char*,...));
static void ir_instr_dump(ir_instr* in, char *ind, int (*oprintf)(const char*,...));
/* error functions */
-static void irerror(lex_ctx ctx, const char *msg, ...)
+static void irerror(lex_ctx_t ctx, const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
- con_cvprintmsg((void*)&ctx, LVL_ERROR, "internal error", msg, ap);
+ con_cvprintmsg(ctx, LVL_ERROR, "internal error", msg, ap);
va_end(ap);
}
-static bool irwarning(lex_ctx ctx, int warntype, const char *fmt, ...)
+static bool irwarning(lex_ctx_t ctx, int warntype, const char *fmt, ...)
{
bool r;
va_list ap;
ir_builder* ir_builder_new(const char *modulename)
{
ir_builder* self;
+ size_t i;
self = (ir_builder*)mem_a(sizeof(*self));
if (!self)
self->nil = ir_value_var("nil", store_value, TYPE_NIL);
self->nil->cvq = CV_CONST;
+ for (i = 0; i != IR_MAX_VINSTR_TEMPS; ++i) {
+ /* we write to them, but they're not supposed to be used outside the IR, so
+ * let's not allow the generation of ir_instrs which use these.
+ * So it's a constant noexpr.
+ */
+ self->vinstr_temp[i] = ir_value_var("vinstr_temp", store_value, TYPE_NOEXPR);
+ self->vinstr_temp[i]->cvq = CV_CONST;
+ }
+
self->reserved_va_count = NULL;
self->code = code_init();
ir_value_delete(self->fields[i]);
}
ir_value_delete(self->nil);
+ for (i = 0; i != IR_MAX_VINSTR_TEMPS; ++i) {
+ ir_value_delete(self->vinstr_temp[i]);
+ }
vec_free(self->fields);
vec_free(self->filenames);
vec_free(self->filestrings);
{
ir_value *ve;
- if (name && name[0] != '#')
+ if (name[0] != '#')
{
ve = ir_builder_get_global(self, name);
if (ve) {
vec_push(self->values, v);
}
-ir_block* ir_function_create_block(lex_ctx ctx, ir_function *self, const char *label)
+ir_block* ir_function_create_block(lex_ctx_t ctx, ir_function *self, const char *label)
{
ir_block* bn = ir_block_new(self, label);
bn->context = ctx;
*IR Instructions
*/
-static ir_instr* ir_instr_new(lex_ctx ctx, ir_block* owner, int op)
+static ir_instr* ir_instr_new(lex_ctx_t ctx, ir_block* owner, int op)
{
ir_instr *self;
self = (ir_instr*)mem_a(sizeof(*self));
return true;
}
-bool ir_value_set_vector(ir_value *self, vector v)
+bool ir_value_set_vector(ir_value *self, vec3_t v)
{
if (self->vtype != TYPE_VECTOR)
return false;
return false;
}
-bool ir_block_create_store_op(ir_block *self, lex_ctx ctx, int op, ir_value *target, ir_value *what)
+bool ir_block_create_store_op(ir_block *self, lex_ctx_t ctx, int op, ir_value *target, ir_value *what)
{
ir_instr *in;
if (!ir_check_unreachable(self))
{
irerror(self->context, "cannot store to an SSA value");
irerror(self->context, "trying to store: %s <- %s", target->name, what->name);
- irerror(self->context, "instruction: %s", asm_instr[op].m);
+ irerror(self->context, "instruction: %s", util_instr_str[op]);
return false;
}
return true;
}
-static bool ir_block_create_store(ir_block *self, lex_ctx ctx, ir_value *target, ir_value *what)
+static bool ir_block_create_store(ir_block *self, lex_ctx_t ctx, ir_value *target, ir_value *what)
{
int op = 0;
int vtype;
return ir_block_create_store_op(self, ctx, op, target, what);
}
-bool ir_block_create_storep(ir_block *self, lex_ctx ctx, ir_value *target, ir_value *what)
+bool ir_block_create_storep(ir_block *self, lex_ctx_t ctx, ir_value *target, ir_value *what)
{
int op = 0;
int vtype;
return ir_block_create_store_op(self, ctx, op, target, what);
}
-bool ir_block_create_return(ir_block *self, lex_ctx ctx, ir_value *v)
+bool ir_block_create_return(ir_block *self, lex_ctx_t ctx, ir_value *v)
{
ir_instr *in;
if (!ir_check_unreachable(self))
return true;
}
-bool ir_block_create_if(ir_block *self, lex_ctx ctx, ir_value *v,
+bool ir_block_create_if(ir_block *self, lex_ctx_t ctx, ir_value *v,
ir_block *ontrue, ir_block *onfalse)
{
ir_instr *in;
return true;
}
-bool ir_block_create_jump(ir_block *self, lex_ctx ctx, ir_block *to)
+bool ir_block_create_jump(ir_block *self, lex_ctx_t ctx, ir_block *to)
{
ir_instr *in;
if (!ir_check_unreachable(self))
return true;
}
-bool ir_block_create_goto(ir_block *self, lex_ctx ctx, ir_block *to)
+bool ir_block_create_goto(ir_block *self, lex_ctx_t ctx, ir_block *to)
{
self->owner->flags |= IR_FLAG_HAS_GOTO;
return ir_block_create_jump(self, ctx, to);
}
-ir_instr* ir_block_create_phi(ir_block *self, lex_ctx ctx, const char *label, int ot)
+ir_instr* ir_block_create_phi(ir_block *self, lex_ctx_t ctx, const char *label, int ot)
{
ir_value *out;
ir_instr *in;
}
/* call related code */
-ir_instr* ir_block_create_call(ir_block *self, lex_ctx ctx, const char *label, ir_value *func, bool noreturn)
+ir_instr* ir_block_create_call(ir_block *self, lex_ctx_t ctx, const char *label, ir_value *func, bool noreturn)
{
ir_value *out;
ir_instr *in;
/* binary op related code */
-ir_value* ir_block_create_binop(ir_block *self, lex_ctx ctx,
+ir_value* ir_block_create_binop(ir_block *self, lex_ctx_t ctx,
const char *label, int opcode,
ir_value *left, ir_value *right)
{
return ir_block_create_general_instr(self, ctx, label, opcode, left, right, ot);
}
-ir_value* ir_block_create_unary(ir_block *self, lex_ctx ctx,
+ir_value* ir_block_create_unary(ir_block *self, lex_ctx_t ctx,
const char *label, int opcode,
ir_value *operand)
{
return ir_block_create_general_instr(self, ctx, label, opcode, operand, NULL, ot);
}
-static ir_value* ir_block_create_general_instr(ir_block *self, lex_ctx ctx, const char *label,
+static ir_value* ir_block_create_general_instr(ir_block *self, lex_ctx_t ctx, const char *label,
int op, ir_value *a, ir_value *b, int outype)
{
ir_instr *instr;
return NULL;
}
-ir_value* ir_block_create_fieldaddress(ir_block *self, lex_ctx ctx, const char *label, ir_value *ent, ir_value *field)
+ir_value* ir_block_create_fieldaddress(ir_block *self, lex_ctx_t ctx, const char *label, ir_value *ent, ir_value *field)
{
ir_value *v;
return v;
}
-ir_value* ir_block_create_load_from_ent(ir_block *self, lex_ctx ctx, const char *label, ir_value *ent, ir_value *field, int outype)
+ir_value* ir_block_create_load_from_ent(ir_block *self, lex_ctx_t ctx, const char *label, ir_value *ent, ir_value *field, int outype)
{
int op;
if (ent->vtype != TYPE_ENTITY)
static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *block)
{
- prog_section_statement stmt;
+ prog_section_statement_t stmt;
ir_instr *instr;
ir_block *target;
ir_block *ontrue;
static bool gen_function_code(code_t *code, ir_function *self)
{
ir_block *block;
- prog_section_statement stmt, *retst;
+ prog_section_statement_t stmt, *retst;
/* Starting from entry point, we generate blocks "as they come"
* for now. Dead blocks will not be translated obviously.
return true;
}
-static qcint ir_builder_filestring(ir_builder *ir, const char *filename)
+static qcint_t ir_builder_filestring(ir_builder *ir, const char *filename)
{
/* NOTE: filename pointers are copied, we never strdup them,
* thus we can use pointer-comparison to find the string.
*/
size_t i;
- qcint str;
+ qcint_t str;
for (i = 0; i < vec_size(ir->filenames); ++i) {
if (ir->filenames[i] == filename)
static bool gen_global_function(ir_builder *ir, ir_value *global)
{
- prog_section_function fun;
- ir_function *irfun;
+ prog_section_function_t fun;
+ ir_function *irfun;
size_t i;
static void ir_gen_extparam(ir_builder *ir)
{
- prog_section_def def;
- ir_value *global;
+ prog_section_def_t def;
+ ir_value *global;
if (vec_size(ir->extparam_protos) < vec_size(ir->extparams)+1)
global = ir_gen_extparam_proto(ir);
ir_builder *ir = self->owner;
ir_value *ep;
- prog_section_statement stmt;
+ prog_section_statement_t stmt;
numparams = vec_size(self->params);
if (!numparams)
ir_builder *ir = self->owner;
ir_value *ep;
- prog_section_statement stmt;
+ prog_section_statement_t stmt;
numparams = vec_size(self->params);
if (!numparams)
static bool gen_function_locals(ir_builder *ir, ir_value *global)
{
- prog_section_function *def;
- ir_function *irfun;
- size_t i;
- uint32_t firstlocal, firstglobal;
+ prog_section_function_t *def;
+ ir_function *irfun;
+ size_t i;
+ uint32_t firstlocal, firstglobal;
irfun = global->constval.vfunc;
def = ir->code->functions + irfun->code_function_def;
static bool gen_global_function_code(ir_builder *ir, ir_value *global)
{
- prog_section_function *fundef;
- ir_function *irfun;
+ prog_section_function_t *fundef;
+ ir_function *irfun;
(void)ir;
return true;
}
-static void gen_vector_defs(code_t *code, prog_section_def def, const char *name)
+static void gen_vector_defs(code_t *code, prog_section_def_t def, const char *name)
{
char *component;
size_t len, i;
mem_d(component);
}
-static void gen_vector_fields(code_t *code, prog_section_field fld, const char *name)
+static void gen_vector_fields(code_t *code, prog_section_field_t fld, const char *name)
{
char *component;
size_t len, i;
static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool islocal)
{
- size_t i;
- int32_t *iptr;
- prog_section_def def;
- bool pushdef = opts.optimizeoff;
+ size_t i;
+ int32_t *iptr;
+ prog_section_def_t def;
+ bool pushdef = opts.optimizeoff;
def.type = global->vtype;
def.offset = vec_size(self->code->globals);
pushdef = false;
}
- if (pushdef && global->name) {
+ if (pushdef) {
if (global->name[0] == '#') {
if (!self->str_immediate)
self->str_immediate = code_genstring(self->code, "IMMEDIATE");
static bool ir_builder_gen_field(ir_builder *self, ir_value *field)
{
- prog_section_def def;
- prog_section_field fld;
+ prog_section_def_t def;
+ prog_section_field_t fld;
(void)self;
bool ir_builder_generate(ir_builder *self, const char *filename)
{
- prog_section_statement stmt;
+ prog_section_statement_t stmt;
size_t i;
char *lnofile = NULL;
vec_push(self->code->globals, 0);
vec_push(self->code->globals, 0);
+ /* generate virtual-instruction temps */
+ for (i = 0; i < IR_MAX_VINSTR_TEMPS; ++i) {
+ ir_value_code_setaddr(self->vinstr_temp[i], vec_size(self->code->globals));
+ vec_push(self->code->globals, 0);
+ vec_push(self->code->globals, 0);
+ vec_push(self->code->globals, 0);
+ }
+
/* generate global temps */
self->first_common_globaltemp = vec_size(self->code->globals);
for (i = 0; i < self->max_globaltemps; ++i) {
memcpy(vec_add(lnofile, 5), ".lno", 5);
}
- if (!OPTS_OPTION_BOOL(OPTION_QUIET)) {
- if (lnofile)
- con_out("writing '%s' and '%s'...\n", filename, lnofile);
- else
- con_out("writing '%s'\n", filename);
- }
if (!code_write(self->code, filename, lnofile)) {
vec_free(lnofile);
return false;
}
+
vec_free(lnofile);
return true;
}
static const char *qc_opname(int op)
{
if (op < 0) return "<INVALID>";
- if (op < (int)( sizeof(asm_instr) / sizeof(asm_instr[0]) ))
- return asm_instr[op].m;
+ if (op < VINSTR_END)
+ return util_instr_str[op];
switch (op) {
+ case VINSTR_END: return "END";
case VINSTR_PHI: return "PHI";
case VINSTR_JUMP: return "JUMP";
case VINSTR_COND: return "COND";