]> de.git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
Make functions copy their extparams
authorWolfgang (Blub) Bumiller <blub@speed.at>
Sun, 18 Nov 2012 19:06:28 +0000 (20:06 +0100)
committerWolfgang (Blub) Bumiller <blub@speed.at>
Sun, 18 Nov 2012 19:06:28 +0000 (20:06 +0100)
ast.c
ir.c
ir.h
parser.c

diff --git a/ast.c b/ast.c
index 9e59ca917d73c9ed561b10f33bcf8087f01b3c28..3fc7353206e80c690c9d4021aab20d4270b7e9a2 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -1247,6 +1247,7 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
 
     /* fill the parameter list */
     ec = &self->vtype->expression;
+    irf->max_parameters = vec_size(ec->params);
     for (i = 0; i < vec_size(ec->params); ++i)
     {
         vec_push(irf->params, ec->params[i]->expression.vtype);
diff --git a/ir.c b/ir.c
index f652f6a11767a766112cedb3ae6ccda6588ba8a8..1fd94a08a13fc482409d51c58c1d8a91c61ed606 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -259,6 +259,7 @@ ir_builder* ir_builder_new(const char *modulename)
     self->functions   = NULL;
     self->globals     = NULL;
     self->fields      = NULL;
+    self->extparams   = NULL;
     self->filenames   = NULL;
     self->filestrings = NULL;
 
@@ -280,6 +281,10 @@ void ir_builder_delete(ir_builder* self)
         ir_function_delete_quick(self->functions[i]);
     }
     vec_free(self->functions);
+    for (i = 0; i != vec_size(self->extparams); ++i) {
+        ir_value_delete(self->extparams[i]);
+    }
+    vec_free(self->extparams);
     for (i = 0; i != vec_size(self->globals); ++i) {
         ir_value_delete(self->globals[i]);
     }
@@ -427,6 +432,8 @@ ir_function* ir_function_new(ir_builder* owner, int outtype)
     self->values = NULL;
     self->locals = NULL;
 
+    self->max_parameters = 0;
+
     self->code_function_def = -1;
     self->allocated_locals = 0;
 
@@ -2698,6 +2705,62 @@ static bool gen_global_function(ir_builder *ir, ir_value *global)
     return true;
 }
 
+static void ir_gen_extparam(ir_builder *ir)
+{
+    prog_section_def def;
+    ir_value        *global;
+    char             name[128];
+
+    snprintf(name, sizeof(name), "EXTPARM%i", (int)(vec_size(ir->extparams)+8));
+    global = ir_value_var(name, store_global, TYPE_VECTOR);
+
+    def.name = code_genstring(name);
+    def.type = TYPE_VECTOR;
+    def.offset = vec_size(code_globals);
+
+    vec_push(code_defs, def);
+    ir_value_code_setaddr(global, def.offset);
+    vec_push(code_globals, 0);
+    vec_push(code_globals, 0);
+    vec_push(code_globals, 0);
+
+    vec_push(ir->extparams, global);
+}
+
+static bool gen_function_extparam_copy(ir_function *self)
+{
+    size_t i, ext;
+
+    ir_builder *ir = self->owner;
+    ir_value   *ep;
+    prog_section_statement stmt;
+
+    if (!self->max_parameters)
+        return true;
+
+    stmt.opcode = INSTR_STORE_F;
+    stmt.o3.s1 = 0;
+    for (i = 8; i < self->max_parameters; ++i) {
+        ext = i - 8;
+        if (ext >= vec_size(ir->extparams))
+            ir_gen_extparam(ir);
+
+        ep = ir->extparams[ext];
+
+        stmt.opcode = type_store_instr[self->locals[i]->vtype];
+        if (self->locals[i]->vtype == TYPE_FIELD &&
+            self->locals[i]->fieldtype == TYPE_VECTOR)
+        {
+            stmt.opcode = INSTR_STORE_V;
+        }
+        stmt.o1.u1 = ir_value_code_addr(ep);
+        stmt.o2.u1 = ir_value_code_addr(self->locals[i]);
+        vec_push(code_statements, stmt);
+    }
+
+    return true;
+}
+
 static bool gen_global_function_code(ir_builder *ir, ir_value *global)
 {
     prog_section_function *fundef;
@@ -2721,6 +2784,10 @@ static bool gen_global_function_code(ir_builder *ir, ir_value *global)
     fundef = &code_functions[irfun->code_function_def];
 
     fundef->entry = vec_size(code_statements);
+    if (!gen_function_extparam_copy(irfun)) {
+        irerror(irfun->context, "Failed to generate extparam-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;
diff --git a/ir.h b/ir.h
index 9b5171d26908dd6423ef07859d5cc830d7b746c6..00e2ddc0382229d5d60f58a12bbafe6388e81b5d 100644 (file)
--- a/ir.h
+++ b/ir.h
@@ -240,6 +240,9 @@ typedef struct ir_function_s
     /* locally defined variables */
     ir_value **locals;
 
+    /* how many of the locals are parameters */
+    size_t max_parameters;
+
     size_t allocated_locals;
 
     ir_block*     first;
@@ -290,6 +293,8 @@ typedef struct ir_builder_s
     ir_value    **globals;
     ir_value    **fields;
 
+    ir_value    **extparams;
+
     const char **filenames;
     qcint       *filestrings;
     /* we cache the #IMMEDIATE string here */
index 600b088008d33e9472db1c57988cebb31d7b9f57..25c9c74c9fd18c7bc45bd3e6da80d00f7874b79f 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -2638,7 +2638,7 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
 
     /* sanity check */
     if (vec_size(params) > 8 && opts_standard == COMPILER_QCC)
-        parsewarning(parser, WARN_EXTENSIONS, "more than 8 parameters are not supported by this standard");
+        (void)!parsewarning(parser, WARN_EXTENSIONS, "more than 8 parameters are not supported by this standard");
 
     /* parse-out */
     if (!parser_next(parser)) {