]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ast.c
Remove trailing whitespace for Blub.
[xonotic/gmqcc.git] / ast.c
diff --git a/ast.c b/ast.c
index a73c586bfbd5458d4c3a2d91032c674f3fdf73e4..a622db649953e4c540844ace93e3c7abb5b4fd6a 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -435,6 +435,8 @@ ast_binstore* ast_binstore_new(lex_ctx ctx, int storop, int op,
     self->dest    = left;
     self->source  = right;
 
+    self->keep_dest = false;
+
     self->expression.vtype = left->expression.vtype;
     if (left->expression.next) {
         self->expression.next = ast_type_copy(ctx, left);
@@ -451,7 +453,8 @@ ast_binstore* ast_binstore_new(lex_ctx ctx, int storop, int op,
 
 void ast_binstore_delete(ast_binstore *self)
 {
-    ast_unref(self->dest);
+    if (!self->keep_dest)
+        ast_unref(self->dest);
     ast_unref(self->source);
     ast_expression_delete((ast_expression*)self);
     mem_d(self);
@@ -844,6 +847,11 @@ void ast_goto_delete(ast_goto *self)
     mem_d(self);
 }
 
+void ast_goto_set_label(ast_goto *self, ast_label *label)
+{
+    self->target = label;
+}
+
 ast_call* ast_call_new(lex_ctx ctx,
                        ast_expression *funcexpr)
 {
@@ -1145,7 +1153,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
 
             v = ir_builder_create_field(ir, self->name, vtype);
             if (!v) {
-                asterror(ast_ctx(self), "ir_builder_create_global failed");
+                asterror(ast_ctx(self), "ir_builder_create_global failed on `%s`", self->name);
                 return false;
             }
             if (vtype == TYPE_FIELD)
@@ -1164,7 +1172,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
                 array->ir_values[ai] = ir_builder_create_field(ir, name, vtype);
                 if (!array->ir_values[ai]) {
                     mem_d(name);
-                    asterror(ast_ctx(self), "ir_builder_create_global failed");
+                    asterror(ast_ctx(self), "ir_builder_create_global failed on `%s`", name);
                     return false;
                 }
                 if (vtype == TYPE_FIELD)
@@ -1198,7 +1206,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
 
         v = ir_builder_create_global(ir, self->name, vtype);
         if (!v) {
-            asterror(ast_ctx(self), "ir_builder_create_global failed");
+            asterror(ast_ctx(self), "ir_builder_create_global failed `%s`", self->name);
             return false;
         }
         if (vtype == TYPE_FIELD)
@@ -1216,7 +1224,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
             self->ir_values[ai] = ir_builder_create_global(ir, name, vtype);
             if (!self->ir_values[ai]) {
                 mem_d(name);
-                asterror(ast_ctx(self), "ir_builder_create_global failed");
+                asterror(ast_ctx(self), "ir_builder_create_global failed `%s`", name);
                 return false;
             }
             if (vtype == TYPE_FIELD)
@@ -1232,7 +1240,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
          */
         v = ir_builder_create_global(ir, self->name, self->expression.vtype);
         if (!v) {
-            asterror(ast_ctx(self), "ir_builder_create_global failed");
+            asterror(ast_ctx(self), "ir_builder_create_global failed on `%s`", self->name);
             return false;
         }
         if (self->expression.vtype == TYPE_FIELD)
@@ -1332,7 +1340,7 @@ bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
             snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
             self->ir_values[ai] = ir_function_create_local(func, name, vtype, param);
             if (!self->ir_values[ai]) {
-                asterror(ast_ctx(self), "ir_builder_create_global failed");
+                asterror(ast_ctx(self), "ir_builder_create_global failed on `%s`", name);
                 return false;
             }
             if (vtype == TYPE_FIELD)
@@ -1432,7 +1440,7 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
         return false;
     }
 
-    self->curblock = ir_function_create_block(irf, "entry");
+    self->curblock = ir_function_create_block(ast_ctx(self), irf, "entry");
     if (!self->curblock) {
         asterror(ast_ctx(self), "failed to allocate entry block for `%s`", self->name);
         return false;
@@ -1511,7 +1519,7 @@ bool ast_block_codegen(ast_block *self, ast_function *func, bool lvalue, ir_valu
     for (i = 0; i < vec_size(self->exprs); ++i)
     {
         ast_expression_codegen *gen = self->exprs[i]->expression.codegen;
-        if (func->curblock->final) {
+        if (func->curblock->final && !ast_istype(self->exprs[i], ast_label)) {
             asterror(ast_ctx(self->exprs[i]), "unreachable statement");
             return false;
         }
@@ -1657,7 +1665,7 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
          */
 
         merge_id = vec_size(func->ir_func->blocks);
-        merge = ir_function_create_block(func->ir_func, ast_function_label(func, "sce_merge"));
+        merge = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_merge"));
 
         cgen = self->left->expression.codegen;
         if (!(*cgen)((ast_expression*)(self->left), func, false, &left))
@@ -1675,7 +1683,7 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
         }
         from_left = func->curblock;
 
-        other = ir_function_create_block(func->ir_func, ast_function_label(func, "sce_other"));
+        other = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_other"));
         if ( !(self->op == INSTR_OR) != !OPTS_FLAG(PERL_LOGIC) ) {
             if (!ir_block_create_if(func->curblock, left, other, merge))
                 return false;
@@ -2040,7 +2048,7 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva
         }
 
         cgen = self->index->expression.codegen;
-        if (!(*cgen)((ast_expression*)(self->index), func, true, &iridx))
+        if (!(*cgen)((ast_expression*)(self->index), func, false, &iridx))
             return false;
 
         cgen = arr->getter->expression.codegen;
@@ -2103,7 +2111,7 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va
 
     if (self->on_true) {
         /* create on-true block */
-        ontrue = ir_function_create_block(func->ir_func, ast_function_label(func, "ontrue"));
+        ontrue = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "ontrue"));
         if (!ontrue)
             return false;
 
@@ -2123,7 +2131,7 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va
     /* on-false path */
     if (self->on_false) {
         /* create on-false block */
-        onfalse = ir_function_create_block(func->ir_func, ast_function_label(func, "onfalse"));
+        onfalse = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "onfalse"));
         if (!onfalse)
             return false;
 
@@ -2141,7 +2149,7 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va
         onfalse = NULL;
 
     /* Merge block were they all merge in to */
-    merge = ir_function_create_block(func->ir_func, ast_function_label(func, "endif"));
+    merge = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "endif"));
     if (!merge)
         return false;
     /* add jumps ot the merge block */
@@ -2174,8 +2182,9 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_
     ir_instr *phi;
 
     ir_block *cond = func->curblock;
-    ir_block *ontrue;
-    ir_block *onfalse;
+    ir_block *cond_out = NULL;
+    ir_block *ontrue, *ontrue_out = NULL;
+    ir_block *onfalse, *onfalse_out = NULL;
     ir_block *merge;
 
     /* Ternary can never create an lvalue... */
@@ -2199,9 +2208,10 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_
     cgen = self->cond->expression.codegen;
     if (!(*cgen)((ast_expression*)(self->cond), func, false, &condval))
         return false;
+    cond_out = func->curblock;
 
     /* create on-true block */
-    ontrue = ir_function_create_block(func->ir_func, ast_function_label(func, "tern_T"));
+    ontrue = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "tern_T"));
     if (!ontrue)
         return false;
     else
@@ -2213,10 +2223,12 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_
         cgen = self->on_true->expression.codegen;
         if (!(*cgen)((ast_expression*)(self->on_true), func, false, &trueval))
             return false;
+
+        ontrue_out = func->curblock;
     }
 
     /* create on-false block */
-    onfalse = ir_function_create_block(func->ir_func, ast_function_label(func, "tern_F"));
+    onfalse = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "tern_F"));
     if (!onfalse)
         return false;
     else
@@ -2228,20 +2240,22 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_
         cgen = self->on_false->expression.codegen;
         if (!(*cgen)((ast_expression*)(self->on_false), func, false, &falseval))
             return false;
+
+        onfalse_out = func->curblock;
     }
 
     /* create merge block */
-    merge = ir_function_create_block(func->ir_func, ast_function_label(func, "tern_out"));
+    merge = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "tern_out"));
     if (!merge)
         return false;
     /* jump to merge block */
-    if (!ir_block_create_jump(ontrue, merge))
+    if (!ir_block_create_jump(ontrue_out, merge))
         return false;
-    if (!ir_block_create_jump(onfalse, merge))
+    if (!ir_block_create_jump(onfalse_out, merge))
         return false;
 
     /* create if instruction */
-    if (!ir_block_create_if(cond, condval, ontrue, onfalse))
+    if (!ir_block_create_if(cond_out, condval, ontrue, onfalse))
         return false;
 
     /* Now enter the merge block */
