]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ir.c
'noreturn' is now an attribute and parsed as [[noreturn]]
[xonotic/gmqcc.git] / ir.c
diff --git a/ir.c b/ir.c
index 18b6387d344a2d05225097657363388b9faadc3e..12f9a5115c4e14dfad82917cb8ae0dd92fe47868 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -45,7 +45,7 @@ const char *type_name[TYPE_COUNT] = {
     "array"
 };
 
-size_t type_sizeof[TYPE_COUNT] = {
+size_t type_sizeof_[TYPE_COUNT] = {
     1, /* TYPE_VOID     */
     1, /* TYPE_STRING   */
     1, /* TYPE_FLOAT    */
@@ -527,7 +527,8 @@ static bool instr_is_operation(uint16_t op)
              (op >= INSTR_LOAD_F && op <= INSTR_LOAD_FNC) ||
              (op == INSTR_ADDRESS) ||
              (op >= INSTR_NOT_F  && op <= INSTR_NOT_FNC) ||
-             (op >= INSTR_AND    && op <= INSTR_BITOR) );
+             (op >= INSTR_AND    && op <= INSTR_BITOR) ||
+             (op >= INSTR_CALL0  && op <= INSTR_CALL8) );
 }
 
 bool ir_function_pass_peephole(ir_function *self)
@@ -638,7 +639,7 @@ bool ir_function_pass_peephole(ir_function *self)
     return true;
 }
 
-bool ir_function_pass_tailcall(ir_function *self)
+bool ir_function_pass_tailrecursion(ir_function *self)
 {
     size_t b, p;
 
@@ -738,8 +739,8 @@ bool ir_function_finalize(ir_function *self)
     }
 
     if (OPTS_OPTIMIZATION(OPTIM_TAIL_RECURSION)) {
-        if (!ir_function_pass_tailcall(self)) {
-            irerror(self->context, "tailcall optimization pass broke something in `%s`", self->name);
+        if (!ir_function_pass_tailrecursion(self)) {
+            irerror(self->context, "tail-recursion optimization pass broke something in `%s`", self->name);
             return false;
         }
     }
@@ -1038,6 +1039,13 @@ ir_value* ir_value_vector_member(ir_value *self, unsigned int member)
     return m;
 }
 
