]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ir.c
Parsing of suffix operators, NOTE: applied like prefix operators just to get it commi...
[xonotic/gmqcc.git] / ir.c
diff --git a/ir.c b/ir.c
index bf0a7459120cb9ed2582832217ff8ec17b21d59c..6c1e58995a8b91a28a97841098d6980726d1c8ef 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -171,6 +171,28 @@ uint16_t type_ne_instr[TYPE_COUNT] = {
     AINSTR_END, /* array  */
 };
 
+uint16_t type_not_instr[TYPE_COUNT] = {
+    INSTR_NOT_F, /* should use I when having integer support */
+    INSTR_NOT_S,
+    INSTR_NOT_F,
+    INSTR_NOT_V,
+    INSTR_NOT_ENT,
+    INSTR_NOT_ENT,
+    INSTR_NOT_FNC,
+    INSTR_NOT_ENT, /* should use I */
+#if 0
+    INSTR_NOT_I, /* integer type */
+#else
+    INSTR_NOT_F,
+#endif
+
+    INSTR_NOT_V, /* variant, should never be accessed */
+
+    AINSTR_END, /* struct */
+    AINSTR_END, /* union  */
+    AINSTR_END, /* array  */
+};
+
 static void irerror(lex_ctx ctx, const char *msg, ...)
 {
     va_list ap;
@@ -520,7 +542,6 @@ bool ir_function_finalize(ir_function *self)
 
     if (!ir_function_calculate_liferanges(self))
         return false;
-
     if (!ir_function_allocate_locals(self))
         return false;
     return true;
@@ -2149,6 +2170,9 @@ static bool ir_block_living_add_instr(ir_block *self, size_t eid)
 static bool ir_block_life_prop_previous(ir_block* self, ir_block *prev, bool *changed)
 {
     size_t i;
+
+    (void)changed;
+
     /* values which have been read in a previous iteration are now
      * in the "living" array even if the previous block doesn't use them.
      * So we have to remove whatever does not exist in the previous block.
@@ -2522,6 +2546,15 @@ tailcall:
                 /* fixup the jump address */
                 code_statements[stidx].o2.s1 = (onfalse->code_start) - (stidx);
                 stmt.opcode = vec_last(code_statements).opcode;
+                if (stmt.opcode == INSTR_GOTO ||
+                    stmt.opcode == INSTR_IF ||
+                    stmt.opcode == INSTR_IFNOT ||
+                    stmt.opcode == INSTR_RETURN ||
+                    stmt.opcode == INSTR_DONE)
+                {
+                    /* no use jumping from here */
+                    return true;
+                }
                 /* may have been generated in the previous recursive call */
                 stmt.opcode = INSTR_GOTO;
                 stmt.o1.s1 = (onfalse->code_start) - vec_size(code_statements);
@@ -2570,20 +2603,20 @@ tailcall:
                 stmt.o2.u1 = OFS_PARM0 + 3 * p;
                 vec_push(code_statements, stmt);
             }
-            /* No whandle extparams */
+            /* Nohandle extparams */
             first = vec_size(instr->params);
             for (; p < first; ++p)
             {
                 ir_builder *ir = func->owner;
                 ir_value *param = instr->params[p];
-                ir_value *target;
+                ir_value *targetparam;
 
                 if (p-8 >= vec_size(ir->extparams)) {
                     irerror(instr->context, "Not enough extparam-globals have been created");
                     return false;
                 }
 
-                target = ir->extparams[p-8];
+                targetparam = ir->extparams[p-8];
 
                 stmt.opcode = INSTR_STORE_F;
                 stmt.o3.u1 = 0;
@@ -2593,7 +2626,7 @@ tailcall:
                 else
                     stmt.opcode = type_store_instr[param->vtype];
                 stmt.o1.u1 = ir_value_code_addr(param);
-                stmt.o2.u1 = ir_value_code_addr(target);
+                stmt.o2.u1 = ir_value_code_addr(targetparam);
                 vec_push(code_statements, stmt);
             }
 
@@ -2841,6 +2874,8 @@ static bool gen_global_function_code(ir_builder *ir, ir_value *global)
     prog_section_function *fundef;
     ir_function           *irfun;
 
+    (void)ir;
+
     irfun = global->constval.vfunc;
     if (!irfun) {
         irwarning(global->context, WARN_IMPLICIT_FUNCTION_POINTER,
@@ -3015,8 +3050,10 @@ static bool ir_builder_gen_field(ir_builder *self, ir_value *field)
     prog_section_def def;
     prog_section_field fld;
 
-    def.type   = field->vtype;
-    def.offset = vec_size(code_globals);
+    (void)self;
+
+    def.type   = (uint16_t)field->vtype;
+    def.offset = (uint16_t)vec_size(code_globals);
 
     /* create a global named the same as the field */
     if (opts_standard == COMPILER_GMQCC) {
@@ -3104,6 +3141,11 @@ bool ir_builder_generate(ir_builder *self, const char *filename)
         }
     }
 
+    if (vec_size(code_globals) >= 65536) {
+        irerror(vec_last(self->globals)->context, "This progs file would require more globals than the metadata can handle. Bailing out.");
+        return false;
+    }
+
     /* DP errors if the last instruction is not an INSTR_DONE
      * and for debugging purposes we add an additional AINSTR_END
      * to the end of functions, so here it goes:
@@ -3132,7 +3174,7 @@ bool ir_builder_generate(ir_builder *self, const char *filename)
 const char *qc_opname(int op)
 {
     if (op < 0) return "<INVALID>";
-    if (op < ( sizeof(asm_instr) / sizeof(asm_instr[0]) ))
+    if (op < (int)( sizeof(asm_instr) / sizeof(asm_instr[0]) ))
         return asm_instr[op].m;
     switch (op) {
         case VINSTR_PHI:  return "PHI";
@@ -3228,8 +3270,7 @@ void ir_block_dump(ir_block* b, char *ind,
     ind[strlen(ind)-1] = 0;
 }
 
-void dump_phi(ir_instr *in, char *ind,
-              int (*oprintf)(const char*, ...))
+void dump_phi(ir_instr *in, int (*oprintf)(const char*, ...))
 {
     size_t i;
     oprintf("%s <- phi ", in->_ops[0]->name);
@@ -3250,7 +3291,7 @@ void ir_instr_dump(ir_instr *in, char *ind,
     oprintf("%s (%i) ", ind, (int)in->eid);
 
     if (in->opcode == VINSTR_PHI) {
-        dump_phi(in, ind, oprintf);
+        dump_phi(in, oprintf);
         return;
     }
 
@@ -3299,6 +3340,26 @@ void ir_instr_dump(ir_instr *in, char *ind,
     ind[strlen(ind)-1] = 0;
 }
 
+void ir_value_dump_string(const char *str, int (*oprintf)(const char*, ...))
+{
+    oprintf("\"");
+    for (; *str; ++str) {
+        switch (*str) {
+            case '\n': oprintf("\\n"); break;
+            case '\r': oprintf("\\r"); break;
+            case '\t': oprintf("\\t"); break;
+            case '\v': oprintf("\\v"); break;
+            case '\f': oprintf("\\f"); break;
+            case '\b': oprintf("\\b"); break;
+            case '\a': oprintf("\\a"); break;
+            case '\\': oprintf("\\\\"); break;
+            case '"': oprintf("\\\""); break;
+            default: oprintf("%c", *str); break;
+        }
+    }
+    oprintf("\"");
+}
+
 void ir_value_dump(ir_value* v, int (*oprintf)(const char*, ...))
 {
     if (v->isconst) {
@@ -3323,7 +3384,7 @@ void ir_value_dump(ir_value* v, int (*oprintf)(const char*, ...))
                 oprintf("(entity)");
                 break;
             case TYPE_STRING:
-                oprintf("\"%s\"", v->constval.vstring);
+                ir_value_dump_string(v->constval.vstring, oprintf);
                 break;
 #if 0
             case TYPE_INTEGER: