]> git.xonotic.org Git - xonotic/gmqcc.git/blob - ast.cpp
7529acdd4ce0ac373fad7420f5c93c4d967602e6
[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
1136     /* initialize */
1137     if (m_hasvalue) {
1138         switch (m_vtype)
1139         {
1140             case TYPE_FLOAT:
1141                 if (!v->setFloat(m_constval.vfloat))
1142                     return false;
1143                 break;
1144             case TYPE_VECTOR:
1145                 if (!v->setVector(m_constval.vvec))
1146                     return false;
1147                 break;
1148             case TYPE_STRING:
1149                 if (!v->setString(m_constval.vstring))
1150                     return false;
1151                 break;
1152             case TYPE_ARRAY:
1153                 if (!setGlobalArray())
1154                     return false;
1155                 break;
1156             case TYPE_FUNCTION:
1157                 compile_error(m_context, "global of type function not properly generated");
1158                 return false;
1159                 /* Cannot generate an IR value for a function,
1160                  * need a pointer pointing to a function rather.
1161                  */
1162             case TYPE_FIELD:
1163                 if (!m_constval.vfield) {
1164                     compile_error(m_context, "field constant without vfield set");
1165                     return false;
1166                 }
1167                 if (!m_constval.vfield->m_ir_v) {
1168                     compile_error(m_context, "field constant generated before its field");
1169                     return false;
1170                 }
1171                 if (!v->setField(m_constval.vfield->m_ir_v))
1172                     return false;
1173                 break;
1174             default:
1175                 compile_error(m_context, "TODO: global constant type %i", m_vtype);
1176                 break;
1177         }
1178     }
1179
1180     return true;
1181 }
1182
1183 bool ast_value::generateGlobalFunction(ir_builder *ir)
1184 {
1185     ir_function *func = ir->createFunction(m_name, m_next->m_vtype);
1186     if (!func)
1187         return false;
1188     func->m_context = m_context;
1189     func->m_value->m_context = m_context;
1190
1191     m_constval.vfunc->m_ir_func = func;
1192     m_ir_v = func->m_value;
1193     if (m_flags & AST_FLAG_INCLUDE_DEF)
1194         m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
1195     if (m_flags & AST_FLAG_ERASEABLE)
1196         m_ir_v->m_flags |= IR_FLAG_ERASABLE;
1197     if (m_flags & AST_FLAG_BLOCK_COVERAGE)
1198         func->m_flags |= IR_FLAG_BLOCK_COVERAGE;
1199     // The function is filled later on ast_function::generateFunction...
1200     return true;
1201 }
1202
1203 bool ast_value::generateGlobalField(ir_builder *ir)
1204 {
1205     ast_expression *fieldtype = m_next;
1206
1207     if (m_hasvalue) {
1208         compile_error(m_context, "TODO: constant field pointers with value");
1209         return false;
1210     }
1211
1212     if (fieldtype->m_vtype == TYPE_ARRAY) {
1213         if (!ast_istype(fieldtype, ast_value)) {
1214             compile_error(m_context, "internal error: ast_value required");
1215             return false;
1216         }
1217         ast_value      *array = reinterpret_cast<ast_value*>(fieldtype);
1218
1219         if (!checkArray(*array))
1220             return false;
1221
1222         ast_expression *elemtype = array->m_next;
1223         qc_type vtype = elemtype->m_vtype;
1224
1225         ir_value *v = ir->createField(m_name, vtype);
1226         if (!v) {
1227             compile_error(m_context, "ir_builder::createGlobal failed on `%s`", m_name);
1228             return false;
1229         }
1230         v->m_context = m_context;
1231         v->m_unique_life = true;
1232         v->m_locked      = true;
1233         array->m_ir_v = m_ir_v = v;
1234
1235         if (m_flags & AST_FLAG_INCLUDE_DEF)
1236             m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
1237         if (m_flags & AST_FLAG_ERASEABLE)
1238             m_ir_v->m_flags |= IR_FLAG_ERASABLE;
1239
1240         const size_t namelen = m_name.length();
1241         std::unique_ptr<char[]> name(new char[namelen+16]);
1242         util_strncpy(name.get(), m_name.c_str(), namelen);
1243
1244         array->m_ir_values.resize(array->m_count);
1245         array->m_ir_values[0] = v;
1246         for (size_t ai = 1; ai < array->m_count; ++ai) {
1247             util_snprintf(name.get() + namelen, 16, "[%u]", (unsigned int)ai);
1248             array->m_ir_values[ai] = ir->createField(name.get(), vtype);
1249             if (!array->m_ir_values[ai]) {
1250                 compile_error(m_context, "ir_builder::createGlobal failed on `%s`", name.get());
1251                 return false;
1252             }
1253             array->m_ir_values[ai]->m_context = m_context;
1254             array->m_ir_values[ai]->m_unique_life = true;
1255             array->m_ir_values[ai]->m_locked      = true;
1256             if (m_flags & AST_FLAG_INCLUDE_DEF)
1257                 m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF;
1258         }
1259     }
1260     else
1261     {
1262         ir_value *v = ir->createField(m_name, m_next->m_vtype);
1263         if (!v)
1264             return false;
1265         v->m_context = m_context;
1266         m_ir_v = v;
1267         if (m_flags & AST_FLAG_INCLUDE_DEF)
1268             m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
1269
1270         if (m_flags & AST_FLAG_ERASEABLE)
1271             m_ir_v->m_flags |= IR_FLAG_ERASABLE;
1272     }
1273     return true;
1274 }
1275
1276 ir_value *ast_value::prepareGlobalArray(ir_builder *ir)
1277 {
1278     ast_expression *elemtype = m_next;
1279     qc_type vtype = elemtype->m_vtype;
1280
1281     if (m_flags & AST_FLAG_ARRAY_INIT && !m_count) {
1282         compile_error(m_context, "array `%s' has no size", m_name);
1283         return nullptr;
1284     }
1285
1286     /* same as with field arrays */
1287     if (!checkArray(*this))
1288         return nullptr;
1289
1290     ir_value *v = ir->createGlobal(m_name, vtype);
1291     if (!v) {
1292         compile_error(m_context, "ir_builder::createGlobal failed `%s`", m_name);
1293         return nullptr;
1294     }
1295     v->m_context = m_context;
1296     v->m_unique_life = true;
1297     v->m_locked      = true;
1298
1299     if (m_flags & AST_FLAG_INCLUDE_DEF)
1300         v->m_flags |= IR_FLAG_INCLUDE_DEF;
1301     if (m_flags & AST_FLAG_ERASEABLE)
1302         m_ir_v->m_flags |= IR_FLAG_ERASABLE;
1303
1304     const size_t namelen = m_name.length();
1305     std::unique_ptr<char[]> name(new char[namelen+16]);
1306     util_strncpy(name.get(), m_name.c_str(), namelen);
1307
1308     m_ir_values.resize(m_count);
1309     m_ir_values[0] = v;
1310     for (size_t ai = 1; ai < m_count; ++ai) {
1311         util_snprintf(name.get() + namelen, 16, "[%u]", (unsigned int)ai);
1312         m_ir_values[ai] = ir->createGlobal(name.get(), vtype);
1313         if (!m_ir_values[ai]) {
1314             compile_error(m_context, "ir_builder::createGlobal failed `%s`", name.get());
1315             return nullptr;
1316         }
1317         m_ir_values[ai]->m_context = m_context;
1318         m_ir_values[ai]->m_unique_life = true;
1319         m_ir_values[ai]->m_locked      = true;
1320         if (m_flags & AST_FLAG_INCLUDE_DEF)
1321             m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF;
1322     }
1323
1324     return v;
1325 }
1326
1327 bool ast_value::generateLocal(ir_function *func, bool param)
1328 {
1329     if (m_vtype == TYPE_NIL) {
1330         compile_error(m_context, "internal error: trying to generate a variable of TYPE_NIL");
1331         return false;
1332     }
1333
1334     if (m_hasvalue && m_vtype == TYPE_FUNCTION)
1335     {
1336         /* Do we allow local functions? I think not...
1337          * this is NOT a function pointer atm.
1338          */
1339         return false;
1340     }
1341
1342     ir_value *v = nullptr;
1343     if (m_vtype == TYPE_ARRAY) {
1344         ast_expression *elemtype = m_next;
1345         qc_type vtype = elemtype->m_vtype;
1346
1347         func->m_flags |= IR_FLAG_HAS_ARRAYS;
1348
1349         if (param && !(m_flags & AST_FLAG_IS_VARARG)) {
1350             compile_error(m_context, "array-parameters are not supported");
1351             return false;
1352         }
1353
1354         /* we are lame now - considering the way QC works we won't tolerate arrays > 1024 elements */
1355         if (!checkArray(*this))
1356             return false;
1357
1358         m_ir_values.resize(m_count);
1359         v = ir_function_create_local(func, m_name, vtype, param);
1360         if (!v) {
1361             compile_error(m_context, "internal error: ir_function_create_local failed");
1362             return false;
1363         }
1364         v->m_context = m_context;
1365         v->m_unique_life = true;
1366         v->m_locked      = true;
1367
1368         const size_t namelen = m_name.length();
1369         std::unique_ptr<char[]> name(new char[namelen+16]);
1370         util_strncpy(name.get(), m_name.c_str(), namelen);
1371
1372         m_ir_values[0] = v;
1373         for (size_t ai = 1; ai < m_count; ++ai) {
1374             util_snprintf(name.get() + namelen, 16, "[%u]", (unsigned int)ai);
1375             m_ir_values[ai] = ir_function_create_local(func, name.get(), vtype, param);
1376             if (!m_ir_values[ai]) {
1377                 compile_error(m_context, "internal_error: ir_builder::createGlobal failed on `%s`", name.get());
1378                 return false;
1379             }
1380             m_ir_values[ai]->m_context = m_context;
1381             m_ir_values[ai]->m_unique_life = true;
1382             m_ir_values[ai]->m_locked      = true;
1383         }
1384     }
1385     else
1386     {
1387         v = ir_function_create_local(func, m_name, m_vtype, param);
1388         if (!v)
1389             return false;
1390         codegen_output_type(this, v);
1391         v->m_context = m_context;
1392     }
1393
1394     // A constant local... hmmm...
1395     // I suppose the IR will have to deal with this
1396     if (m_hasvalue) {
1397         switch (m_vtype)
1398         {
1399             case TYPE_FLOAT:
1400                 if (!v->setFloat(m_constval.vfloat))
1401                     goto error;
1402                 break;
1403             case TYPE_VECTOR:
1404                 if (!v->setVector(m_constval.vvec))
1405                     goto error;
1406                 break;
1407             case TYPE_STRING:
1408                 if (!v->setString(m_constval.vstring))
1409                     goto error;
1410                 break;
1411             default:
1412                 compile_error(m_context, "TODO: global constant type %i", m_vtype);
1413                 break;
1414         }
1415     }
1416
1417     // link us to the ir_value
1418     v->m_cvq = m_cvq;
1419     m_ir_v = v;
1420
1421     if (!generateAccessors(func->m_owner))
1422         return false;
1423     return true;
1424
1425 error: /* clean up */
1426     delete v;
1427     return false;
1428 }
1429
1430 bool ast_value::generateAccessors(ir_builder *ir)
1431 {
1432     size_t i;
1433     bool warn = OPTS_WARN(WARN_USED_UNINITIALIZED);
1434     if (!m_setter || !m_getter)
1435         return true;
1436     if (m_count && m_ir_values.empty()) {
1437         compile_error(m_context, "internal error: no array values generated for `%s`", m_name);
1438         return false;
1439     }
1440     for (i = 0; i < m_count; ++i) {
1441         if (!m_ir_values[i]) {
1442             compile_error(m_context, "internal error: not all array values have been generated for `%s`", m_name);
1443             return false;
1444         }
1445         if (!m_ir_values[i]->m_life.empty()) {
1446             compile_error(m_context, "internal error: function containing `%s` already generated", m_name);
1447             return false;
1448         }
1449     }
1450
1451     opts_set(opts.warn, WARN_USED_UNINITIALIZED, false);
1452     if (m_setter) {
1453         if (!m_setter->generateGlobal(ir, false) ||
1454             !m_setter->m_constval.vfunc->generateFunction(ir) ||
1455             !ir_function_finalize(m_setter->m_constval.vfunc->m_ir_func))
1456         {
1457             compile_error(m_context, "internal error: failed to generate setter for `%s`", m_name);
1458             opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
1459             return false;
1460         }
1461     }
1462     if (m_getter) {
1463         if (!m_getter->generateGlobal(ir, false) ||
1464             !m_getter->m_constval.vfunc->generateFunction(ir) ||
1465             !ir_function_finalize(m_getter->m_constval.vfunc->m_ir_func))
1466         {
1467             compile_error(m_context, "internal error: failed to generate getter for `%s`", m_name);
1468             opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
1469             return false;
1470         }
1471     }
1472     for (i = 0; i < m_count; ++i)
1473         m_ir_values[i]->m_life.clear();
1474     opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
1475     return true;
1476 }
1477
1478 bool ast_function::generateFunction(ir_builder *ir)
1479 {
1480     (void)ir;
1481
1482     ir_value *dummy;
1483
1484     ir_function *irf = m_ir_func;
1485     if (!irf) {
1486         compile_error(m_context, "internal error: ast_function's related ast_value was not generated yet");
1487         return false;
1488     }
1489
1490     /* fill the parameter list */
1491     for (auto &it : m_function_type->m_type_params) {
1492         if (it->m_vtype == TYPE_FIELD)
1493             vec_push(irf->m_params, it->m_next->m_vtype);
1494         else
1495             vec_push(irf->m_params, it->m_vtype);
1496         if (!m_builtin) {
1497             if (!it->generateLocal(m_ir_func, true))
1498                 return false;
1499         }
1500     }
1501
1502     if (m_varargs) {
1503         if (!m_varargs->generateLocal(m_ir_func, true))
1504             return false;
1505         irf->m_max_varargs = m_varargs->m_count;
1506     }
1507
1508     if (m_builtin) {
1509         irf->m_builtin = m_builtin;
1510         return true;
1511     }
1512
1513     /* have a local return value variable? */
1514     if (m_return_value) {
1515         if (!m_return_value->generateLocal(m_ir_func, false))
1516             return false;
1517     }
1518
1519     if (m_blocks.empty()) {
1520         compile_error(m_context, "function `%s` has no body", m_name);
1521         return false;
1522     }
1523
1524     irf->m_first = m_curblock = ir_function_create_block(m_context, irf, "entry");
1525     if (!m_curblock) {
1526         compile_error(m_context, "failed to allocate entry block for `%s`", m_name);
1527         return false;
1528     }
1529
1530     if (m_argc) {
1531         ir_value *va_count;
1532         ir_value *fixed;
1533         ir_value *sub;
1534         if (!m_argc->generateLocal(m_ir_func, true))
1535             return false;
1536         if (!m_argc->codegen(this, false, &va_count))
1537             return false;
1538         if (!m_fixedparams->codegen(this, false, &fixed))
1539             return false;
1540         sub = ir_block_create_binop(m_curblock, m_context,
1541                                     makeLabel("va_count"), INSTR_SUB_F,
1542                                     ir->get_va_count(), fixed);
1543         if (!sub)
1544             return false;
1545         if (!ir_block_create_store_op(m_curblock, m_context, INSTR_STORE_F,
1546                                       va_count, sub))
1547         {
1548             return false;
1549         }
1550     }
1551
1552     for (auto &it : m_blocks) {
1553         if (!it->codegen(this, false, &dummy))
1554           return false;
1555     }
1556
1557     /* TODO: check return types */
1558     if (!m_curblock->m_final)
1559     {
1560         if (!m_function_type->m_next ||
1561             m_function_type->m_next->m_vtype == TYPE_VOID)
1562         {
1563             return ir_block_create_return(m_curblock, m_context, nullptr);
1564         }
1565         else if (vec_size(m_curblock->m_entries) || m_curblock == irf->m_first)
1566         {
1567             if (m_return_value) {
1568                 if (!m_return_value->codegen(this, false, &dummy))
1569                     return false;
1570                 return ir_block_create_return(m_curblock, m_context, dummy);
1571             }
1572             else if (compile_warning(m_context, WARN_MISSING_RETURN_VALUES,
1573                                 "control reaches end of non-void function (`%s`) via %s",
1574                                 m_name.c_str(), m_curblock->m_label.c_str()))
1575             {
1576                 return false;
1577             }
1578             return ir_block_create_return(m_curblock, m_context, nullptr);
1579         }
1580     }
1581     return true;
1582 }
1583
1584 static bool starts_a_label(const ast_expression *ex)
1585 {
1586     while (ex && ast_istype(ex, ast_block)) {
1587         auto b = reinterpret_cast<const ast_block*>(ex);
1588         ex = b->m_exprs[0];
1589     }
1590     if (!ex)
1591         return false;
1592     return ast_istype(ex, ast_label);
1593 }
1594
1595 /* Note, you will not see ast_block_codegen generate ir_blocks.
1596  * To the AST and the IR, blocks are 2 different things.
1597  * In the AST it represents a block of code, usually enclosed in
1598  * curly braces {...}.
1599  * While in the IR it represents a block in terms of control-flow.
1600  */
1601 bool ast_block::codegen(ast_function *func, bool lvalue, ir_value **out)
1602 {
1603     /* We don't use this
1604      * Note: an ast-representation using the comma-operator
1605      * of the form: (a, b, c) = x should not assign to c...
1606      */
1607     if (lvalue) {
1608         compile_error(m_context, "not an l-value (code-block)");
1609         return false;
1610     }
1611
1612     if (m_outr) {
1613         *out = m_outr;
1614         return true;
1615     }
1616
1617     /* output is nullptr at first, we'll have each expression
1618      * assign to out output, thus, a comma-operator represention
1619      * using an ast_block will return the last generated value,
1620      * so: (b, c) + a  executed both b and c, and returns c,
1621      * which is then added to a.
1622      */
1623     *out = nullptr;
1624
1625     /* generate locals */
1626     for (auto &it : m_locals) {
1627         if (!it->generateLocal(func->m_ir_func, false)) {
1628             if (OPTS_OPTION_BOOL(OPTION_DEBUG))
1629                 compile_error(m_context, "failed to generate local `%s`", it->m_name);
1630             return false;
1631         }
1632     }
1633
1634     for (auto &it : m_exprs) {
1635         if (func->m_curblock->m_final && !starts_a_label(it)) {
1636             if (compile_warning(it->m_context, WARN_UNREACHABLE_CODE, "unreachable statement"))
1637                 return false;
1638             continue;
1639         }
1640         if (!it->codegen(func, false, out))
1641             return false;
1642     }
1643
1644     m_outr = *out;
1645
1646     return true;
1647 }
1648
1649 bool ast_store::codegen(ast_function *func, bool lvalue, ir_value **out)
1650 {
1651     ir_value *left  = nullptr;
1652     ir_value *right = nullptr;
1653
1654     ast_value       *idx = 0;
1655     ast_array_index *ai = nullptr;
1656
1657     if (lvalue && m_outl) {
1658         *out = m_outl;
1659         return true;
1660     }
1661
1662     if (!lvalue && m_outr) {
1663         *out = m_outr;
1664         return true;
1665     }
1666
1667     if (ast_istype(m_dest, ast_array_index))
1668     {
1669
1670         ai = (ast_array_index*)m_dest;
1671         idx = (ast_value*)ai->m_index;
1672
1673         if (ast_istype(ai->m_index, ast_value) && idx->m_hasvalue && idx->m_cvq == CV_CONST)
1674             ai = nullptr;
1675     }
1676
1677     if (ai) {
1678         /* we need to call the setter */
1679         ir_value  *iridx, *funval;
1680         ir_instr  *call;
1681
1682         if (lvalue) {
1683             compile_error(m_context, "array-subscript assignment cannot produce lvalues");
1684             return false;
1685         }
1686
1687         auto arr = reinterpret_cast<ast_value*>(ai->m_array);
1688         if (!ast_istype(ai->m_array, ast_value) || !arr->m_setter) {
1689             compile_error(m_context, "value has no setter (%s)", arr->m_name);
1690             return false;
1691         }
1692
1693         if (!idx->codegen(func, false, &iridx))
1694             return false;
1695
1696         if (!arr->m_setter->codegen(func, true, &funval))
1697             return false;
1698
1699         if (!m_source->codegen(func, false, &right))
1700             return false;
1701
1702         call = ir_block_create_call(func->m_curblock, m_context, func->makeLabel("store"), funval, false);
1703         if (!call)
1704             return false;
1705         ir_call_param(call, iridx);
1706         ir_call_param(call, right);
1707         m_outr = right;
1708     }
1709     else
1710     {
1711         // regular code
1712
1713         // lvalue!
1714         if (!m_dest->codegen(func, true, &left))
1715             return false;
1716         m_outl = left;
1717
1718         /* rvalue! */
1719         if (!m_source->codegen(func, false, &right))
1720             return false;
1721
1722         if (!ir_block_create_store_op(func->m_curblock, m_context, m_op, left, right))
1723             return false;
1724         m_outr = right;
1725     }
1726
1727     /* Theoretically, an assinment returns its left side as an
1728      * lvalue, if we don't need an lvalue though, we return
1729      * the right side as an rvalue, otherwise we have to
1730      * somehow know whether or not we need to dereference the pointer
1731      * on the left side - that is: OP_LOAD if it was an address.
1732      * Also: in original QC we cannot OP_LOADP *anyway*.
1733      */
1734     *out = (lvalue ? left : right);
1735
1736     return true;
1737 }
1738
1739 bool ast_binary::codegen(ast_function *func, bool lvalue, ir_value **out)
1740 {
1741     ir_value *left, *right;
1742
1743     /* A binary operation cannot yield an l-value */
1744     if (lvalue) {
1745         compile_error(m_context, "not an l-value (binop)");
1746         return false;
1747     }
1748
1749     if (m_outr) {
1750         *out = m_outr;
1751         return true;
1752     }
1753
1754     if ((OPTS_FLAG(SHORT_LOGIC) || OPTS_FLAG(PERL_LOGIC)) &&
1755         (m_op == INSTR_AND || m_op == INSTR_OR))
1756     {
1757         /* NOTE: The short-logic path will ignore right_first */
1758
1759         /* short circuit evaluation */
1760         ir_block *other, *merge;
1761         ir_block *from_left, *from_right;
1762         ir_instr *phi;
1763         size_t    merge_id;
1764
1765         /* prepare end-block */
1766         merge_id = func->m_ir_func->m_blocks.size();
1767         merge    = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("sce_merge"));
1768
1769         /* generate the left expression */
1770         if (!m_left->codegen(func, false, &left))
1771             return false;
1772         /* remember the block */
1773         from_left = func->m_curblock;
1774
1775         /* create a new block for the right expression */
1776         other = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("sce_other"));
1777         if (m_op == INSTR_AND) {
1778             /* on AND: left==true -> other */
1779             if (!ir_block_create_if(func->m_curblock, m_context, left, other, merge))
1780                 return false;
1781         } else {
1782             /* on OR: left==false -> other */
1783             if (!ir_block_create_if(func->m_curblock, m_context, left, merge, other))
1784                 return false;
1785         }
1786         /* use the likely flag */
1787         vec_last(func->m_curblock->m_instr)->m_likely = true;
1788
1789         /* enter the right-expression's block */
1790         func->m_curblock = other;
1791         /* generate */
1792         if (!m_right->codegen(func, false, &right))
1793             return false;
1794         /* remember block */
1795         from_right = func->m_curblock;
1796
1797         /* jump to the merge block */
1798         if (!ir_block_create_jump(func->m_curblock, m_context, merge))
1799             return false;
1800
1801         algo::shiftback(func->m_ir_func->m_blocks.begin() + merge_id,
1802                         func->m_ir_func->m_blocks.end());
1803         // FIXME::DELME::
1804         //func->m_ir_func->m_blocks[merge_id].release();
1805         //func->m_ir_func->m_blocks.erase(func->m_ir_func->m_blocks.begin() + merge_id);
1806         //func->m_ir_func->m_blocks.emplace_back(merge);
1807
1808         func->m_curblock = merge;
1809         phi = ir_block_create_phi(func->m_curblock, m_context,
1810                                   func->makeLabel("sce_value"),
1811                                   m_vtype);
1812         ir_phi_add(phi, from_left, left);
1813         ir_phi_add(phi, from_right, right);
1814         *out = ir_phi_value(phi);
1815         if (!*out)
1816             return false;
1817
1818         if (!OPTS_FLAG(PERL_LOGIC)) {
1819             /* cast-to-bool */
1820             if (OPTS_FLAG(CORRECT_LOGIC) && (*out)->m_vtype == TYPE_VECTOR) {
1821                 *out = ir_block_create_unary(func->m_curblock, m_context,
1822                                              func->makeLabel("sce_bool_v"),
1823                                              INSTR_NOT_V, *out);
1824                 if (!*out)
1825                     return false;
1826                 *out = ir_block_create_unary(func->m_curblock, m_context,
1827                                              func->makeLabel("sce_bool"),
1828                                              INSTR_NOT_F, *out);
1829                 if (!*out)
1830                     return false;
1831             }
1832             else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && (*out)->m_vtype == TYPE_STRING) {
1833                 *out = ir_block_create_unary(func->m_curblock, m_context,
1834                                              func->makeLabel("sce_bool_s"),
1835                                              INSTR_NOT_S, *out);
1836                 if (!*out)
1837                     return false;
1838                 *out = ir_block_create_unary(func->m_curblock, m_context,
1839                                              func->makeLabel("sce_bool"),
1840                                              INSTR_NOT_F, *out);
1841                 if (!*out)
1842                     return false;
1843             }
1844             else {
1845                 *out = ir_block_create_binop(func->m_curblock, m_context,
1846                                              func->makeLabel("sce_bool"),
1847                                              INSTR_AND, *out, *out);
1848                 if (!*out)
1849                     return false;
1850             }
1851         }
1852
1853         m_outr = *out;
1854         codegen_output_type(this, *out);
1855         return true;
1856     }
1857
1858     if (m_right_first) {
1859         if (!m_right->codegen(func, false, &right))
1860             return false;
1861         if (!m_left->codegen(func, false, &left))
1862             return false;
1863     } else {
1864         if (!m_left->codegen(func, false, &left))
1865             return false;
1866         if (!m_right->codegen(func, false, &right))
1867             return false;
1868     }
1869
1870     *out = ir_block_create_binop(func->m_curblock, m_context, func->makeLabel("bin"),
1871                                  m_op, left, right);
1872     if (!*out)
1873         return false;
1874     m_outr = *out;
1875     codegen_output_type(this, *out);
1876
1877     return true;
1878 }
1879
1880 bool ast_binstore::codegen(ast_function *func, bool lvalue, ir_value **out)
1881 {
1882     ir_value *leftl = nullptr, *leftr, *right, *bin;
1883
1884     ast_value       *arr;
1885     ast_value       *idx = 0;
1886     ast_array_index *ai = nullptr;
1887     ir_value        *iridx = nullptr;
1888
1889     if (lvalue && m_outl) {
1890         *out = m_outl;
1891         return true;
1892     }
1893
1894     if (!lvalue && m_outr) {
1895         *out = m_outr;
1896         return true;
1897     }
1898
1899     if (ast_istype(m_dest, ast_array_index))
1900     {
1901
1902         ai = (ast_array_index*)m_dest;
1903         idx = (ast_value*)ai->m_index;
1904
1905         if (ast_istype(ai->m_index, ast_value) && idx->m_hasvalue && idx->m_cvq == CV_CONST)
1906             ai = nullptr;
1907     }
1908
1909     /* for a binstore we need both an lvalue and an rvalue for the left side */
1910     /* rvalue of destination! */
1911     if (ai) {
1912         if (!idx->codegen(func, false, &iridx))
1913             return false;
1914     }
1915     if (!m_dest->codegen(func, false, &leftr))
1916         return false;
1917
1918     /* source as rvalue only */
1919     if (!m_source->codegen(func, false, &right))
1920         return false;
1921
1922     /* now the binary */
1923     bin = ir_block_create_binop(func->m_curblock, m_context, func->makeLabel("binst"),
1924                                 m_opbin, leftr, right);
1925     m_outr = bin;
1926
1927     if (ai) {
1928         /* we need to call the setter */
1929         ir_value  *funval;
1930         ir_instr  *call;
1931
1932         if (lvalue) {
1933             compile_error(m_context, "array-subscript assignment cannot produce lvalues");
1934             return false;
1935         }
1936
1937         arr = (ast_value*)ai->m_array;
1938         if (!ast_istype(ai->m_array, ast_value) || !arr->m_setter) {
1939             compile_error(m_context, "value has no setter (%s)", arr->m_name);
1940             return false;
1941         }
1942
1943         if (!arr->m_setter->codegen(func, true, &funval))
1944             return false;
1945
1946         call = ir_block_create_call(func->m_curblock, m_context, func->makeLabel("store"), funval, false);
1947         if (!call)
1948             return false;
1949         ir_call_param(call, iridx);
1950         ir_call_param(call, bin);
1951         m_outr = bin;
1952     } else {
1953         // now store them
1954         // lvalue of destination
1955         if (!m_dest->codegen(func, true, &leftl))
1956             return false;
1957         m_outl = leftl;
1958
1959         if (!ir_block_create_store_op(func->m_curblock, m_context, m_opstore, leftl, bin))
1960             return false;
1961         m_outr = bin;
1962     }
1963
1964     /* Theoretically, an assinment returns its left side as an
1965      * lvalue, if we don't need an lvalue though, we return
1966      * the right side as an rvalue, otherwise we have to
1967      * somehow know whether or not we need to dereference the pointer
1968      * on the left side - that is: OP_LOAD if it was an address.
1969      * Also: in original QC we cannot OP_LOADP *anyway*.
1970      */
1971     *out = (lvalue ? leftl : bin);
1972
1973     return true;
1974 }
1975
1976 bool ast_unary::codegen(ast_function *func, bool lvalue, ir_value **out)
1977 {
1978     ir_value *operand;
1979
1980     /* An unary operation cannot yield an l-value */
1981     if (lvalue) {
1982         compile_error(m_context, "not an l-value (binop)");
1983         return false;
1984     }
1985
1986     if (m_outr) {
1987         *out = m_outr;
1988         return true;
1989     }
1990
1991     /* lvalue! */
1992     if (!m_operand->codegen(func, false, &operand))
1993         return false;
1994
1995     *out = ir_block_create_unary(func->m_curblock, m_context, func->makeLabel("unary"),
1996                                  m_op, operand);
1997     if (!*out)
1998         return false;
1999     m_outr = *out;
2000
2001     return true;
2002 }
2003
2004 bool ast_return::codegen(ast_function *func, bool lvalue, ir_value **out)
2005 {
2006     ir_value *operand;
2007
2008     *out = nullptr;
2009
2010     /* In the context of a return operation, we don't actually return
2011      * anything...
2012      */
2013     if (lvalue) {
2014         compile_error(m_context, "return-expression is not an l-value");
2015         return false;
2016     }
2017
2018     if (m_outr) {
2019         compile_error(m_context, "internal error: ast_return cannot be reused, it bears no result!");
2020         return false;
2021     }
2022     m_outr = (ir_value*)1;
2023
2024     if (m_operand) {
2025         /* lvalue! */
2026         if (!m_operand->codegen(func, false, &operand))
2027             return false;
2028
2029         if (!ir_block_create_return(func->m_curblock, m_context, operand))
2030             return false;
2031     } else {
2032         if (!ir_block_create_return(func->m_curblock, m_context, nullptr))
2033             return false;
2034     }
2035
2036     return true;
2037 }
2038
2039 bool ast_entfield::codegen(ast_function *func, bool lvalue, ir_value **out)
2040 {
2041     ir_value *ent, *field;
2042
2043     // This function needs to take the 'lvalue' flag into account!
2044     // As lvalue we provide a field-pointer, as rvalue we provide the
2045     // value in a temp.
2046
2047     if (lvalue && m_outl) {
2048         *out = m_outl;
2049         return true;
2050     }
2051
2052     if (!lvalue && m_outr) {
2053         *out = m_outr;
2054         return true;
2055     }
2056
2057     if (!m_entity->codegen(func, false, &ent))
2058         return false;
2059
2060     if (!m_field->codegen(func, false, &field))
2061         return false;
2062
2063     if (lvalue) {
2064         /* address! */
2065         *out = ir_block_create_fieldaddress(func->m_curblock, m_context, func->makeLabel("efa"),
2066                                             ent, field);
2067     } else {
2068         *out = ir_block_create_load_from_ent(func->m_curblock, m_context, func->makeLabel("efv"),
2069                                              ent, field, m_vtype);
2070         /* Done AFTER error checking:
2071         codegen_output_type(this, *out);
2072         */
2073     }
2074     if (!*out) {
2075         compile_error(m_context, "failed to create %s instruction (output type %s)",
2076                  (lvalue ? "ADDRESS" : "FIELD"),
2077                  type_name[m_vtype]);
2078         return false;
2079     }
2080     if (!lvalue)
2081         codegen_output_type(this, *out);
2082
2083     if (lvalue)
2084         m_outl = *out;
2085     else
2086         m_outr = *out;
2087
2088     // Hm that should be it...
2089     return true;
2090 }
2091
2092 bool ast_member::codegen(ast_function *func, bool lvalue, ir_value **out)
2093 {
2094     ir_value *vec;
2095
2096     /* in QC this is always an lvalue */
2097     if (lvalue && m_rvalue) {
2098         compile_error(m_context, "not an l-value (member access)");
2099         return false;
2100     }
2101     if (lvalue && m_outl) {
2102         *out = m_outl;
2103         return true;
2104     }
2105     if (!lvalue && m_outr) {
2106         *out = m_outr;
2107         return true;
2108     }
2109
2110     if (ast_istype(m_owner, ast_entfield)) {
2111         ir_value *ent, *field;
2112         auto entfield = reinterpret_cast<ast_entfield*>(m_owner);
2113         if (!entfield->m_entity->codegen(func, false, &ent))
2114             return false;
2115         if (!entfield->m_field->codegen(func, false, &vec))
2116             return false;
2117         field = vec->vectorMember(m_field);
2118         if (lvalue) {
2119             *out = ir_block_create_fieldaddress(func->m_curblock, m_context, func->makeLabel("mefa"),
2120                                                 ent, field);
2121         } else {
2122             *out = ir_block_create_load_from_ent(func->m_curblock, m_context, func->makeLabel("mefv"),
2123                                                  ent, field, m_vtype);
2124         }
2125         if (!*out) {
2126             compile_error(m_context, "failed to create %s instruction (output type %s)",
2127                      (lvalue ? "ADDRESS" : "FIELD"),
2128                      type_name[m_vtype]);
2129             return false;
2130         }
2131         if (lvalue)
2132             m_outl = *out;
2133         else
2134             m_outr = *out;
2135         return (*out != nullptr);
2136     } else {
2137         if (!m_owner->codegen(func, false, &vec))
2138             return false;
2139     }
2140
2141     if (vec->m_vtype != TYPE_VECTOR &&
2142         !(vec->m_vtype == TYPE_FIELD && m_owner->m_next->m_vtype == TYPE_VECTOR))
2143     {
2144         return false;
2145     }
2146
2147     *out = vec->vectorMember(m_field);
2148     m_outl = *out;
2149
2150     return (*out != nullptr);
2151 }
2152
2153 bool ast_array_index::codegen(ast_function *func, bool lvalue, ir_value **out)
2154 {
2155     ast_value *arr;
2156     ast_value *idx;
2157
2158     if (!lvalue && m_outr) {
2159         *out = m_outr;
2160         return true;
2161     }
2162     if (lvalue && m_outl) {
2163         *out = m_outl;
2164         return true;
2165     }
2166
2167     if (!ast_istype(m_array, ast_value)) {
2168         compile_error(m_context, "array indexing this way is not supported");
2169         /* note this would actually be pointer indexing because the left side is
2170          * not an actual array but (hopefully) an indexable expression.
2171          * Once we get integer arithmetic, and GADDRESS/GSTORE/GLOAD instruction
2172          * support this path will be filled.
2173          */
2174         return false;
2175     }
2176
2177     arr = reinterpret_cast<ast_value*>(m_array);
2178     idx = reinterpret_cast<ast_value*>(m_index);
2179
2180     if (!ast_istype(m_index, ast_value) || !idx->m_hasvalue || idx->m_cvq != CV_CONST) {
2181         /* Time to use accessor functions */
2182         ir_value               *iridx, *funval;
2183         ir_instr               *call;
2184
2185         if (lvalue) {
2186             compile_error(m_context, "(.2) array indexing here needs a compile-time constant");
2187             return false;
2188         }
2189
2190         if (!arr->m_getter) {
2191             compile_error(m_context, "value has no getter, don't know how to index it");
2192             return false;
2193         }
2194
2195         if (!m_index->codegen(func, false, &iridx))
2196             return false;
2197
2198         if (!arr->m_getter->codegen(func, true, &funval))
2199             return false;
2200
2201         call = ir_block_create_call(func->m_curblock, m_context, func->makeLabel("fetch"), funval, false);
2202         if (!call)
2203             return false;
2204         ir_call_param(call, iridx);
2205
2206         *out = ir_call_value(call);
2207         m_outr = *out;
2208         (*out)->m_vtype = m_vtype;
2209         codegen_output_type(this, *out);
2210         return true;
2211     }
2212
2213     if (idx->m_vtype == TYPE_FLOAT) {
2214         unsigned int arridx = idx->m_constval.vfloat;
2215         if (arridx >= m_array->m_count)
2216         {
2217             compile_error(m_context, "array index out of bounds: %i", arridx);
2218             return false;
2219         }
2220         *out = arr->m_ir_values[arridx];
2221     }
2222     else if (idx->m_vtype == TYPE_INTEGER) {
2223         unsigned int arridx = idx->m_constval.vint;
2224         if (arridx >= m_array->m_count)
2225         {
2226             compile_error(m_context, "array index out of bounds: %i", arridx);
2227             return false;
2228         }
2229         *out = arr->m_ir_values[arridx];
2230     }
2231     else {
2232         compile_error(m_context, "array indexing here needs an integer constant");
2233         return false;
2234     }
2235     (*out)->m_vtype = m_vtype;
2236     codegen_output_type(this, *out);
2237     return true;
2238 }
2239
2240 bool ast_argpipe::codegen(ast_function *func, bool lvalue, ir_value **out)
2241 {
2242     *out = nullptr;
2243     if (lvalue) {
2244         compile_error(m_context, "argpipe node: not an lvalue");
2245         return false;
2246     }
2247     (void)func;
2248     (void)out;
2249     compile_error(m_context, "TODO: argpipe codegen not implemented");
2250     return false;
2251 }
2252
2253 bool ast_ifthen::codegen(ast_function *func, bool lvalue, ir_value **out)
2254 {
2255     ir_value *condval;
2256     ir_value *dummy;
2257
2258     ir_block *cond;
2259     ir_block *ontrue;
2260     ir_block *onfalse;
2261     ir_block *ontrue_endblock = nullptr;
2262     ir_block *onfalse_endblock = nullptr;
2263     ir_block *merge = nullptr;
2264     int folded = 0;
2265
2266     /* We don't output any value, thus also don't care about r/lvalue */
2267     (void)out;
2268     (void)lvalue;
2269
2270     if (m_outr) {
2271         compile_error(m_context, "internal error: ast_ifthen cannot be reused, it bears no result!");
2272         return false;
2273     }
2274     m_outr = (ir_value*)1;
2275
2276     /* generate the condition */
2277     if (!m_cond->codegen(func, false, &condval))
2278         return false;
2279     /* update the block which will get the jump - because short-logic or ternaries may have changed this */
2280     cond = func->m_curblock;
2281
2282     /* try constant folding away the condition */
2283     if ((folded = fold::cond_ifthen(condval, func, this)) != -1)
2284         return folded;
2285
2286     if (m_on_true) {
2287         /* create on-true block */
2288         ontrue = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("ontrue"));
2289         if (!ontrue)
2290             return false;
2291
2292         /* enter the block */
2293         func->m_curblock = ontrue;
2294
2295         /* generate */
2296         if (!m_on_true->codegen(func, false, &dummy))
2297             return false;
2298
2299         /* we now need to work from the current endpoint */
2300         ontrue_endblock = func->m_curblock;
2301     } else
2302         ontrue = nullptr;
2303
2304     /* on-false path */
2305     if (m_on_false) {
2306         /* create on-false block */
2307         onfalse = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("onfalse"));
2308         if (!onfalse)
2309             return false;
2310
2311         /* enter the block */
2312         func->m_curblock = onfalse;
2313
2314         /* generate */
2315         if (!m_on_false->codegen(func, false, &dummy))
2316             return false;
2317
2318         /* we now need to work from the current endpoint */
2319         onfalse_endblock = func->m_curblock;
2320     } else
2321         onfalse = nullptr;
2322
2323     /* Merge block were they all merge in to */
2324     if (!ontrue || !onfalse || !ontrue_endblock->m_final || !onfalse_endblock->m_final)
2325     {
2326         merge = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("endif"));
2327         if (!merge)
2328             return false;
2329         /* add jumps ot the merge block */
2330         if (ontrue && !ontrue_endblock->m_final && !ir_block_create_jump(ontrue_endblock, m_context, merge))
2331             return false;
2332         if (onfalse && !onfalse_endblock->m_final && !ir_block_create_jump(onfalse_endblock, m_context, merge))
2333             return false;
2334
2335         /* Now enter the merge block */
2336         func->m_curblock = merge;
2337     }
2338
2339     /* we create the if here, that way all blocks are ordered :)
2340      */
2341     if (!ir_block_create_if(cond, m_context, condval,
2342                             (ontrue  ? ontrue  : merge),
2343                             (onfalse ? onfalse : merge)))
2344     {
2345         return false;
2346     }
2347
2348     return true;
2349 }
2350
2351 bool ast_ternary::codegen(ast_function *func, bool lvalue, ir_value **out)
2352 {
2353     ir_value *condval;
2354     ir_value *trueval, *falseval;
2355     ir_instr *phi;
2356
2357     ir_block *cond = func->m_curblock;
2358     ir_block *cond_out = nullptr;
2359     ir_block *ontrue, *ontrue_out = nullptr;
2360     ir_block *onfalse, *onfalse_out = nullptr;
2361     ir_block *merge;
2362     int folded = 0;
2363
2364     /* Ternary can never create an lvalue... */
2365     if (lvalue)
2366         return false;
2367
2368     /* In theory it shouldn't be possible to pass through a node twice, but
2369      * in case we add any kind of optimization pass for the AST itself, it
2370      * may still happen, thus we remember a created ir_value and simply return one
2371      * if it already exists.
2372      */
2373     if (m_outr) {
2374         *out = m_outr;
2375         return true;
2376     }
2377
2378     /* In the following, contraty to ast_ifthen, we assume both paths exist. */
2379
2380     /* generate the condition */
2381     func->m_curblock = cond;
2382     if (!m_cond->codegen(func, false, &condval))
2383         return false;
2384     cond_out = func->m_curblock;
2385
2386     /* try constant folding away the condition */
2387     if ((folded = fold::cond_ternary(condval, func, this)) != -1)
2388         return folded;
2389
2390     /* create on-true block */
2391     ontrue = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("tern_T"));
2392     if (!ontrue)
2393         return false;
2394     else
2395     {
2396         /* enter the block */
2397         func->m_curblock = ontrue;
2398
2399         /* generate */
2400         if (!m_on_true->codegen(func, false, &trueval))
2401             return false;
2402
2403         ontrue_out = func->m_curblock;
2404     }
2405
2406     /* create on-false block */
2407     onfalse = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("tern_F"));
2408     if (!onfalse)
2409         return false;
2410     else
2411     {
2412         /* enter the block */
2413         func->m_curblock = onfalse;
2414
2415         /* generate */
2416         if (!m_on_false->codegen(func, false, &falseval))
2417             return false;
2418
2419         onfalse_out = func->m_curblock;
2420     }
2421
2422     /* create merge block */
2423     merge = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("tern_out"));
2424     if (!merge)
2425         return false;
2426     /* jump to merge block */
2427     if (!ir_block_create_jump(ontrue_out, m_context, merge))
2428         return false;
2429     if (!ir_block_create_jump(onfalse_out, m_context, merge))
2430         return false;
2431
2432     /* create if instruction */
2433     if (!ir_block_create_if(cond_out, m_context, condval, ontrue, onfalse))
2434         return false;
2435
2436     /* Now enter the merge block */
2437     func->m_curblock = merge;
2438
2439     /* Here, now, we need a PHI node
2440      * but first some sanity checking...
2441      */
2442     if (trueval->m_vtype != falseval->m_vtype && trueval->m_vtype != TYPE_NIL && falseval->m_vtype != TYPE_NIL) {
2443         /* error("ternary with different types on the two sides"); */
2444         compile_error(m_context, "internal error: ternary operand types invalid");
2445         return false;
2446     }
2447
2448     /* create PHI */
2449     phi = ir_block_create_phi(merge, m_context, func->makeLabel("phi"), m_vtype);
2450     if (!phi) {
2451         compile_error(m_context, "internal error: failed to generate phi node");
2452         return false;
2453     }
2454     ir_phi_add(phi, ontrue_out,  trueval);
2455     ir_phi_add(phi, onfalse_out, falseval);
2456
2457     m_outr = ir_phi_value(phi);
2458     *out = m_outr;
2459
2460     codegen_output_type(this, *out);
2461
2462     return true;
2463 }
2464
2465 bool ast_loop::codegen(ast_function *func, bool lvalue, ir_value **out)
2466 {
2467     ir_value *dummy      = nullptr;
2468     ir_value *precond    = nullptr;
2469     ir_value *postcond   = nullptr;
2470
2471     /* Since we insert some jumps "late" so we have blocks
2472      * ordered "nicely", we need to keep track of the actual end-blocks
2473      * of expressions to add the jumps to.
2474      */
2475     ir_block *bbody      = nullptr, *end_bbody      = nullptr;
2476     ir_block *bprecond   = nullptr, *end_bprecond   = nullptr;
2477     ir_block *bpostcond  = nullptr, *end_bpostcond  = nullptr;
2478     ir_block *bincrement = nullptr, *end_bincrement = nullptr;
2479     ir_block *bout       = nullptr, *bin            = nullptr;
2480
2481     /* let's at least move the outgoing block to the end */
2482     size_t    bout_id;
2483
2484     /* 'break' and 'continue' need to be able to find the right blocks */
2485     ir_block *bcontinue     = nullptr;
2486     ir_block *bbreak        = nullptr;
2487
2488     ir_block *tmpblock      = nullptr;
2489
2490     (void)lvalue;
2491     (void)out;
2492
2493     if (m_outr) {
2494         compile_error(m_context, "internal error: ast_loop cannot be reused, it bears no result!");
2495         return false;
2496     }
2497     m_outr = (ir_value*)1;
2498
2499     /* NOTE:
2500      * Should we ever need some kind of block ordering, better make this function
2501      * move blocks around than write a block ordering algorithm later... after all
2502      * the ast and ir should work together, not against each other.
2503      */
2504
2505     /* initexpr doesn't get its own block, it's pointless, it could create more blocks
2506      * anyway if for example it contains a ternary.
2507      */
2508     if (m_initexpr)
2509     {
2510         if (!m_initexpr->codegen(func, false, &dummy))
2511             return false;
2512     }
2513
2514     /* Store the block from which we enter this chaos */
2515     bin = func->m_curblock;
2516
2517     /* The pre-loop condition needs its own block since we
2518      * need to be able to jump to the start of that expression.
2519      */
2520     if (m_precond)
2521     {
2522         bprecond = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("pre_loop_cond"));
2523         if (!bprecond)
2524             return false;
2525
2526         /* the pre-loop-condition the least important place to 'continue' at */
2527         bcontinue = bprecond;
2528
2529         /* enter */
2530         func->m_curblock = bprecond;
2531
2532         /* generate */
2533         if (!m_precond->codegen(func, false, &precond))
2534             return false;
2535
2536         end_bprecond = func->m_curblock;
2537     } else {
2538         bprecond = end_bprecond = nullptr;
2539     }
2540
2541     /* Now the next blocks won't be ordered nicely, but we need to
2542      * generate them this early for 'break' and 'continue'.
2543      */
2544     if (m_increment) {
2545         bincrement = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("loop_increment"));
2546         if (!bincrement)
2547             return false;
2548         bcontinue = bincrement; /* increment comes before the pre-loop-condition */
2549     } else {
2550         bincrement = end_bincrement = nullptr;
2551     }
2552
2553     if (m_postcond) {
2554         bpostcond = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("post_loop_cond"));
2555         if (!bpostcond)
2556             return false;
2557         bcontinue = bpostcond; /* postcond comes before the increment */
2558     } else {
2559         bpostcond = end_bpostcond = nullptr;
2560     }
2561
2562     bout_id = func->m_ir_func->m_blocks.size();
2563     bout = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("after_loop"));
2564     if (!bout)
2565         return false;
2566     bbreak = bout;
2567
2568     /* The loop body... */
2569     /* if (m_body) */
2570     {
2571         bbody = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("loop_body"));
2572         if (!bbody)
2573             return false;
2574
2575         /* enter */
2576         func->m_curblock = bbody;
2577
2578         func->m_breakblocks.push_back(bbreak);
2579         if (bcontinue)
2580             func->m_continueblocks.push_back(bcontinue);
2581         else
2582             func->m_continueblocks.push_back(bbody);
2583
2584         /* generate */
2585         if (m_body) {
2586             if (!m_body->codegen(func, false, &dummy))
2587                 return false;
2588         }
2589
2590         end_bbody = func->m_curblock;
2591         func->m_breakblocks.pop_back();
2592         func->m_continueblocks.pop_back();
2593     }
2594
2595     /* post-loop-condition */
2596     if (m_postcond)
2597     {
2598         /* enter */
2599         func->m_curblock = bpostcond;
2600
2601         /* generate */
2602         if (!m_postcond->codegen(func, false, &postcond))
2603             return false;
2604
2605         end_bpostcond = func->m_curblock;
2606     }
2607
2608     /* The incrementor */
2609     if (m_increment)
2610     {
2611         /* enter */
2612         func->m_curblock = bincrement;
2613
2614         /* generate */
2615         if (!m_increment->codegen(func, false, &dummy))
2616             return false;
2617
2618         end_bincrement = func->m_curblock;
2619     }
2620
2621     /* In any case now, we continue from the outgoing block */
2622     func->m_curblock = bout;
2623
2624     /* Now all blocks are in place */
2625     /* From 'bin' we jump to whatever comes first */
2626     if      (bprecond)   tmpblock = bprecond;
2627     else                 tmpblock = bbody;    /* can never be null */
2628
2629     /* DEAD CODE
2630     else if (bpostcond)  tmpblock = bpostcond;
2631     else                 tmpblock = bout;
2632     */
2633
2634     if (!ir_block_create_jump(bin, m_context, tmpblock))
2635         return false;
2636
2637     /* From precond */
2638     if (bprecond)
2639     {
2640         ir_block *ontrue, *onfalse;
2641         ontrue = bbody; /* can never be null */
2642
2643         /* all of this is dead code
2644         else if (bincrement) ontrue = bincrement;
2645         else                 ontrue = bpostcond;
2646         */
2647
2648         onfalse = bout;
2649         if (m_pre_not) {
2650             tmpblock = ontrue;
2651             ontrue   = onfalse;
2652             onfalse  = tmpblock;
2653         }
2654         if (!ir_block_create_if(end_bprecond, m_context, precond, ontrue, onfalse))
2655             return false;
2656     }
2657
2658     /* from body */
2659     if (bbody)
2660     {
2661         if      (bincrement) tmpblock = bincrement;
2662         else if (bpostcond)  tmpblock = bpostcond;
2663         else if (bprecond)   tmpblock = bprecond;
2664         else                 tmpblock = bbody;
2665         if (!end_bbody->m_final && !ir_block_create_jump(end_bbody, m_context, tmpblock))
2666             return false;
2667     }
2668
2669     /* from increment */
2670     if (bincrement)
2671     {
2672         if      (bpostcond)  tmpblock = bpostcond;
2673         else if (bprecond)   tmpblock = bprecond;
2674         else if (bbody)      tmpblock = bbody;
2675         else                 tmpblock = bout;
2676         if (!ir_block_create_jump(end_bincrement, m_context, tmpblock))
2677             return false;
2678     }
2679
2680     /* from postcond */
2681     if (bpostcond)
2682     {
2683         ir_block *ontrue, *onfalse;
2684         if      (bprecond)   ontrue = bprecond;
2685         else                 ontrue = bbody; /* can never be null */
2686
2687         /* all of this is dead code
2688         else if (bincrement) ontrue = bincrement;
2689         else                 ontrue = bpostcond;
2690         */
2691
2692         onfalse = bout;
2693         if (m_post_not) {
2694             tmpblock = ontrue;
2695             ontrue   = onfalse;
2696             onfalse  = tmpblock;
2697         }
2698         if (!ir_block_create_if(end_bpostcond, m_context, postcond, ontrue, onfalse))
2699             return false;
2700     }
2701
2702     /* Move 'bout' to the end */
2703     algo::shiftback(func->m_ir_func->m_blocks.begin() + bout_id,
2704                     func->m_ir_func->m_blocks.end());
2705     // FIXME::DELME::
2706     //func->m_ir_func->m_blocks[bout_id].release(); // it's a vector<std::unique_ptr<>>
2707     //func->m_ir_func->m_blocks.erase(func->m_ir_func->m_blocks.begin() + bout_id);
2708     //func->m_ir_func->m_blocks.emplace_back(bout);
2709
2710     return true;
2711 }
2712
2713 bool ast_breakcont::codegen(ast_function *func, bool lvalue, ir_value **out)
2714 {
2715     ir_block *target;
2716
2717     *out = nullptr;
2718
2719     if (lvalue) {
2720         compile_error(m_context, "break/continue expression is not an l-value");
2721         return false;
2722     }
2723
2724     if (m_outr) {
2725         compile_error(m_context, "internal error: ast_breakcont cannot be reused!");
2726         return false;
2727     }
2728     m_outr = (ir_value*)1;
2729
2730     if (m_is_continue)
2731         target = func->m_continueblocks[func->m_continueblocks.size()-1-m_levels];
2732     else
2733         target = func->m_breakblocks[func->m_breakblocks.size()-1-m_levels];
2734
2735     if (!target) {
2736         compile_error(m_context, "%s is lacking a target block", (m_is_continue ? "continue" : "break"));
2737         return false;
2738     }
2739
2740     if (!ir_block_create_jump(func->m_curblock, m_context, target))
2741         return false;
2742     return true;
2743 }
2744
2745 bool ast_switch::codegen(ast_function *func, bool lvalue, ir_value **out)
2746 {
2747     ast_switch_case *def_case     = nullptr;
2748     ir_block        *def_bfall    = nullptr;
2749     ir_block        *def_bfall_to = nullptr;
2750     bool set_def_bfall_to = false;
2751
2752     ir_value *dummy     = nullptr;
2753     ir_value *irop      = nullptr;
2754     ir_block *bout      = nullptr;
2755     ir_block *bfall     = nullptr;
2756     size_t    bout_id;
2757
2758     char      typestr[1024];
2759     uint16_t  cmpinstr;
2760
2761     if (lvalue) {
2762         compile_error(m_context, "switch expression is not an l-value");
2763         return false;
2764     }
2765
2766     if (m_outr) {
2767         compile_error(m_context, "internal error: ast_switch cannot be reused!");
2768         return false;
2769     }
2770     m_outr = (ir_value*)1;
2771
2772     (void)lvalue;
2773     (void)out;
2774
2775     if (!m_operand->codegen(func, false, &irop))
2776         return false;
2777
2778     if (m_cases.empty())
2779         return true;
2780
2781     cmpinstr = type_eq_instr[irop->m_vtype];
2782     if (cmpinstr >= VINSTR_END) {
2783         ast_type_to_string(m_operand, typestr, sizeof(typestr));
2784         compile_error(m_context, "invalid type to perform a switch on: %s", typestr);
2785         return false;
2786     }
2787
2788     bout_id = func->m_ir_func->m_blocks.size();
2789     bout = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("after_switch"));
2790     if (!bout)
2791         return false;
2792
2793     /* setup the break block */
2794     func->m_breakblocks.push_back(bout);
2795
2796     /* Now create all cases */
2797     for (auto &it : m_cases) {
2798         ir_value *cond, *val;
2799         ir_block *bcase, *bnot;
2800         size_t bnot_id;
2801
2802         ast_switch_case *swcase = &it;
2803
2804         if (swcase->m_value) {
2805             /* A regular case */
2806             /* generate the condition operand */
2807             if (!swcase->m_value->codegen(func, false, &val))
2808                 return false;
2809             /* generate the condition */
2810             cond = ir_block_create_binop(func->m_curblock, m_context, func->makeLabel("switch_eq"), cmpinstr, irop, val);
2811             if (!cond)
2812                 return false;
2813
2814             bcase = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("case"));
2815             bnot_id = func->m_ir_func->m_blocks.size();
2816             bnot = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("not_case"));
2817             if (!bcase || !bnot)
2818                 return false;
2819             if (set_def_bfall_to) {
2820                 set_def_bfall_to = false;
2821                 def_bfall_to = bcase;
2822             }
2823             if (!ir_block_create_if(func->m_curblock, m_context, cond, bcase, bnot))
2824                 return false;
2825
2826             /* Make the previous case-end fall through */
2827             if (bfall && !bfall->m_final) {
2828                 if (!ir_block_create_jump(bfall, m_context, bcase))
2829                     return false;
2830             }
2831
2832             /* enter the case */
2833             func->m_curblock = bcase;
2834             if (!swcase->m_code->codegen(func, false, &dummy))
2835                 return false;
2836
2837             /* remember this block to fall through from */
2838             bfall = func->m_curblock;
2839
2840             /* enter the else and move it down */
2841             func->m_curblock = bnot;
2842             algo::shiftback(func->m_ir_func->m_blocks.begin() + bnot_id,
2843                             func->m_ir_func->m_blocks.end());
2844             // FIXME::DELME::
2845             //func->m_ir_func->m_blocks[bnot_id].release();
2846             //func->m_ir_func->m_blocks.erase(func->m_ir_func->m_blocks.begin() + bnot_id);
2847             //func->m_ir_func->m_blocks.emplace_back(bnot);
2848         } else {
2849             /* The default case */
2850             /* Remember where to fall through from: */
2851             def_bfall = bfall;
2852             bfall     = nullptr;
2853             /* remember which case it was */
2854             def_case  = swcase;
2855             /* And the next case will be remembered */
2856             set_def_bfall_to = true;
2857         }
2858     }
2859
2860     /* Jump from the last bnot to bout */
2861     if (bfall && !bfall->m_final && !ir_block_create_jump(bfall, m_context, bout)) {
2862         /*
2863         astwarning(bfall->m_context, WARN_???, "missing break after last case");
2864         */
2865         return false;
2866     }
2867
2868     /* If there was a default case, put it down here */
2869     if (def_case) {
2870         ir_block *bcase;
2871
2872         /* No need to create an extra block */
2873         bcase = func->m_curblock;
2874
2875         /* Insert the fallthrough jump */
2876         if (def_bfall && !def_bfall->m_final) {
2877             if (!ir_block_create_jump(def_bfall, m_context, bcase))
2878                 return false;
2879         }
2880
2881         /* Now generate the default code */
2882         if (!def_case->m_code->codegen(func, false, &dummy))
2883             return false;
2884
2885         /* see if we need to fall through */
2886         if (def_bfall_to && !func->m_curblock->m_final)
2887         {
2888             if (!ir_block_create_jump(func->m_curblock, m_context, def_bfall_to))
2889                 return false;
2890         }
2891     }
2892
2893     /* Jump from the last bnot to bout */
2894     if (!func->m_curblock->m_final && !ir_block_create_jump(func->m_curblock, m_context, bout))
2895         return false;
2896     /* enter the outgoing block */
2897     func->m_curblock = bout;
2898
2899     /* restore the break block */
2900     func->m_breakblocks.pop_back();
2901
2902     /* Move 'bout' to the end, it's nicer */
2903     algo::shiftback(func->m_ir_func->m_blocks.begin() + bout_id,
2904                     func->m_ir_func->m_blocks.end());
2905     // FIXME::DELME::
2906     //func->m_ir_func->m_blocks[bout_id].release();
2907     //func->m_ir_func->m_blocks.erase(func->m_ir_func->m_blocks.begin() + bout_id);
2908     //func->m_ir_func->m_blocks.emplace_back(bout);
2909
2910     return true;
2911 }
2912
2913 bool ast_label::codegen(ast_function *func, bool lvalue, ir_value **out)
2914 {
2915     ir_value *dummy;
2916
2917     if (m_undefined) {
2918         compile_error(m_context, "internal error: ast_label never defined");
2919         return false;
2920     }
2921
2922     *out = nullptr;
2923     if (lvalue) {
2924         compile_error(m_context, "internal error: ast_label cannot be an lvalue");
2925         return false;
2926     }
2927
2928     /* simply create a new block and jump to it */
2929     m_irblock = ir_function_create_block(m_context, func->m_ir_func, m_name.c_str());
2930     if (!m_irblock) {
2931         compile_error(m_context, "failed to allocate label block `%s`", m_name);
2932         return false;
2933     }
2934     if (!func->m_curblock->m_final) {
2935         if (!ir_block_create_jump(func->m_curblock, m_context, m_irblock))
2936             return false;
2937     }
2938
2939     /* enter the new block */
2940     func->m_curblock = m_irblock;
2941
2942     /* Generate all the leftover gotos */
2943     for (auto &it : m_gotos) {
2944         if (!it->codegen(func, false, &dummy))
2945             return false;
2946     }
2947
2948     return true;
2949 }
2950
2951 bool ast_goto::codegen(ast_function *func, bool lvalue, ir_value **out)
2952 {
2953     *out = nullptr;
2954     if (lvalue) {
2955         compile_error(m_context, "internal error: ast_goto cannot be an lvalue");
2956         return false;
2957     }
2958
2959     if (m_target->m_irblock) {
2960         if (m_irblock_from) {
2961             /* we already tried once, this is the callback */
2962             m_irblock_from->m_final = false;
2963             if (!ir_block_create_goto(m_irblock_from, m_context, m_target->m_irblock)) {
2964                 compile_error(m_context, "failed to generate goto to `%s`", m_name);
2965                 return false;
2966             }
2967         }
2968         else
2969         {
2970             if (!ir_block_create_goto(func->m_curblock, m_context, m_target->m_irblock)) {
2971                 compile_error(m_context, "failed to generate goto to `%s`", m_name);
2972                 return false;
2973             }
2974         }
2975     }
2976     else
2977     {
2978         /* the target has not yet been created...
2979          * close this block in a sneaky way:
2980          */
2981         func->m_curblock->m_final = true;
2982         m_irblock_from = func->m_curblock;
2983         m_target->registerGoto(this);
2984     }
2985
2986     return true;
2987 }
2988
2989 bool ast_state::codegen(ast_function *func, bool lvalue, ir_value **out)
2990 {
2991     ir_value *frameval, *thinkval;
2992
2993     if (lvalue) {
2994         compile_error(m_context, "not an l-value (state operation)");
2995         return false;
2996     }
2997     if (m_outr) {
2998         compile_error(m_context, "internal error: ast_state cannot be reused!");
2999         return false;
3000     }
3001     *out = nullptr;
3002
3003     if (!m_framenum->codegen(func, false, &frameval))
3004         return false;
3005     if (!frameval)
3006         return false;
3007
3008     if (!m_nextthink->codegen(func, false, &thinkval))
3009         return false;
3010     if (!frameval)
3011         return false;
3012
3013     if (!ir_block_create_state_op(func->m_curblock, m_context, frameval, thinkval)) {
3014         compile_error(m_context, "failed to create STATE instruction");
3015         return false;
3016     }
3017
3018     m_outr = (ir_value*)1;
3019     return true;
3020 }
3021
3022 bool ast_call::codegen(ast_function *func, bool lvalue, ir_value **out)
3023 {
3024     std::vector<ir_value*> params;
3025     ir_instr *callinstr;
3026
3027     ir_value *funval = nullptr;
3028
3029     /* return values are never lvalues */
3030     if (lvalue) {
3031         compile_error(m_context, "not an l-value (function call)");
3032         return false;
3033     }
3034
3035     if (m_outr) {
3036         *out = m_outr;
3037         return true;
3038     }
3039
3040     if (!m_func->codegen(func, false, &funval))
3041         return false;
3042     if (!funval)
3043         return false;
3044
3045     /* parameters */
3046     for (auto &it : m_params) {
3047         ir_value *param;
3048         if (!it->codegen(func, false, &param))
3049             return false;
3050         if (!param)
3051             return false;
3052         params.push_back(param);
3053     }
3054
3055     /* varargs counter */
3056     if (m_va_count) {
3057         ir_value   *va_count;
3058         ir_builder *builder = func->m_curblock->m_owner->m_owner;
3059         if (!m_va_count->codegen(func, false, &va_count))
3060             return false;
3061         if (!ir_block_create_store_op(func->m_curblock, m_context, INSTR_STORE_F,
3062                                       builder->get_va_count(), va_count))
3063         {
3064             return false;
3065         }
3066     }
3067
3068     callinstr = ir_block_create_call(func->m_curblock, m_context,
3069                                      func->makeLabel("call"),
3070                                      funval, !!(m_func->m_flags & AST_FLAG_NORETURN));
3071     if (!callinstr)
3072         return false;
3073
3074     for (auto &it : params)
3075         ir_call_param(callinstr, it);
3076
3077     *out = ir_call_value(callinstr);
3078     m_outr = *out;
3079
3080     codegen_output_type(this, *out);
3081
3082     return true;
3083 }