@@ -2259,8 +2273,8 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_
     phi = ir_block_create_phi(merge, ast_function_label(func, "phi"), trueval->vtype);
     if (!phi)
         return false;
-    ir_phi_add(phi, ontrue,  trueval);
-    ir_phi_add(phi, onfalse, falseval);
+    ir_phi_add(phi, ontrue_out,  trueval);
+    ir_phi_add(phi, onfalse_out, falseval);
 
     self->expression.outr = ir_phi_value(phi);
     *out = self->expression.outr;
@@ -2331,7 +2345,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
      */
     if (self->precond)
     {
-        bprecond = ir_function_create_block(func->ir_func, ast_function_label(func, "pre_loop_cond"));
+        bprecond = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "pre_loop_cond"));
         if (!bprecond)
             return false;
 
@@ -2355,7 +2369,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
      * generate them this early for 'break' and 'continue'.
      */
     if (self->increment) {
-        bincrement = ir_function_create_block(func->ir_func, ast_function_label(func, "loop_increment"));
+        bincrement = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "loop_increment"));
         if (!bincrement)
             return false;
         bcontinue = bincrement; /* increment comes before the pre-loop-condition */
@@ -2364,7 +2378,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
     }
 
     if (self->postcond) {
-        bpostcond = ir_function_create_block(func->ir_func, ast_function_label(func, "post_loop_cond"));
+        bpostcond = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "post_loop_cond"));
         if (!bpostcond)
             return false;
         bcontinue = bpostcond; /* postcond comes before the increment */
@@ -2373,7 +2387,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
     }
 
     bout_id = vec_size(func->ir_func->blocks);
-    bout = ir_function_create_block(func->ir_func, ast_function_label(func, "after_loop"));
+    bout = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "after_loop"));
     if (!bout)
         return false;
     bbreak = bout;
@@ -2381,7 +2395,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
     /* The loop body... */
     if (self->body)
     {
-        bbody = ir_function_create_block(func->ir_func, ast_function_label(func, "loop_body"));
+        bbody = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "loop_body"));
         if (!bbody)
             return false;
 
@@ -2392,6 +2406,8 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
         old_bcontinue       = func->continueblock;
         func->breakblock    = bbreak;
         func->continueblock = bcontinue;
+        if (!func->continueblock)
+            func->continueblock = bbody;
 
         /* generate */
         cgen = self->body->expression.codegen;
@@ -2520,6 +2536,11 @@ bool ast_breakcont_codegen(ast_breakcont *self, ast_function *func, bool lvalue,
     else
         target = func->breakblock;
 
+    if (!target) {
+        asterror(ast_ctx(self), "%s is lacking a target block", (self->is_continue ? "continue" : "break"));
+        return false;
+    }
+
     if (!ir_block_create_jump(func->curblock, target))
         return false;
     return true;
@@ -2572,7 +2593,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
     }
 
     bout_id = vec_size(func->ir_func->blocks);
-    bout = ir_function_create_block(func->ir_func, ast_function_label(func, "after_switch"));
+    bout = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "after_switch"));
     if (!bout)
         return false;
 
@@ -2599,9 +2620,9 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
             if (!cond)
                 return false;
 
-            bcase = ir_function_create_block(func->ir_func, ast_function_label(func, "case"));
+            bcase = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "case"));
             bnot_id = vec_size(func->ir_func->blocks);
-            bnot = ir_function_create_block(func->ir_func, ast_function_label(func, "not_case"));
+            bnot = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "not_case"));
             if (!bcase || !bnot)
                 return false;
             if (!ir_block_create_if(func->curblock, cond, bcase, bnot))
@@ -2691,7 +2712,7 @@ bool ast_label_codegen(ast_label *self, ast_function *func, bool lvalue, ir_valu
     }
 
     /* simply create a new block and jump to it */
-    self->irblock = ir_function_create_block(func->ir_func, self->name);
+    self->irblock = ir_function_create_block(ast_ctx(self), func->ir_func, self->name);
     if (!self->irblock) {
         asterror(ast_ctx(self), "failed to allocate label block `%s`", self->name);
         return false;