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