]> git.rm.cloudns.org Git - xonotic/gmqcc.git/commitdiff
generate extparam protos before finalizing functions - not adding immediates/globals...
authorWolfgang Bumiller <wry.git@bumiller.com>
Wed, 17 Apr 2013 15:38:34 +0000 (17:38 +0200)
committerWolfgang Bumiller <wry.git@bumiller.com>
Wed, 17 Apr 2013 15:38:34 +0000 (17:38 +0200)
ir.c
ir.h
parser.c

diff --git a/ir.c b/ir.c
index 772ad1b746879858617e14e492ee1ebd1ffcf018..b178d3eb290f7b1bb89b44afcb82355be5f6398f 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -211,7 +211,6 @@ uint16_t type_not_instr[TYPE_COUNT] = {
 };
 
 /* protos */
-static ir_value* ir_gen_extparam_proto(ir_builder *ir);
 static void      ir_gen_extparam      (ir_builder *ir);
 
 /* error functions */
@@ -309,6 +308,7 @@ ir_builder* ir_builder_new(const char *modulename)
     self->max_globaltemps         = 0;
     self->first_common_local      = 0;
     self->max_locals              = 0;
+    self->max_used_params         = 0;
 
     self->str_immediate = 0;
     self->name = NULL;
@@ -1706,8 +1706,14 @@ ir_value* ir_call_value(ir_instr *self)
 
 void ir_call_param(ir_instr* self, ir_value *v)
 {
+    size_t *maxparams, param;
     vec_push(self->params, v);
     vec_push(v->reads, self);
+
+    param = vec_size(self->params);
+    maxparams = &self->owner->owner->owner->max_used_params;
+    if (param > *maxparams)
+        *maxparams = param;
 }
 
 /* binary op related code */
@@ -2182,17 +2188,7 @@ bool ir_function_allocate_locals(ir_function *self)
                 if (param < 8)
                     ir_value_code_setaddr(v, OFS_PARM0 + 3*param);
                 else {
-                    size_t nprotos = vec_size(self->owner->extparam_protos);
-                    ir_value *ep;
-                    param -= 8;
-                    if (nprotos > param)
-                        ep = self->owner->extparam_protos[param];
-                    else
-                    {
-                        ep = ir_gen_extparam_proto(self->owner);
-                        while (++nprotos <= param)
-                            ep = ir_gen_extparam_proto(self->owner);
-                    }
+                    ir_value *ep = self->owner->extparam_protos[param-=8];
                     ir_instr_op(v->writes[0], 0, ep, true);
                     call->params[param+8] = ep;
                 }
@@ -2450,20 +2446,30 @@ static bool ir_block_life_propagate(ir_block *self, bool *changed)
         if (instr->opcode == INSTR_MUL_VF)
         {
             value = instr->_ops[2];
-            /* the float source will get an additional lifetime */
-            if (ir_value_life_merge(value, instr->eid+1))
-                *changed = true;
-            if (value->memberof && ir_value_life_merge(value->memberof, instr->eid+1))
-                *changed = true;
+            if (value->store == store_value ||
+                value->store == store_local ||
+                value->store == store_param)
+            {
+                /* the float source will get an additional lifetime */
+                if (ir_value_life_merge(value, instr->eid+1))
+                    *changed = true;
+                if (value->memberof && ir_value_life_merge(value->memberof, instr->eid+1))
+                    *changed = true;
+            }
         }
         else if (instr->opcode == INSTR_MUL_FV || instr->opcode == INSTR_LOAD_V)
         {
             value = instr->_ops[1];
-            /* the float source will get an additional lifetime */
-            if (ir_value_life_merge(value, instr->eid+1))
-                *changed = true;
-            if (value->memberof && ir_value_life_merge(value->memberof, instr->eid+1))
-                *changed = true;
+            if (value->store == store_value ||
+                value->store == store_local ||
+                value->store == store_param)
+            {
+                /* the float source will get an additional lifetime */
+                if (ir_value_life_merge(value, instr->eid+1))
+                    *changed = true;
+                if (value->memberof && ir_value_life_merge(value->memberof, instr->eid+1))
+                    *changed = true;
+            }
         }
 
         for (o = 0; o < 3; ++o)
@@ -2499,6 +2505,10 @@ static bool ir_block_life_propagate(ir_block *self, bool *changed)
         for (p = 0; p < vec_size(instr->phi); ++p)
         {
             value = instr->phi[p].value;
+            if (value->store != store_value &&
+                value->store != store_local &&
+                value->store != store_param)
+                continue;
             if (!vec_ir_value_find(self->living, value, NULL))
                 vec_push(self->living, value);
             /* reading adds the full vector */
@@ -2519,6 +2529,10 @@ static bool ir_block_life_propagate(ir_block *self, bool *changed)
         for (p = 0; p < vec_size(instr->params); ++p)
         {
             value = instr->params[p];
+            if (value->store != store_value &&
+                value->store != store_local &&
+                value->store != store_param)
+                continue;
             if (!vec_ir_value_find(self->living, value, NULL))
                 vec_push(self->living, value);
             /* reading adds the full vector */
@@ -3571,6 +3585,16 @@ static bool ir_builder_gen_field(ir_builder *self, ir_value *field)
     return field->code.globaladdr >= 0;
 }
 
+bool ir_builder_prepare(ir_builder *self)
+{
+    size_t extparams = self->max_used_params;
+    if (extparams > 8) {
+        for (extparams -= 8; extparams; --extparams)
+            ir_gen_extparam_proto(self);
+    }
+    return true;
+}
+
 bool ir_builder_generate(ir_builder *self, const char *filename)
 {
     prog_section_statement stmt;
diff --git a/ir.h b/ir.h
index bce85f4fb5e09fd1da578266707158698801b37b..49da8897bd177560936ebfff6b33f1edf992b5ec 100644 (file)
--- a/ir.h
+++ b/ir.h
@@ -325,6 +325,9 @@ typedef struct ir_builder_s
     uint32_t      first_common_local;
     uint32_t      first_common_globaltemp;
 
+    /* highest number of parameters */
+    size_t        max_used_params;
+
     const char **filenames;
     qcint       *filestrings;
     /* we cache the #IMMEDIATE string here */
@@ -349,6 +352,7 @@ ir_value* ir_builder_create_field(ir_builder*, const char *name, int vtype);
 
 ir_value* ir_builder_get_va_count(ir_builder*);
 
+bool ir_builder_prepare(ir_builder *self);
 bool ir_builder_generate(ir_builder *self, const char *filename);
 
 void ir_builder_dump(ir_builder*, int (*oprintf)(const char*, ...));
index db9428967441fa5854217f64059bc91a19c90d1b..174c3ad4923ce3419ab7b99d7a44e1169897e6b1 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -6334,6 +6334,12 @@ bool parser_finish(parser_t *parser, const char *output)
     }
     if (OPTS_OPTION_BOOL(OPTION_DUMP))
         ir_builder_dump(ir, con_out);
+
+    if (!ir_builder_prepare(ir)) {
+        con_out("failed to prepare builder for output\n");
+        ir_builder_delete(ir);
+        return false;
+    }
 #if 0
     for (i = 0; i < vec_size(parser->functions); ++i) {
         if (!ir_function_finalize(parser->functions[i]->ir_func)) {