]> de.git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ast.c
moving -Olocal-temps to -O4 until the issues are solved
[xonotic/gmqcc.git] / ast.c
diff --git a/ast.c b/ast.c
index 7fcab1538e4b12fe00db1b4dd034736841cffcbc..2b4a456ebb08e5e388d79bbe9a910d49c51d1a9e 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -1,6 +1,7 @@
 /*
- * Copyright (C) 2012
+ * Copyright (C) 2012, 2013
  *     Wolfgang Bumiller
+ *     Dale Weiler 
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy of
  * this software and associated documentation files (the "Software"), to deal in
@@ -203,14 +204,20 @@ ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex)
 
 bool ast_compare_type(ast_expression *a, ast_expression *b)
 {
+    if (a->expression.vtype == TYPE_NIL ||
+        b->expression.vtype == TYPE_NIL)
+        return true;
     if (a->expression.vtype != b->expression.vtype)
         return false;
     if (!a->expression.next != !b->expression.next)
         return false;
     if (vec_size(a->expression.params) != vec_size(b->expression.params))
         return false;
-    if (a->expression.flags != b->expression.flags)
+    if ((a->expression.flags & AST_FLAG_TYPE_MASK) !=
+        (b->expression.flags & AST_FLAG_TYPE_MASK) )
+    {
         return false;
+    }
     if (vec_size(a->expression.params)) {
         size_t i;
         for (i = 0; i < vec_size(a->expression.params); ++i) {
@@ -338,6 +345,7 @@ ast_value* ast_value_new(lex_ctx ctx, const char *name, int t)
 
     self->setter = NULL;
     self->getter = NULL;
+    self->desc   = NULL;
 
     return self;
 }
@@ -365,6 +373,10 @@ void ast_value_delete(ast_value* self)
     }
     if (self->ir_values)
         mem_d(self->ir_values);
+
+    if (self->desc)
+        mem_d(self->desc);
+
     ast_expression_delete((ast_expression*)self);
     mem_d(self);
 }
@@ -570,7 +582,8 @@ ast_member* ast_member_new(lex_ctx ctx, ast_expression *owner, unsigned int fiel
         self->expression.next = ast_shallow_type(ctx, TYPE_FLOAT);
     }
 
-    self->owner = owner;
+    self->rvalue = false;
+    self->owner  = owner;
     ast_propagate_effects(self, owner);
 
     self->field = field;
@@ -596,6 +609,14 @@ void ast_member_delete(ast_member *self)
     mem_d(self);
 }
 
+bool ast_member_set_name(ast_member *self, const char *name)
+{
+    if (self->name)
+        mem_d((void*)self->name);
+    self->name = util_strdup(name);
+    return !!self->name;
+}
+
 ast_array_index* ast_array_index_new(lex_ctx ctx, ast_expression *array, ast_expression *index)
 {
     ast_expression *outtype;
@@ -675,6 +696,7 @@ void ast_ifthen_delete(ast_ifthen *self)
 
 ast_ternary* ast_ternary_new(lex_ctx ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse)
 {
+    ast_expression *exprtype = ontrue;
     ast_instantiate(ast_ternary, ctx, ast_ternary_delete);
     /* This time NEITHER must be NULL */
     if (!ontrue || !onfalse) {
@@ -690,7 +712,9 @@ ast_ternary* ast_ternary_new(lex_ctx ctx, ast_expression *cond, ast_expression *
     ast_propagate_effects(self, ontrue);
     ast_propagate_effects(self, onfalse);
 
-    if (!ast_type_adopt(self, ontrue)) {
+    if (ontrue->expression.vtype == TYPE_NIL)
+        exprtype = onfalse;
+    if (!ast_type_adopt(self, exprtype)) {
         ast_ternary_delete(self);
         return NULL;
     }
@@ -700,9 +724,12 @@ ast_ternary* ast_ternary_new(lex_ctx ctx, ast_expression *cond, ast_expression *
 
 void ast_ternary_delete(ast_ternary *self)
 {
-    ast_unref(self->cond);
-    ast_unref(self->on_true);
-    ast_unref(self->on_false);
+    /* the if()s are only there because computed-gotos can set them
+     * to NULL
+     */
+    if (self->cond)     ast_unref(self->cond);
+    if (self->on_true)  ast_unref(self->on_true);
+    if (self->on_false) ast_unref(self->on_false);
     ast_expression_delete((ast_expression*)self);
     mem_d(self);
 }
@@ -756,12 +783,13 @@ void ast_loop_delete(ast_loop *self)
     mem_d(self);
 }
 
-ast_breakcont* ast_breakcont_new(lex_ctx ctx, bool iscont)
+ast_breakcont* ast_breakcont_new(lex_ctx ctx, bool iscont, unsigned int levels)
 {
     ast_instantiate(ast_breakcont, ctx, ast_breakcont_delete);
     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_breakcont_codegen);
 
     self->is_continue = iscont;
+    self->levels      = levels;
 
     return self;
 }
@@ -801,14 +829,17 @@ void ast_switch_delete(ast_switch *self)
     mem_d(self);
 }
 
-ast_label* ast_label_new(lex_ctx ctx, const char *name)
+ast_label* ast_label_new(lex_ctx ctx, const char *name, bool undefined)
 {
     ast_instantiate(ast_label, ctx, ast_label_delete);
     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_label_codegen);
 
-    self->name    = util_strdup(name);
-    self->irblock = NULL;
-    self->gotos   = NULL;
+    self->expression.vtype = TYPE_NOEXPR;
+
+    self->name      = util_strdup(name);
+    self->irblock   = NULL;
+    self->gotos     = NULL;
+    self->undefined = undefined;
 
     return self;
 }
