]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ir.c
Merge branch 'master' into blub/bc3
[xonotic/gmqcc.git] / ir.c
diff --git a/ir.c b/ir.c
index 78dbc8ab3ab7c503c5cd81abdd079672fe82ae2d..7f9cdb1e4d7a57359fb3dc14d2fdba8ad6bce021 100644 (file)
--- a/ir.c
+++ b/ir.c
  * Type sizes used at multiple points in the IR codegen
  */
 
+const char *type_name[TYPE_COUNT] = {
+    "void",
+    "string",
+    "float",
+    "vector",
+    "entity",
+    "field",
+    "function",
+    "pointer",
+#if 0
+    "integer",
+#endif
+    "quaternion",
+    "matrix",
+    "variant"
+};
+
 size_t type_sizeof[TYPE_COUNT] = {
     1, /* TYPE_VOID     */
     1, /* TYPE_STRING   */
@@ -64,6 +81,24 @@ uint16_t type_store_instr[TYPE_COUNT] = {
     INSTR_STORE_M, /* variant, should never be accessed */
 };
 
+uint16_t type_storep_instr[TYPE_COUNT] = {
+    INSTR_STOREP_F, /* should use I when having integer support */
+    INSTR_STOREP_S,
+    INSTR_STOREP_F,
+    INSTR_STOREP_V,
+    INSTR_STOREP_ENT,
+    INSTR_STOREP_FLD,
+    INSTR_STOREP_FNC,
+    INSTR_STOREP_ENT, /* should use I */
+#if 0
+    INSTR_STOREP_ENT, /* integer type */
+#endif
+    INSTR_STOREP_Q,
+    INSTR_STOREP_M,
+
+    INSTR_STOREP_M, /* variant, should never be accessed */
+};
+
 MEM_VEC_FUNCTIONS(ir_value_vector, ir_value*, v)
 
 /***********************************************************************
@@ -171,9 +206,14 @@ ir_value* ir_builder_get_global(ir_builder *self, const char *name)
 
 ir_value* ir_builder_create_global(ir_builder *self, const char *name, int vtype)
 {
-    ir_value *ve = ir_builder_get_global(self, name);
-    if (ve) {
-        return NULL;
+    ir_value *ve;
+
+    if (name && name[0] != '#')
+    {
+        ve = ir_builder_get_global(self, name);
+        if (ve) {
+            return NULL;
+        }
     }
 
     ve = ir_value_var(name, store_global, vtype);
@@ -301,14 +341,21 @@ ir_value* ir_function_get_local(ir_function *self, const char *name)
     return NULL;
 }
 
-ir_value* ir_function_create_local(ir_function *self, const char *name, int vtype)
+ir_value* ir_function_create_local(ir_function *self, const char *name, int vtype, bool param)
 {
     ir_value *ve = ir_function_get_local(self, name);
     if (ve) {
         return NULL;
     }
 
-    ve = ir_value_var(name, store_local, vtype);
+    if (param &&
+        self->locals_count &&
+        self->locals[self->locals_count-1]->store != store_param) {
+        printf("cannot add parameters after adding locals\n");
+        return NULL;
+    }
+
+    ve = ir_value_var(name, (param ? store_param : store_local), vtype);
     if (!ir_function_locals_add(self, ve)) {
         ir_value_delete(ve);
         return NULL;
@@ -561,7 +608,7 @@ bool ir_value_set_quaternion(ir_value *self, quaternion v)
 {
     if (self->vtype != TYPE_QUATERNION)
         return false;
-    self->constval.vquat = v;
+    memcpy(&self->constval.vquat, v, sizeof(self->constval.vquat));
     self->isconst = true;
     return true;
 }
@@ -570,7 +617,7 @@ bool ir_value_set_matrix(ir_value *self, matrix v)
 {
     if (self->vtype != TYPE_MATRIX)
         return false;
-    self->constval.vmat = v;
+    memcpy(&self->constval.vmat, v, sizeof(self->constval.vmat));
     self->isconst = true;
     return true;
 }
@@ -853,52 +900,14 @@ bool ir_block_create_store(ir_block *self, ir_value *target, ir_value *what)
     else
         vtype = target->vtype;
 
-    switch (vtype) {
-        case TYPE_FLOAT:
-#if 0
-            if (what->vtype == TYPE_INTEGER)
-                op = INSTR_CONV_ITOF;
-            else
-#endif
-                op = INSTR_STORE_F;
-            break;
-        case TYPE_VECTOR:
-            op = INSTR_STORE_V;
-            break;
-        case TYPE_ENTITY:
-            op = INSTR_STORE_ENT;
-            break;
-        case TYPE_STRING:
-            op = INSTR_STORE_S;
-            break;
-        case TYPE_FIELD:
-            op = INSTR_STORE_FLD;
-            break;
-#if 0
-        case TYPE_INTEGER:
-            if (what->vtype == TYPE_INTEGER)
-                op = INSTR_CONV_FTOI;
-            else
-                op = INSTR_STORE_I;
-            break;
-#endif
-        case TYPE_POINTER:
 #if 0
-            op = INSTR_STORE_I;
-#else
-            op = INSTR_STORE_ENT;
+    if      (vtype == TYPE_FLOAT   && what->vtype == TYPE_INTEGER)
+        op = INSTR_CONV_ITOF;
+    else if (vtype == TYPE_INTEGER && what->vtype == TYPE_FLOAT)
+        op = INSTR_CONV_FTOI;
 #endif
-            break;
-        case TYPE_QUATERNION:
-            op = INSTR_STORE_Q;
-            break;
-        case TYPE_MATRIX:
-            op = INSTR_STORE_M;
-            break;
-        default:
-            /* Unknown type */
-            return false;
-    }
+        op = type_store_instr[vtype];
+
     return ir_block_create_store_op(self, op, target, what);
 }
 
