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