@@ -890,7 +921,8 @@ bool ast_call_check_types(ast_call *self)
         count = vec_size(func->expression.params);
 
     for (i = 0; i < count; ++i) {
-        if (!ast_compare_type(self->params[i], (ast_expression*)(func->expression.params[i]))) {
+        if (!ast_compare_type(self->params[i], (ast_expression*)(func->expression.params[i])))
+        {
             char texp[1024];
             char tgot[1024];
             ast_type_to_string(self->params[i], tgot, sizeof(tgot));
@@ -1017,8 +1049,8 @@ ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype)
     self->ir_func = NULL;
     self->curblock = NULL;
 
-    self->breakblock    = NULL;
-    self->continueblock = NULL;
+    self->breakblocks    = NULL;
+    self->continueblocks = NULL;
 
     vtype->hasvalue = true;
     vtype->constval.vfunc = self;
@@ -1043,6 +1075,8 @@ void ast_function_delete(ast_function *self)
     for (i = 0; i < vec_size(self->blocks); ++i)
         ast_delete(self->blocks[i]);
     vec_free(self->blocks);
+    vec_free(self->breakblocks);
+    vec_free(self->continueblocks);
     mem_d(self);
 }
 
@@ -1061,10 +1095,10 @@ const char* ast_function_label(ast_function *self, const char *prefix)
     from = self->labelbuf + sizeof(self->labelbuf)-1;
     *from-- = 0;
     do {
-        unsigned int digit = id % 10;
-        *from = digit + '0';
+        *from-- = (id%10) + '0';
         id /= 10;
     } while (id);
+    ++from;
     memcpy(from - len, prefix, len);
     return from - len;
 }
@@ -1085,12 +1119,15 @@ void _ast_codegen_output_type(ast_expression_common *self, ir_value *out)
 }
 
 #define codegen_output_type(a,o) (_ast_codegen_output_type(&((a)->expression),(o)))
