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