@@ -915,44 +924,7 @@ bool ir_block_create_storep(ir_block *self, ir_value *target, ir_value *what)
      */
     vtype = what->vtype;
 
-    switch (vtype) {
-        case TYPE_FLOAT:
-            op = INSTR_STOREP_F;
-            break;
-        case TYPE_VECTOR:
-            op = INSTR_STOREP_V;
-            break;
-        case TYPE_ENTITY:
-            op = INSTR_STOREP_ENT;
-            break;
-        case TYPE_STRING:
-            op = INSTR_STOREP_S;
-            break;
-        case TYPE_FIELD:
-            op = INSTR_STOREP_FLD;
-            break;
-#if 0
-        case TYPE_INTEGER:
-            op = INSTR_STOREP_I;
-            break;
-#endif
-        case TYPE_POINTER:
-#if 0
-            op = INSTR_STOREP_I;
-#else
-            op = INSTR_STOREP_ENT;
-#endif
-            break;
-        case TYPE_QUATERNION:
-            op = INSTR_STOREP_Q;
-            break;
-        case TYPE_MATRIX:
-            op = INSTR_STOREP_M;
-            break;
-        default:
-            /* Unknown type */
-            return false;
-    }
+    op = type_storep_instr[vtype];
     return ir_block_create_store_op(self, op, target, what);
 }
 
@@ -1210,6 +1182,7 @@ ir_value* ir_block_create_binop(ir_block *self,
         case INSTR_ADD_V:
         case INSTR_SUB_V:
         case INSTR_MUL_VF:
+        case INSTR_MUL_FV:
 #if 0
         case INSTR_DIV_VF:
         case INSTR_MUL_IV:
@@ -1550,7 +1523,7 @@ static bool ir_block_naive_phi(ir_block *self)
                 if (v->writes[w]->_ops[0] == v)
                     v->writes[w]->_ops[0] = instr->_ops[0];
 
-                if (old->store != store_value && old->store != store_local)
+                if (old->store != store_value && old->store != store_local && old->store != store_param)
                 {
                     /* If it originally wrote to a global we need to store the value
                      * there as welli
@@ -1930,8 +1903,11 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change
             value = instr->_ops[o];
 
             /* We only care about locals */
+            /* we also calculate parameter liferanges so that locals
+             * can take up parameter slots */
             if (value->store != store_value &&
-                value->store != store_local)
+                value->store != store_local &&
+                value->store != store_param)
                 continue;
 
             /* read operands */
@@ -2454,6 +2430,7 @@ static bool gen_global_function(ir_builder *ir, ir_value *global)
 
 static bool ir_builder_gen_global(ir_builder *self, ir_value *global)
 {
+    size_t           i;
     int32_t         *iptr;
     prog_section_def def;
 
@@ -2509,7 +2486,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global)
             global->code.globaladdr = code_globals_add(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)
             {
                 if (code_globals_add(iptr[d]) < 0)
                     return false;
@@ -2518,7 +2495,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global)
             global->code.globaladdr = code_globals_add(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)
             {
                 if (code_globals_add(0) < 0)
                     return false;
@@ -2535,8 +2512,8 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global)
     case TYPE_VARIANT:
         /* assume biggest type */
             global->code.globaladdr = code_globals_add(0);
-            code_globals_add(0);
-            code_globals_add(0);
+            for (i = 1; i < type_sizeof[TYPE_VARIANT]; ++i)
+                code_globals_add(0);
             return true;
     default:
         /* refuse to create 'void' type or any other fancy business. */
@@ -2606,6 +2583,10 @@ void ir_function_dump(ir_function *f, char *ind,
                       int (*oprintf)(const char*, ...))
 {
        size_t i;
+       if (f->builtin != 0) {
+           oprintf("%sfunction %s = builtin %i\n", ind, f->name, -f->builtin);
+           return;
+       }
        oprintf("%sfunction %s\n", ind, f->name);
        strncat(ind, "\t", IND_BUFSZ);
        if (f->locals_count)