killing the union types
[xonotic/gmqcc.git] / ast.c
1 /*
2  * Copyright (C) 2012, 2013
3  *     Wolfgang Bumiller
4  *     Dale Weiler
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy of
7  * this software and associated documentation files (the "Software"), to deal in
8  * the Software without restriction, including without limitation the rights to
9  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10  * of the Software, and to permit persons to whom the Software is furnished to do
11  * so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "gmqcc.h"
29 #include "ast.h"
30
31 #define ast_instantiate(T, ctx, destroyfn)                          \
32     T* self = (T*)mem_a(sizeof(T));                                 \
33     if (!self) {                                                    \
34         return NULL;                                                \
35     }                                                               \
36     ast_node_init((ast_node*)self, ctx, TYPE_##T);                  \
37     ( (ast_node*)self )->destroy = (ast_node_delete*)destroyfn
38
39
40 /* It must not be possible to get here. */
41 static GMQCC_NORETURN void _ast_node_destroy(ast_node *self)
42 {
43     (void)self;
44     con_err("ast node missing destroy()\n");
45     exit(EXIT_FAILURE);
46 }
47
48 /* Initialize main ast node aprts */
49 static void ast_node_init(ast_node *self, lex_ctx ctx, int nodetype)
50 {
51     self->context = ctx;
52     self->destroy = &_ast_node_destroy;
53     self->keep    = false;
54     self->nodetype = nodetype;
55     self->side_effects = false;
56 }
57
58 /* weight and side effects */
59 static void _ast_propagate_effects(ast_node *self, ast_node *other)
60 {
61     if (ast_side_effects(other))
62         ast_side_effects(self) = true;
63 }
64 #define ast_propagate_effects(s,o) _ast_propagate_effects(((ast_node*)(s)), ((ast_node*)(o)))
65
66 /* General expression initialization */
67 static void ast_expression_init(ast_expression *self,
68                                 ast_expression_codegen *codegen)
69 {
70     self->codegen  = codegen;
71     self->vtype    = TYPE_VOID;
72     self->next     = NULL;
73     self->outl     = NULL;
74     self->outr     = NULL;
75     self->params   = NULL;
76     self->count    = 0;
77     self->flags    = 0;
78     self->varparam = NULL;
79 }
80
81 static void ast_expression_delete(ast_expression *self)
82 {
83     size_t i;
84     if (self->next)
85         ast_delete(self->next);
86     for (i = 0; i < vec_size(self->params); ++i) {
87         ast_delete(self->params[i]);
88     }
89     vec_free(self->params);
90     if (self->varparam)
91         ast_delete(self->varparam);
92 }
93
94 static void ast_expression_delete_full(ast_expression *self)
95 {
96     ast_expression_delete(self);
97     mem_d(self);
98 }
99
100 ast_value* ast_value_copy(const ast_value *self)
101 {
102     size_t i;
103     const ast_expression *fromex;
104     ast_expression       *selfex;
105     ast_value *cp = ast_value_new(self->expression.node.context, self->name, self->expression.vtype);
106     if (self->expression.next) {
107         cp->expression.next = ast_type_copy(self->expression.node.context, self->expression.next);
108     }
109     fromex   = &self->expression;
110     selfex = &cp->expression;
111     selfex->count    = fromex->count;
112     selfex->flags    = fromex->flags;
113     for (i = 0; i < vec_size(fromex->params); ++i) {
114         ast_value *v = ast_value_copy(fromex->params[i]);
115         vec_push(selfex->params, v);
116     }
117     return cp;
118 }
119
120 void ast_type_adopt_impl(ast_expression *self, const ast_expression *other)
121 {
122     size_t i;
123     const ast_expression *fromex;
124     ast_expression       *selfex;
125     self->vtype = other->vtype;
126     if (other->next) {
127         self->next = (ast_expression*)ast_type_copy(ast_ctx(self), other->next);
128     }
129     fromex = other;
130     selfex = self;
131     selfex->count    = fromex->count;
132     selfex->flags    = fromex->flags;
133     for (i = 0; i < vec_size(fromex->params); ++i) {
134         ast_value *v = ast_value_copy(fromex->params[i]);
135         vec_push(selfex->params, v);
136     }
137 }
138
139 static ast_expression* ast_shallow_type(lex_ctx ctx, int vtype)
140 {
141     ast_instantiate(ast_expression, ctx, ast_expression_delete_full);
142     ast_expression_init(self, NULL);
143     self->codegen = NULL;
144     self->next    = NULL;
145     self->vtype   = vtype;
146     return self;
147 }
148
149 ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex)
150 {
151     size_t i;
152     const ast_expression *fromex;
153     ast_expression       *selfex;
154
155     if (!ex)
156         return NULL;
157     else
158     {
159         ast_instantiate(ast_expression, ctx, ast_expression_delete_full);
160         ast_expression_init(self, NULL);
161
162         fromex = ex;
163         selfex = self;
164
165         /* This may never be codegen()d */
166         selfex->codegen = NULL;
167
168         selfex->vtype = fromex->vtype;
169         if (fromex->next)
170             selfex->next = ast_type_copy(ctx, fromex->next);
171         else
172             selfex->next = NULL;
173
174         selfex->count    = fromex->count;
175         selfex->flags    = fromex->flags;
176         for (i = 0; i < vec_size(fromex->params); ++i) {
177             ast_value *v = ast_value_copy(fromex->params[i]);
178             vec_push(selfex->params, v);
179         }
180
181         return self;
182     }
183 }
184
185 bool ast_compare_type(ast_expression *a, ast_expression *b)
186 {
187     if (a->vtype == TYPE_NIL ||
188         b->vtype == TYPE_NIL)
189         return true;
190     if (a->vtype != b->vtype)
191         return false;
192     if (!a->next != !b->next)
193         return false;
194     if (vec_size(a->params) != vec_size(b->params))
195         return false;
196     if ((a->flags & AST_FLAG_TYPE_MASK) !=
197         (b->flags & AST_FLAG_TYPE_MASK) )
198     {
199         return false;
200     }
201     if (vec_size(a->params)) {
202         size_t i;
203         for (i = 0; i < vec_size(a->params); ++i) {
204             if (!ast_compare_type((ast_expression*)a->params[i],
205                                   (ast_expression*)b->params[i]))
206                 return false;
207         }
208     }
209     if (a->next)
210         return ast_compare_type(a->next, b->next);
211     return true;
212 }
213
214 static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsize, size_t pos)
215 {
216     const char *typestr;
217     size_t typelen;
218     size_t i;
219
220     if (!e) {
221         if (pos + 6 >= bufsize)
222             goto full;
223         util_strncpy(buf + pos, "(null)", 6);
224         return pos + 6;
225     }
226
227     if (pos + 1 >= bufsize)
228         goto full;
229
230     switch (e->vtype) {
231         case TYPE_VARIANT:
232             util_strncpy(buf + pos, "(variant)", 9);
233             return pos + 9;
234
235         case TYPE_FIELD:
236             buf[pos++] = '.';
237             return ast_type_to_string_impl(e->next, buf, bufsize, pos);
238
239         case TYPE_POINTER:
240             if (pos + 3 >= bufsize)
241                 goto full;
242             buf[pos++] = '*';
243             buf[pos++] = '(';
244             pos = ast_type_to_string_impl(e->next, buf, bufsize, pos);
245             if (pos + 1 >= bufsize)
246                 goto full;
247             buf[pos++] = ')';
248             return pos;
249
250         case TYPE_FUNCTION:
251             pos = ast_type_to_string_impl(e->next, buf, bufsize, pos);
252             if (pos + 2 >= bufsize)
253                 goto full;
254             if (!vec_size(e->params)) {
255                 buf[pos++] = '(';
256                 buf[pos++] = ')';
257                 return pos;
258             }
259             buf[pos++] = '(';
260             pos = ast_type_to_string_impl((ast_expression*)(e->params[0]), buf, bufsize, pos);
261             for (i = 1; i < vec_size(e->params); ++i) {
262                 if (pos + 2 >= bufsize)
263                     goto full;
264                 buf[pos++] = ',';
265                 buf[pos++] = ' ';
266                 pos = ast_type_to_string_impl((ast_expression*)(e->params[i]), buf, bufsize, pos);
267             }
268             if (pos + 1 >= bufsize)
269                 goto full;
270             buf[pos++] = ')';
271             return pos;
272
273         case TYPE_ARRAY:
274             pos = ast_type_to_string_impl(e->next, buf, bufsize, pos);
275             if (pos + 1 >= bufsize)
276                 goto full;
277             buf[pos++] = '[';
278             pos += util_snprintf(buf + pos, bufsize - pos - 1, "%i", (int)e->count);
279             if (pos + 1 >= bufsize)
280                 goto full;
281             buf[pos++] = ']';
282             return pos;
283
284         default:
285             typestr = type_name[e->vtype];
286             typelen = strlen(typestr);
287             if (pos + typelen >= bufsize)
288                 goto full;
289             util_strncpy(buf + pos, typestr, typelen);
290             return pos + typelen;
291     }
292
293 full:
294     buf[bufsize-3] = '.';
295     buf[bufsize-2] = '.';
296     buf[bufsize-1] = '.';
297     return bufsize;
298 }
299
300 void ast_type_to_string(ast_expression *e, char *buf, size_t bufsize)
301 {
302     size_t pos = ast_type_to_string_impl(e, buf, bufsize-1, 0);
303     buf[pos] = 0;
304 }
305
306 ast_value* ast_value_new(lex_ctx ctx, const char *name, int t)
307 {
308     ast_instantiate(ast_value, ctx, ast_value_delete);
309     ast_expression_init((ast_expression*)self,
310                         (ast_expression_codegen*)&ast_value_codegen);
311     self->expression.node.keep = true; /* keep */
312
313     self->name = name ? util_strdup(name) : NULL;
314     self->expression.vtype = t;
315     self->expression.next  = NULL;
316     self->isfield  = false;
317     self->cvq      = CV_NONE;
318     self->hasvalue = false;
319     self->isimm    = false;
320     self->uses     = 0;
321     memset(&self->constval, 0, sizeof(self->constval));
322     self->initlist = NULL;
323
324     self->ir_v           = NULL;
325     self->ir_values      = NULL;
326     self->ir_value_count = 0;
327
328     self->setter = NULL;
329     self->getter = NULL;
330     self->desc   = NULL;
331
332     self->argcounter  = NULL;
333
334     return self;
335 }
336
337 void ast_value_delete(ast_value* self)
338 {
339     if (self->name)
340         mem_d((void*)self->name);
341     if (self->argcounter)
342         mem_d((void*)self->argcounter);
343     if (self->hasvalue) {
344         switch (self->expression.vtype)
345         {
346         case TYPE_STRING:
347             mem_d((void*)self->constval.vstring);
348             break;
349         case TYPE_FUNCTION:
350             /* unlink us from the function node */
351             self->constval.vfunc->vtype = NULL;
352             break;
353         /* NOTE: delete function? currently collected in
354          * the parser structure
355          */
356         default:
357             break;
358         }
359     }
360     if (self->ir_values)
361         mem_d(self->ir_values);
362
363     if (self->desc)
364         mem_d(self->desc);
365
366     if (self->initlist) {
367         if (self->expression.next->vtype == TYPE_STRING) {
368             /* strings are allocated, free them */
369             size_t i, len = vec_size(self->initlist);
370             /* in theory, len should be expression.count
371              * but let's not take any chances */
372             for (i = 0; i < len; ++i) {
373                 if (self->initlist[i].vstring)
374                     mem_d(self->initlist[i].vstring);
375             }
376         }
377         vec_free(self->initlist);
378     }
379
380     ast_expression_delete((ast_expression*)self);
381     mem_d(self);
382 }
383
384 void ast_value_params_add(ast_value *self, ast_value *p)
385 {
386     vec_push(self->expression.params, p);
387 }
388
389 bool ast_value_set_name(ast_value *self, const char *name)
390 {
391     if (self->name)
392         mem_d((void*)self->name);
393     self->name = util_strdup(name);
394     return !!self->name;
395 }
396
397 ast_binary* ast_binary_new(lex_ctx ctx, int op,
398                            ast_expression* left, ast_expression* right)
399 {
400     ast_instantiate(ast_binary, ctx, ast_binary_delete);
401     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_binary_codegen);
402
403     self->op = op;
404     self->left = left;
405     self->right = right;
406
407     ast_propagate_effects(self, left);
408     ast_propagate_effects(self, right);
409
410     if (op >= INSTR_EQ_F && op <= INSTR_GT)
411         self->expression.vtype = TYPE_FLOAT;
412     else if (op == INSTR_AND || op == INSTR_OR) {
413         if (OPTS_FLAG(PERL_LOGIC))
414             ast_type_adopt(self, right);
415         else
416             self->expression.vtype = TYPE_FLOAT;
417     }
418     else if (op == INSTR_BITAND || op == INSTR_BITOR)
419         self->expression.vtype = TYPE_FLOAT;
420     else if (op == INSTR_MUL_VF || op == INSTR_MUL_FV)
421         self->expression.vtype = TYPE_VECTOR;
422     else if (op == INSTR_MUL_V)
423         self->expression.vtype = TYPE_FLOAT;
424     else
425         self->expression.vtype = left->vtype;
426
427     /* references all */
428     self->refs = AST_REF_ALL;
429
430     return self;
431 }
432
433 void ast_binary_delete(ast_binary *self)
434 {
435     if (self->refs & AST_REF_LEFT)  ast_unref(self->left);
436     if (self->refs & AST_REF_RIGHT) ast_unref(self->right);
437
438     ast_expression_delete((ast_expression*)self);
439     mem_d(self);
440 }
441
442 ast_binstore* ast_binstore_new(lex_ctx ctx, int storop, int op,
443                                ast_expression* left, ast_expression* right)
444 {
445     ast_instantiate(ast_binstore, ctx, ast_binstore_delete);
446     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_binstore_codegen);
447
448     ast_side_effects(self) = true;
449
450     self->opstore = storop;
451     self->opbin   = op;
452     self->dest    = left;
453     self->source  = right;
454
455     self->keep_dest = false;
456
457     ast_type_adopt(self, left);
458     return self;
459 }
460
461 void ast_binstore_delete(ast_binstore *self)
462 {
463     if (!self->keep_dest)
464         ast_unref(self->dest);
465     ast_unref(self->source);
466     ast_expression_delete((ast_expression*)self);
467     mem_d(self);
468 }
469
470 ast_unary* ast_unary_new(lex_ctx ctx, int op,
471                          ast_expression *expr)
472 {
473     ast_instantiate(ast_unary, ctx, ast_unary_delete);
474     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_unary_codegen);
475
476     self->op = op;
477     self->operand = expr;
478
479     ast_propagate_effects(self, expr);
480
481     if (op >= INSTR_NOT_F && op <= INSTR_NOT_FNC) {
482         self->expression.vtype = TYPE_FLOAT;
483     } else
484         compile_error(ctx, "cannot determine type of unary operation %s", asm_instr[op].m);
485
486     return self;
487 }
488
489 void ast_unary_delete(ast_unary *self)
490 {
491     if (self->operand) ast_unref(self->operand);
492     ast_expression_delete((ast_expression*)self);
493     mem_d(self);
494 }
495
496 ast_return* ast_return_new(lex_ctx ctx, ast_expression *expr)
497 {
498     ast_instantiate(ast_return, ctx, ast_return_delete);
499     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_return_codegen);
500
501     self->operand = expr;
502
503     if (expr)
504         ast_propagate_effects(self, expr);
505
506     return self;
507 }
508
509 void ast_return_delete(ast_return *self)
510 {
511     if (self->operand)
512         ast_unref(self->operand);
513     ast_expression_delete((ast_expression*)self);
514     mem_d(self);
515 }
516
517 ast_entfield* ast_entfield_new(lex_ctx ctx, ast_expression *entity, ast_expression *field)
518 {
519     if (field->vtype != TYPE_FIELD) {
520         compile_error(ctx, "ast_entfield_new with expression not of type field");
521         return NULL;
522     }
523     return ast_entfield_new_force(ctx, entity, field, field->next);
524 }
525
526 ast_entfield* ast_entfield_new_force(lex_ctx ctx, ast_expression *entity, ast_expression *field, const ast_expression *outtype)
527 {
528     ast_instantiate(ast_entfield, ctx, ast_entfield_delete);
529
530     if (!outtype) {
531         mem_d(self);
532         /* Error: field has no type... */
533         return NULL;
534     }
535
536     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_entfield_codegen);
537
538     self->entity = entity;
539     self->field  = field;
540     ast_propagate_effects(self, entity);
541     ast_propagate_effects(self, field);
542
543     ast_type_adopt(self, outtype);
544     return self;
545 }
546
547 void ast_entfield_delete(ast_entfield *self)
548 {
549     ast_unref(self->entity);
550     ast_unref(self->field);
551     ast_expression_delete((ast_expression*)self);
552     mem_d(self);
553 }
554
555 ast_member* ast_member_new(lex_ctx ctx, ast_expression *owner, unsigned int field, const char *name)
556 {
557     ast_instantiate(ast_member, ctx, ast_member_delete);
558     if (field >= 3) {
559         mem_d(self);
560         return NULL;
561     }
562
563     if (owner->vtype != TYPE_VECTOR &&
564         owner->vtype != TYPE_FIELD) {
565         compile_error(ctx, "member-access on an invalid owner of type %s", type_name[owner->vtype]);
566         mem_d(self);
567         return NULL;
568     }
569
570     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_member_codegen);
571     self->expression.node.keep = true; /* keep */
572
573     if (owner->vtype == TYPE_VECTOR) {
574         self->expression.vtype = TYPE_FLOAT;
575         self->expression.next  = NULL;
576     } else {
577         self->expression.vtype = TYPE_FIELD;
578         self->expression.next = ast_shallow_type(ctx, TYPE_FLOAT);
579     }
580
581     self->rvalue = false;
582     self->owner  = owner;
583     ast_propagate_effects(self, owner);
584
585     self->field = field;
586     if (name)
587         self->name = util_strdup(name);
588     else
589         self->name = NULL;
590
591     return self;
592 }
593
594 void ast_member_delete(ast_member *self)
595 {
596     /* The owner is always an ast_value, which has .keep=true,
597      * also: ast_members are usually deleted after the owner, thus
598      * this will cause invalid access
599     ast_unref(self->owner);
600      * once we allow (expression).x to access a vector-member, we need
601      * to change this: preferably by creating an alternate ast node for this
602      * purpose that is not garbage-collected.
603     */
604     ast_expression_delete((ast_expression*)self);
605     mem_d(self->name);
606     mem_d(self);
607 }
608
609 bool ast_member_set_name(ast_member *self, const char *name)
610 {
611     if (self->name)
612         mem_d((void*)self->name);
613     self->name = util_strdup(name);
614     return !!self->name;
615 }
616
617 ast_array_index* ast_array_index_new(lex_ctx ctx, ast_expression *array, ast_expression *index)
618 {
619     ast_expression *outtype;
620     ast_instantiate(ast_array_index, ctx, ast_array_index_delete);
621
622     outtype = array->next;
623     if (!outtype) {
624         mem_d(self);
625         /* Error: field has no type... */
626         return NULL;
627     }
628
629     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_array_index_codegen);
630
631     self->array = array;
632     self->index = index;
633     ast_propagate_effects(self, array);
634     ast_propagate_effects(self, index);
635
636     ast_type_adopt(self, outtype);
637     if (array->vtype == TYPE_FIELD && outtype->vtype == TYPE_ARRAY) {
638         if (self->expression.vtype != TYPE_ARRAY) {
639             compile_error(ast_ctx(self), "array_index node on type");
640             ast_array_index_delete(self);
641             return NULL;
642         }
643         self->array = outtype;
644         self->expression.vtype = TYPE_FIELD;
645     }
646
647     return self;
648 }
649
650 void ast_array_index_delete(ast_array_index *self)
651 {
652     if (self->array)
653         ast_unref(self->array);
654     if (self->index)
655         ast_unref(self->index);
656     ast_expression_delete((ast_expression*)self);
657     mem_d(self);
658 }
659
660 ast_ifthen* ast_ifthen_new(lex_ctx ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse)
661 {
662     ast_instantiate(ast_ifthen, ctx, ast_ifthen_delete);
663     if (!ontrue && !onfalse) {
664         /* because it is invalid */
665         mem_d(self);
666         return NULL;
667     }
668     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_ifthen_codegen);
669
670     self->cond     = cond;
671     self->on_true  = ontrue;
672     self->on_false = onfalse;
673     ast_propagate_effects(self, cond);
674     if (ontrue)
675         ast_propagate_effects(self, ontrue);
676     if (onfalse)
677         ast_propagate_effects(self, onfalse);
678
679     return self;
680 }
681
682 void ast_ifthen_delete(ast_ifthen *self)
683 {
684     ast_unref(self->cond);
685     if (self->on_true)
686         ast_unref(self->on_true);
687     if (self->on_false)
688         ast_unref(self->on_false);
689     ast_expression_delete((ast_expression*)self);
690     mem_d(self);
691 }
692
693 ast_ternary* ast_ternary_new(lex_ctx ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse)
694 {
695     ast_expression *exprtype = ontrue;
696     ast_instantiate(ast_ternary, ctx, ast_ternary_delete);
697     /* This time NEITHER must be NULL */
698     if (!ontrue || !onfalse) {
699         mem_d(self);
700         return NULL;
701     }
702     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_ternary_codegen);
703
704     self->cond     = cond;
705     self->on_true  = ontrue;
706     self->on_false = onfalse;
707     ast_propagate_effects(self, cond);
708     ast_propagate_effects(self, ontrue);
709     ast_propagate_effects(self, onfalse);
710
711     if (ontrue->vtype == TYPE_NIL)
712         exprtype = onfalse;
713     ast_type_adopt(self, exprtype);
714
715     return self;
716 }
717
718 void ast_ternary_delete(ast_ternary *self)
719 {
720     /* the if()s are only there because computed-gotos can set them
721      * to NULL
722      */
723     if (self->cond)     ast_unref(self->cond);
724     if (self->on_true)  ast_unref(self->on_true);
725     if (self->on_false) ast_unref(self->on_false);
726     ast_expression_delete((ast_expression*)self);
727     mem_d(self);
728 }
729
730 ast_loop* ast_loop_new(lex_ctx ctx,
731                        ast_expression *initexpr,
732                        ast_expression *precond, bool pre_not,
733                        ast_expression *postcond, bool post_not,
734                        ast_expression *increment,
735                        ast_expression *body)
736 {
737     ast_instantiate(ast_loop, ctx, ast_loop_delete);
738     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_loop_codegen);
739
740     self->initexpr  = initexpr;
741     self->precond   = precond;
742     self->postcond  = postcond;
743     self->increment = increment;
744     self->body      = body;
745
746     self->pre_not   = pre_not;
747     self->post_not  = post_not;
748
749     if (initexpr)
750         ast_propagate_effects(self, initexpr);
751     if (precond)
752         ast_propagate_effects(self, precond);
753     if (postcond)
754         ast_propagate_effects(self, postcond);
755     if (increment)
756         ast_propagate_effects(self, increment);
757     if (body)
758         ast_propagate_effects(self, body);
759
760     return self;
761 }
762
763 void ast_loop_delete(ast_loop *self)
764 {
765     if (self->initexpr)
766         ast_unref(self->initexpr);
767     if (self->precond)
768         ast_unref(self->precond);
769     if (self->postcond)
770         ast_unref(self->postcond);
771     if (self->increment)
772         ast_unref(self->increment);
773     if (self->body)
774         ast_unref(self->body);
775     ast_expression_delete((ast_expression*)self);
776     mem_d(self);
777 }
778
779 ast_breakcont* ast_breakcont_new(lex_ctx ctx, bool iscont, unsigned int levels)
780 {
781     ast_instantiate(ast_breakcont, ctx, ast_breakcont_delete);
782     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_breakcont_codegen);
783
784     self->is_continue = iscont;
785     self->levels      = levels;
786
787     return self;
788 }
789
790 void ast_breakcont_delete(ast_breakcont *self)
791 {
792     ast_expression_delete((ast_expression*)self);
793     mem_d(self);
794 }
795
796 ast_switch* ast_switch_new(lex_ctx ctx, ast_expression *op)
797 {
798     ast_instantiate(ast_switch, ctx, ast_switch_delete);
799     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_switch_codegen);
800
801     self->operand = op;
802     self->cases   = NULL;
803
804     ast_propagate_effects(self, op);
805
806     return self;
807 }
808
809 void ast_switch_delete(ast_switch *self)
810 {
811     size_t i;
812     ast_unref(self->operand);
813
814     for (i = 0; i < vec_size(self->cases); ++i) {
815         if (self->cases[i].value)
816             ast_unref(self->cases[i].value);
817         ast_unref(self->cases[i].code);
818     }
819     vec_free(self->cases);
820
821     ast_expression_delete((ast_expression*)self);
822     mem_d(self);
823 }
824
825 ast_label* ast_label_new(lex_ctx ctx, const char *name, bool undefined)
826 {
827     ast_instantiate(ast_label, ctx, ast_label_delete);
828     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_label_codegen);
829
830     self->expression.vtype = TYPE_NOEXPR;
831
832     self->name      = util_strdup(name);
833     self->irblock   = NULL;
834     self->gotos     = NULL;
835     self->undefined = undefined;
836
837     return self;
838 }
839
840 void ast_label_delete(ast_label *self)
841 {
842     mem_d((void*)self->name);
843     vec_free(self->gotos);
844     ast_expression_delete((ast_expression*)self);
845     mem_d(self);
846 }
847
848 void ast_label_register_goto(ast_label *self, ast_goto *g)
849 {
850     vec_push(self->gotos, g);
851 }
852
853 ast_goto* ast_goto_new(lex_ctx ctx, const char *name)
854 {
855     ast_instantiate(ast_goto, ctx, ast_goto_delete);
856     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_goto_codegen);
857
858     self->name    = util_strdup(name);
859     self->target  = NULL;
860     self->irblock_from = NULL;
861
862     return self;
863 }
864
865 void ast_goto_delete(ast_goto *self)
866 {
867     mem_d((void*)self->name);
868     ast_expression_delete((ast_expression*)self);
869     mem_d(self);
870 }
871
872 void ast_goto_set_label(ast_goto *self, ast_label *label)
873 {
874     self->target = label;
875 }
876
877 ast_call* ast_call_new(lex_ctx ctx,
878                        ast_expression *funcexpr)
879 {
880     ast_instantiate(ast_call, ctx, ast_call_delete);
881     if (!funcexpr->next) {
882         compile_error(ctx, "not a function");
883         mem_d(self);
884         return NULL;
885     }
886     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_call_codegen);
887
888     ast_side_effects(self) = true;
889
890     self->params   = NULL;
891     self->func     = funcexpr;
892     self->va_count = NULL;
893
894     ast_type_adopt(self, funcexpr->next);
895
896     return self;
897 }
898
899 void ast_call_delete(ast_call *self)
900 {
901     size_t i;
902     for (i = 0; i < vec_size(self->params); ++i)
903         ast_unref(self->params[i]);
904     vec_free(self->params);
905
906     if (self->func)
907         ast_unref(self->func);
908
909     if (self->va_count)
910         ast_unref(self->va_count);
911
912     ast_expression_delete((ast_expression*)self);
913     mem_d(self);
914 }
915
916 bool ast_call_check_types(ast_call *self)
917 {
918     char texp[1024];
919     char tgot[1024];
920     size_t i;
921     bool   retval = true;
922     const  ast_expression *func = self->func;
923     size_t count = vec_size(self->params);
924     if (count > vec_size(func->params))
925         count = vec_size(func->params);
926
927     for (i = 0; i < count; ++i) {
928         if (!ast_compare_type(self->params[i], (ast_expression*)(func->params[i])))
929         {
930             ast_type_to_string(self->params[i], tgot, sizeof(tgot));
931             ast_type_to_string((ast_expression*)func->params[i], texp, sizeof(texp));
932             compile_error(ast_ctx(self), "invalid type for parameter %u in function call: expected %s, got %s",
933                      (unsigned int)(i+1), texp, tgot);
934             /* we don't immediately return */
935             retval = false;
936         }
937     }
938     count = vec_size(self->params);
939     if (count > vec_size(func->params) && func->varparam) {
940         for (; i < count; ++i) {
941             if (!ast_compare_type(self->params[i], func->varparam))
942             {
943                 ast_type_to_string(self->params[i], tgot, sizeof(tgot));
944                 ast_type_to_string(func->varparam, texp, sizeof(texp));
945                 compile_error(ast_ctx(self), "invalid type for parameter %u in function call: expected %s, got %s",
946                          (unsigned int)(i+1), texp, tgot);
947                 /* we don't immediately return */
948                 retval = false;
949             }
950         }
951     }
952     return retval;
953 }
954
955 ast_store* ast_store_new(lex_ctx ctx, int op,
956                          ast_expression *dest, ast_expression *source)
957 {
958     ast_instantiate(ast_store, ctx, ast_store_delete);
959     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_store_codegen);
960
961     ast_side_effects(self) = true;
962
963     self->op = op;
964     self->dest = dest;
965     self->source = source;
966
967     ast_type_adopt(self, dest);
968
969     return self;
970 }
971
972 void ast_store_delete(ast_store *self)
973 {
974     ast_unref(self->dest);
975     ast_unref(self->source);
976     ast_expression_delete((ast_expression*)self);
977     mem_d(self);
978 }
979
980 ast_block* ast_block_new(lex_ctx ctx)
981 {
982     ast_instantiate(ast_block, ctx, ast_block_delete);
983     ast_expression_init((ast_expression*)self,
984                         (ast_expression_codegen*)&ast_block_codegen);
985
986     self->locals  = NULL;
987     self->exprs   = NULL;
988     self->collect = NULL;
989
990     return self;
991 }
992
993 bool ast_block_add_expr(ast_block *self, ast_expression *e)
994 {
995     ast_propagate_effects(self, e);
996     vec_push(self->exprs, e);
997     if (self->expression.next) {
998         ast_delete(self->expression.next);
999         self->expression.next = NULL;
1000     }
1001     ast_type_adopt(self, e);
1002     return true;
1003 }
1004
1005 void ast_block_collect(ast_block *self, ast_expression *expr)
1006 {
1007     vec_push(self->collect, expr);
1008     expr->node.keep = true;
1009 }
1010
1011 void ast_block_delete(ast_block *self)
1012 {
1013     size_t i;
1014     for (i = 0; i < vec_size(self->exprs); ++i)
1015         ast_unref(self->exprs[i]);
1016     vec_free(self->exprs);
1017     for (i = 0; i < vec_size(self->locals); ++i)
1018         ast_delete(self->locals[i]);
1019     vec_free(self->locals);
1020     for (i = 0; i < vec_size(self->collect); ++i)
1021         ast_delete(self->collect[i]);
1022     vec_free(self->collect);
1023     ast_expression_delete((ast_expression*)self);
1024     mem_d(self);
1025 }
1026
1027 void ast_block_set_type(ast_block *self, ast_expression *from)
1028 {
1029     if (self->expression.next)
1030         ast_delete(self->expression.next);
1031     ast_type_adopt(self, from);
1032 }
1033
1034 ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype)
1035 {
1036     ast_instantiate(ast_function, ctx, ast_function_delete);
1037
1038     if (!vtype ||
1039         vtype->hasvalue ||
1040         vtype->expression.vtype != TYPE_FUNCTION)
1041     {
1042         compile_error(ast_ctx(self), "internal error: ast_function_new condition %i %i type=%i (probably 2 bodies?)",
1043                  (int)!vtype,
1044                  (int)vtype->hasvalue,
1045                  vtype->expression.vtype);
1046         mem_d(self);
1047         return NULL;
1048     }
1049
1050     self->vtype  = vtype;
1051     self->name   = name ? util_strdup(name) : NULL;
1052     self->blocks = NULL;
1053
1054     self->labelcount = 0;
1055     self->builtin = 0;
1056
1057     self->ir_func = NULL;
1058     self->curblock = NULL;
1059
1060     self->breakblocks    = NULL;
1061     self->continueblocks = NULL;
1062
1063     vtype->hasvalue = true;
1064     vtype->constval.vfunc = self;
1065
1066     self->varargs     = NULL;
1067     self->argc        = NULL;
1068     self->fixedparams = NULL;
1069
1070     return self;
1071 }
1072
1073 void ast_function_delete(ast_function *self)
1074 {
1075     size_t i;
1076     if (self->name)
1077         mem_d((void*)self->name);
1078     if (self->vtype) {
1079         /* ast_value_delete(self->vtype); */
1080         self->vtype->hasvalue = false;
1081         self->vtype->constval.vfunc = NULL;
1082         /* We use unref - if it was stored in a global table it is supposed
1083          * to be deleted from *there*
1084          */
1085         ast_unref(self->vtype);
1086     }
1087     for (i = 0; i < vec_size(self->blocks); ++i)
1088         ast_delete(self->blocks[i]);
1089     vec_free(self->blocks);
1090     vec_free(self->breakblocks);
1091     vec_free(self->continueblocks);
1092     if (self->varargs)
1093         ast_delete(self->varargs);
1094     if (self->argc)
1095         ast_delete(self->argc);
1096     if (self->fixedparams)
1097         ast_unref(self->fixedparams);
1098     mem_d(self);
1099 }
1100
1101 const char* ast_function_label(ast_function *self, const char *prefix)
1102 {
1103     size_t id;
1104     size_t len;
1105     char  *from;
1106
1107     if (!OPTS_OPTION_BOOL(OPTION_DUMP)    &&
1108         !OPTS_OPTION_BOOL(OPTION_DUMPFIN) &&
1109         !OPTS_OPTION_BOOL(OPTION_DEBUG))
1110     {
1111         return NULL;
1112     }
1113
1114     id  = (self->labelcount++);
1115     len = strlen(prefix);
1116
1117     from = self->labelbuf + sizeof(self->labelbuf)-1;
1118     *from-- = 0;
1119     do {
1120         *from-- = (id%10) + '0';
1121         id /= 10;
1122     } while (id);
1123     ++from;
1124     memcpy(from - len, prefix, len);
1125     return from - len;
1126 }
1127
1128 /*********************************************************************/
1129 /* AST codegen part
1130  * by convention you must never pass NULL to the 'ir_value **out'
1131  * parameter. If you really don't care about the output, pass a dummy.
1132  * But I can't imagine a pituation where the output is truly unnecessary.
1133  */
1134
1135 void _ast_codegen_output_type(ast_expression *self, ir_value *out)
1136 {
1137     if (out->vtype == TYPE_FIELD)
1138         out->fieldtype = self->next->vtype;
1139     if (out->vtype == TYPE_FUNCTION)
1140         out->outtype = self->next->vtype;
1141 }
1142
1143 #define codegen_output_type(a,o) (_ast_codegen_output_type(&((a)->expression),(o)))
1144
1145 bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_value **out)
1146 {
1147     (void)func;
1148     (void)lvalue;
1149     if (self->expression.vtype == TYPE_NIL) {
1150         *out = func->ir_func->owner->nil;
1151         return true;
1152     }
1153     /* NOTE: This is the codegen for a variable used in an expression.
1154      * It is not the codegen to generate the value. For this purpose,
1155      * ast_local_codegen and ast_global_codegen are to be used before this
1156      * is executed. ast_function_codegen should take care of its locals,
1157      * and the ast-user should take care of ast_global_codegen to be used
1158      * on all the globals.
1159      */
1160     if (!self->ir_v) {
1161         char tname[1024]; /* typename is reserved in C++ */
1162         ast_type_to_string((ast_expression*)self, tname, sizeof(tname));
1163         compile_error(ast_ctx(self), "ast_value used before generated %s %s", tname, self->name);
1164         return false;
1165     }
1166     *out = self->ir_v;
1167     return true;
1168 }
1169
1170 bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
1171 {
1172     ir_value *v = NULL;
1173
1174     if (self->expression.vtype == TYPE_NIL) {
1175         compile_error(ast_ctx(self), "internal error: trying to generate a variable of TYPE_NIL");
1176         return false;
1177     }
1178
1179     if (self->hasvalue && self->expression.vtype == TYPE_FUNCTION)
1180     {
1181         ir_function *func = ir_builder_create_function(ir, self->name, self->expression.next->vtype);
1182         if (!func)
1183             return false;
1184         func->context = ast_ctx(self);
1185         func->value->context = ast_ctx(self);
1186
1187         self->constval.vfunc->ir_func = func;
1188         self->ir_v = func->value;
1189         if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
1190             self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
1191         /* The function is filled later on ast_function_codegen... */
1192         return true;
1193     }
1194
1195     if (isfield && self->expression.vtype == TYPE_FIELD) {
1196         ast_expression *fieldtype = self->expression.next;
1197
1198         if (self->hasvalue) {
1199             compile_error(ast_ctx(self), "TODO: constant field pointers with value");
1200             goto error;
1201         }
1202
1203         if (fieldtype->vtype == TYPE_ARRAY) {
1204             size_t ai;
1205             char   *name;
1206             size_t  namelen;
1207
1208             ast_expression *elemtype;
1209             int             vtype;
1210             ast_value      *array = (ast_value*)fieldtype;
1211
1212             if (!ast_istype(fieldtype, ast_value)) {
1213                 compile_error(ast_ctx(self), "internal error: ast_value required");
1214                 return false;
1215             }
1216
1217             /* we are lame now - considering the way QC works we won't tolerate arrays > 1024 elements */
1218             if (!array->expression.count || array->expression.count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE))
1219                 compile_error(ast_ctx(self), "Invalid array of size %lu", (unsigned long)array->expression.count);
1220
1221             elemtype = array->expression.next;
1222             vtype = elemtype->vtype;
1223
1224             v = ir_builder_create_field(ir, self->name, vtype);
1225             if (!v) {
1226                 compile_error(ast_ctx(self), "ir_builder_create_global failed on `%s`", self->name);
1227                 return false;
1228             }
1229             v->context = ast_ctx(self);
1230             v->unique_life = true;
1231             v->locked      = true;
1232             array->ir_v = self->ir_v = v;
1233             if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
1234                 self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
1235
1236             namelen = strlen(self->name);
1237             name    = (char*)mem_a(namelen + 16);
1238             util_strncpy(name, self->name, namelen);
1239
1240             array->ir_values = (ir_value**)mem_a(sizeof(array->ir_values[0]) * array->expression.count);
1241             array->ir_values[0] = v;
1242             for (ai = 1; ai < array->expression.count; ++ai) {
1243                 util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
1244                 array->ir_values[ai] = ir_builder_create_field(ir, name, vtype);
1245                 if (!array->ir_values[ai]) {
1246                     mem_d(name);
1247                     compile_error(ast_ctx(self), "ir_builder_create_global failed on `%s`", name);
1248                     return false;
1249                 }
1250                 array->ir_values[ai]->context = ast_ctx(self);
1251                 array->ir_values[ai]->unique_life = true;
1252                 array->ir_values[ai]->locked      = true;
1253                 if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
1254                     self->ir_values[ai]->flags |= IR_FLAG_INCLUDE_DEF;
1255             }
1256             mem_d(name);
1257         }
1258         else
1259         {
1260             v = ir_builder_create_field(ir, self->name, self->expression.next->vtype);
1261             if (!v)
1262                 return false;
1263             v->context = ast_ctx(self);
1264             self->ir_v = v;
1265             if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
1266                 self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
1267         }
1268         return true;
1269     }
1270
1271     if (self->expression.vtype == TYPE_ARRAY) {
1272         size_t ai;
1273         char   *name;
1274         size_t  namelen;
1275
1276         ast_expression *elemtype = self->expression.next;
1277         int vtype = elemtype->vtype;
1278
1279         /* same as with field arrays */
1280         if (!self->expression.count || self->expression.count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE))
1281             compile_error(ast_ctx(self), "Invalid array of size %lu", (unsigned long)self->expression.count);
1282
1283         v = ir_builder_create_global(ir, self->name, vtype);
1284         if (!v) {
1285             compile_error(ast_ctx(self), "ir_builder_create_global failed `%s`", self->name);
1286             return false;
1287         }
1288         v->context = ast_ctx(self);
1289         v->unique_life = true;
1290         v->locked      = true;
1291         if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
1292             v->flags |= IR_FLAG_INCLUDE_DEF;
1293
1294         namelen = strlen(self->name);
1295         name    = (char*)mem_a(namelen + 16);
1296         util_strncpy(name, self->name, namelen);
1297
1298         self->ir_values = (ir_value**)mem_a(sizeof(self->ir_values[0]) * self->expression.count);
1299         self->ir_values[0] = v;
1300         for (ai = 1; ai < self->expression.count; ++ai) {
1301             util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
1302             self->ir_values[ai] = ir_builder_create_global(ir, name, vtype);
1303             if (!self->ir_values[ai]) {
1304                 mem_d(name);
1305                 compile_error(ast_ctx(self), "ir_builder_create_global failed `%s`", name);
1306                 return false;
1307             }
1308             self->ir_values[ai]->context = ast_ctx(self);
1309             self->ir_values[ai]->unique_life = true;
1310             self->ir_values[ai]->locked      = true;
1311             if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
1312                 self->ir_values[ai]->flags |= IR_FLAG_INCLUDE_DEF;
1313         }
1314         mem_d(name);
1315     }
1316     else
1317     {
1318         /* Arrays don't do this since there's no "array" value which spans across the
1319          * whole thing.
1320          */
1321         v = ir_builder_create_global(ir, self->name, self->expression.vtype);
1322         if (!v) {
1323             compile_error(ast_ctx(self), "ir_builder_create_global failed on `%s`", self->name);
1324             return false;
1325         }
1326         codegen_output_type(self, v);
1327         v->context = ast_ctx(self);
1328     }
1329
1330     if (self->hasvalue) {
1331         switch (self->expression.vtype)
1332         {
1333             case TYPE_FLOAT:
1334                 if (!ir_value_set_float(v, self->constval.vfloat))
1335                     goto error;
1336                 break;
1337             case TYPE_VECTOR:
1338                 if (!ir_value_set_vector(v, self->constval.vvec))
1339                     goto error;
1340                 break;
1341             case TYPE_STRING:
1342                 if (!ir_value_set_string(v, self->constval.vstring))
1343                     goto error;
1344                 break;
1345             case TYPE_ARRAY:
1346                 compile_error(ast_ctx(self), "TODO: global constant array");
1347                 break;
1348             case TYPE_FUNCTION:
1349                 compile_error(ast_ctx(self), "global of type function not properly generated");
1350                 goto error;
1351                 /* Cannot generate an IR value for a function,
1352                  * need a pointer pointing to a function rather.
1353                  */
1354             case TYPE_FIELD:
1355                 if (!self->constval.vfield) {
1356                     compile_error(ast_ctx(self), "field constant without vfield set");
1357                     goto error;
1358                 }
1359                 if (!self->constval.vfield->ir_v) {
1360                     compile_error(ast_ctx(self), "field constant generated before its field");
1361                     goto error;
1362                 }
1363                 if (!ir_value_set_field(v, self->constval.vfield->ir_v))
1364                     goto error;
1365                 break;
1366             default:
1367                 compile_error(ast_ctx(self), "TODO: global constant type %i", self->expression.vtype);
1368                 break;
1369         }
1370     }
1371
1372     /* link us to the ir_value */
1373     v->cvq = self->cvq;
1374     self->ir_v = v;
1375     if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
1376         self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
1377     return true;
1378
1379 error: /* clean up */
1380     ir_value_delete(v);
1381     return false;
1382 }
1383
1384 bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
1385 {
1386     ir_value *v = NULL;
1387
1388     if (self->expression.vtype == TYPE_NIL) {
1389         compile_error(ast_ctx(self), "internal error: trying to generate a variable of TYPE_NIL");
1390         return false;
1391     }
1392
1393     if (self->hasvalue && self->expression.vtype == TYPE_FUNCTION)
1394     {
1395         /* Do we allow local functions? I think not...
1396          * this is NOT a function pointer atm.
1397          */
1398         return false;
1399     }
1400
1401     if (self->expression.vtype == TYPE_ARRAY) {
1402         size_t ai;
1403         char   *name;
1404         size_t  namelen;
1405
1406         ast_expression *elemtype = self->expression.next;
1407         int vtype = elemtype->vtype;
1408
1409         func->flags |= IR_FLAG_HAS_ARRAYS;
1410
1411         if (param && !(self->expression.flags & AST_FLAG_IS_VARARG)) {
1412             compile_error(ast_ctx(self), "array-parameters are not supported");
1413             return false;
1414         }
1415
1416         /* we are lame now - considering the way QC works we won't tolerate arrays > 1024 elements */
1417         if (!self->expression.count || self->expression.count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE)) {
1418             compile_error(ast_ctx(self), "Invalid array of size %lu", (unsigned long)self->expression.count);
1419         }
1420
1421         self->ir_values = (ir_value**)mem_a(sizeof(self->ir_values[0]) * self->expression.count);
1422         if (!self->ir_values) {
1423             compile_error(ast_ctx(self), "failed to allocate array values");
1424             return false;
1425         }
1426
1427         v = ir_function_create_local(func, self->name, vtype, param);
1428         if (!v) {
1429             compile_error(ast_ctx(self), "internal error: ir_function_create_local failed");
1430             return false;
1431         }
1432         v->context = ast_ctx(self);
1433         v->unique_life = true;
1434         v->locked      = true;
1435
1436         namelen = strlen(self->name);
1437         name    = (char*)mem_a(namelen + 16);
1438         util_strncpy(name, self->name, namelen);
1439
1440         self->ir_values[0] = v;
1441         for (ai = 1; ai < self->expression.count; ++ai) {
1442             util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
1443             self->ir_values[ai] = ir_function_create_local(func, name, vtype, param);
1444             if (!self->ir_values[ai]) {
1445                 compile_error(ast_ctx(self), "internal_error: ir_builder_create_global failed on `%s`", name);
1446                 return false;
1447             }
1448             self->ir_values[ai]->context = ast_ctx(self);
1449             self->ir_values[ai]->unique_life = true;
1450             self->ir_values[ai]->locked      = true;
1451         }
1452         mem_d(name);
1453     }
1454     else
1455     {
1456         v = ir_function_create_local(func, self->name, self->expression.vtype, param);
1457         if (!v)
1458             return false;
1459         codegen_output_type(self, v);
1460         v->context = ast_ctx(self);
1461     }
1462
1463     /* A constant local... hmmm...
1464      * I suppose the IR will have to deal with this
1465      */
1466     if (self->hasvalue) {
1467         switch (self->expression.vtype)
1468         {
1469             case TYPE_FLOAT:
1470                 if (!ir_value_set_float(v, self->constval.vfloat))
1471                     goto error;
1472                 break;
1473             case TYPE_VECTOR:
1474                 if (!ir_value_set_vector(v, self->constval.vvec))
1475                     goto error;
1476                 break;
1477             case TYPE_STRING:
1478                 if (!ir_value_set_string(v, self->constval.vstring))
1479                     goto error;
1480                 break;
1481             default:
1482                 compile_error(ast_ctx(self), "TODO: global constant type %i", self->expression.vtype);
1483                 break;
1484         }
1485     }
1486
1487     /* link us to the ir_value */
1488     v->cvq = self->cvq;
1489     self->ir_v = v;
1490
1491     if (!ast_generate_accessors(self, func->owner))
1492         return false;
1493     return true;
1494
1495 error: /* clean up */
1496     ir_value_delete(v);
1497     return false;
1498 }
1499
1500 bool ast_generate_accessors(ast_value *self, ir_builder *ir)
1501 {
1502     size_t i;
1503     bool warn = OPTS_WARN(WARN_USED_UNINITIALIZED);
1504     if (!self->setter || !self->getter)
1505         return true;
1506     for (i = 0; i < self->expression.count; ++i) {
1507         if (!self->ir_values) {
1508             compile_error(ast_ctx(self), "internal error: no array values generated for `%s`", self->name);
1509             return false;
1510         }
1511         if (!self->ir_values[i]) {
1512             compile_error(ast_ctx(self), "internal error: not all array values have been generated for `%s`", self->name);
1513             return false;
1514         }
1515         if (self->ir_values[i]->life) {
1516             compile_error(ast_ctx(self), "internal error: function containing `%s` already generated", self->name);
1517             return false;
1518         }
1519     }
1520
1521     opts_set(opts.warn, WARN_USED_UNINITIALIZED, false);
1522     if (self->setter) {
1523         if (!ast_global_codegen  (self->setter, ir, false) ||
1524             !ast_function_codegen(self->setter->constval.vfunc, ir) ||
1525             !ir_function_finalize(self->setter->constval.vfunc->ir_func))
1526         {
1527             compile_error(ast_ctx(self), "internal error: failed to generate setter for `%s`", self->name);
1528             opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
1529             return false;
1530         }
1531     }
1532     if (self->getter) {
1533         if (!ast_global_codegen  (self->getter, ir, false) ||
1534             !ast_function_codegen(self->getter->constval.vfunc, ir) ||
1535             !ir_function_finalize(self->getter->constval.vfunc->ir_func))
1536         {
1537             compile_error(ast_ctx(self), "internal error: failed to generate getter for `%s`", self->name);
1538             opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
1539             return false;
1540         }
1541     }
1542     for (i = 0; i < self->expression.count; ++i) {
1543         vec_free(self->ir_values[i]->life);
1544     }
1545     opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
1546     return true;
1547 }
1548
1549 bool ast_function_codegen(ast_function *self, ir_builder *ir)
1550 {
1551     ir_function *irf;
1552     ir_value    *dummy;
1553     ast_expression         *ec;
1554     ast_expression_codegen *cgen;
1555     size_t    i;
1556
1557     (void)ir;
1558
1559     irf = self->ir_func;
1560     if (!irf) {
1561         compile_error(ast_ctx(self), "internal error: ast_function's related ast_value was not generated yet");
1562         return false;
1563     }
1564
1565     /* fill the parameter list */
1566     ec = &self->vtype->expression;
1567     for (i = 0; i < vec_size(ec->params); ++i)
1568     {
1569         if (ec->params[i]->expression.vtype == TYPE_FIELD)
1570             vec_push(irf->params, ec->params[i]->expression.next->vtype);
1571         else
1572             vec_push(irf->params, ec->params[i]->expression.vtype);
1573         if (!self->builtin) {
1574             if (!ast_local_codegen(ec->params[i], self->ir_func, true))
1575                 return false;
1576         }
1577     }
1578
1579     if (self->varargs) {
1580         if (!ast_local_codegen(self->varargs, self->ir_func, true))
1581             return false;
1582         irf->max_varargs = self->varargs->expression.count;
1583     }
1584
1585     if (self->builtin) {
1586         irf->builtin = self->builtin;
1587         return true;
1588     }
1589
1590     if (!vec_size(self->blocks)) {
1591         compile_error(ast_ctx(self), "function `%s` has no body", self->name);
1592         return false;
1593     }
1594
1595     irf->first = self->curblock = ir_function_create_block(ast_ctx(self), irf, "entry");
1596     if (!self->curblock) {
1597         compile_error(ast_ctx(self), "failed to allocate entry block for `%s`", self->name);
1598         return false;
1599     }
1600
1601     if (self->argc) {
1602         ir_value *va_count;
1603         ir_value *fixed;
1604         ir_value *sub;
1605         if (!ast_local_codegen(self->argc, self->ir_func, true))
1606             return false;
1607         cgen = self->argc->expression.codegen;
1608         if (!(*cgen)((ast_expression*)(self->argc), self, false, &va_count))
1609             return false;
1610         cgen = self->fixedparams->expression.codegen;
1611         if (!(*cgen)((ast_expression*)(self->fixedparams), self, false, &fixed))
1612             return false;
1613         sub = ir_block_create_binop(self->curblock, ast_ctx(self),
1614                                     ast_function_label(self, "va_count"), INSTR_SUB_F,
1615                                     ir_builder_get_va_count(ir), fixed);
1616         if (!sub)
1617             return false;
1618         if (!ir_block_create_store_op(self->curblock, ast_ctx(self), INSTR_STORE_F,
1619                                       va_count, sub))
1620         {
1621             return false;
1622         }
1623     }
1624
1625     for (i = 0; i < vec_size(self->blocks); ++i) {
1626         cgen = self->blocks[i]->expression.codegen;
1627         if (!(*cgen)((ast_expression*)self->blocks[i], self, false, &dummy))
1628             return false;
1629     }
1630
1631     /* TODO: check return types */
1632     if (!self->curblock->final)
1633     {
1634         if (!self->vtype->expression.next ||
1635             self->vtype->expression.next->vtype == TYPE_VOID)
1636         {
1637             return ir_block_create_return(self->curblock, ast_ctx(self), NULL);
1638         }
1639         else if (vec_size(self->curblock->entries) || self->curblock == irf->first)
1640         {
1641             /* error("missing return"); */
1642             if (compile_warning(ast_ctx(self), WARN_MISSING_RETURN_VALUES,
1643                                 "control reaches end of non-void function (`%s`) via %s",
1644                                 self->name, self->curblock->label))
1645             {
1646                 return false;
1647             }
1648             return ir_block_create_return(self->curblock, ast_ctx(self), NULL);
1649         }
1650     }
1651     return true;
1652 }
1653
1654 /* Note, you will not see ast_block_codegen generate ir_blocks.
1655  * To the AST and the IR, blocks are 2 different things.
1656  * In the AST it represents a block of code, usually enclosed in
1657  * curly braces {...}.
1658  * While in the IR it represents a block in terms of control-flow.
1659  */
1660 bool ast_block_codegen(ast_block *self, ast_function *func, bool lvalue, ir_value **out)
1661 {
1662     size_t i;
1663
1664     /* We don't use this
1665      * Note: an ast-representation using the comma-operator
1666      * of the form: (a, b, c) = x should not assign to c...
1667      */
1668     if (lvalue) {
1669         compile_error(ast_ctx(self), "not an l-value (code-block)");
1670         return false;
1671     }
1672
1673     if (self->expression.outr) {
1674         *out = self->expression.outr;
1675         return true;
1676     }
1677
1678     /* output is NULL at first, we'll have each expression
1679      * assign to out output, thus, a comma-operator represention
1680      * using an ast_block will return the last generated value,
1681      * so: (b, c) + a  executed both b and c, and returns c,
1682      * which is then added to a.
1683      */
1684     *out = NULL;
1685
1686     /* generate locals */
1687     for (i = 0; i < vec_size(self->locals); ++i)
1688     {
1689         if (!ast_local_codegen(self->locals[i], func->ir_func, false)) {
1690             if (OPTS_OPTION_BOOL(OPTION_DEBUG))
1691                 compile_error(ast_ctx(self), "failed to generate local `%s`", self->locals[i]->name);
1692             return false;
1693         }
1694     }
1695
1696     for (i = 0; i < vec_size(self->exprs); ++i)
1697     {
1698         ast_expression_codegen *gen;
1699         if (func->curblock->final && !ast_istype(self->exprs[i], ast_label)) {
1700             if (compile_warning(ast_ctx(self->exprs[i]), WARN_UNREACHABLE_CODE, "unreachable statement"))
1701                 return false;
1702             continue;
1703         }
1704         gen = self->exprs[i]->codegen;
1705         if (!(*gen)(self->exprs[i], func, false, out))
1706             return false;
1707     }
1708
1709     self->expression.outr = *out;
1710
1711     return true;
1712 }
1713
1714 bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_value **out)
1715 {
1716     ast_expression_codegen *cgen;
1717     ir_value *left  = NULL;
1718     ir_value *right = NULL;
1719
1720     ast_value       *arr;
1721     ast_value       *idx = 0;
1722     ast_array_index *ai = NULL;
1723
1724     if (lvalue && self->expression.outl) {
1725         *out = self->expression.outl;
1726         return true;
1727     }
1728
1729     if (!lvalue && self->expression.outr) {
1730         *out = self->expression.outr;
1731         return true;
1732     }
1733
1734     if (ast_istype(self->dest, ast_array_index))
1735     {
1736
1737         ai = (ast_array_index*)self->dest;
1738         idx = (ast_value*)ai->index;
1739
1740         if (ast_istype(ai->index, ast_value) && idx->hasvalue && idx->cvq == CV_CONST)
1741             ai = NULL;
1742     }
1743
1744     if (ai) {
1745         /* we need to call the setter */
1746         ir_value  *iridx, *funval;
1747         ir_instr  *call;
1748
1749         if (lvalue) {
1750             compile_error(ast_ctx(self), "array-subscript assignment cannot produce lvalues");
1751             return false;
1752         }
1753
1754         arr = (ast_value*)ai->array;
1755         if (!ast_istype(ai->array, ast_value) || !arr->setter) {
1756             compile_error(ast_ctx(self), "value has no setter (%s)", arr->name);
1757             return false;
1758         }
1759
1760         cgen = idx->expression.codegen;
1761         if (!(*cgen)((ast_expression*)(idx), func, false, &iridx))
1762             return false;
1763
1764         cgen = arr->setter->expression.codegen;
1765         if (!(*cgen)((ast_expression*)(arr->setter), func, true, &funval))
1766             return false;
1767
1768         cgen = self->source->codegen;
1769         if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
1770             return false;
1771
1772         call = ir_block_create_call(func->curblock, ast_ctx(self), ast_function_label(func, "store"), funval, false);
1773         if (!call)
1774             return false;
1775         ir_call_param(call, iridx);
1776         ir_call_param(call, right);
1777         self->expression.outr = right;
1778     }
1779     else
1780     {
1781         /* regular code */
1782
1783         cgen = self->dest->codegen;
1784         /* lvalue! */
1785         if (!(*cgen)((ast_expression*)(self->dest), func, true, &left))
1786             return false;
1787         self->expression.outl = left;
1788
1789         cgen = self->source->codegen;
1790         /* rvalue! */
1791         if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
1792             return false;
1793
1794         if (!ir_block_create_store_op(func->curblock, ast_ctx(self), self->op, left, right))
1795             return false;
1796         self->expression.outr = right;
1797     }
1798
1799     /* Theoretically, an assinment returns its left side as an
1800      * lvalue, if we don't need an lvalue though, we return
1801      * the right side as an rvalue, otherwise we have to
1802      * somehow know whether or not we need to dereference the pointer
1803      * on the left side - that is: OP_LOAD if it was an address.
1804      * Also: in original QC we cannot OP_LOADP *anyway*.
1805      */
1806     *out = (lvalue ? left : right);
1807
1808     return true;
1809 }
1810
1811 bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_value **out)
1812 {
1813     ast_expression_codegen *cgen;
1814     ir_value *left, *right;
1815
1816     /* A binary operation cannot yield an l-value */
1817     if (lvalue) {
1818         compile_error(ast_ctx(self), "not an l-value (binop)");
1819         return false;
1820     }
1821
1822     if (self->expression.outr) {
1823         *out = self->expression.outr;
1824         return true;
1825     }
1826
1827     if ((OPTS_FLAG(SHORT_LOGIC) || OPTS_FLAG(PERL_LOGIC)) &&
1828         (self->op == INSTR_AND || self->op == INSTR_OR))
1829     {
1830         /* short circuit evaluation */
1831         ir_block *other, *merge;
1832         ir_block *from_left, *from_right;
1833         ir_instr *phi;
1834         size_t    merge_id;
1835
1836         /* prepare end-block */
1837         merge_id = vec_size(func->ir_func->blocks);
1838         merge    = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_merge"));
1839
1840         /* generate the left expression */
1841         cgen = self->left->codegen;
1842         if (!(*cgen)((ast_expression*)(self->left), func, false, &left))
1843             return false;
1844         /* remember the block */
1845         from_left = func->curblock;
1846
1847         /* create a new block for the right expression */
1848         other = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_other"));
1849         if (self->op == INSTR_AND) {
1850             /* on AND: left==true -> other */
1851             if (!ir_block_create_if(func->curblock, ast_ctx(self), left, other, merge))
1852                 return false;
1853         } else {
1854             /* on OR: left==false -> other */
1855             if (!ir_block_create_if(func->curblock, ast_ctx(self), left, merge, other))
1856                 return false;
1857         }
1858         /* use the likely flag */
1859         vec_last(func->curblock->instr)->likely = true;
1860
1861         /* enter the right-expression's block */
1862         func->curblock = other;
1863         /* generate */
1864         cgen = self->right->codegen;
1865         if (!(*cgen)((ast_expression*)(self->right), func, false, &right))
1866             return false;
1867         /* remember block */
1868         from_right = func->curblock;
1869
1870         /* jump to the merge block */
1871         if (!ir_block_create_jump(func->curblock, ast_ctx(self), merge))
1872             return false;
1873
1874         vec_remove(func->ir_func->blocks, merge_id, 1);
1875         vec_push(func->ir_func->blocks, merge);
1876
1877         func->curblock = merge;
1878         phi = ir_block_create_phi(func->curblock, ast_ctx(self),
1879                                   ast_function_label(func, "sce_value"),
1880                                   self->expression.vtype);
1881         ir_phi_add(phi, from_left, left);
1882         ir_phi_add(phi, from_right, right);
1883         *out = ir_phi_value(phi);
1884         if (!*out)
1885             return false;
1886
1887         if (!OPTS_FLAG(PERL_LOGIC)) {
1888             /* cast-to-bool */
1889             if (OPTS_FLAG(CORRECT_LOGIC) && (*out)->vtype == TYPE_VECTOR) {
1890                 *out = ir_block_create_unary(func->curblock, ast_ctx(self),
1891                                              ast_function_label(func, "sce_bool_v"),
1892                                              INSTR_NOT_V, *out);
1893                 if (!*out)
1894                     return false;
1895                 *out = ir_block_create_unary(func->curblock, ast_ctx(self),
1896                                              ast_function_label(func, "sce_bool"),
1897                                              INSTR_NOT_F, *out);
1898                 if (!*out)
1899                     return false;
1900             }
1901             else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && (*out)->vtype == TYPE_STRING) {
1902                 *out = ir_block_create_unary(func->curblock, ast_ctx(self),
1903                                              ast_function_label(func, "sce_bool_s"),
1904                                              INSTR_NOT_S, *out);
1905                 if (!*out)
1906                     return false;
1907                 *out = ir_block_create_unary(func->curblock, ast_ctx(self),
1908                                              ast_function_label(func, "sce_bool"),
1909                                              INSTR_NOT_F, *out);
1910                 if (!*out)
1911                     return false;
1912             }
1913             else {
1914                 *out = ir_block_create_binop(func->curblock, ast_ctx(self),
1915                                              ast_function_label(func, "sce_bool"),
1916                                              INSTR_AND, *out, *out);
1917                 if (!*out)
1918                     return false;
1919             }
1920         }
1921
1922         self->expression.outr = *out;
1923         codegen_output_type(self, *out);
1924         return true;
1925     }
1926
1927     cgen = self->left->codegen;
1928     if (!(*cgen)((ast_expression*)(self->left), func, false, &left))
1929         return false;
1930
1931     cgen = self->right->codegen;
1932     if (!(*cgen)((ast_expression*)(self->right), func, false, &right))
1933         return false;
1934
1935     *out = ir_block_create_binop(func->curblock, ast_ctx(self), ast_function_label(func, "bin"),
1936                                  self->op, left, right);
1937     if (!*out)
1938         return false;
1939     self->expression.outr = *out;
1940     codegen_output_type(self, *out);
1941
1942     return true;
1943 }
1944
1945 bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, ir_value **out)
1946 {
1947     ast_expression_codegen *cgen;
1948     ir_value *leftl = NULL, *leftr, *right, *bin;
1949
1950     ast_value       *arr;
1951     ast_value       *idx = 0;
1952     ast_array_index *ai = NULL;
1953     ir_value        *iridx = NULL;
1954
1955     if (lvalue && self->expression.outl) {
1956         *out = self->expression.outl;
1957         return true;
1958     }
1959
1960     if (!lvalue && self->expression.outr) {
1961         *out = self->expression.outr;
1962         return true;
1963     }
1964
1965     if (ast_istype(self->dest, ast_array_index))
1966     {
1967
1968         ai = (ast_array_index*)self->dest;
1969         idx = (ast_value*)ai->index;
1970
1971         if (ast_istype(ai->index, ast_value) && idx->hasvalue && idx->cvq == CV_CONST)
1972             ai = NULL;
1973     }
1974
1975     /* for a binstore we need both an lvalue and an rvalue for the left side */
1976     /* rvalue of destination! */
1977     if (ai) {
1978         cgen = idx->expression.codegen;
1979         if (!(*cgen)((ast_expression*)(idx), func, false, &iridx))
1980             return false;
1981     }
1982     cgen = self->dest->codegen;
1983     if (!(*cgen)((ast_expression*)(self->dest), func, false, &leftr))
1984         return false;
1985
1986     /* source as rvalue only */
1987     cgen = self->source->codegen;
1988     if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
1989         return false;
1990
1991     /* now the binary */
1992     bin = ir_block_create_binop(func->curblock, ast_ctx(self), ast_function_label(func, "binst"),
1993                                 self->opbin, leftr, right);
1994     self->expression.outr = bin;
1995
1996
1997     if (ai) {
1998         /* we need to call the setter */
1999         ir_value  *funval;
2000         ir_instr  *call;
2001
2002         if (lvalue) {
2003             compile_error(ast_ctx(self), "array-subscript assignment cannot produce lvalues");
2004             return false;
2005         }
2006
2007         arr = (ast_value*)ai->array;
2008         if (!ast_istype(ai->array, ast_value) || !arr->setter) {
2009             compile_error(ast_ctx(self), "value has no setter (%s)", arr->name);
2010             return false;
2011         }
2012
2013         cgen = arr->setter->expression.codegen;
2014         if (!(*cgen)((ast_expression*)(arr->setter), func, true, &funval))
2015             return false;
2016
2017         call = ir_block_create_call(func->curblock, ast_ctx(self), ast_function_label(func, "store"), funval, false);
2018         if (!call)
2019             return false;
2020         ir_call_param(call, iridx);
2021         ir_call_param(call, bin);
2022         self->expression.outr = bin;
2023     } else {
2024         /* now store them */
2025         cgen = self->dest->codegen;
2026         /* lvalue of destination */
2027         if (!(*cgen)((ast_expression*)(self->dest), func, true, &leftl))
2028             return false;
2029         self->expression.outl = leftl;
2030
2031         if (!ir_block_create_store_op(func->curblock, ast_ctx(self), self->opstore, leftl, bin))
2032             return false;
2033         self->expression.outr = bin;
2034     }
2035
2036     /* Theoretically, an assinment returns its left side as an
2037      * lvalue, if we don't need an lvalue though, we return
2038      * the right side as an rvalue, otherwise we have to
2039      * somehow know whether or not we need to dereference the pointer
2040      * on the left side - that is: OP_LOAD if it was an address.
2041      * Also: in original QC we cannot OP_LOADP *anyway*.
2042      */
2043     *out = (lvalue ? leftl : bin);
2044
2045     return true;
2046 }
2047
2048 bool ast_unary_codegen(ast_unary *self, ast_function *func, bool lvalue, ir_value **out)
2049 {
2050     ast_expression_codegen *cgen;
2051     ir_value *operand;
2052
2053     /* An unary operation cannot yield an l-value */
2054     if (lvalue) {
2055         compile_error(ast_ctx(self), "not an l-value (binop)");
2056         return false;
2057     }
2058
2059     if (self->expression.outr) {
2060         *out = self->expression.outr;
2061         return true;
2062     }
2063
2064     cgen = self->operand->codegen;
2065     /* lvalue! */
2066     if (!(*cgen)((ast_expression*)(self->operand), func, false, &operand))
2067         return false;
2068
2069     *out = ir_block_create_unary(func->curblock, ast_ctx(self), ast_function_label(func, "unary"),
2070                                  self->op, operand);
2071     if (!*out)
2072         return false;
2073     self->expression.outr = *out;
2074
2075     return true;
2076 }
2077
2078 bool ast_return_codegen(ast_return *self, ast_function *func, bool lvalue, ir_value **out)
2079 {
2080     ast_expression_codegen *cgen;
2081     ir_value *operand;
2082
2083     *out = NULL;
2084
2085     /* In the context of a return operation, we don't actually return
2086      * anything...
2087      */
2088     if (lvalue) {
2089         compile_error(ast_ctx(self), "return-expression is not an l-value");
2090         return false;
2091     }
2092
2093     if (self->expression.outr) {
2094         compile_error(ast_ctx(self), "internal error: ast_return cannot be reused, it bears no result!");
2095         return false;
2096     }
2097     self->expression.outr = (ir_value*)1;
2098
2099     if (self->operand) {
2100         cgen = self->operand->codegen;
2101         /* lvalue! */
2102         if (!(*cgen)((ast_expression*)(self->operand), func, false, &operand))
2103             return false;
2104
2105         if (!ir_block_create_return(func->curblock, ast_ctx(self), operand))
2106             return false;
2107     } else {
2108         if (!ir_block_create_return(func->curblock, ast_ctx(self), NULL))
2109             return false;
2110     }
2111
2112     return true;
2113 }
2114
2115 bool ast_entfield_codegen(ast_entfield *self, ast_function *func, bool lvalue, ir_value **out)
2116 {
2117     ast_expression_codegen *cgen;
2118     ir_value *ent, *field;
2119
2120     /* This function needs to take the 'lvalue' flag into account!
2121      * As lvalue we provide a field-pointer, as rvalue we provide the
2122      * value in a temp.
2123      */
2124
2125     if (lvalue && self->expression.outl) {
2126         *out = self->expression.outl;
2127         return true;
2128     }
2129
2130     if (!lvalue && self->expression.outr) {
2131         *out = self->expression.outr;
2132         return true;
2133     }
2134
2135     cgen = self->entity->codegen;
2136     if (!(*cgen)((ast_expression*)(self->entity), func, false, &ent))
2137         return false;
2138
2139     cgen = self->field->codegen;
2140     if (!(*cgen)((ast_expression*)(self->field), func, false, &field))
2141         return false;
2142
2143     if (lvalue) {
2144         /* address! */
2145         *out = ir_block_create_fieldaddress(func->curblock, ast_ctx(self), ast_function_label(func, "efa"),
2146                                             ent, field);
2147     } else {
2148         *out = ir_block_create_load_from_ent(func->curblock, ast_ctx(self), ast_function_label(func, "efv"),
2149                                              ent, field, self->expression.vtype);
2150         /* Done AFTER error checking:
2151         codegen_output_type(self, *out);
2152         */
2153     }
2154     if (!*out) {
2155         compile_error(ast_ctx(self), "failed to create %s instruction (output type %s)",
2156                  (lvalue ? "ADDRESS" : "FIELD"),
2157                  type_name[self->expression.vtype]);
2158         return false;
2159     }
2160     if (!lvalue)
2161         codegen_output_type(self, *out);
2162
2163     if (lvalue)
2164         self->expression.outl = *out;
2165     else
2166         self->expression.outr = *out;
2167
2168     /* Hm that should be it... */
2169     return true;
2170 }
2171
2172 bool ast_member_codegen(ast_member *self, ast_function *func, bool lvalue, ir_value **out)
2173 {
2174     ast_expression_codegen *cgen;
2175     ir_value *vec;
2176
2177     /* in QC this is always an lvalue */
2178     if (lvalue && self->rvalue) {
2179         compile_error(ast_ctx(self), "not an l-value (member access)");
2180         return false;
2181     }
2182     if (self->expression.outl) {
2183         *out = self->expression.outl;
2184         return true;
2185     }
2186
2187     cgen = self->owner->codegen;
2188     if (!(*cgen)((ast_expression*)(self->owner), func, false, &vec))
2189         return false;
2190
2191     if (vec->vtype != TYPE_VECTOR &&
2192         !(vec->vtype == TYPE_FIELD && self->owner->next->vtype == TYPE_VECTOR))
2193     {
2194         return false;
2195     }
2196
2197     *out = ir_value_vector_member(vec, self->field);
2198     self->expression.outl = *out;
2199
2200     return (*out != NULL);
2201 }
2202
2203 bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lvalue, ir_value **out)
2204 {
2205     ast_value *arr;
2206     ast_value *idx;
2207
2208     if (!lvalue && self->expression.outr) {
2209         *out = self->expression.outr;
2210         return true;
2211     }
2212     if (lvalue && self->expression.outl) {
2213         *out = self->expression.outl;
2214         return true;
2215     }
2216
2217     if (!ast_istype(self->array, ast_value)) {
2218         compile_error(ast_ctx(self), "array indexing this way is not supported");
2219         /* note this would actually be pointer indexing because the left side is
2220          * not an actual array but (hopefully) an indexable expression.
2221          * Once we get integer arithmetic, and GADDRESS/GSTORE/GLOAD instruction
2222          * support this path will be filled.
2223          */
2224         return false;
2225     }
2226
2227     arr = (ast_value*)self->array;
2228     idx = (ast_value*)self->index;
2229
2230     if (!ast_istype(self->index, ast_value) || !idx->hasvalue || idx->cvq != CV_CONST) {
2231         /* Time to use accessor functions */
2232         ast_expression_codegen *cgen;
2233         ir_value               *iridx, *funval;
2234         ir_instr               *call;
2235
2236         if (lvalue) {
2237             compile_error(ast_ctx(self), "(.2) array indexing here needs a compile-time constant");
2238             return false;
2239         }
2240
2241         if (!arr->getter) {
2242             compile_error(ast_ctx(self), "value has no getter, don't know how to index it");
2243             return false;
2244         }
2245
2246         cgen = self->index->codegen;
2247         if (!(*cgen)((ast_expression*)(self->index), func, false, &iridx))
2248             return false;
2249
2250         cgen = arr->getter->expression.codegen;
2251         if (!(*cgen)((ast_expression*)(arr->getter), func, true, &funval))
2252             return false;
2253
2254         call = ir_block_create_call(func->curblock, ast_ctx(self), ast_function_label(func, "fetch"), funval, false);
2255         if (!call)
2256             return false;
2257         ir_call_param(call, iridx);
2258
2259         *out = ir_call_value(call);
2260         self->expression.outr = *out;
2261         (*out)->vtype = self->expression.vtype;
2262         codegen_output_type(self, *out);
2263         return true;
2264     }
2265
2266     if (idx->expression.vtype == TYPE_FLOAT) {
2267         unsigned int arridx = idx->constval.vfloat;
2268         if (arridx >= self->array->count)
2269         {
2270             compile_error(ast_ctx(self), "array index out of bounds: %i", arridx);
2271             return false;
2272         }
2273         *out = arr->ir_values[arridx];
2274     }
2275     else if (idx->expression.vtype == TYPE_INTEGER) {
2276         unsigned int arridx = idx->constval.vint;
2277         if (arridx >= self->array->count)
2278         {
2279             compile_error(ast_ctx(self), "array index out of bounds: %i", arridx);
2280             return false;
2281         }
2282         *out = arr->ir_values[arridx];
2283     }
2284     else {
2285         compile_error(ast_ctx(self), "array indexing here needs an integer constant");
2286         return false;
2287     }
2288     (*out)->vtype = self->expression.vtype;
2289     codegen_output_type(self, *out);
2290     return true;
2291 }
2292
2293 bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_value **out)
2294 {
2295     ast_expression_codegen *cgen;
2296
2297     ir_value *condval;
2298     ir_value *dummy;
2299
2300     ir_block *cond;
2301     ir_block *ontrue;
2302     ir_block *onfalse;
2303     ir_block *ontrue_endblock = NULL;
2304     ir_block *onfalse_endblock = NULL;
2305     ir_block *merge = NULL;
2306
2307     /* We don't output any value, thus also don't care about r/lvalue */
2308     (void)out;
2309     (void)lvalue;
2310
2311     if (self->expression.outr) {
2312         compile_error(ast_ctx(self), "internal error: ast_ifthen cannot be reused, it bears no result!");
2313         return false;
2314     }
2315     self->expression.outr = (ir_value*)1;
2316
2317     /* generate the condition */
2318     cgen = self->cond->codegen;
2319     if (!(*cgen)((ast_expression*)(self->cond), func, false, &condval))
2320         return false;
2321     /* update the block which will get the jump - because short-logic or ternaries may have changed this */
2322     cond = func->curblock;
2323
2324     /* on-true path */
2325
2326     if (self->on_true) {
2327         /* create on-true block */
2328         ontrue = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "ontrue"));
2329         if (!ontrue)
2330             return false;
2331
2332         /* enter the block */
2333         func->curblock = ontrue;
2334
2335         /* generate */
2336         cgen = self->on_true->codegen;
2337         if (!(*cgen)((ast_expression*)(self->on_true), func, false, &dummy))
2338             return false;
2339
2340         /* we now need to work from the current endpoint */
2341         ontrue_endblock = func->curblock;
2342     } else
2343         ontrue = NULL;
2344
2345     /* on-false path */
2346     if (self->on_false) {
2347         /* create on-false block */
2348         onfalse = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "onfalse"));
2349         if (!onfalse)
2350             return false;
2351
2352         /* enter the block */
2353         func->curblock = onfalse;
2354
2355         /* generate */
2356         cgen = self->on_false->codegen;
2357         if (!(*cgen)((ast_expression*)(self->on_false), func, false, &dummy))
2358             return false;
2359
2360         /* we now need to work from the current endpoint */
2361         onfalse_endblock = func->curblock;
2362     } else
2363         onfalse = NULL;
2364
2365     /* Merge block were they all merge in to */
2366     if (!ontrue || !onfalse || !ontrue_endblock->final || !onfalse_endblock->final)
2367     {
2368         merge = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "endif"));
2369         if (!merge)
2370             return false;
2371         /* add jumps ot the merge block */
2372         if (ontrue && !ontrue_endblock->final && !ir_block_create_jump(ontrue_endblock, ast_ctx(self), merge))
2373             return false;
2374         if (onfalse && !onfalse_endblock->final && !ir_block_create_jump(onfalse_endblock, ast_ctx(self), merge))
2375             return false;
2376
2377         /* Now enter the merge block */
2378         func->curblock = merge;
2379     }
2380
2381     /* we create the if here, that way all blocks are ordered :)
2382      */
2383     if (!ir_block_create_if(cond, ast_ctx(self), condval,
2384                             (ontrue  ? ontrue  : merge),
2385                             (onfalse ? onfalse : merge)))
2386     {
2387         return false;
2388     }
2389
2390     return true;
2391 }
2392
2393 bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_value **out)
2394 {
2395     ast_expression_codegen *cgen;
2396
2397     ir_value *condval;
2398     ir_value *trueval, *falseval;
2399     ir_instr *phi;
2400
2401     ir_block *cond = func->curblock;
2402     ir_block *cond_out = NULL;
2403     ir_block *ontrue, *ontrue_out = NULL;
2404     ir_block *onfalse, *onfalse_out = NULL;
2405     ir_block *merge;
2406
2407     /* Ternary can never create an lvalue... */
2408     if (lvalue)
2409         return false;
2410
2411     /* In theory it shouldn't be possible to pass through a node twice, but
2412      * in case we add any kind of optimization pass for the AST itself, it
2413      * may still happen, thus we remember a created ir_value and simply return one
2414      * if it already exists.
2415      */
2416     if (self->expression.outr) {
2417         *out = self->expression.outr;
2418         return true;
2419     }
2420
2421     /* In the following, contraty to ast_ifthen, we assume both paths exist. */
2422
2423     /* generate the condition */
2424     func->curblock = cond;
2425     cgen = self->cond->codegen;
2426     if (!(*cgen)((ast_expression*)(self->cond), func, false, &condval))
2427         return false;
2428     cond_out = func->curblock;
2429
2430     /* create on-true block */
2431     ontrue = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "tern_T"));
2432     if (!ontrue)
2433         return false;
2434     else
2435     {
2436         /* enter the block */
2437         func->curblock = ontrue;
2438
2439         /* generate */
2440         cgen = self->on_true->codegen;
2441         if (!(*cgen)((ast_expression*)(self->on_true), func, false, &trueval))
2442             return false;
2443
2444         ontrue_out = func->curblock;
2445     }
2446
2447     /* create on-false block */
2448     onfalse = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "tern_F"));
2449     if (!onfalse)
2450         return false;
2451     else
2452     {
2453         /* enter the block */
2454         func->curblock = onfalse;
2455
2456         /* generate */
2457         cgen = self->on_false->codegen;
2458         if (!(*cgen)((ast_expression*)(self->on_false), func, false, &falseval))
2459             return false;
2460
2461         onfalse_out = func->curblock;
2462     }
2463
2464     /* create merge block */
2465     merge = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "tern_out"));
2466     if (!merge)
2467         return false;
2468     /* jump to merge block */
2469     if (!ir_block_create_jump(ontrue_out, ast_ctx(self), merge))
2470         return false;
2471     if (!ir_block_create_jump(onfalse_out, ast_ctx(self), merge))
2472         return false;
2473
2474     /* create if instruction */
2475     if (!ir_block_create_if(cond_out, ast_ctx(self), condval, ontrue, onfalse))
2476         return false;
2477
2478     /* Now enter the merge block */
2479     func->curblock = merge;
2480
2481     /* Here, now, we need a PHI node
2482      * but first some sanity checking...
2483      */
2484     if (trueval->vtype != falseval->vtype && trueval->vtype != TYPE_NIL && falseval->vtype != TYPE_NIL) {
2485         /* error("ternary with different types on the two sides"); */
2486         compile_error(ast_ctx(self), "internal error: ternary operand types invalid");
2487         return false;
2488     }
2489
2490     /* create PHI */
2491     phi = ir_block_create_phi(merge, ast_ctx(self), ast_function_label(func, "phi"), self->expression.vtype);
2492     if (!phi) {
2493         compile_error(ast_ctx(self), "internal error: failed to generate phi node");
2494         return false;
2495     }
2496     ir_phi_add(phi, ontrue_out,  trueval);
2497     ir_phi_add(phi, onfalse_out, falseval);
2498
2499     self->expression.outr = ir_phi_value(phi);
2500     *out = self->expression.outr;
2501
2502     codegen_output_type(self, *out);
2503
2504     return true;
2505 }
2506
2507 bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value **out)
2508 {
2509     ast_expression_codegen *cgen;
2510
2511     ir_value *dummy      = NULL;
2512     ir_value *precond    = NULL;
2513     ir_value *postcond   = NULL;
2514
2515     /* Since we insert some jumps "late" so we have blocks
2516      * ordered "nicely", we need to keep track of the actual end-blocks
2517      * of expressions to add the jumps to.
2518      */
2519     ir_block *bbody      = NULL, *end_bbody      = NULL;
2520     ir_block *bprecond   = NULL, *end_bprecond   = NULL;
2521     ir_block *bpostcond  = NULL, *end_bpostcond  = NULL;
2522     ir_block *bincrement = NULL, *end_bincrement = NULL;
2523     ir_block *bout       = NULL, *bin            = NULL;
2524
2525     /* let's at least move the outgoing block to the end */
2526     size_t    bout_id;
2527
2528     /* 'break' and 'continue' need to be able to find the right blocks */
2529     ir_block *bcontinue     = NULL;
2530     ir_block *bbreak        = NULL;
2531
2532     ir_block *tmpblock      = NULL;
2533
2534     (void)lvalue;
2535     (void)out;
2536
2537     if (self->expression.outr) {
2538         compile_error(ast_ctx(self), "internal error: ast_loop cannot be reused, it bears no result!");
2539         return false;
2540     }
2541     self->expression.outr = (ir_value*)1;
2542
2543     /* NOTE:
2544      * Should we ever need some kind of block ordering, better make this function
2545      * move blocks around than write a block ordering algorithm later... after all
2546      * the ast and ir should work together, not against each other.
2547      */
2548
2549     /* initexpr doesn't get its own block, it's pointless, it could create more blocks
2550      * anyway if for example it contains a ternary.
2551      */
2552     if (self->initexpr)
2553     {
2554         cgen = self->initexpr->codegen;
2555         if (!(*cgen)((ast_expression*)(self->initexpr), func, false, &dummy))
2556             return false;
2557     }
2558
2559     /* Store the block from which we enter this chaos */
2560     bin = func->curblock;
2561
2562     /* The pre-loop condition needs its own block since we
2563      * need to be able to jump to the start of that expression.
2564      */
2565     if (self->precond)
2566     {
2567         bprecond = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "pre_loop_cond"));
2568         if (!bprecond)
2569             return false;
2570
2571         /* the pre-loop-condition the least important place to 'continue' at */
2572         bcontinue = bprecond;
2573
2574         /* enter */
2575         func->curblock = bprecond;
2576
2577         /* generate */
2578         cgen = self->precond->codegen;
2579         if (!(*cgen)((ast_expression*)(self->precond), func, false, &precond))
2580             return false;
2581
2582         end_bprecond = func->curblock;
2583     } else {
2584         bprecond = end_bprecond = NULL;
2585     }
2586
2587     /* Now the next blocks won't be ordered nicely, but we need to
2588      * generate them this early for 'break' and 'continue'.
2589      */
2590     if (self->increment) {
2591         bincrement = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "loop_increment"));
2592         if (!bincrement)
2593             return false;
2594         bcontinue = bincrement; /* increment comes before the pre-loop-condition */
2595     } else {
2596         bincrement = end_bincrement = NULL;
2597     }
2598
2599     if (self->postcond) {
2600         bpostcond = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "post_loop_cond"));
2601         if (!bpostcond)
2602             return false;
2603         bcontinue = bpostcond; /* postcond comes before the increment */
2604     } else {
2605         bpostcond = end_bpostcond = NULL;
2606     }
2607
2608     bout_id = vec_size(func->ir_func->blocks);
2609     bout = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "after_loop"));
2610     if (!bout)
2611         return false;
2612     bbreak = bout;
2613
2614     /* The loop body... */
2615     /* if (self->body) */
2616     {
2617         bbody = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "loop_body"));
2618         if (!bbody)
2619             return false;
2620
2621         /* enter */
2622         func->curblock = bbody;
2623
2624         vec_push(func->breakblocks,    bbreak);
2625         if (bcontinue)
2626             vec_push(func->continueblocks, bcontinue);
2627         else
2628             vec_push(func->continueblocks, bbody);
2629
2630         /* generate */
2631         if (self->body) {
2632             cgen = self->body->codegen;
2633             if (!(*cgen)((ast_expression*)(self->body), func, false, &dummy))
2634                 return false;
2635         }
2636
2637         end_bbody = func->curblock;
2638         vec_pop(func->breakblocks);
2639         vec_pop(func->continueblocks);
2640     }
2641
2642     /* post-loop-condition */
2643     if (self->postcond)
2644     {
2645         /* enter */
2646         func->curblock = bpostcond;
2647
2648         /* generate */
2649         cgen = self->postcond->codegen;
2650         if (!(*cgen)((ast_expression*)(self->postcond), func, false, &postcond))
2651             return false;
2652
2653         end_bpostcond = func->curblock;
2654     }
2655
2656     /* The incrementor */
2657     if (self->increment)
2658     {
2659         /* enter */
2660         func->curblock = bincrement;
2661
2662         /* generate */
2663         cgen = self->increment->codegen;
2664         if (!(*cgen)((ast_expression*)(self->increment), func, false, &dummy))
2665             return false;
2666
2667         end_bincrement = func->curblock;
2668     }
2669
2670     /* In any case now, we continue from the outgoing block */
2671     func->curblock = bout;
2672
2673     /* Now all blocks are in place */
2674     /* From 'bin' we jump to whatever comes first */
2675     if      (bprecond)   tmpblock = bprecond;
2676     else if (bbody)      tmpblock = bbody;
2677     else if (bpostcond)  tmpblock = bpostcond;
2678     else                 tmpblock = bout;
2679     if (!ir_block_create_jump(bin, ast_ctx(self), tmpblock))
2680         return false;
2681
2682     /* From precond */
2683     if (bprecond)
2684     {
2685         ir_block *ontrue, *onfalse;
2686         if      (bbody)      ontrue = bbody;
2687         else if (bincrement) ontrue = bincrement;
2688         else if (bpostcond)  ontrue = bpostcond;
2689         else                 ontrue = bprecond;
2690         onfalse = bout;
2691         if (self->pre_not) {
2692             tmpblock = ontrue;
2693             ontrue   = onfalse;
2694             onfalse  = tmpblock;
2695         }
2696         if (!ir_block_create_if(end_bprecond, ast_ctx(self), precond, ontrue, onfalse))
2697             return false;
2698     }
2699
2700     /* from body */
2701     if (bbody)
2702     {
2703         if      (bincrement) tmpblock = bincrement;
2704         else if (bpostcond)  tmpblock = bpostcond;
2705         else if (bprecond)   tmpblock = bprecond;
2706         else                 tmpblock = bbody;
2707         if (!end_bbody->final && !ir_block_create_jump(end_bbody, ast_ctx(self), tmpblock))
2708             return false;
2709     }
2710
2711     /* from increment */
2712     if (bincrement)
2713     {
2714         if      (bpostcond)  tmpblock = bpostcond;
2715         else if (bprecond)   tmpblock = bprecond;
2716         else if (bbody)      tmpblock = bbody;
2717         else                 tmpblock = bout;
2718         if (!ir_block_create_jump(end_bincrement, ast_ctx(self), tmpblock))
2719             return false;
2720     }
2721
2722     /* from postcond */
2723     if (bpostcond)
2724     {
2725         ir_block *ontrue, *onfalse;
2726         if      (bprecond)   ontrue = bprecond;
2727         else if (bbody)      ontrue = bbody;
2728         else if (bincrement) ontrue = bincrement;
2729         else                 ontrue = bpostcond;
2730         onfalse = bout;
2731         if (self->post_not) {
2732             tmpblock = ontrue;
2733             ontrue   = onfalse;
2734             onfalse  = tmpblock;
2735         }
2736         if (!ir_block_create_if(end_bpostcond, ast_ctx(self), postcond, ontrue, onfalse))
2737             return false;
2738     }
2739
2740     /* Move 'bout' to the end */
2741     vec_remove(func->ir_func->blocks, bout_id, 1);
2742     vec_push(func->ir_func->blocks, bout);
2743
2744     return true;
2745 }
2746
2747 bool ast_breakcont_codegen(ast_breakcont *self, ast_function *func, bool lvalue, ir_value **out)
2748 {
2749     ir_block *target;
2750
2751     *out = NULL;
2752
2753     if (lvalue) {
2754         compile_error(ast_ctx(self), "break/continue expression is not an l-value");
2755         return false;
2756     }
2757
2758     if (self->expression.outr) {
2759         compile_error(ast_ctx(self), "internal error: ast_breakcont cannot be reused!");
2760         return false;
2761     }
2762     self->expression.outr = (ir_value*)1;
2763
2764     if (self->is_continue)
2765         target = func->continueblocks[vec_size(func->continueblocks)-1-self->levels];
2766     else
2767         target = func->breakblocks[vec_size(func->breakblocks)-1-self->levels];
2768
2769     if (!target) {
2770         compile_error(ast_ctx(self), "%s is lacking a target block", (self->is_continue ? "continue" : "break"));
2771         return false;
2772     }
2773
2774     if (!ir_block_create_jump(func->curblock, ast_ctx(self), target))
2775         return false;
2776     return true;
2777 }
2778
2779 bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_value **out)
2780 {
2781     ast_expression_codegen *cgen;
2782
2783     ast_switch_case *def_case     = NULL;
2784     ir_block        *def_bfall    = NULL;
2785     ir_block        *def_bfall_to = NULL;
2786     bool set_def_bfall_to = false;
2787
2788     ir_value *dummy     = NULL;
2789     ir_value *irop      = NULL;
2790     ir_block *bout      = NULL;
2791     ir_block *bfall     = NULL;
2792     size_t    bout_id;
2793     size_t    c;
2794
2795     char      typestr[1024];
2796     uint16_t  cmpinstr;
2797
2798     if (lvalue) {
2799         compile_error(ast_ctx(self), "switch expression is not an l-value");
2800         return false;
2801     }
2802
2803     if (self->expression.outr) {
2804         compile_error(ast_ctx(self), "internal error: ast_switch cannot be reused!");
2805         return false;
2806     }
2807     self->expression.outr = (ir_value*)1;
2808
2809     (void)lvalue;
2810     (void)out;
2811
2812     cgen = self->operand->codegen;
2813     if (!(*cgen)((ast_expression*)(self->operand), func, false, &irop))
2814         return false;
2815
2816     if (!vec_size(self->cases))
2817         return true;
2818
2819     cmpinstr = type_eq_instr[irop->vtype];
2820     if (cmpinstr >= VINSTR_END) {
2821         ast_type_to_string(self->operand, typestr, sizeof(typestr));
2822         compile_error(ast_ctx(self), "invalid type to perform a switch on: %s", typestr);
2823         return false;
2824     }
2825
2826     bout_id = vec_size(func->ir_func->blocks);
2827     bout = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "after_switch"));
2828     if (!bout)
2829         return false;
2830
2831     /* setup the break block */
2832     vec_push(func->breakblocks, bout);
2833
2834     /* Now create all cases */
2835     for (c = 0; c < vec_size(self->cases); ++c) {
2836         ir_value *cond, *val;
2837         ir_block *bcase, *bnot;
2838         size_t bnot_id;
2839
2840         ast_switch_case *swcase = &self->cases[c];
2841
2842         if (swcase->value) {
2843             /* A regular case */
2844             /* generate the condition operand */
2845             cgen = swcase->value->codegen;
2846             if (!(*cgen)((ast_expression*)(swcase->value), func, false, &val))
2847                 return false;
2848             /* generate the condition */
2849             cond = ir_block_create_binop(func->curblock, ast_ctx(self), ast_function_label(func, "switch_eq"), cmpinstr, irop, val);
2850             if (!cond)
2851                 return false;
2852
2853             bcase = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "case"));
2854             bnot_id = vec_size(func->ir_func->blocks);
2855             bnot = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "not_case"));
2856             if (!bcase || !bnot)
2857                 return false;
2858             if (set_def_bfall_to) {
2859                 set_def_bfall_to = false;
2860                 def_bfall_to = bcase;
2861             }
2862             if (!ir_block_create_if(func->curblock, ast_ctx(self), cond, bcase, bnot))
2863                 return false;
2864
2865             /* Make the previous case-end fall through */
2866             if (bfall && !bfall->final) {
2867                 if (!ir_block_create_jump(bfall, ast_ctx(self), bcase))
2868                     return false;
2869             }
2870
2871             /* enter the case */
2872             func->curblock = bcase;
2873             cgen = swcase->code->codegen;
2874             if (!(*cgen)((ast_expression*)swcase->code, func, false, &dummy))
2875                 return false;
2876
2877             /* remember this block to fall through from */
2878             bfall = func->curblock;
2879
2880             /* enter the else and move it down */
2881             func->curblock = bnot;
2882             vec_remove(func->ir_func->blocks, bnot_id, 1);
2883             vec_push(func->ir_func->blocks, bnot);
2884         } else {
2885             /* The default case */
2886             /* Remember where to fall through from: */
2887             def_bfall = bfall;
2888             bfall     = NULL;
2889             /* remember which case it was */
2890             def_case  = swcase;
2891             /* And the next case will be remembered */
2892             set_def_bfall_to = true;
2893         }
2894     }
2895
2896     /* Jump from the last bnot to bout */
2897     if (bfall && !bfall->final && !ir_block_create_jump(bfall, ast_ctx(self), bout)) {
2898         /*
2899         astwarning(ast_ctx(bfall), WARN_???, "missing break after last case");
2900         */
2901         return false;
2902     }
2903
2904     /* If there was a default case, put it down here */
2905     if (def_case) {
2906         ir_block *bcase;
2907
2908         /* No need to create an extra block */
2909         bcase = func->curblock;
2910
2911         /* Insert the fallthrough jump */
2912         if (def_bfall && !def_bfall->final) {
2913             if (!ir_block_create_jump(def_bfall, ast_ctx(self), bcase))
2914                 return false;
2915         }
2916
2917         /* Now generate the default code */
2918         cgen = def_case->code->codegen;
2919         if (!(*cgen)((ast_expression*)def_case->code, func, false, &dummy))
2920             return false;
2921
2922         /* see if we need to fall through */
2923         if (def_bfall_to && !func->curblock->final)
2924         {
2925             if (!ir_block_create_jump(func->curblock, ast_ctx(self), def_bfall_to))
2926                 return false;
2927         }
2928     }
2929
2930     /* Jump from the last bnot to bout */
2931     if (!func->curblock->final && !ir_block_create_jump(func->curblock, ast_ctx(self), bout))
2932         return false;
2933     /* enter the outgoing block */
2934     func->curblock = bout;
2935
2936     /* restore the break block */
2937     vec_pop(func->breakblocks);
2938
2939     /* Move 'bout' to the end, it's nicer */
2940     vec_remove(func->ir_func->blocks, bout_id, 1);
2941     vec_push(func->ir_func->blocks, bout);
2942
2943     return true;
2944 }
2945
2946 bool ast_label_codegen(ast_label *self, ast_function *func, bool lvalue, ir_value **out)
2947 {
2948     size_t i;
2949     ir_value *dummy;
2950
2951     if (self->undefined) {
2952         compile_error(ast_ctx(self), "internal error: ast_label never defined");
2953         return false;
2954     }
2955
2956     *out = NULL;
2957     if (lvalue) {
2958         compile_error(ast_ctx(self), "internal error: ast_label cannot be an lvalue");
2959         return false;
2960     }
2961
2962     /* simply create a new block and jump to it */
2963     self->irblock = ir_function_create_block(ast_ctx(self), func->ir_func, self->name);
2964     if (!self->irblock) {
2965         compile_error(ast_ctx(self), "failed to allocate label block `%s`", self->name);
2966         return false;
2967     }
2968     if (!func->curblock->final) {
2969         if (!ir_block_create_jump(func->curblock, ast_ctx(self), self->irblock))
2970             return false;
2971     }
2972
2973     /* enter the new block */
2974     func->curblock = self->irblock;
2975
2976     /* Generate all the leftover gotos */
2977     for (i = 0; i < vec_size(self->gotos); ++i) {
2978         if (!ast_goto_codegen(self->gotos[i], func, false, &dummy))
2979             return false;
2980     }
2981
2982     return true;
2983 }
2984
2985 bool ast_goto_codegen(ast_goto *self, ast_function *func, bool lvalue, ir_value **out)
2986 {
2987     *out = NULL;
2988     if (lvalue) {
2989         compile_error(ast_ctx(self), "internal error: ast_goto cannot be an lvalue");
2990         return false;
2991     }
2992
2993     if (self->target->irblock) {
2994         if (self->irblock_from) {
2995             /* we already tried once, this is the callback */
2996             self->irblock_from->final = false;
2997             if (!ir_block_create_goto(self->irblock_from, ast_ctx(self), self->target->irblock)) {
2998                 compile_error(ast_ctx(self), "failed to generate goto to `%s`", self->name);
2999                 return false;
3000             }
3001         }
3002         else
3003         {
3004             if (!ir_block_create_goto(func->curblock, ast_ctx(self), self->target->irblock)) {
3005                 compile_error(ast_ctx(self), "failed to generate goto to `%s`", self->name);
3006                 return false;
3007             }
3008         }
3009     }
3010     else
3011     {
3012         /* the target has not yet been created...
3013          * close this block in a sneaky way:
3014          */
3015         func->curblock->final = true;
3016         self->irblock_from = func->curblock;
3017         ast_label_register_goto(self->target, self);
3018     }
3019
3020     return true;
3021 }
3022
3023 bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value **out)
3024 {
3025     ast_expression_codegen *cgen;
3026     ir_value              **params;
3027     ir_instr               *callinstr;
3028     size_t i;
3029
3030     ir_value *funval = NULL;
3031
3032     /* return values are never lvalues */
3033     if (lvalue) {
3034         compile_error(ast_ctx(self), "not an l-value (function call)");
3035         return false;
3036     }
3037
3038     if (self->expression.outr) {
3039         *out = self->expression.outr;
3040         return true;
3041     }
3042
3043     cgen = self->func->codegen;
3044     if (!(*cgen)((ast_expression*)(self->func), func, false, &funval))
3045         return false;
3046     if (!funval)
3047         return false;
3048
3049     params = NULL;
3050
3051     /* parameters */
3052     for (i = 0; i < vec_size(self->params); ++i)
3053     {
3054         ir_value *param;
3055         ast_expression *expr = self->params[i];
3056
3057         cgen = expr->codegen;
3058         if (!(*cgen)(expr, func, false, &param))
3059             goto error;
3060         if (!param)
3061             goto error;
3062         vec_push(params, param);
3063     }
3064
3065     /* varargs counter */
3066     if (self->va_count) {
3067         ir_value   *va_count;
3068         ir_builder *builder = func->curblock->owner->owner;
3069         cgen = self->va_count->codegen;
3070         if (!(*cgen)((ast_expression*)(self->va_count), func, false, &va_count))
3071             return false;
3072         if (!ir_block_create_store_op(func->curblock, ast_ctx(self), INSTR_STORE_F,
3073                                       ir_builder_get_va_count(builder), va_count))
3074         {
3075             return false;
3076         }
3077     }
3078
3079     callinstr = ir_block_create_call(func->curblock, ast_ctx(self),
3080                                      ast_function_label(func, "call"),
3081                                      funval, !!(self->func->flags & AST_FLAG_NORETURN));
3082     if (!callinstr)
3083         goto error;
3084
3085     for (i = 0; i < vec_size(params); ++i) {
3086         ir_call_param(callinstr, params[i]);
3087     }
3088
3089     *out = ir_call_value(callinstr);
3090     self->expression.outr = *out;
3091
3092     codegen_output_type(self, *out);
3093
3094     vec_free(params);
3095     return true;
3096 error:
3097     vec_free(params);
3098     return false;
3099 }