]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ir.c
ir_block_create_{phi,call} now check self->final
[xonotic/gmqcc.git] / ir.c
diff --git a/ir.c b/ir.c
index 9578e44a224ffa72d301114ceee755b23c48a836..009cf764a7e26b04ce78df67fc28be4f3c19abe1 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -1357,9 +1357,6 @@ bool ir_block_create_store_op(ir_block *self, lex_ctx ctx, int op, ir_value *tar
         irerror(self->context, "unreachable statement (%s)", self->label);
         return false;
     }
-    in = ir_instr_new(ctx, self, op);
-    if (!in)
-        return false;
 
     if (target->store == store_value &&
         (op < INSTR_STOREP_F || op > INSTR_STOREP_FNC))
@@ -1370,9 +1367,14 @@ bool ir_block_create_store_op(ir_block *self, lex_ctx ctx, int op, ir_value *tar
         return false;
     }
 
+    in = ir_instr_new(ctx, self, op);
+    if (!in)
+        return false;
+
     if (!ir_instr_op(in, 0, target, true) ||
         !ir_instr_op(in, 1, what, false))
     {
+        ir_instr_delete(in);
         return false;
     }
     vec_push(self->instr, in);
@@ -1439,8 +1441,10 @@ bool ir_block_create_return(ir_block *self, lex_ctx ctx, ir_value *v)
     if (!in)
         return false;
 
-    if (v && !ir_instr_op(in, 0, v, false))
+    if (v && !ir_instr_op(in, 0, v, false)) {
+        ir_instr_delete(in);
         return false;
+    }
 
     vec_push(self->instr, in);
     return true;
@@ -1521,6 +1525,10 @@ ir_instr* ir_block_create_phi(ir_block *self, lex_ctx ctx, const char *label, in
 {
     ir_value *out;
     ir_instr *in;
+    if (self->final) {
+        irerror(self->context, "unreachable statement (%s)", self->label);
+        return false;
+    }
     in = ir_instr_new(ctx, self, VINSTR_PHI);
     if (!in)
         return NULL;
@@ -1562,11 +1570,15 @@ void ir_phi_add(ir_instr* self, ir_block *b, ir_value *v)
 }
 
 /* call related code */
-ir_instr* ir_block_create_call(ir_block *self, lex_ctx ctx, const char *label, ir_value *func)
+ir_instr* ir_block_create_call(ir_block *self, lex_ctx ctx, const char *label, ir_value *func, bool noreturn)
 {
     ir_value *out;
     ir_instr *in;
-    in = ir_instr_new(ctx, self, INSTR_CALL0);
+    if (self->final) {
+        irerror(self->context, "unreachable statement (%s)", self->label);
+        return false;
+    }
+    in = ir_instr_new(ctx, self, (noreturn ? VINSTR_NRCALL : INSTR_CALL0));
     if (!in)
         return NULL;
     out = ir_value_out(self->owner, label, (func->outtype == TYPE_VOID) ? store_return : store_value, func->outtype);
@@ -2712,12 +2724,14 @@ tailcall:
             if (ontrue->generated) {
                 stmt.opcode = INSTR_IF;
                 stmt.o2.s1 = (ontrue->code_start) - vec_size(code_statements);
-                code_push_statement(&stmt, instr->context.line);
+                if (stmt.o2.s1 != 1)
+                    code_push_statement(&stmt, instr->context.line);
             }
             if (onfalse->generated) {
                 stmt.opcode = INSTR_IFNOT;
                 stmt.o2.s1 = (onfalse->code_start) - vec_size(code_statements);
-                code_push_statement(&stmt, instr->context.line);
+                if (stmt.o2.s1 != 1)
+                    code_push_statement(&stmt, instr->context.line);
             }
             if (!ontrue->generated) {
                 if (onfalse->generated) {
@@ -2751,6 +2765,12 @@ tailcall:
             if (onfalse->generated) {
                 /* fixup the jump address */
                 code_statements[stidx].o2.s1 = (onfalse->code_start) - (stidx);
+                if (code_statements[stidx].o2.s1 == 1) {
+                    code_statements[stidx] = code_statements[stidx+1];
+                    if (code_statements[stidx].o1.s1 < 0)
+                        code_statements[stidx].o1.s1++;
+                    code_pop_statement();
+                }
                 stmt.opcode = vec_last(code_statements).opcode;
                 if (stmt.opcode == INSTR_GOTO ||
                     stmt.opcode == INSTR_IF ||
@@ -2770,12 +2790,20 @@ tailcall:
                     code_push_statement(&stmt, instr->context.line);
                 return true;
             }
+            else if (code_statements[stidx].o2.s1 == 1) {
+                code_statements[stidx] = code_statements[stidx+1];
+                if (code_statements[stidx].o1.s1 < 0)
+                    code_statements[stidx].o1.s1++;
+                code_pop_statement();
+            }
             /* if not, generate now */
             block = onfalse;
             goto tailcall;
         }
 
-        if (instr->opcode >= INSTR_CALL0 && instr->opcode <= INSTR_CALL8) {
+        if ( (instr->opcode >= INSTR_CALL0 && instr->opcode <= INSTR_CALL8)
+           || instr->opcode == VINSTR_NRCALL)
+        {
             /* Trivial call translation:
              * copy all params to OFS_PARM*
              * if the output's storetype is not store_return,
@@ -3152,9 +3180,11 @@ static void gen_vector_defs(prog_section_def def, const char *name)
     char  *component;
     size_t len, i;
 
-    if (!name)
+    if (!name || OPTS_FLAG(SINGLE_VECTOR_DEFS))
         return;
 
+    def.type = TYPE_FLOAT;
+
     len = strlen(name);
 
     component = (char*)mem_a(len+3);
@@ -3178,9 +3208,11 @@ static void gen_vector_fields(prog_section_field fld, const char *name)
     char  *component;
     size_t len, i;
 
-    if (!name)
+    if (!name || OPTS_FLAG(SINGLE_VECTOR_DEFS))
         return;
 
+    fld.type = TYPE_FLOAT;
+
     len = strlen(name);
 
     component = (char*)mem_a(len+3);
@@ -3641,7 +3673,7 @@ void ir_instr_dump(ir_instr *in, char *ind,
         if (in->_ops[1] || in->_ops[2])
             oprintf(" <- ");
     }
-    if (in->opcode == INSTR_CALL0) {
+    if (in->opcode == INSTR_CALL0 || in->opcode == VINSTR_NRCALL) {
         oprintf("CALL%i\t", vec_size(in->params));
     } else
         oprintf("%s\t", qc_opname(in->opcode));