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