]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ir.c
ir_builder now has a vinstr_temp array, a bunch of temps (currently 1) which can...
[xonotic/gmqcc.git] / ir.c
diff --git a/ir.c b/ir.c
index f570cbec6de06c8c3d9ceffb5531b041c979a1d3..ec45a8f67cf78081e3db109e2f0e3d8fe0b82994 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -227,11 +227,11 @@ static bool            ir_function_set_name(ir_function*, const char *name);
 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*,...));
 
@@ -240,15 +240,15 @@ static void            ir_instr_delete(ir_instr*);
 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;
@@ -312,6 +312,7 @@ static void ir_function_delete_quick(ir_function *self);
 ir_builder* ir_builder_new(const char *modulename)
 {
     ir_builder* self;
+    size_t      i;
 
     self = (ir_builder*)mem_a(sizeof(*self));
     if (!self)
@@ -344,6 +345,15 @@ ir_builder* ir_builder_new(const char *modulename)
     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();
 
@@ -374,6 +384,9 @@ void ir_builder_delete(ir_builder* self)
         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);
@@ -434,7 +447,7 @@ ir_value* ir_builder_create_global(ir_builder *self, const char *name, int vtype
 {
     ir_value *ve;
 
-    if (name && name[0] != '#')
+    if (name[0] != '#')
     {
         ve = ir_builder_get_global(self, name);
         if (ve) {
@@ -584,7 +597,7 @@ static void ir_function_collect_value(ir_function *self, ir_value *v)
     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;
@@ -954,7 +967,7 @@ bool ir_block_set_label(ir_block *self, const char *name)
  *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));
@@ -1216,7 +1229,7 @@ bool ir_value_set_func(ir_value *self, int f)
     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;
@@ -1482,7 +1495,7 @@ static bool ir_check_unreachable(ir_block *self)
     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))
@@ -1493,7 +1506,7 @@ bool ir_block_create_store_op(ir_block *self, lex_ctx ctx, int op, ir_value *tar
     {
         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;
     }
 
@@ -1511,7 +1524,7 @@ bool ir_block_create_store_op(ir_block *self, lex_ctx ctx, int op, ir_value *tar
     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;
@@ -1536,7 +1549,7 @@ static bool ir_block_create_store(ir_block *self, lex_ctx ctx, ir_value *target,
     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;
@@ -1558,7 +1571,7 @@ bool ir_block_create_storep(ir_block *self, lex_ctx ctx, ir_value *target, ir_va
     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))
@@ -1578,7 +1591,7 @@ bool ir_block_create_return(ir_block *self, lex_ctx ctx, ir_value *v)
     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;
@@ -1607,7 +1620,7 @@ bool ir_block_create_if(ir_block *self, lex_ctx ctx, ir_value *v,
     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))
@@ -1625,13 +1638,13 @@ bool ir_block_create_jump(ir_block *self, lex_ctx ctx, ir_block *to)
     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;
@@ -1678,7 +1691,7 @@ void ir_phi_add(ir_instr* self, ir_block *b, ir_value *v)
 }
 
 /* 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;
@@ -1729,7 +1742,7 @@ void ir_call_param(ir_instr* self, ir_value *v)
 
 /* 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)
 {
@@ -1840,7 +1853,7 @@ ir_value* ir_block_create_binop(ir_block *self, lex_ctx ctx,
     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)
 {
@@ -1873,7 +1886,7 @@ ir_value* ir_block_create_unary(ir_block *self, lex_ctx ctx,
     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;
@@ -1905,7 +1918,7 @@ on_error:
     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;
 
@@ -1921,7 +1934,7 @@ ir_value* ir_block_create_fieldaddress(ir_block *self, lex_ctx ctx, const char *
     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)
@@ -2741,7 +2754,7 @@ static bool gen_global_pointer(code_t *code, ir_value *global)
 
 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;
@@ -3002,7 +3015,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc
 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.
@@ -3040,13 +3053,13 @@ static bool gen_function_code(code_t *code, ir_function *self)
     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)
@@ -3061,8 +3074,8 @@ static qcint ir_builder_filestring(ir_builder *ir, const char *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;
 
@@ -3116,8 +3129,8 @@ static ir_value* ir_gen_extparam_proto(ir_builder *ir)
 
 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);
@@ -3145,7 +3158,7 @@ static bool gen_function_extparam_copy(code_t *code, ir_function *self)
 
     ir_builder *ir = self->owner;
     ir_value   *ep;
-    prog_section_statement stmt;
+    prog_section_statement_t stmt;
 
     numparams = vec_size(self->params);
     if (!numparams)
@@ -3180,7 +3193,7 @@ static bool gen_function_varargs_copy(code_t *code, ir_function *self)
 
     ir_builder *ir = self->owner;
     ir_value   *ep;
-    prog_section_statement stmt;
+    prog_section_statement_t stmt;
 
     numparams = vec_size(self->params);
     if (!numparams)
@@ -3212,10 +3225,10 @@ static bool gen_function_varargs_copy(code_t *code, ir_function *self)
 
 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;
@@ -3261,8 +3274,8 @@ static bool gen_function_locals(ir_builder *ir, ir_value *global)
 
 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;
 
@@ -3305,7 +3318,7 @@ static bool gen_global_function_code(ir_builder *ir, ir_value *global)
     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;
@@ -3335,7 +3348,7 @@ static void gen_vector_defs(code_t *code, prog_section_def def, const char *name
     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;
@@ -3367,10 +3380,10 @@ static void gen_vector_fields(code_t *code, prog_section_field fld, const char *
 
 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);
@@ -3386,7 +3399,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc
             pushdef = false;
         }
 
-        if (pushdef && global->name) {
+        if (pushdef) {
             if (global->name[0] == '#') {
                 if (!self->str_immediate)
                     self->str_immediate = code_genstring(self->code, "IMMEDIATE");
@@ -3543,8 +3556,8 @@ static GMQCC_INLINE void ir_builder_prepare_field(code_t *code, ir_value *field)
 
 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;
 
@@ -3613,7 +3626,7 @@ static bool ir_builder_gen_field(ir_builder *self, ir_value *field)
 
 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;
 
@@ -3652,6 +3665,14 @@ bool ir_builder_generate(ir_builder *self, const char *filename)
     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) {
@@ -3709,16 +3730,11 @@ bool ir_builder_generate(ir_builder *self, const char *filename)
         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;
 }
@@ -3736,9 +3752,10 @@ bool ir_builder_generate(ir_builder *self, const char *filename)
 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";