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