+static GMQCC_INLINE size_t ir_value_sizeof(const ir_value *self)
+{
+    if (self->vtype == TYPE_FIELD && self->fieldtype == TYPE_VECTOR)
+        return type_sizeof_[TYPE_VECTOR];
+    return type_sizeof_[self->vtype];
+}
+
 ir_value* ir_value_out(ir_function *owner, const char *name, int storetype, int vtype)
 {
     ir_value *v = ir_value_var(name, storetype, vtype);
@@ -2242,7 +2250,7 @@ typedef struct {
 static bool function_allocator_alloc(function_allocator *alloc, const ir_value *var)
 {
     ir_value *slot;
-    size_t vsize = type_sizeof[var->vtype];
+    size_t vsize = ir_value_sizeof(var);
 
     slot = ir_value_var("reg", store_global, var->vtype);
     if (!slot)
@@ -2283,7 +2291,9 @@ bool ir_function_allocate_locals(ir_function *self)
 
     for (i = 0; i < vec_size(self->locals); ++i)
     {
+#if 0
         if (!OPTS_OPTIMIZATION(OPTIM_LOCALTEMPS))
+#endif
             self->locals[i]->unique_life = true;
         if (!function_allocator_alloc(&alloc, self->locals[i]))
             goto error;
@@ -2309,7 +2319,7 @@ bool ir_function_allocate_locals(ir_function *self)
              * will be required later when overlapping temps + locals
              */
             if (a < vec_size(self->params) &&
-                alloc.sizes[a] < type_sizeof[v->vtype])
+                alloc.sizes[a] < ir_value_sizeof(v))
             {
                 continue;
             }
@@ -2321,8 +2331,8 @@ bool ir_function_allocate_locals(ir_function *self)
                 goto error;
 
             /* adjust size for this slot */
-            if (alloc.sizes[a] < type_sizeof[v->vtype])
-                alloc.sizes[a] = type_sizeof[v->vtype];
+            if (alloc.sizes[a] < ir_value_sizeof(v))
+                alloc.sizes[a] = ir_value_sizeof(v);
 
             self->values[i]->code.local = a;
             break;
@@ -2901,11 +2911,11 @@ tailcall:
             code_push_statement(&stmt, instr->context.line);
 
             retvalue = instr->_ops[0];
-            if (retvalue && retvalue->store != store_return && vec_size(retvalue->life))
+            if (retvalue && retvalue->store != store_return && (vec_size(retvalue->life) || retvalue->store == store_global))
             {
                 /* not to be kept in OFS_RETURN */
-                if (retvalue->vtype == TYPE_FIELD)
-                    stmt.opcode = field_store_instr[retvalue->vtype];
+                if (retvalue->vtype == TYPE_FIELD && OPTS_FLAG(ADJUST_VECTOR_FIELDS))
+                    stmt.opcode = field_store_instr[retvalue->fieldtype];
                 else
                     stmt.opcode = type_store_instr[retvalue->vtype];
                 stmt.o1.u1 = OFS_RETURN;
@@ -3022,9 +3032,6 @@ static bool gen_global_function(ir_builder *ir, ir_value *global)
     ir_function          *irfun;
 
     size_t i;
-#ifndef NEW_ALLOC_STRAT
-    size_t local_var_end;
-#endif
 
     if (!global->hasvalue || (!global->constval.vfunc))
     {
@@ -3045,40 +3052,11 @@ static bool gen_global_function(ir_builder *ir, ir_value *global)
         if ((int32_t)i >= fun.nargs)
             fun.argsize[i] = 0;
         else
-            fun.argsize[i] = type_sizeof[irfun->params[i]];
+            fun.argsize[i] = type_sizeof_[irfun->params[i]];
     }
 
     fun.firstlocal = vec_size(code_globals);
 
-#ifndef NEW_ALLOC_STRAT
-    local_var_end = fun.firstlocal;
-    for (i = 0; i < vec_size(irfun->locals); ++i) {
-        if (!ir_builder_gen_global(ir, irfun->locals[i], true)) {
-            irerror(irfun->locals[i]->context, "Failed to generate local %s", irfun->locals[i]->name);
-            return false;
-        }
-    }
-    if (vec_size(irfun->locals)) {
-        ir_value *last = vec_last(irfun->locals);
-        local_var_end = last->code.globaladdr;
-        if (last->vtype == TYPE_FIELD && last->fieldtype == TYPE_VECTOR)
-            local_var_end += type_sizeof[TYPE_VECTOR];
-        else
-            local_var_end += type_sizeof[last->vtype];
-    }
-    for (i = 0; i < vec_size(irfun->values); ++i)
-    {
-        /* generate code.globaladdr for ssa values */
-        ir_value *v = irfun->values[i];
-        ir_value_code_setaddr(v, local_var_end + v->code.local);
-    }
-    for (i = 0; i < irfun->allocated_locals; ++i) {
-        /* fill the locals with zeros */
-        vec_push(code_globals, 0);
-    }
-
-    fun.locals = vec_size(code_globals) - fun.firstlocal;
-#else
     fun.locals = irfun->allocated_locals;
     for (i = 0; i < vec_size(irfun->locals); ++i) {
         if (!ir_builder_gen_global(ir, irfun->locals[i], true)) {
@@ -3087,16 +3065,14 @@ static bool gen_global_function(ir_builder *ir, ir_value *global)
         }
         ir_value_code_setaddr(irfun->locals[i], fun.firstlocal + irfun->locals[i]->code.local);
     }
-    for (i = vec_size(code_globals) - fun.firstlocal; i < fun.locals; ++i) {
-        vec_push(code_globals, 0);
-    }
     for (i = 0; i < vec_size(irfun->values); ++i)
     {
         /* generate code.globaladdr for ssa values */
         ir_value *v = irfun->values[i];
         ir_value_code_setaddr(v, fun.firstlocal + v->code.local);
     }
-#endif
+    for (i = vec_size(code_globals); i < fun.firstlocal + irfun->allocated_locals; ++i)
+        vec_push(code_globals, 0);
 
     if (irfun->builtin)
         fun.entry = irfun->builtin+1;
@@ -3352,14 +3328,14 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc
             vec_push(code_globals, iptr[0]);
             if (global->code.globaladdr < 0)
                 return false;
-            for (d = 1; d < type_sizeof[global->vtype]; ++d) {
+            for (d = 1; d < type_sizeof_[global->vtype]; ++d) {
                 vec_push(code_globals, iptr[d]);
             }
         } else {
             vec_push(code_globals, 0);
             if (global->code.globaladdr < 0)
                 return false;
-            for (d = 1; d < type_sizeof[global->vtype]; ++d) {
+            for (d = 1; d < type_sizeof_[global->vtype]; ++d) {
                 vec_push(code_globals, 0);
             }
         }
@@ -3390,7 +3366,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc
         /* assume biggest type */
             ir_value_code_setaddr(global, vec_size(code_globals));
             vec_push(code_globals, 0);
-            for (i = 1; i < type_sizeof[TYPE_VARIANT]; ++i)
+            for (i = 1; i < type_sizeof_[TYPE_VARIANT]; ++i)
                 vec_push(code_globals, 0);
             return true;
     default:
@@ -3403,7 +3379,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc
 
 static void ir_builder_prepare_field(ir_value *field)
 {
-    field->code.fieldaddr = code_alloc_field(type_sizeof[field->fieldtype]);
+    field->code.fieldaddr = code_alloc_field(type_sizeof_[field->fieldtype]);
 }
 
 static bool ir_builder_gen_field(ir_builder *self, ir_value *field)