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