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