Remove parser m_uses in favor of {IR,AST}_FLAG_NOREF instead
[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             vec_push(irf->m_params, it->m_next->m_vtype);
1514         else
1515             vec_push(irf->m_params, 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 (vec_size(m_curblock->m_entries) || 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         vec_last(func->m_curblock->m_instr)->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     if (!m_dest->codegen(func, false, &leftr))
1936         return false;
1937
1938     /* source as rvalue only */
1939     if (!m_source->codegen(func, false, &right))
1940         return false;
1941
1942     /* now the binary */
1943     bin = ir_block_create_binop(func->m_curblock, m_context, func->makeLabel("binst"),
1944                                 m_opbin, leftr, right);
1945     m_outr = bin;
1946
1947     if (ai) {
1948         /* we need to call the setter */
1949         ir_value  *funval;
1950         ir_instr  *call;
1951
1952         if (lvalue) {
1953             compile_error(m_context, "array-subscript assignment cannot produce lvalues");
1954             return false;
1955         }
1956
1957         arr = (ast_value*)ai->m_array;
1958         if (!ast_istype(ai->m_array, ast_value) || !arr->m_setter) {
1959             compile_error(m_context, "value has no setter (%s)", arr->m_name);
1960             return false;
1961         }
1962
1963         if (!arr->m_setter->codegen(func, true, &funval))
1964             return false;
1965
1966         call = ir_block_create_call(func->m_curblock, m_context, func->makeLabel("store"), funval, false);
1967         if (!call)
1968             return false;
1969         ir_call_param(call, iridx);
1970         ir_call_param(call, bin);
1971         m_outr = bin;
1972     } else {
1973         // now store them
1974         // lvalue of destination
1975         if (!m_dest->codegen(func, true, &leftl))
1976             return false;
1977         m_outl = leftl;
1978
1979         if (!ir_block_create_store_op(func->m_curblock, m_context, m_opstore, leftl, bin))
1980             return false;
1981         m_outr = bin;
1982     }
1983
1984     /* Theoretically, an assinment returns its left side as an
1985      * lvalue, if we don't need an lvalue though, we return
1986      * the right side as an rvalue, otherwise we have to
1987      * somehow know whether or not we need to dereference the pointer
1988      * on the left side - that is: OP_LOAD if it was an address.
1989      * Also: in original QC we cannot OP_LOADP *anyway*.
1990      */
1991     *out = (lvalue ? leftl : bin);
1992
1993     return true;
1994 }
1995
1996 bool ast_unary::codegen(ast_function *func, bool lvalue, ir_value **out)
1997 {
1998     ir_value *operand;
1999
2000     /* An unary operation cannot yield an l-value */
2001     if (lvalue) {
2002         compile_error(m_context, "not an l-value (binop)");
2003         return false;
2004     }
2005
2006     if (m_outr) {
2007         *out = m_outr;
2008         return true;
2009     }
2010
2011     /* lvalue! */
2012     if (!m_operand->codegen(func, false, &operand))
2013         return false;
2014
2015     *out = ir_block_create_unary(func->m_curblock, m_context, func->makeLabel("unary"),
2016                                  m_op, operand);
2017     if (!*out)
2018         return false;
2019     m_outr = *out;
2020
2021     return true;
2022 }
2023
2024 bool ast_return::codegen(ast_function *func, bool lvalue, ir_value **out)
2025 {
2026     ir_value *operand;
2027
2028     *out = nullptr;
2029
2030     /* In the context of a return operation, we don't actually return
2031      * anything...
2032      */
2033     if (lvalue) {
2034         compile_error(m_context, "return-expression is not an l-value");
2035         return false;
2036     }
2037
2038     if (m_outr) {
2039         compile_error(m_context, "internal error: ast_return cannot be reused, it bears no result!");
2040         return false;
2041     }
2042     m_outr = (ir_value*)1;
2043
2044     if (m_operand) {
2045         /* lvalue! */
2046         if (!m_operand->codegen(func, false, &operand))
2047             return false;
2048
2049         if (!ir_block_create_return(func->m_curblock, m_context, operand))
2050             return false;
2051     } else {
2052         if (!ir_block_create_return(func->m_curblock, m_context, nullptr))
2053             return false;
2054     }
2055
2056     return true;
2057 }
2058
2059 bool ast_entfield::codegen(ast_function *func, bool lvalue, ir_value **out)
2060 {
2061     ir_value *ent, *field;
2062
2063     // This function needs to take the 'lvalue' flag into account!
2064     // As lvalue we provide a field-pointer, as rvalue we provide the
2065     // value in a temp.
2066
2067     if (lvalue && m_outl) {
2068         *out = m_outl;
2069         return true;
2070     }
2071
2072     if (!lvalue && m_outr) {
2073         *out = m_outr;
2074         return true;
2075     }
2076
2077     if (!m_entity->codegen(func, false, &ent))
2078         return false;
2079
2080     if (!m_field->codegen(func, false, &field))
2081         return false;
2082
2083     if (lvalue) {
2084         /* address! */
2085         *out = ir_block_create_fieldaddress(func->m_curblock, m_context, func->makeLabel("efa"),
2086                                             ent, field);
2087     } else {
2088         *out = ir_block_create_load_from_ent(func->m_curblock, m_context, func->makeLabel("efv"),
2089                                              ent, field, m_vtype);
2090         /* Done AFTER error checking:
2091         codegen_output_type(this, *out);
2092         */
2093     }
2094     if (!*out) {
2095         compile_error(m_context, "failed to create %s instruction (output type %s)",
2096                  (lvalue ? "ADDRESS" : "FIELD"),
2097                  type_name[m_vtype]);
2098         return false;
2099     }
2100     if (!lvalue)
2101         codegen_output_type(this, *out);
2102
2103     if (lvalue)
2104         m_outl = *out;
2105     else
2106         m_outr = *out;
2107
2108     // Hm that should be it...
2109     return true;
2110 }
2111
2112 bool ast_member::codegen(ast_function *func, bool lvalue, ir_value **out)
2113 {
2114     ir_value *vec;
2115
2116     /* in QC this is always an lvalue */
2117     if (lvalue && m_rvalue) {
2118         compile_error(m_context, "not an l-value (member access)");
2119         return false;
2120     }
2121     if (lvalue && m_outl) {
2122         *out = m_outl;
2123         return true;
2124     }
2125     if (!lvalue && m_outr) {
2126         *out = m_outr;
2127         return true;
2128     }
2129
2130     if (ast_istype(m_owner, ast_entfield)) {
2131         ir_value *ent, *field;
2132         auto entfield = reinterpret_cast<ast_entfield*>(m_owner);
2133         if (!entfield->m_entity->codegen(func, false, &ent))
2134             return false;
2135         if (!entfield->m_field->codegen(func, false, &vec))
2136             return false;
2137         field = vec->vectorMember(m_field);
2138         if (lvalue) {
2139             *out = ir_block_create_fieldaddress(func->m_curblock, m_context, func->makeLabel("mefa"),
2140                                                 ent, field);
2141         } else {
2142             *out = ir_block_create_load_from_ent(func->m_curblock, m_context, func->makeLabel("mefv"),
2143                                                  ent, field, m_vtype);
2144         }
2145         if (!*out) {
2146             compile_error(m_context, "failed to create %s instruction (output type %s)",
2147                      (lvalue ? "ADDRESS" : "FIELD"),
2148                      type_name[m_vtype]);
2149             return false;
2150         }
2151         if (lvalue)
2152             m_outl = *out;
2153         else
2154             m_outr = *out;
2155         return (*out != nullptr);
2156     } else {
2157         if (!m_owner->codegen(func, false, &vec))
2158             return false;
2159     }
2160
2161     if (vec->m_vtype != TYPE_VECTOR &&
2162         !(vec->m_vtype == TYPE_FIELD && m_owner->m_next->m_vtype == TYPE_VECTOR))
2163     {
2164         return false;
2165     }
2166
2167     *out = vec->vectorMember(m_field);
2168     m_outl = *out;
2169
2170     return (*out != nullptr);
2171 }
2172
2173 bool ast_array_index::codegen(ast_function *func, bool lvalue, ir_value **out)
2174 {
2175     ast_value *arr;
2176     ast_value *idx;
2177
2178     if (!lvalue && m_outr) {
2179         *out = m_outr;
2180         return true;
2181     }
2182     if (lvalue && m_outl) {
2183         *out = m_outl;
2184         return true;
2185     }
2186
2187     if (!ast_istype(m_array, ast_value)) {
2188         compile_error(m_context, "array indexing this way is not supported");
2189         /* note this would actually be pointer indexing because the left side is
2190          * not an actual array but (hopefully) an indexable expression.
2191          * Once we get integer arithmetic, and GADDRESS/GSTORE/GLOAD instruction
2192          * support this path will be filled.
2193          */
2194         return false;
2195     }
2196
2197     arr = reinterpret_cast<ast_value*>(m_array);
2198     idx = reinterpret_cast<ast_value*>(m_index);
2199
2200     if (!ast_istype(m_index, ast_value) || !idx->m_hasvalue || idx->m_cvq != CV_CONST) {
2201         /* Time to use accessor functions */
2202         ir_value               *iridx, *funval;
2203         ir_instr               *call;
2204
2205         if (lvalue) {
2206             compile_error(m_context, "(.2) array indexing here needs a compile-time constant");
2207             return false;
2208         }
2209
2210         if (!arr->m_getter) {
2211             compile_error(m_context, "value has no getter, don't know how to index it");
2212             return false;
2213         }
2214
2215         if (!m_index->codegen(func, false, &iridx))
2216             return false;
2217
2218         if (!arr->m_getter->codegen(func, true, &funval))
2219             return false;
2220
2221         call = ir_block_create_call(func->m_curblock, m_context, func->makeLabel("fetch"), funval, false);
2222         if (!call)
2223             return false;
2224         ir_call_param(call, iridx);
2225
2226         *out = ir_call_value(call);
2227         m_outr = *out;
2228         (*out)->m_vtype = m_vtype;
2229         codegen_output_type(this, *out);
2230         return true;
2231     }
2232
2233     if (idx->m_vtype == TYPE_FLOAT) {
2234         unsigned int arridx = idx->m_constval.vfloat;
2235         if (arridx >= m_array->m_count)
2236         {
2237             compile_error(m_context, "array index out of bounds: %i", arridx);
2238             return false;
2239         }
2240         *out = arr->m_ir_values[arridx];
2241     }
2242     else if (idx->m_vtype == TYPE_INTEGER) {
2243         unsigned int arridx = idx->m_constval.vint;
2244         if (arridx >= m_array->m_count)
2245         {
2246             compile_error(m_context, "array index out of bounds: %i", arridx);
2247             return false;
2248         }
2249         *out = arr->m_ir_values[arridx];
2250     }
2251     else {
2252         compile_error(m_context, "array indexing here needs an integer constant");
2253         return false;
2254     }
2255     (*out)->m_vtype = m_vtype;
2256     codegen_output_type(this, *out);
2257     return true;
2258 }
2259
2260 bool ast_argpipe::codegen(ast_function *func, bool lvalue, ir_value **out)
2261 {
2262     *out = nullptr;
2263     if (lvalue) {
2264         compile_error(m_context, "argpipe node: not an lvalue");
2265         return false;
2266     }
2267     (void)func;
2268     (void)out;
2269     compile_error(m_context, "TODO: argpipe codegen not implemented");
2270     return false;
2271 }
2272
2273 bool ast_ifthen::codegen(ast_function *func, bool lvalue, ir_value **out)
2274 {
2275     ir_value *condval;
2276     ir_value *dummy;
2277
2278     ir_block *cond;
2279     ir_block *ontrue;
2280     ir_block *onfalse;
2281     ir_block *ontrue_endblock = nullptr;
2282     ir_block *onfalse_endblock = nullptr;
2283     ir_block *merge = nullptr;
2284     int folded = 0;
2285
2286     /* We don't output any value, thus also don't care about r/lvalue */
2287     (void)out;
2288     (void)lvalue;
2289
2290     if (m_outr) {
2291         compile_error(m_context, "internal error: ast_ifthen cannot be reused, it bears no result!");
2292         return false;
2293     }
2294     m_outr = (ir_value*)1;
2295
2296     /* generate the condition */
2297     if (!m_cond->codegen(func, false, &condval))
2298         return false;
2299     /* update the block which will get the jump - because short-logic or ternaries may have changed this */
2300     cond = func->m_curblock;
2301
2302     /* try constant folding away the condition */
2303     if ((folded = fold::cond_ifthen(condval, func, this)) != -1)
2304         return folded;
2305
2306     if (m_on_true) {
2307         /* create on-true block */
2308         ontrue = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("ontrue"));
2309         if (!ontrue)
2310             return false;
2311
2312         /* enter the block */
2313         func->m_curblock = ontrue;
2314
2315         /* generate */
2316         if (!m_on_true->codegen(func, false, &dummy))
2317             return false;
2318
2319         /* we now need to work from the current endpoint */
2320         ontrue_endblock = func->m_curblock;
2321     } else
2322         ontrue = nullptr;
2323
2324     /* on-false path */
2325     if (m_on_false) {
2326         /* create on-false block */
2327         onfalse = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("onfalse"));
2328         if (!onfalse)
2329             return false;
2330
2331         /* enter the block */
2332         func->m_curblock = onfalse;
2333
2334         /* generate */
2335         if (!m_on_false->codegen(func, false, &dummy))
2336             return false;
2337
2338         /* we now need to work from the current endpoint */
2339         onfalse_endblock = func->m_curblock;
2340     } else
2341         onfalse = nullptr;
2342
2343     /* Merge block were they all merge in to */
2344     if (!ontrue || !onfalse || !ontrue_endblock->m_final || !onfalse_endblock->m_final)
2345     {
2346         merge = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("endif"));
2347         if (!merge)
2348             return false;
2349         /* add jumps ot the merge block */
2350         if (ontrue && !ontrue_endblock->m_final && !ir_block_create_jump(ontrue_endblock, m_context, merge))
2351             return false;
2352         if (onfalse && !onfalse_endblock->m_final && !ir_block_create_jump(onfalse_endblock, m_context, merge))
2353             return false;
2354
2355         /* Now enter the merge block */
2356         func->m_curblock = merge;
2357     }
2358
2359     /* we create the if here, that way all blocks are ordered :)
2360      */
2361     if (!ir_block_create_if(cond, m_context, condval,
2362                             (ontrue  ? ontrue  : merge),
2363                             (onfalse ? onfalse : merge)))
2364     {
2365         return false;
2366     }
2367
2368     return true;
2369 }
2370
2371 bool ast_ternary::codegen(ast_function *func, bool lvalue, ir_value **out)
2372 {
2373     ir_value *condval;
2374     ir_value *trueval, *falseval;
2375     ir_instr *phi;
2376
2377     ir_block *cond = func->m_curblock;
2378     ir_block *cond_out = nullptr;
2379     ir_block *ontrue, *ontrue_out = nullptr;
2380     ir_block *onfalse, *onfalse_out = nullptr;
2381     ir_block *merge;
2382     int folded = 0;
2383
2384     /* Ternary can never create an lvalue... */
2385     if (lvalue)
2386         return false;
2387
2388     /* In theory it shouldn't be possible to pass through a node twice, but
2389      * in case we add any kind of optimization pass for the AST itself, it
2390      * may still happen, thus we remember a created ir_value and simply return one
2391      * if it already exists.
2392      */
2393     if (m_outr) {
2394         *out = m_outr;
2395         return true;
2396     }
2397
2398     /* In the following, contraty to ast_ifthen, we assume both paths exist. */
2399
2400     /* generate the condition */
2401     func->m_curblock = cond;
2402     if (!m_cond->codegen(func, false, &condval))
2403         return false;
2404     cond_out = func->m_curblock;
2405
2406     /* try constant folding away the condition */
2407     if ((folded = fold::cond_ternary(condval, func, this)) != -1)
2408         return folded;
2409
2410     /* create on-true block */
2411     ontrue = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("tern_T"));
2412     if (!ontrue)
2413         return false;
2414     else
2415     {
2416         /* enter the block */
2417         func->m_curblock = ontrue;
2418
2419         /* generate */
2420         if (!m_on_true->codegen(func, false, &trueval))
2421             return false;
2422
2423         ontrue_out = func->m_curblock;
2424     }
2425
2426     /* create on-false block */
2427     onfalse = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("tern_F"));
2428     if (!onfalse)
2429         return false;
2430     else
2431     {
2432         /* enter the block */
2433         func->m_curblock = onfalse;
2434
2435         /* generate */
2436         if (!m_on_false->codegen(func, false, &falseval))
2437             return false;
2438
2439         onfalse_out = func->m_curblock;
2440     }
2441
2442     /* create merge block */
2443     merge = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("tern_out"));
2444     if (!merge)
2445         return false;
2446     /* jump to merge block */
2447     if (!ir_block_create_jump(ontrue_out, m_context, merge))
2448         return false;
2449     if (!ir_block_create_jump(onfalse_out, m_context, merge))
2450         return false;
2451
2452     /* create if instruction */
2453     if (!ir_block_create_if(cond_out, m_context, condval, ontrue, onfalse))
2454         return false;
2455
2456     /* Now enter the merge block */
2457     func->m_curblock = merge;
2458
2459     /* Here, now, we need a PHI node
2460      * but first some sanity checking...
2461      */
2462     if (trueval->m_vtype != falseval->m_vtype && trueval->m_vtype != TYPE_NIL && falseval->m_vtype != TYPE_NIL) {
2463         /* error("ternary with different types on the two sides"); */
2464         compile_error(m_context, "internal error: ternary operand types invalid");
2465         return false;
2466     }
2467
2468     /* create PHI */
2469     phi = ir_block_create_phi(merge, m_context, func->makeLabel("phi"), m_vtype);
2470     if (!phi) {
2471         compile_error(m_context, "internal error: failed to generate phi node");
2472         return false;
2473     }
2474     ir_phi_add(phi, ontrue_out,  trueval);
2475     ir_phi_add(phi, onfalse_out, falseval);
2476
2477     m_outr = ir_phi_value(phi);
2478     *out = m_outr;
2479
2480     codegen_output_type(this, *out);
2481
2482     return true;
2483 }
2484
2485 bool ast_loop::codegen(ast_function *func, bool lvalue, ir_value **out)
2486 {
2487     ir_value *dummy      = nullptr;
2488     ir_value *precond    = nullptr;
2489     ir_value *postcond   = nullptr;
2490
2491     /* Since we insert some jumps "late" so we have blocks
2492      * ordered "nicely", we need to keep track of the actual end-blocks
2493      * of expressions to add the jumps to.
2494      */
2495     ir_block *bbody      = nullptr, *end_bbody      = nullptr;
2496     ir_block *bprecond   = nullptr, *end_bprecond   = nullptr;
2497     ir_block *bpostcond  = nullptr, *end_bpostcond  = nullptr;
2498     ir_block *bincrement = nullptr, *end_bincrement = nullptr;
2499     ir_block *bout       = nullptr, *bin            = nullptr;
2500
2501     /* let's at least move the outgoing block to the end */
2502     size_t    bout_id;
2503
2504     /* 'break' and 'continue' need to be able to find the right blocks */
2505     ir_block *bcontinue     = nullptr;
2506     ir_block *bbreak        = nullptr;
2507
2508     ir_block *tmpblock      = nullptr;
2509
2510     (void)lvalue;
2511     (void)out;
2512
2513     if (m_outr) {
2514         compile_error(m_context, "internal error: ast_loop cannot be reused, it bears no result!");
2515         return false;
2516     }
2517     m_outr = (ir_value*)1;
2518
2519     /* NOTE:
2520      * Should we ever need some kind of block ordering, better make this function
2521      * move blocks around than write a block ordering algorithm later... after all
2522      * the ast and ir should work together, not against each other.
2523      */
2524
2525     /* initexpr doesn't get its own block, it's pointless, it could create more blocks
2526      * anyway if for example it contains a ternary.
2527      */
2528     if (m_initexpr)
2529     {
2530         if (!m_initexpr->codegen(func, false, &dummy))
2531             return false;
2532     }
2533
2534     /* Store the block from which we enter this chaos */
2535     bin = func->m_curblock;
2536
2537     /* The pre-loop condition needs its own block since we
2538      * need to be able to jump to the start of that expression.
2539      */
2540     if (m_precond)
2541     {
2542         bprecond = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("pre_loop_cond"));
2543         if (!bprecond)
2544             return false;
2545
2546         /* the pre-loop-condition the least important place to 'continue' at */
2547         bcontinue = bprecond;
2548
2549         /* enter */
2550         func->m_curblock = bprecond;
2551
2552         /* generate */
2553         if (!m_precond->codegen(func, false, &precond))
2554             return false;
2555
2556         end_bprecond = func->m_curblock;
2557     } else {
2558         bprecond = end_bprecond = nullptr;
2559     }
2560
2561     /* Now the next blocks won't be ordered nicely, but we need to
2562      * generate them this early for 'break' and 'continue'.
2563      */
2564     if (m_increment) {
2565         bincrement = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("loop_increment"));
2566         if (!bincrement)
2567             return false;
2568         bcontinue = bincrement; /* increment comes before the pre-loop-condition */
2569     } else {
2570         bincrement = end_bincrement = nullptr;
2571     }
2572
2573     if (m_postcond) {
2574         bpostcond = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("post_loop_cond"));
2575         if (!bpostcond)
2576             return false;
2577         bcontinue = bpostcond; /* postcond comes before the increment */
2578     } else {
2579         bpostcond = end_bpostcond = nullptr;
2580     }
2581
2582     bout_id = func->m_ir_func->m_blocks.size();
2583     bout = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("after_loop"));
2584     if (!bout)
2585         return false;
2586     bbreak = bout;
2587
2588     /* The loop body... */
2589     /* if (m_body) */
2590     {
2591         bbody = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("loop_body"));
2592         if (!bbody)
2593             return false;
2594
2595         /* enter */
2596         func->m_curblock = bbody;
2597
2598         func->m_breakblocks.push_back(bbreak);
2599         if (bcontinue)
2600             func->m_continueblocks.push_back(bcontinue);
2601         else
2602             func->m_continueblocks.push_back(bbody);
2603
2604         /* generate */
2605         if (m_body) {
2606             if (!m_body->codegen(func, false, &dummy))
2607                 return false;
2608         }
2609
2610         end_bbody = func->m_curblock;
2611         func->m_breakblocks.pop_back();
2612         func->m_continueblocks.pop_back();
2613     }
2614
2615     /* post-loop-condition */
2616     if (m_postcond)
2617     {
2618         /* enter */
2619         func->m_curblock = bpostcond;
2620
2621         /* generate */
2622         if (!m_postcond->codegen(func, false, &postcond))
2623             return false;
2624
2625         end_bpostcond = func->m_curblock;
2626     }
2627
2628     /* The incrementor */
2629     if (m_increment)
2630     {
2631         /* enter */
2632         func->m_curblock = bincrement;
2633
2634         /* generate */
2635         if (!m_increment->codegen(func, false, &dummy))
2636             return false;
2637
2638         end_bincrement = func->m_curblock;
2639     }
2640
2641     /* In any case now, we continue from the outgoing block */
2642     func->m_curblock = bout;
2643
2644     /* Now all blocks are in place */
2645     /* From 'bin' we jump to whatever comes first */
2646     if      (bprecond)   tmpblock = bprecond;
2647     else                 tmpblock = bbody;    /* can never be null */
2648
2649     /* DEAD CODE
2650     else if (bpostcond)  tmpblock = bpostcond;
2651     else                 tmpblock = bout;
2652     */
2653
2654     if (!ir_block_create_jump(bin, m_context, tmpblock))
2655         return false;
2656
2657     /* From precond */
2658     if (bprecond)
2659     {
2660         ir_block *ontrue, *onfalse;
2661         ontrue = bbody; /* can never be null */
2662
2663         /* all of this is dead code
2664         else if (bincrement) ontrue = bincrement;
2665         else                 ontrue = bpostcond;
2666         */
2667
2668         onfalse = bout;
2669         if (m_pre_not) {
2670             tmpblock = ontrue;
2671             ontrue   = onfalse;
2672             onfalse  = tmpblock;
2673         }
2674         if (!ir_block_create_if(end_bprecond, m_context, precond, ontrue, onfalse))
2675             return false;
2676     }
2677
2678     /* from body */
2679     if (bbody)
2680     {
2681         if      (bincrement) tmpblock = bincrement;
2682         else if (bpostcond)  tmpblock = bpostcond;
2683         else if (bprecond)   tmpblock = bprecond;
2684         else                 tmpblock = bbody;
2685         if (!end_bbody->m_final && !ir_block_create_jump(end_bbody, m_context, tmpblock))
2686             return false;
2687     }
2688
2689     /* from increment */
2690     if (bincrement)
2691     {
2692         if      (bpostcond)  tmpblock = bpostcond;
2693         else if (bprecond)   tmpblock = bprecond;
2694         else if (bbody)      tmpblock = bbody;
2695         else                 tmpblock = bout;
2696         if (!ir_block_create_jump(end_bincrement, m_context, tmpblock))
2697             return false;
2698     }
2699
2700     /* from postcond */
2701     if (bpostcond)
2702     {
2703         ir_block *ontrue, *onfalse;
2704         if      (bprecond)   ontrue = bprecond;
2705         else                 ontrue = bbody; /* can never be null */
2706
2707         /* all of this is dead code
2708         else if (bincrement) ontrue = bincrement;
2709         else                 ontrue = bpostcond;
2710         */
2711
2712         onfalse = bout;
2713         if (m_post_not) {
2714             tmpblock = ontrue;
2715             ontrue   = onfalse;
2716             onfalse  = tmpblock;
2717         }
2718         if (!ir_block_create_if(end_bpostcond, m_context, postcond, ontrue, onfalse))
2719             return false;
2720     }
2721
2722     /* Move 'bout' to the end */
2723     algo::shiftback(func->m_ir_func->m_blocks.begin() + bout_id,
2724                     func->m_ir_func->m_blocks.end());
2725     // FIXME::DELME::
2726     //func->m_ir_func->m_blocks[bout_id].release(); // it's a vector<std::unique_ptr<>>
2727     //func->m_ir_func->m_blocks.erase(func->m_ir_func->m_blocks.begin() + bout_id);
2728     //func->m_ir_func->m_blocks.emplace_back(bout);
2729
2730     return true;
2731 }
2732
2733 bool ast_breakcont::codegen(ast_function *func, bool lvalue, ir_value **out)
2734 {
2735     ir_block *target;
2736
2737     *out = nullptr;
2738
2739     if (lvalue) {
2740         compile_error(m_context, "break/continue expression is not an l-value");
2741         return false;
2742     }
2743
2744     if (m_outr) {
2745         compile_error(m_context, "internal error: ast_breakcont cannot be reused!");
2746         return false;
2747     }
2748     m_outr = (ir_value*)1;
2749
2750     if (m_is_continue)
2751         target = func->m_continueblocks[func->m_continueblocks.size()-1-m_levels];
2752     else
2753         target = func->m_breakblocks[func->m_breakblocks.size()-1-m_levels];
2754
2755     if (!target) {
2756         compile_error(m_context, "%s is lacking a target block", (m_is_continue ? "continue" : "break"));
2757         return false;
2758     }
2759
2760     if (!ir_block_create_jump(func->m_curblock, m_context, target))
2761         return false;
2762     return true;
2763 }
2764
2765 bool ast_switch::codegen(ast_function *func, bool lvalue, ir_value **out)
2766 {
2767     ast_switch_case *def_case     = nullptr;
2768     ir_block        *def_bfall    = nullptr;
2769     ir_block        *def_bfall_to = nullptr;
2770     bool set_def_bfall_to = false;
2771
2772     ir_value *dummy     = nullptr;
2773     ir_value *irop      = nullptr;
2774     ir_block *bout      = nullptr;
2775     ir_block *bfall     = nullptr;
2776     size_t    bout_id;
2777
2778     char      typestr[1024];
2779     uint16_t  cmpinstr;
2780
2781     if (lvalue) {
2782         compile_error(m_context, "switch expression is not an l-value");
2783         return false;
2784     }
2785
2786     if (m_outr) {
2787         compile_error(m_context, "internal error: ast_switch cannot be reused!");
2788         return false;
2789     }
2790     m_outr = (ir_value*)1;
2791
2792     (void)lvalue;
2793     (void)out;
2794
2795     if (!m_operand->codegen(func, false, &irop))
2796         return false;
2797
2798     if (m_cases.empty())
2799         return true;
2800
2801     cmpinstr = type_eq_instr[irop->m_vtype];
2802     if (cmpinstr >= VINSTR_END) {
2803         ast_type_to_string(m_operand, typestr, sizeof(typestr));
2804         compile_error(m_context, "invalid type to perform a switch on: %s", typestr);
2805         return false;
2806     }
2807
2808     bout_id = func->m_ir_func->m_blocks.size();
2809     bout = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("after_switch"));
2810     if (!bout)
2811         return false;
2812
2813     /* setup the break block */
2814     func->m_breakblocks.push_back(bout);
2815
2816     /* Now create all cases */
2817     for (auto &it : m_cases) {
2818         ir_value *cond, *val;
2819         ir_block *bcase, *bnot;
2820         size_t bnot_id;
2821
2822         ast_switch_case *swcase = &it;
2823
2824         if (swcase->m_value) {
2825             /* A regular case */
2826             /* generate the condition operand */
2827             if (!swcase->m_value->codegen(func, false, &val))
2828                 return false;
2829             /* generate the condition */
2830             cond = ir_block_create_binop(func->m_curblock, m_context, func->makeLabel("switch_eq"), cmpinstr, irop, val);
2831             if (!cond)
2832                 return false;
2833
2834             bcase = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("case"));
2835             bnot_id = func->m_ir_func->m_blocks.size();
2836             bnot = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("not_case"));
2837             if (!bcase || !bnot)
2838                 return false;
2839             if (set_def_bfall_to) {
2840                 set_def_bfall_to = false;
2841                 def_bfall_to = bcase;
2842             }
2843             if (!ir_block_create_if(func->m_curblock, m_context, cond, bcase, bnot))
2844                 return false;
2845
2846             /* Make the previous case-end fall through */
2847             if (bfall && !bfall->m_final) {
2848                 if (!ir_block_create_jump(bfall, m_context, bcase))
2849                     return false;
2850             }
2851
2852             /* enter the case */
2853             func->m_curblock = bcase;
2854             if (!swcase->m_code->codegen(func, false, &dummy))
2855                 return false;
2856
2857             /* remember this block to fall through from */
2858             bfall = func->m_curblock;
2859
2860             /* enter the else and move it down */
2861             func->m_curblock = bnot;
2862             algo::shiftback(func->m_ir_func->m_blocks.begin() + bnot_id,
2863                             func->m_ir_func->m_blocks.end());
2864             // FIXME::DELME::
2865             //func->m_ir_func->m_blocks[bnot_id].release();
2866             //func->m_ir_func->m_blocks.erase(func->m_ir_func->m_blocks.begin() + bnot_id);
2867             //func->m_ir_func->m_blocks.emplace_back(bnot);
2868         } else {
2869             /* The default case */
2870             /* Remember where to fall through from: */
2871             def_bfall = bfall;
2872             bfall     = nullptr;
2873             /* remember which case it was */
2874             def_case  = swcase;
2875             /* And the next case will be remembered */
2876             set_def_bfall_to = true;
2877         }
2878     }
2879
2880     /* Jump from the last bnot to bout */
2881     if (bfall && !bfall->m_final && !ir_block_create_jump(bfall, m_context, bout)) {
2882         /*
2883         astwarning(bfall->m_context, WARN_???, "missing break after last case");
2884         */
2885         return false;
2886     }
2887
2888     /* If there was a default case, put it down here */
2889     if (def_case) {
2890         ir_block *bcase;
2891
2892         /* No need to create an extra block */
2893         bcase = func->m_curblock;
2894
2895         /* Insert the fallthrough jump */
2896         if (def_bfall && !def_bfall->m_final) {
2897             if (!ir_block_create_jump(def_bfall, m_context, bcase))
2898                 return false;
2899         }
2900
2901         /* Now generate the default code */
2902         if (!def_case->m_code->codegen(func, false, &dummy))
2903             return false;
2904
2905         /* see if we need to fall through */
2906         if (def_bfall_to && !func->m_curblock->m_final)
2907         {
2908             if (!ir_block_create_jump(func->m_curblock, m_context, def_bfall_to))
2909                 return false;
2910         }
2911     }
2912
2913     /* Jump from the last bnot to bout */
2914     if (!func->m_curblock->m_final && !ir_block_create_jump(func->m_curblock, m_context, bout))
2915         return false;
2916     /* enter the outgoing block */
2917     func->m_curblock = bout;
2918
2919     /* restore the break block */
2920     func->m_breakblocks.pop_back();
2921
2922     /* Move 'bout' to the end, it's nicer */
2923     algo::shiftback(func->m_ir_func->m_blocks.begin() + bout_id,
2924                     func->m_ir_func->m_blocks.end());
2925     // FIXME::DELME::
2926     //func->m_ir_func->m_blocks[bout_id].release();
2927     //func->m_ir_func->m_blocks.erase(func->m_ir_func->m_blocks.begin() + bout_id);
2928     //func->m_ir_func->m_blocks.emplace_back(bout);
2929
2930     return true;
2931 }
2932
2933 bool ast_label::codegen(ast_function *func, bool lvalue, ir_value **out)
2934 {
2935     ir_value *dummy;
2936
2937     if (m_undefined) {
2938         compile_error(m_context, "internal error: ast_label never defined");
2939         return false;
2940     }
2941
2942     *out = nullptr;
2943     if (lvalue) {
2944         compile_error(m_context, "internal error: ast_label cannot be an lvalue");
2945         return false;
2946     }
2947
2948     /* simply create a new block and jump to it */
2949     m_irblock = ir_function_create_block(m_context, func->m_ir_func, m_name.c_str());
2950     if (!m_irblock) {
2951         compile_error(m_context, "failed to allocate label block `%s`", m_name);
2952         return false;
2953     }
2954     if (!func->m_curblock->m_final) {
2955         if (!ir_block_create_jump(func->m_curblock, m_context, m_irblock))
2956             return false;
2957     }
2958
2959     /* enter the new block */
2960     func->m_curblock = m_irblock;
2961
2962     /* Generate all the leftover gotos */
2963     for (auto &it : m_gotos) {
2964         if (!it->codegen(func, false, &dummy))
2965             return false;
2966     }
2967
2968     return true;
2969 }
2970
2971 bool ast_goto::codegen(ast_function *func, bool lvalue, ir_value **out)
2972 {
2973     *out = nullptr;
2974     if (lvalue) {
2975         compile_error(m_context, "internal error: ast_goto cannot be an lvalue");
2976         return false;
2977     }
2978
2979     if (m_target->m_irblock) {
2980         if (m_irblock_from) {
2981             /* we already tried once, this is the callback */
2982             m_irblock_from->m_final = false;
2983             if (!ir_block_create_goto(m_irblock_from, m_context, m_target->m_irblock)) {
2984                 compile_error(m_context, "failed to generate goto to `%s`", m_name);
2985                 return false;
2986             }
2987         }
2988         else
2989         {
2990             if (!ir_block_create_goto(func->m_curblock, m_context, m_target->m_irblock)) {
2991                 compile_error(m_context, "failed to generate goto to `%s`", m_name);
2992                 return false;
2993             }
2994         }
2995     }
2996     else
2997     {
2998         /* the target has not yet been created...
2999          * close this block in a sneaky way:
3000          */
3001         func->m_curblock->m_final = true;
3002         m_irblock_from = func->m_curblock;
3003         m_target->registerGoto(this);
3004     }
3005
3006     return true;
3007 }
3008
3009 bool ast_state::codegen(ast_function *func, bool lvalue, ir_value **out)
3010 {
3011     ir_value *frameval, *thinkval;
3012
3013     if (lvalue) {
3014         compile_error(m_context, "not an l-value (state operation)");
3015         return false;
3016     }
3017     if (m_outr) {
3018         compile_error(m_context, "internal error: ast_state cannot be reused!");
3019         return false;
3020     }
3021     *out = nullptr;
3022
3023     if (!m_framenum->codegen(func, false, &frameval))
3024         return false;
3025     if (!frameval)
3026         return false;
3027
3028     if (!m_nextthink->codegen(func, false, &thinkval))
3029         return false;
3030     if (!frameval)
3031         return false;
3032
3033     if (!ir_block_create_state_op(func->m_curblock, m_context, frameval, thinkval)) {
3034         compile_error(m_context, "failed to create STATE instruction");
3035         return false;
3036     }
3037
3038     m_outr = (ir_value*)1;
3039     return true;
3040 }
3041
3042 bool ast_call::codegen(ast_function *func, bool lvalue, ir_value **out)
3043 {
3044     std::vector<ir_value*> params;
3045     ir_instr *callinstr;
3046
3047     ir_value *funval = nullptr;
3048
3049     /* return values are never lvalues */
3050     if (lvalue) {
3051         compile_error(m_context, "not an l-value (function call)");
3052         return false;
3053     }
3054
3055     if (m_outr) {
3056         *out = m_outr;
3057         return true;
3058     }
3059
3060     if (!m_func->codegen(func, false, &funval))
3061         return false;
3062     if (!funval)
3063         return false;
3064
3065     /* parameters */
3066     for (auto &it : m_params) {
3067         ir_value *param;
3068         if (!it->codegen(func, false, &param))
3069             return false;
3070         if (!param)
3071             return false;
3072         params.push_back(param);
3073     }
3074
3075     /* varargs counter */
3076     if (m_va_count) {
3077         ir_value   *va_count;
3078         ir_builder *builder = func->m_curblock->m_owner->m_owner;
3079         if (!m_va_count->codegen(func, false, &va_count))
3080             return false;
3081         if (!ir_block_create_store_op(func->m_curblock, m_context, INSTR_STORE_F,
3082                                       builder->get_va_count(), va_count))
3083         {
3084             return false;
3085         }
3086     }
3087
3088     callinstr = ir_block_create_call(func->m_curblock, m_context,
3089                                      func->makeLabel("call"),
3090                                      funval, !!(m_func->m_flags & AST_FLAG_NORETURN));
3091     if (!callinstr)
3092         return false;
3093
3094     for (auto &it : params)
3095         ir_call_param(callinstr, it);
3096
3097     *out = ir_call_value(callinstr);
3098     m_outr = *out;
3099
3100     codegen_output_type(this, *out);
3101
3102     return true;
3103 }