]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ir.c
gitignore: be more clever
[xonotic/gmqcc.git] / ir.c
diff --git a/ir.c b/ir.c
index 5fde1bad5b466db162ee01d218112d36bb77cc5d..a641310644dc950712894eef33cfe9965c9c1d09 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -320,6 +320,8 @@ ir_builder* ir_builder_new(const char *modulename)
     self->nil = ir_value_var("nil", store_value, TYPE_NIL);
     self->nil->cvq = CV_CONST;
 
+    self->reserved_va_count = NULL;
+
     return self;
 }
 
@@ -418,6 +420,13 @@ ir_value* ir_builder_create_global(ir_builder *self, const char *name, int vtype
     return ve;
 }
 
+ir_value* ir_builder_get_va_count(ir_builder *self)
+{
+    if (self->reserved_va_count)
+        return self->reserved_va_count;
+    return (self->reserved_va_count = ir_builder_create_global(self, "reserved:va_count", TYPE_FLOAT));
+}
+
 ir_value* ir_builder_get_field(ir_builder *self, const char *name)
 {
     return (ir_value*)util_htget(self->htfields, name);
@@ -476,6 +485,8 @@ ir_function* ir_function_new(ir_builder* owner, int outtype)
     self->values = NULL;
     self->locals = NULL;
 
+    self->max_varargs = 0;
+
     self->code_function_def = -1;
     self->allocated_locals = 0;
     self->globaltemps      = 0;
@@ -1018,6 +1029,7 @@ ir_value* ir_value_var(const char *name, int storetype, int vtype)
     self->fieldtype = TYPE_VOID;
     self->outtype = TYPE_VOID;
     self->store = storetype;
+    self->flags = 0;
 
     self->reads  = NULL;
     self->writes = NULL;
@@ -1997,6 +2009,7 @@ void ir_function_enumerate(ir_function *self)
         /* each block now gets an additional "entry" instruction id
          * we can use to avoid point-life issues
          */
+        self->blocks[i]->entry_id = instruction_id;
         ++instruction_id;
 
         self->blocks[i]->eid = i;
@@ -2191,7 +2204,7 @@ bool ir_function_allocate_locals(ir_function *self)
     for (i = 0; i < vec_size(self->locals); ++i)
     {
         v = self->locals[i];
-        if (!OPTS_OPTIMIZATION(OPTIM_LOCAL_TEMPS)) {
+        if ((self->flags & IR_FLAG_MASK_NO_LOCAL_TEMPS) || !OPTS_OPTIMIZATION(OPTIM_LOCAL_TEMPS)) {
             v->locked      = true;
             v->unique_life = true;
         }
@@ -2297,8 +2310,6 @@ bool ir_function_allocate_locals(ir_function *self)
     /* Locals need to know their new position */
     for (i = 0; i < vec_size(self->locals); ++i) {
         v = self->locals[i];
-        if (i >= vec_size(self->params) && !vec_size(v->life))
-            continue;
         if (v->locked || !opt_gt)
             v->code.local = lockalloc.positions[v->code.local];
         else
@@ -2307,8 +2318,6 @@ bool ir_function_allocate_locals(ir_function *self)
     /* Take over the actual slot positions on values */
     for (i = 0; i < vec_size(self->values); ++i) {
         v = self->values[i];
-        if (!vec_size(v->life))
-            continue;
         if (v->locked || !opt_gt)
             v->code.local = lockalloc.positions[v->code.local];
         else
@@ -2625,7 +2634,7 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change
         *changed = *changed || tempbool;
     }
     /* the "entry" instruction ID */
-    tempbool = ir_block_living_add_instr(self, instr->eid-1);
+    tempbool = ir_block_living_add_instr(self, self->entry_id);
     *changed = *changed || tempbool;
 
     if (self->run_id == self->owner->run_id)
@@ -3163,6 +3172,42 @@ static bool gen_function_extparam_copy(ir_function *self)
     return true;
 }
 
+static bool gen_function_varargs_copy(ir_function *self)
+{
+    size_t i, ext, numparams, maxparams;
+
+    ir_builder *ir = self->owner;
+    ir_value   *ep;
+    prog_section_statement stmt;
+
+    numparams = vec_size(self->params);
+    if (!numparams)
+        return true;
+
+    stmt.opcode = INSTR_STORE_V;
+    stmt.o3.s1 = 0;
+    maxparams = numparams + self->max_varargs;
+    for (i = numparams; i < maxparams; ++i) {
+        if (i <= 8) {
+            stmt.o1.u1 = OFS_PARM0 + 3*i;
+            stmt.o2.u1 = ir_value_code_addr(self->locals[i]);
+            code_push_statement(&stmt, self->context.line);
+            continue;
+        }
+        ext = i - 8;
+        if (ext >= vec_size(ir->extparams))
+            ir_gen_extparam(ir);
+
+        ep = ir->extparams[ext];
+
+        stmt.o1.u1 = ir_value_code_addr(ep);
+        stmt.o2.u1 = ir_value_code_addr(self->locals[i]);
+        code_push_statement(&stmt, self->context.line);
+    }
+
+    return true;
+}
+
 static bool gen_function_locals(ir_builder *ir, ir_value *global)
 {
     prog_section_function *def;
@@ -3244,6 +3289,10 @@ static bool gen_global_function_code(ir_builder *ir, ir_value *global)
         irerror(irfun->context, "Failed to generate extparam-copy code for function %s", irfun->name);
         return false;
     }
+    if (irfun->max_varargs && !gen_function_varargs_copy(irfun)) {
+        irerror(irfun->context, "Failed to generate vararg-copy code for function %s", irfun->name);
+        return false;
+    }
     if (!gen_function_code(irfun)) {
         irerror(irfun->context, "Failed to generate code for function %s", irfun->name);
         return false;
@@ -3322,6 +3371,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc
         pushdef = true;
 
         if (OPTS_OPTIMIZATION(OPTIM_STRIP_CONSTANT_NAMES) &&
+            !(global->flags & IR_FLAG_INCLUDE_DEF) &&
             (global->name[0] == '#' || global->cvq == CV_CONST))
         {
             pushdef = false;