-#define codegen_output_type_expr(a,o) (_ast_codegen_output_type(a,(o)))
 
 bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_value **out)
 {
     (void)func;
     (void)lvalue;
+    if (self->expression.vtype == TYPE_NIL) {
+        *out = func->ir_func->owner->nil;
+        return true;
+    }
     /* NOTE: This is the codegen for a variable used in an expression.
      * It is not the codegen to generate the value. For this purpose,
      * ast_local_codegen and ast_global_codegen are to be used before this
@@ -1099,9 +1136,9 @@ bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_valu
      * on all the globals.
      */
     if (!self->ir_v) {
-        char typename[1024];
-        ast_type_to_string((ast_expression*)self, typename, sizeof(typename));
-        compile_error(ast_ctx(self), "ast_value used before generated %s %s", typename, self->name);
+        char tname[1024]; /* typename is reserved in C++ */
+        ast_type_to_string((ast_expression*)self, tname, sizeof(tname));
+        compile_error(ast_ctx(self), "ast_value used before generated %s %s", tname, self->name);
         return false;
     }
     *out = self->ir_v;
@@ -1112,6 +1149,11 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
 {
     ir_value *v = NULL;
 
+    if (self->expression.vtype == TYPE_NIL) {
+        compile_error(ast_ctx(self), "internal error: trying to generate a variable of TYPE_NIL");
+        return false;
+    }
+
     if (self->hasvalue && self->expression.vtype == TYPE_FUNCTION)
     {
         ir_function *func = ir_builder_create_function(ir, self->name, self->expression.next->expression.vtype);
@@ -1162,6 +1204,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
             }
             v->context = ast_ctx(self);
             v->unique_life = true;
+            v->locked      = true;
             array->ir_v = self->ir_v = v;
 
             namelen = strlen(self->name);
@@ -1180,6 +1223,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
                 }
                 array->ir_values[ai]->context = ast_ctx(self);
                 array->ir_values[ai]->unique_life = true;
+                array->ir_values[ai]->locked      = true;
             }
             mem_d(name);
         }
@@ -1213,6 +1257,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
         }
         v->context = ast_ctx(self);
         v->unique_life = true;
+        v->locked      = true;
 
         namelen = strlen(self->name);
         name    = (char*)mem_a(namelen + 16);
@@ -1230,6 +1275,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
             }
             self->ir_values[ai]->context = ast_ctx(self);
             self->ir_values[ai]->unique_life = true;
+            self->ir_values[ai]->locked      = true;
         }
         mem_d(name);
     }
@@ -1302,6 +1348,12 @@ error: /* clean up */
 bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
 {
     ir_value *v = NULL;
+
+    if (self->expression.vtype == TYPE_NIL) {
+        compile_error(ast_ctx(self), "internal error: trying to generate a variable of TYPE_NIL");
+        return false;
+    }
+
     if (self->hasvalue && self->expression.vtype == TYPE_FUNCTION)
     {
         /* Do we allow local functions? I think not...
@@ -1318,6 +1370,8 @@ bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
         ast_expression_common *elemtype = &self->expression.next->expression;
         int vtype = elemtype->vtype;
 
+        func->flags |= IR_FLAG_HAS_ARRAYS;
+
         if (param) {
             compile_error(ast_ctx(self), "array-parameters are not supported");
             return false;
@@ -1341,6 +1395,7 @@ bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
         }
         v->context = ast_ctx(self);
         v->unique_life = true;
+        v->locked      = true;
 
         namelen = strlen(self->name);
         name    = (char*)mem_a(namelen + 16);
@@ -1356,6 +1411,7 @@ bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
             }
             self->ir_values[ai]->context = ast_ctx(self);
             self->ir_values[ai]->unique_life = true;
+            self->ir_values[ai]->locked      = true;
         }
     }
     else
@@ -1505,7 +1561,7 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
     }
 
     /* TODO: check return types */
-    if (!self->curblock->is_return)
+    if (!self->curblock->final)
     {
         if (!self->vtype->expression.next ||
             self->vtype->expression.next->expression.vtype == TYPE_VOID)
@@ -1700,7 +1756,7 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
         return true;
     }
 
-    if (OPTS_FLAG(SHORT_LOGIC) &&
+    if ((OPTS_FLAG(SHORT_LOGIC) || OPTS_FLAG(PERL_LOGIC)) &&
         (self->op == INSTR_AND || self->op == INSTR_OR))
     {
         /* short circuit evaluation */
@@ -1708,64 +1764,42 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
         ir_block *from_left, *from_right;
         ir_instr *phi;
         size_t    merge_id;
-        uint16_t  notop;
-
-        /* Note about casting to true boolean values:
-         * We use a single NOT for sub expressions, and an
-         * overall NOT at the end, and for that purpose swap
-         * all the jump conditions in order for the NOT to get
-         * doubled.
-         * ie: (a && b) usually becomes (!!a ? !!b : !!a)
-         * but we translate this to (!(!a ? !a : !b))
-         */
 
+        /* prepare end-block */
         merge_id = vec_size(func->ir_func->blocks);
-        merge = ir_function_create_block(ast_ctx(self), 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"));
 
+        /* generate the left expression */
         cgen = self->left->expression.codegen;
         if (!(*cgen)((ast_expression*)(self->left), func, false, &left))
             return false;
-        if (!OPTS_FLAG(PERL_LOGIC)) {
-            notop = type_not_instr[left->vtype];
-            if (notop == AINSTR_END) {
-                compile_error(ast_ctx(self), "don't know how to cast to bool...");
-                return false;
-            }
-            left = ir_block_create_unary(func->curblock, ast_ctx(self),
-                                         ast_function_label(func, "sce_not"),
-                                         notop,
-                                         left);
-        }
+        /* remember the block */
         from_left = func->curblock;
 
+        /* create a new block for the right expression */
         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 (self->op == INSTR_AND) {
+            /* on AND: left==true -> other */
             if (!ir_block_create_if(func->curblock, ast_ctx(self), left, other, merge))
                 return false;
         } else {
+            /* on OR: left==false -> other */
             if (!ir_block_create_if(func->curblock, ast_ctx(self), left, merge, other))
                 return false;
         }
         /* use the likely flag */
         vec_last(func->curblock->instr)->likely = true;
 
+        /* enter the right-expression's block */
         func->curblock = other;
+        /* generate */
         cgen = self->right->expression.codegen;
         if (!(*cgen)((ast_expression*)(self->right), func, false, &right))
             return false;
-        if (!OPTS_FLAG(PERL_LOGIC)) {
-            notop = type_not_instr[right->vtype];
-            if (notop == AINSTR_END) {
-                compile_error(ast_ctx(self), "don't know how to cast to bool...");
-                return false;
-            }
-            right = ir_block_create_unary(func->curblock, ast_ctx(self),
-                                          ast_function_label(func, "sce_not"),
-                                          notop,
-                                          right);
-        }
+        /* remember block */
         from_right = func->curblock;
 
+        /* jump to the merge block */
         if (!ir_block_create_jump(func->curblock, ast_ctx(self), merge))
             return false;
 
@@ -1773,24 +1807,52 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
         vec_push(func->ir_func->blocks, merge);
 
         func->curblock = merge;
-        phi = ir_block_create_phi(func->curblock, ast_ctx(self), ast_function_label(func, "sce_value"), TYPE_FLOAT);
+        phi = ir_block_create_phi(func->curblock, ast_ctx(self),
+                                  ast_function_label(func, "sce_value"),
+                                  self->expression.vtype);
         ir_phi_add(phi, from_left, left);
         ir_phi_add(phi, from_right, right);
         *out = ir_phi_value(phi);
+        if (!*out)
+            return false;
+
         if (!OPTS_FLAG(PERL_LOGIC)) {
-            notop = type_not_instr[(*out)->vtype];
-            if (notop == AINSTR_END) {
-                compile_error(ast_ctx(self), "don't know how to cast to bool...");
-                return false;
+            /* cast-to-bool */
+            if (OPTS_FLAG(CORRECT_LOGIC) && (*out)->vtype == TYPE_VECTOR) {
+                *out = ir_block_create_unary(func->curblock, ast_ctx(self),
+                                             ast_function_label(func, "sce_bool_v"),
+                                             INSTR_NOT_V, *out);
+                if (!*out)
+                    return false;
+                *out = ir_block_create_unary(func->curblock, ast_ctx(self),
+                                             ast_function_label(func, "sce_bool"),
+                                             INSTR_NOT_F, *out);
+                if (!*out)
+                    return false;
+            }
+            else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && (*out)->vtype == TYPE_STRING) {
+                *out = ir_block_create_unary(func->curblock, ast_ctx(self),
+                                             ast_function_label(func, "sce_bool_s"),
+                                             INSTR_NOT_S, *out);
+                if (!*out)
+                    return false;
+                *out = ir_block_create_unary(func->curblock, ast_ctx(self),
+                                             ast_function_label(func, "sce_bool"),
+                                             INSTR_NOT_F, *out);
+                if (!*out)
+                    return false;
+            }
+            else {
+                *out = ir_block_create_binop(func->curblock, ast_ctx(self),
+                                             ast_function_label(func, "sce_bool"),
+                                             INSTR_AND, *out, *out);
+                if (!*out)
+                    return false;
             }
-            *out = ir_block_create_unary(func->curblock, ast_ctx(self),
-                                         ast_function_label(func, "sce_final_not"),
-                                         notop,
-                                         *out);
         }
-        if (!*out)
-            return false;
+
         self->expression.outr = *out;
+        codegen_output_type(self, *out);
         return true;
     }
 
@@ -1807,6 +1869,7 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
     if (!*out)
         return false;
     self->expression.outr = *out;
+    codegen_output_type(self, *out);
 
     return true;
 }
@@ -2044,14 +2107,17 @@ bool ast_member_codegen(ast_member *self, ast_function *func, bool lvalue, ir_va
     ir_value *vec;
 
     /* in QC this is always an lvalue */
-    (void)lvalue;
+    if (lvalue && self->rvalue) {
+        compile_error(ast_ctx(self), "not an l-value (member access)");
+        return false;
+    }
     if (self->expression.outl) {
         *out = self->expression.outl;
         return true;
     }
 
     cgen = self->owner->expression.codegen;
-    if (!(*cgen)((ast_expression*)(self->owner), func, true, &vec))
+    if (!(*cgen)((ast_expression*)(self->owner), func, false, &vec))
         return false;
 
     if (vec->vtype != TYPE_VECTOR &&
@@ -2341,15 +2407,18 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_
     /* Here, now, we need a PHI node
      * but first some sanity checking...
      */
-    if (trueval->vtype != falseval->vtype) {
+    if (trueval->vtype != falseval->vtype && trueval->vtype != TYPE_NIL && falseval->vtype != TYPE_NIL) {
         /* error("ternary with different types on the two sides"); */
+        compile_error(ast_ctx(self), "internal error: ternary operand types invalid");
         return false;
     }
 
     /* create PHI */
-    phi = ir_block_create_phi(merge, ast_ctx(self), ast_function_label(func, "phi"), trueval->vtype);
-    if (!phi)
+    phi = ir_block_create_phi(merge, ast_ctx(self), ast_function_label(func, "phi"), self->expression.vtype);
+    if (!phi) {
+        compile_error(ast_ctx(self), "internal error: failed to generate phi node");
         return false;
+    }
     ir_phi_add(phi, ontrue_out,  trueval);
     ir_phi_add(phi, onfalse_out, falseval);
 
@@ -2386,9 +2455,6 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
     ir_block *bcontinue     = NULL;
     ir_block *bbreak        = NULL;
 
-    ir_block *old_bcontinue = NULL;
-    ir_block *old_bbreak    = NULL;
-
     ir_block *tmpblock      = NULL;
 
     (void)lvalue;
@@ -2481,12 +2547,11 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
         /* enter */
         func->curblock = bbody;
 
-        old_bbreak          = func->breakblock;
-        old_bcontinue       = func->continueblock;
-        func->breakblock    = bbreak;
-        func->continueblock = bcontinue;
-        if (!func->continueblock)
-            func->continueblock = bbody;
+        vec_push(func->breakblocks,    bbreak);
+        if (bcontinue)
+            vec_push(func->continueblocks, bcontinue);
+        else
+            vec_push(func->continueblocks, bbody);
 
         /* generate */
         if (self->body) {
@@ -2496,8 +2561,8 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
         }
 
         end_bbody = func->curblock;
-        func->breakblock    = old_bbreak;
-        func->continueblock = old_bcontinue;
+        vec_pop(func->breakblocks);
+        vec_pop(func->continueblocks);
     }
 
     /* post-loop-condition */
@@ -2623,9 +2688,9 @@ bool ast_breakcont_codegen(ast_breakcont *self, ast_function *func, bool lvalue,
     self->expression.outr = (ir_value*)1;
 
     if (self->is_continue)
-        target = func->continueblock;
+        target = func->continueblocks[vec_size(func->continueblocks)-1-self->levels];
     else
-        target = func->breakblock;
+        target = func->breakblocks[vec_size(func->breakblocks)-1-self->levels];
 
     if (!target) {
         compile_error(ast_ctx(self), "%s is lacking a target block", (self->is_continue ? "continue" : "break"));
@@ -2648,7 +2713,6 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
 
     ir_value *dummy     = NULL;
     ir_value *irop      = NULL;
-    ir_block *old_break = NULL;
     ir_block *bout      = NULL;
     ir_block *bfall     = NULL;
     size_t    bout_id;
@@ -2691,8 +2755,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
         return false;
 
     /* setup the break block */
-    old_break        = func->breakblock;
-    func->breakblock = bout;
+    vec_push(func->breakblocks, bout);
 
     /* Now create all cases */
     for (c = 0; c < vec_size(self->cases); ++c) {
@@ -2797,7 +2860,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
     func->curblock = bout;
 
     /* restore the break block */
-    func->breakblock = old_break;
+    vec_pop(func->breakblocks);
 
     /* Move 'bout' to the end, it's nicer */
     vec_remove(func->ir_func->blocks, bout_id, 1);
@@ -2811,6 +2874,11 @@ bool ast_label_codegen(ast_label *self, ast_function *func, bool lvalue, ir_valu
     size_t i;
     ir_value *dummy;
 
+    if (self->undefined) {
+        compile_error(ast_ctx(self), "internal error: ast_label never defined");
+        return false;
+    }
+
     *out = NULL;
     if (lvalue) {
         compile_error(ast_ctx(self), "internal error: ast_label cannot be an lvalue");
@@ -2852,14 +2920,14 @@ bool ast_goto_codegen(ast_goto *self, ast_function *func, bool lvalue, ir_value
         if (self->irblock_from) {
             /* we already tried once, this is the callback */
             self->irblock_from->final = false;
-            if (!ir_block_create_jump(self->irblock_from, ast_ctx(self), self->target->irblock)) {
+            if (!ir_block_create_goto(self->irblock_from, ast_ctx(self), self->target->irblock)) {
                 compile_error(ast_ctx(self), "failed to generate goto to `%s`", self->name);
                 return false;
             }
         }
         else
         {
-            if (!ir_block_create_jump(func->curblock, ast_ctx(self), self->target->irblock)) {
+            if (!ir_block_create_goto(func->curblock, ast_ctx(self), self->target->irblock)) {
                 compile_error(ast_ctx(self), "failed to generate goto to `%s`", self->name);
                 return false;
             }