13 #define ast_instantiate(T, ctx, destroyfn) \
15 if (!self) return nullptr; \
16 ast_node_init(self, ctx, TYPE_##T); \
17 self->m_destroy = (ast_node_delete*)destroyfn
20 * forward declarations, these need not be in ast.h for obvious
23 static bool ast_member_codegen(ast_member*, ast_function*, bool lvalue, ir_value**);
24 static void ast_array_index_delete(ast_array_index*);
25 static bool ast_array_index_codegen(ast_array_index*, ast_function*, bool lvalue, ir_value**);
26 static void ast_argpipe_delete(ast_argpipe*);
27 static bool ast_argpipe_codegen(ast_argpipe*, ast_function*, bool lvalue, ir_value**);
28 static void ast_store_delete(ast_store*);
29 static bool ast_store_codegen(ast_store*, ast_function*, bool lvalue, ir_value**);
30 static void ast_ifthen_delete(ast_ifthen*);
31 static bool ast_ifthen_codegen(ast_ifthen*, ast_function*, bool lvalue, ir_value**);
32 static void ast_ternary_delete(ast_ternary*);
33 static bool ast_ternary_codegen(ast_ternary*, ast_function*, bool lvalue, ir_value**);
34 static void ast_loop_delete(ast_loop*);
35 static bool ast_loop_codegen(ast_loop*, ast_function*, bool lvalue, ir_value**);
36 static void ast_breakcont_delete(ast_breakcont*);
37 static bool ast_breakcont_codegen(ast_breakcont*, ast_function*, bool lvalue, ir_value**);
38 static void ast_switch_delete(ast_switch*);
39 static bool ast_switch_codegen(ast_switch*, ast_function*, bool lvalue, ir_value**);
40 static void ast_label_delete(ast_label*);
41 static void ast_label_register_goto(ast_label*, ast_goto*);
42 static bool ast_label_codegen(ast_label*, ast_function*, bool lvalue, ir_value**);
43 static bool ast_goto_codegen(ast_goto*, ast_function*, bool lvalue, ir_value**);
44 static void ast_goto_delete(ast_goto*);
45 static void ast_call_delete(ast_call*);
46 static bool ast_call_codegen(ast_call*, ast_function*, bool lvalue, ir_value**);
47 static bool ast_block_codegen(ast_block*, ast_function*, bool lvalue, ir_value**);
48 static void ast_unary_delete(ast_unary*);
49 static bool ast_unary_codegen(ast_unary*, ast_function*, bool lvalue, ir_value**);
50 static void ast_entfield_delete(ast_entfield*);
51 static bool ast_entfield_codegen(ast_entfield*, ast_function*, bool lvalue, ir_value**);
52 static void ast_return_delete(ast_return*);
53 static bool ast_return_codegen(ast_return*, ast_function*, bool lvalue, ir_value**);
54 static void ast_binstore_delete(ast_binstore*);
55 static bool ast_binstore_codegen(ast_binstore*, ast_function*, bool lvalue, ir_value**);
56 static void ast_binary_delete(ast_binary*);
57 static bool ast_binary_codegen(ast_binary*, ast_function*, bool lvalue, ir_value**);
58 static bool ast_state_codegen(ast_state*, ast_function*, bool lvalue, ir_value**);
60 /* It must not be possible to get here. */
61 static GMQCC_NORETURN void _ast_node_destroy(ast_node *self)
64 con_err("ast node missing destroy()\n");
68 /* Initialize main ast node aprts */
69 static void ast_node_init(ast_node *self, lex_ctx_t ctx, int node_type)
71 self->m_context = ctx;
72 self->m_destroy = &_ast_node_destroy;
73 self->m_keep_node = false;
74 self->m_node_type = node_type;
75 self->m_side_effects = false;
78 /* weight and side effects */
79 static void _ast_propagate_effects(ast_node *self, ast_node *other)
81 if (other->m_side_effects)
82 self->m_side_effects = true;
84 #define ast_propagate_effects(s,o) _ast_propagate_effects(((ast_node*)(s)), ((ast_node*)(o)))
86 /* General expression initialization */
87 static void ast_expression_init(ast_expression *self,
88 ast_expression_codegen *codegen)
90 self->m_codegen = codegen;
91 self->m_vtype = TYPE_VOID;
92 self->m_next = nullptr;
93 self->m_outl = nullptr;
94 self->m_outr = nullptr;
96 self->m_varparam = nullptr;
98 if (OPTS_OPTION_BOOL(OPTION_COVERAGE))
99 self->m_flags |= AST_FLAG_BLOCK_COVERAGE;
102 static void ast_expression_delete(ast_expression *self)
105 ast_delete(self->m_next);
106 for (auto &it : self->m_type_params)
108 if (self->m_varparam)
109 ast_delete(self->m_varparam);
112 static void ast_expression_delete_full(ast_expression *self)
114 ast_expression_delete(self);
118 ast_value* ast_value_copy(const ast_value *self)
120 ast_value *cp = ast_value_new(self->m_context, self->m_name, self->m_vtype);
122 cp->m_next = ast_type_copy(self->m_context, self->m_next);
124 const ast_expression *fromex = self;
125 ast_expression *selfex = cp;
126 selfex->m_count = fromex->m_count;
127 selfex->m_flags = fromex->m_flags;
128 for (auto &it : fromex->m_type_params) {
129 ast_value *v = ast_value_copy(it);
130 selfex->m_type_params.push_back(v);
135 void ast_type_adopt_impl(ast_expression *self, const ast_expression *other)
137 const ast_expression *fromex;
138 ast_expression *selfex;
139 self->m_vtype = other->m_vtype;
141 self->m_next = (ast_expression*)ast_type_copy(self->m_context, other->m_next);
145 selfex->m_count = fromex->m_count;
146 selfex->m_flags = fromex->m_flags;
147 for (auto &it : fromex->m_type_params) {
148 ast_value *v = ast_value_copy(it);
149 selfex->m_type_params.push_back(v);
153 static ast_expression* ast_shallow_type(lex_ctx_t ctx, qc_type vtype)
155 ast_instantiate(ast_expression, ctx, ast_expression_delete_full);
156 ast_expression_init(self, nullptr);
157 self->m_codegen = nullptr;
158 self->m_next = nullptr;
159 self->m_vtype = vtype;
163 ast_expression* ast_type_copy(lex_ctx_t ctx, const ast_expression *ex)
165 const ast_expression *fromex;
166 ast_expression *selfex;
172 ast_instantiate(ast_expression, ctx, ast_expression_delete_full);
173 ast_expression_init(self, nullptr);
178 /* This may never be codegen()d */
179 selfex->m_codegen = nullptr;
181 selfex->m_vtype = fromex->m_vtype;
183 selfex->m_next = ast_type_copy(ctx, fromex->m_next);
185 selfex->m_next = nullptr;
187 selfex->m_count = fromex->m_count;
188 selfex->m_flags = fromex->m_flags;
189 for (auto &it : fromex->m_type_params) {
190 ast_value *v = ast_value_copy(it);
191 selfex->m_type_params.push_back(v);
198 bool ast_compare_type(ast_expression *a, ast_expression *b)
200 if (a->m_vtype == TYPE_NIL ||
201 b->m_vtype == TYPE_NIL)
203 if (a->m_vtype != b->m_vtype)
205 if (!a->m_next != !b->m_next)
207 if (a->m_type_params.size() != b->m_type_params.size())
209 if ((a->m_flags & AST_FLAG_TYPE_MASK) !=
210 (b->m_flags & AST_FLAG_TYPE_MASK) )
214 if (a->m_type_params.size()) {
216 for (i = 0; i < a->m_type_params.size(); ++i) {
217 if (!ast_compare_type((ast_expression*)a->m_type_params[i],
218 (ast_expression*)b->m_type_params[i]))
223 return ast_compare_type(a->m_next, b->m_next);
227 static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsize, size_t pos)
234 if (pos + 6 >= bufsize)
236 util_strncpy(buf + pos, "(null)", 6);
240 if (pos + 1 >= bufsize)
243 switch (e->m_vtype) {
245 util_strncpy(buf + pos, "(variant)", 9);
250 return ast_type_to_string_impl(e->m_next, buf, bufsize, pos);
253 if (pos + 3 >= bufsize)
257 pos = ast_type_to_string_impl(e->m_next, buf, bufsize, pos);
258 if (pos + 1 >= bufsize)
264 pos = ast_type_to_string_impl(e->m_next, buf, bufsize, pos);
265 if (pos + 2 >= bufsize)
267 if (e->m_type_params.empty()) {
273 pos = ast_type_to_string_impl((ast_expression*)(e->m_type_params[0]), buf, bufsize, pos);
274 for (i = 1; i < e->m_type_params.size(); ++i) {
275 if (pos + 2 >= bufsize)
279 pos = ast_type_to_string_impl((ast_expression*)(e->m_type_params[i]), buf, bufsize, pos);
281 if (pos + 1 >= bufsize)
287 pos = ast_type_to_string_impl(e->m_next, buf, bufsize, pos);
288 if (pos + 1 >= bufsize)
291 pos += util_snprintf(buf + pos, bufsize - pos - 1, "%i", (int)e->m_count);
292 if (pos + 1 >= bufsize)
298 typestr = type_name[e->m_vtype];
299 typelen = strlen(typestr);
300 if (pos + typelen >= bufsize)
302 util_strncpy(buf + pos, typestr, typelen);
303 return pos + typelen;
307 buf[bufsize-3] = '.';
308 buf[bufsize-2] = '.';
309 buf[bufsize-1] = '.';
313 void ast_type_to_string(ast_expression *e, char *buf, size_t bufsize)
315 size_t pos = ast_type_to_string_impl(e, buf, bufsize-1, 0);
319 static bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_value **out);
320 ast_value* ast_value_new(lex_ctx_t ctx, const char *name, qc_type t)
322 ast_instantiate(ast_value, ctx, ast_value_delete);
323 ast_expression_init((ast_expression*)self,
324 (ast_expression_codegen*)&ast_value_codegen);
325 self->m_keep_node = true; /* keep */
327 self->m_name = name ? util_strdup(name) : nullptr;
329 self->m_next = nullptr;
330 self->m_isfield = false;
331 self->m_cvq = CV_NONE;
332 self->m_hasvalue = false;
333 self->m_isimm = false;
334 self->m_inexact = false;
336 memset(&self->m_constval, 0, sizeof(self->m_constval));
338 self->m_ir_v = nullptr;
339 self->m_ir_values = nullptr;
340 self->m_ir_value_count = 0;
342 self->m_setter = nullptr;
343 self->m_getter = nullptr;
344 self->m_desc = nullptr;
346 self->m_argcounter = nullptr;
347 self->m_intrinsic = false;
352 void ast_value_delete(ast_value* self)
355 mem_d((void*)self->m_name);
356 if (self->m_argcounter)
357 mem_d((void*)self->m_argcounter);
358 if (self->m_hasvalue) {
359 switch (self->m_vtype)
362 mem_d((void*)self->m_constval.vstring);
365 /* unlink us from the function node */
366 self->m_constval.vfunc->m_function_type = nullptr;
368 /* NOTE: delete function? currently collected in
369 * the parser structure
375 if (self->m_ir_values)
376 mem_d(self->m_ir_values);
381 // initlist imples an array which implies .next in the expression exists.
382 if (self->m_initlist.size() && self->m_next->m_vtype == TYPE_STRING) {
383 for (auto &it : self->m_initlist)
388 ast_expression_delete((ast_expression*)self);
393 void ast_value_params_add(ast_value *self, ast_value *p)
395 self->m_type_params.push_back(p);
398 bool ast_value_set_name(ast_value *self, const char *name)
401 mem_d((void*)self->m_name);
402 self->m_name = util_strdup(name);
403 return !!self->m_name;
406 ast_binary* ast_binary_new(lex_ctx_t ctx, int op,
407 ast_expression* left, ast_expression* right)
409 ast_instantiate(ast_binary, ctx, ast_binary_delete);
410 ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_binary_codegen);
412 if (ast_istype(right, ast_unary) && OPTS_OPTIMIZATION(OPTIM_PEEPHOLE)) {
413 ast_unary *unary = ((ast_unary*)right);
414 ast_expression *normal = unary->m_operand;
416 /* make a-(-b) => a + b */
417 if (unary->m_op == VINSTR_NEG_F || unary->m_op == VINSTR_NEG_V) {
418 if (op == INSTR_SUB_F) {
421 ++opts_optimizationcount[OPTIM_PEEPHOLE];
422 } else if (op == INSTR_SUB_V) {
425 ++opts_optimizationcount[OPTIM_PEEPHOLE];
432 self->m_right = right;
433 self->m_right_first = false;
435 ast_propagate_effects(self, left);
436 ast_propagate_effects(self, right);
438 if (op >= INSTR_EQ_F && op <= INSTR_GT)
439 self->m_vtype = TYPE_FLOAT;
440 else if (op == INSTR_AND || op == INSTR_OR) {
441 if (OPTS_FLAG(PERL_LOGIC))
442 ast_type_adopt(self, right);
444 self->m_vtype = TYPE_FLOAT;
446 else if (op == INSTR_BITAND || op == INSTR_BITOR)
447 self->m_vtype = TYPE_FLOAT;
448 else if (op == INSTR_MUL_VF || op == INSTR_MUL_FV)
449 self->m_vtype = TYPE_VECTOR;
450 else if (op == INSTR_MUL_V)
451 self->m_vtype = TYPE_FLOAT;
453 self->m_vtype = left->m_vtype;
456 self->m_refs = AST_REF_ALL;
461 void ast_binary_delete(ast_binary *self)
463 if (self->m_refs & AST_REF_LEFT) ast_unref(self->m_left);
464 if (self->m_refs & AST_REF_RIGHT) ast_unref(self->m_right);
466 ast_expression_delete((ast_expression*)self);
471 ast_binstore* ast_binstore_new(lex_ctx_t ctx, int storop, int op,
472 ast_expression* left, ast_expression* right)
474 ast_instantiate(ast_binstore, ctx, ast_binstore_delete);
475 ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_binstore_codegen);
477 self->m_side_effects = true;
479 self->m_opstore = storop;
482 self->m_source = right;
484 self->m_keep_dest = false;
486 ast_type_adopt(self, left);
490 void ast_binstore_delete(ast_binstore *self)
492 if (!self->m_keep_dest)
493 ast_unref(self->m_dest);
494 ast_unref(self->m_source);
495 ast_expression_delete((ast_expression*)self);
496 self->~ast_binstore();
500 ast_unary* ast_unary_new(lex_ctx_t ctx, int op,
501 ast_expression *expr)
503 ast_instantiate(ast_unary, ctx, ast_unary_delete);
504 ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_unary_codegen);
507 self->m_operand = expr;
510 if (ast_istype(expr, ast_unary) && OPTS_OPTIMIZATION(OPTIM_PEEPHOLE)) {
511 ast_unary *prev = (ast_unary*)((ast_unary*)expr)->m_operand;
513 /* Handle for double negation */
514 if (((ast_unary*)expr)->m_op == op)
515 prev = (ast_unary*)((ast_unary*)expr)->m_operand;
517 if (ast_istype(prev, ast_unary)) {
518 ast_expression_delete((ast_expression*)self);
520 ++opts_optimizationcount[OPTIM_PEEPHOLE];
525 ast_propagate_effects(self, expr);
527 if ((op >= INSTR_NOT_F && op <= INSTR_NOT_FNC) || op == VINSTR_NEG_F) {
528 self->m_vtype = TYPE_FLOAT;
529 } else if (op == VINSTR_NEG_V) {
530 self->m_vtype = TYPE_VECTOR;
532 compile_error(ctx, "cannot determine type of unary operation %s", util_instr_str[op]);
538 void ast_unary_delete(ast_unary *self)
540 if (self->m_operand) ast_unref(self->m_operand);
541 ast_expression_delete((ast_expression*)self);
546 ast_return* ast_return_new(lex_ctx_t ctx, ast_expression *expr)
548 ast_instantiate(ast_return, ctx, ast_return_delete);
549 ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_return_codegen);
551 self->m_operand = expr;
554 ast_propagate_effects(self, expr);
559 void ast_return_delete(ast_return *self)
562 ast_unref(self->m_operand);
563 ast_expression_delete((ast_expression*)self);
568 ast_entfield* ast_entfield_new(lex_ctx_t ctx, ast_expression *entity, ast_expression *field)
570 if (field->m_vtype != TYPE_FIELD) {
571 compile_error(ctx, "ast_entfield_new with expression not of type field");
574 return ast_entfield_new_force(ctx, entity, field, field->m_next);
577 ast_entfield* ast_entfield_new_force(lex_ctx_t ctx, ast_expression *entity, ast_expression *field, const ast_expression *outtype)
579 ast_instantiate(ast_entfield, ctx, ast_entfield_delete);
583 /* Error: field has no type... */
587 ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_entfield_codegen);
589 self->m_entity = entity;
590 self->m_field = field;
591 ast_propagate_effects(self, entity);
592 ast_propagate_effects(self, field);
594 ast_type_adopt(self, outtype);
598 void ast_entfield_delete(ast_entfield *self)
600 ast_unref(self->m_entity);
601 ast_unref(self->m_field);
602 ast_expression_delete((ast_expression*)self);
603 self->~ast_entfield();
607 ast_member* ast_member_new(lex_ctx_t ctx, ast_expression *owner, unsigned int field, const char *name)
609 ast_instantiate(ast_member, ctx, ast_member_delete);
615 if (owner->m_vtype != TYPE_VECTOR &&
616 owner->m_vtype != TYPE_FIELD) {
617 compile_error(ctx, "member-access on an invalid owner of type %s", type_name[owner->m_vtype]);
622 ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_member_codegen);
623 self->m_keep_node = true; /* keep */
625 if (owner->m_vtype == TYPE_VECTOR) {
626 self->m_vtype = TYPE_FLOAT;
627 self->m_next = nullptr;
629 self->m_vtype = TYPE_FIELD;
630 self->m_next = ast_shallow_type(ctx, TYPE_FLOAT);
633 self->m_rvalue = false;
634 self->m_owner = owner;
635 ast_propagate_effects(self, owner);
637 self->m_field = field;
639 self->m_name = util_strdup(name);
641 self->m_name = nullptr;
646 void ast_member_delete(ast_member *self)
648 /* The owner is always an ast_value, which has .keep_node=true,
649 * also: ast_members are usually deleted after the owner, thus
650 * this will cause invalid access
651 ast_unref(self->m_owner);
652 * once we allow (expression).x to access a vector-member, we need
653 * to change this: preferably by creating an alternate ast node for this
654 * purpose that is not garbage-collected.
656 ast_expression_delete((ast_expression*)self);
662 bool ast_member_set_name(ast_member *self, const char *name)
665 mem_d((void*)self->m_name);
666 self->m_name = util_strdup(name);
667 return !!self->m_name;
670 ast_array_index* ast_array_index_new(lex_ctx_t ctx, ast_expression *array, ast_expression *index)
672 ast_expression *outtype;
673 ast_instantiate(ast_array_index, ctx, ast_array_index_delete);
675 outtype = array->m_next;
678 /* Error: field has no type... */
682 ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_array_index_codegen);
684 self->m_array = array;
685 self->m_index = index;
686 ast_propagate_effects(self, array);
687 ast_propagate_effects(self, index);
689 ast_type_adopt(self, outtype);
690 if (array->m_vtype == TYPE_FIELD && outtype->m_vtype == TYPE_ARRAY) {
691 if (self->m_vtype != TYPE_ARRAY) {
692 compile_error(self->m_context, "array_index node on type");
693 ast_array_index_delete(self);
696 self->m_array = outtype;
697 self->m_vtype = TYPE_FIELD;
703 void ast_array_index_delete(ast_array_index *self)
706 ast_unref(self->m_array);
708 ast_unref(self->m_index);
709 ast_expression_delete((ast_expression*)self);
713 ast_argpipe* ast_argpipe_new(lex_ctx_t ctx, ast_expression *index)
715 ast_instantiate(ast_argpipe, ctx, ast_argpipe_delete);
716 ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_argpipe_codegen);
717 self->m_index = index;
718 self->m_vtype = TYPE_NOEXPR;
722 void ast_argpipe_delete(ast_argpipe *self)
725 ast_unref(self->m_index);
726 ast_expression_delete((ast_expression*)self);
727 self->~ast_argpipe();
731 ast_ifthen* ast_ifthen_new(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse)
733 ast_instantiate(ast_ifthen, ctx, ast_ifthen_delete);
734 if (!ontrue && !onfalse) {
735 /* because it is invalid */
739 ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_ifthen_codegen);
742 self->m_on_true = ontrue;
743 self->m_on_false = onfalse;
744 ast_propagate_effects(self, cond);
746 ast_propagate_effects(self, ontrue);
748 ast_propagate_effects(self, onfalse);
753 void ast_ifthen_delete(ast_ifthen *self)
755 ast_unref(self->m_cond);
757 ast_unref(self->m_on_true);
758 if (self->m_on_false)
759 ast_unref(self->m_on_false);
760 ast_expression_delete((ast_expression*)self);
765 ast_ternary* ast_ternary_new(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse)
767 ast_expression *exprtype = ontrue;
768 ast_instantiate(ast_ternary, ctx, ast_ternary_delete);
769 /* This time NEITHER must be nullptr */
770 if (!ontrue || !onfalse) {
774 ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_ternary_codegen);
777 self->m_on_true = ontrue;
778 self->m_on_false = onfalse;
779 ast_propagate_effects(self, cond);
780 ast_propagate_effects(self, ontrue);
781 ast_propagate_effects(self, onfalse);
783 if (ontrue->m_vtype == TYPE_NIL)
785 ast_type_adopt(self, exprtype);
790 void ast_ternary_delete(ast_ternary *self)
792 /* the if()s are only there because computed-gotos can set them
795 if (self->m_cond) ast_unref(self->m_cond);
796 if (self->m_on_true) ast_unref(self->m_on_true);
797 if (self->m_on_false) ast_unref(self->m_on_false);
798 ast_expression_delete((ast_expression*)self);
799 self->~ast_ternary();
803 ast_loop* ast_loop_new(lex_ctx_t ctx,
804 ast_expression *initexpr,
805 ast_expression *precond, bool pre_not,
806 ast_expression *postcond, bool post_not,
807 ast_expression *increment,
808 ast_expression *body)
810 ast_instantiate(ast_loop, ctx, ast_loop_delete);
811 ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_loop_codegen);
813 self->m_initexpr = initexpr;
814 self->m_precond = precond;
815 self->m_postcond = postcond;
816 self->m_increment = increment;
819 self->m_pre_not = pre_not;
820 self->m_post_not = post_not;
823 ast_propagate_effects(self, initexpr);
825 ast_propagate_effects(self, precond);
827 ast_propagate_effects(self, postcond);
829 ast_propagate_effects(self, increment);
831 ast_propagate_effects(self, body);
836 void ast_loop_delete(ast_loop *self)
838 if (self->m_initexpr)
839 ast_unref(self->m_initexpr);
841 ast_unref(self->m_precond);
842 if (self->m_postcond)
843 ast_unref(self->m_postcond);
844 if (self->m_increment)
845 ast_unref(self->m_increment);
847 ast_unref(self->m_body);
848 ast_expression_delete((ast_expression*)self);
853 ast_breakcont* ast_breakcont_new(lex_ctx_t ctx, bool iscont, unsigned int levels)
855 ast_instantiate(ast_breakcont, ctx, ast_breakcont_delete);
856 ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_breakcont_codegen);
858 self->m_is_continue = iscont;
859 self->m_levels = levels;
864 void ast_breakcont_delete(ast_breakcont *self)
866 ast_expression_delete((ast_expression*)self);
867 self->~ast_breakcont();
871 ast_switch* ast_switch_new(lex_ctx_t ctx, ast_expression *op)
873 ast_instantiate(ast_switch, ctx, ast_switch_delete);
874 ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_switch_codegen);
876 self->m_operand = op;
878 ast_propagate_effects(self, op);
883 void ast_switch_delete(ast_switch *self)
885 ast_unref(self->m_operand);
887 for (auto &it : self->m_cases) {
889 ast_unref(it.m_value);
890 ast_unref(it.m_code);
893 ast_expression_delete((ast_expression*)self);
898 ast_label* ast_label_new(lex_ctx_t ctx, const char *name, bool undefined)
900 ast_instantiate(ast_label, ctx, ast_label_delete);
901 ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_label_codegen);
903 self->m_vtype = TYPE_NOEXPR;
905 self->m_name = util_strdup(name);
906 self->m_irblock = nullptr;
907 self->m_undefined = undefined;
912 void ast_label_delete(ast_label *self)
914 mem_d((void*)self->m_name);
915 ast_expression_delete((ast_expression*)self);
920 static void ast_label_register_goto(ast_label *self, ast_goto *g)
922 self->m_gotos.push_back(g);
925 ast_goto* ast_goto_new(lex_ctx_t ctx, const char *name)
927 ast_instantiate(ast_goto, ctx, ast_goto_delete);
928 ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_goto_codegen);
930 self->m_name = util_strdup(name);
931 self->m_target = nullptr;
932 self->m_irblock_from = nullptr;
937 void ast_goto_delete(ast_goto *self)
939 mem_d((void*)self->m_name);
940 ast_expression_delete((ast_expression*)self);
945 void ast_goto_set_label(ast_goto *self, ast_label *label)
947 self->m_target = label;
950 ast_state* ast_state_new(lex_ctx_t ctx, ast_expression *frame, ast_expression *think)
952 ast_instantiate(ast_state, ctx, ast_state_delete);
953 ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_state_codegen);
954 self->m_framenum = frame;
955 self->m_nextthink = think;
959 void ast_state_delete(ast_state *self)
961 if (self->m_framenum)
962 ast_unref(self->m_framenum);
963 if (self->m_nextthink)
964 ast_unref(self->m_nextthink);
966 ast_expression_delete((ast_expression*)self);
971 ast_call* ast_call_new(lex_ctx_t ctx,
972 ast_expression *funcexpr)
974 ast_instantiate(ast_call, ctx, ast_call_delete);
975 if (!funcexpr->m_next) {
976 compile_error(ctx, "not a function");
980 ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_call_codegen);
982 self->m_side_effects = true;
984 self->m_func = funcexpr;
985 self->m_va_count = nullptr;
987 ast_type_adopt(self, funcexpr->m_next);
992 void ast_call_delete(ast_call *self)
994 for (auto &it : self->m_params)
998 ast_unref(self->m_func);
1000 if (self->m_va_count)
1001 ast_unref(self->m_va_count);
1003 ast_expression_delete((ast_expression*)self);
1008 static bool ast_call_check_vararg(ast_call *self, ast_expression *va_type, ast_expression *exp_type)
1014 if (!va_type || !ast_compare_type(va_type, exp_type))
1016 if (va_type && exp_type)
1018 ast_type_to_string(va_type, tgot, sizeof(tgot));
1019 ast_type_to_string(exp_type, texp, sizeof(texp));
1020 if (OPTS_FLAG(UNSAFE_VARARGS)) {
1021 if (compile_warning(self->m_context, WARN_UNSAFE_TYPES,
1022 "piped variadic argument differs in type: constrained to type %s, expected type %s",
1026 compile_error(self->m_context,
1027 "piped variadic argument differs in type: constrained to type %s, expected type %s",
1034 ast_type_to_string(exp_type, texp, sizeof(texp));
1035 if (OPTS_FLAG(UNSAFE_VARARGS)) {
1036 if (compile_warning(self->m_context, WARN_UNSAFE_TYPES,
1037 "piped variadic argument may differ in type: expected type %s",
1041 compile_error(self->m_context,
1042 "piped variadic argument may differ in type: expected type %s",
1051 bool ast_call_check_types(ast_call *self, ast_expression *va_type)
1057 const ast_expression *func = self->m_func;
1058 size_t count = self->m_params.size();
1059 if (count > func->m_type_params.size())
1060 count = func->m_type_params.size();
1062 for (i = 0; i < count; ++i) {
1063 if (ast_istype(self->m_params[i], ast_argpipe)) {
1064 /* warn about type safety instead */
1066 compile_error(self->m_context, "argpipe must be the last parameter to a function call");
1069 if (!ast_call_check_vararg(self, va_type, (ast_expression*)func->m_type_params[i]))
1072 else if (!ast_compare_type(self->m_params[i], (ast_expression*)(func->m_type_params[i])))
1074 ast_type_to_string(self->m_params[i], tgot, sizeof(tgot));
1075 ast_type_to_string((ast_expression*)func->m_type_params[i], texp, sizeof(texp));
1076 compile_error(self->m_context, "invalid type for parameter %u in function call: expected %s, got %s",
1077 (unsigned int)(i+1), texp, tgot);
1078 /* we don't immediately return */
1082 count = self->m_params.size();
1083 if (count > func->m_type_params.size() && func->m_varparam) {
1084 for (; i < count; ++i) {
1085 if (ast_istype(self->m_params[i], ast_argpipe)) {
1086 /* warn about type safety instead */
1088 compile_error(self->m_context, "argpipe must be the last parameter to a function call");
1091 if (!ast_call_check_vararg(self, va_type, func->m_varparam))
1094 else if (!ast_compare_type(self->m_params[i], func->m_varparam))
1096 ast_type_to_string(self->m_params[i], tgot, sizeof(tgot));
1097 ast_type_to_string(func->m_varparam, texp, sizeof(texp));
1098 compile_error(self->m_context, "invalid type for variadic parameter %u in function call: expected %s, got %s",
1099 (unsigned int)(i+1), texp, tgot);
1100 /* we don't immediately return */
1108 ast_store* ast_store_new(lex_ctx_t ctx, int op,
1109 ast_expression *dest, ast_expression *source)
1111 ast_instantiate(ast_store, ctx, ast_store_delete);
1112 ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_store_codegen);
1114 self->m_side_effects = true;
1117 self->m_dest = dest;
1118 self->m_source = source;
1120 ast_type_adopt(self, dest);
1125 void ast_store_delete(ast_store *self)
1127 ast_unref(self->m_dest);
1128 ast_unref(self->m_source);
1129 ast_expression_delete((ast_expression*)self);
1134 ast_block* ast_block_new(lex_ctx_t ctx)
1136 ast_instantiate(ast_block, ctx, ast_block_delete);
1137 ast_expression_init((ast_expression*)self,
1138 (ast_expression_codegen*)&ast_block_codegen);
1142 bool ast_block_add_expr(ast_block *self, ast_expression *e)
1144 ast_propagate_effects(self, e);
1145 self->m_exprs.push_back(e);
1147 ast_delete(self->m_next);
1148 self->m_next = nullptr;
1150 ast_type_adopt(self, e);
1154 void ast_block_collect(ast_block *self, ast_expression *expr)
1156 self->m_collect.push_back(expr);
1157 expr->m_keep_node = true;
1160 void ast_block_delete(ast_block *self)
1162 for (auto &it : self->m_exprs) ast_unref(it);
1163 for (auto &it : self->m_locals) ast_delete(it);
1164 for (auto &it : self->m_collect) ast_delete(it);
1165 ast_expression_delete((ast_expression*)self);
1170 void ast_block_set_type(ast_block *self, ast_expression *from)
1173 ast_delete(self->m_next);
1174 ast_type_adopt(self, from);
1177 ast_function* ast_function_new(lex_ctx_t ctx, const char *name, ast_value *vtype)
1179 ast_instantiate(ast_function, ctx, ast_function_delete);
1182 compile_error(self->m_context, "internal error: ast_function_new condition 0");
1184 } else if (vtype->m_hasvalue || vtype->m_vtype != TYPE_FUNCTION) {
1185 compile_error(self->m_context, "internal error: ast_function_new condition %i %i type=%i (probably 2 bodies?)",
1187 (int)vtype->m_hasvalue,
1192 self->m_function_type = vtype;
1193 self->m_name = name ? util_strdup(name) : nullptr;
1195 self->m_labelcount = 0;
1196 self->m_builtin = 0;
1198 self->m_ir_func = nullptr;
1199 self->m_curblock = nullptr;
1201 vtype->m_hasvalue = true;
1202 vtype->m_constval.vfunc = self;
1204 self->m_varargs = nullptr;
1205 self->m_argc = nullptr;
1206 self->m_fixedparams = nullptr;
1207 self->m_return_value = nullptr;
1208 self->m_static_count = 0;
1217 void ast_function_delete(ast_function *self)
1220 mem_d((void*)self->m_name);
1221 if (self->m_function_type) {
1222 /* ast_value_delete(self->m_function_type); */
1223 self->m_function_type->m_hasvalue = false;
1224 self->m_function_type->m_constval.vfunc = nullptr;
1225 /* We use unref - if it was stored in a global table it is supposed
1226 * to be deleted from *there*
1228 ast_unref(self->m_function_type);
1230 for (auto &it : self->m_static_names)
1232 // FIXME::DELME:: unique_ptr used on ast_block
1233 //for (auto &it : self->m_blocks)
1235 if (self->m_varargs)
1236 ast_delete(self->m_varargs);
1238 ast_delete(self->m_argc);
1239 if (self->m_fixedparams)
1240 ast_unref(self->m_fixedparams);
1241 if (self->m_return_value)
1242 ast_unref(self->m_return_value);
1243 self->~ast_function();
1247 const char* ast_function_label(ast_function *self, const char *prefix)
1253 if (!OPTS_OPTION_BOOL(OPTION_DUMP) &&
1254 !OPTS_OPTION_BOOL(OPTION_DUMPFIN) &&
1255 !OPTS_OPTION_BOOL(OPTION_DEBUG))
1260 id = (self->m_labelcount++);
1261 len = strlen(prefix);
1263 from = self->m_labelbuf + sizeof(self->m_labelbuf)-1;
1266 *from-- = (id%10) + '0';
1270 memcpy(from - len, prefix, len);
1274 /*********************************************************************/
1276 * by convention you must never pass nullptr to the 'ir_value **out'
1277 * parameter. If you really don't care about the output, pass a dummy.
1278 * But I can't imagine a pituation where the output is truly unnecessary.
1281 static void _ast_codegen_output_type(ast_expression *self, ir_value *out)
1283 if (out->m_vtype == TYPE_FIELD)
1284 out->m_fieldtype = self->m_next->m_vtype;
1285 if (out->m_vtype == TYPE_FUNCTION)
1286 out->m_outtype = self->m_next->m_vtype;
1289 #define codegen_output_type(a,o) (_ast_codegen_output_type(static_cast<ast_expression*>((a)),(o)))
1291 bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_value **out)
1295 if (self->m_vtype == TYPE_NIL) {
1296 *out = func->m_ir_func->m_owner->m_nil;
1299 /* NOTE: This is the codegen for a variable used in an
1300 * It is not the codegen to generate the value. For this purpose,
1301 * ast_local_codegen and ast_global_codegen are to be used before this
1302 * is executed. ast_function_codegen should take care of its locals,
1303 * and the ast-user should take care of ast_global_codegen to be used
1304 * on all the globals.
1306 if (!self->m_ir_v) {
1307 char tname[1024]; /* typename is reserved in C++ */
1308 ast_type_to_string((ast_expression*)self, tname, sizeof(tname));
1309 compile_error(self->m_context, "ast_value used before generated %s %s", tname, self->m_name);
1312 *out = self->m_ir_v;
1316 static bool ast_global_array_set(ast_value *self)
1318 size_t count = self->m_initlist.size();
1321 if (count > self->m_count) {
1322 compile_error(self->m_context, "too many elements in initializer");
1323 count = self->m_count;
1325 else if (count < self->m_count) {
1327 compile_warning(self->m_context, "not all elements are initialized");
1331 for (i = 0; i != count; ++i) {
1332 switch (self->m_next->m_vtype) {
1334 if (!ir_value_set_float(self->m_ir_values[i], self->m_initlist[i].vfloat))
1338 if (!ir_value_set_vector(self->m_ir_values[i], self->m_initlist[i].vvec))
1342 if (!ir_value_set_string(self->m_ir_values[i], self->m_initlist[i].vstring))
1346 /* we don't support them in any other place yet either */
1347 compile_error(self->m_context, "TODO: nested arrays");
1350 /* this requiers a bit more work - similar to the fields I suppose */
1351 compile_error(self->m_context, "global of type function not properly generated");
1354 if (!self->m_initlist[i].vfield) {
1355 compile_error(self->m_context, "field constant without vfield set");
1358 if (!self->m_initlist[i].vfield->m_ir_v) {
1359 compile_error(self->m_context, "field constant generated before its field");
1362 if (!ir_value_set_field(self->m_ir_values[i], self->m_initlist[i].vfield->m_ir_v))
1366 compile_error(self->m_context, "TODO: global constant type %i", self->m_vtype);
1373 static bool check_array(ast_value *self, ast_value *array)
1375 if (array->m_flags & AST_FLAG_ARRAY_INIT && array->m_initlist.empty()) {
1376 compile_error(self->m_context, "array without size: %s", self->m_name);
1379 /* we are lame now - considering the way QC works we won't tolerate arrays > 1024 elements */
1380 if (!array->m_count || array->m_count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE)) {
1381 compile_error(self->m_context, "Invalid array of size %lu", (unsigned long)array->m_count);
1387 bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
1389 ir_value *v = nullptr;
1391 if (self->m_vtype == TYPE_NIL) {
1392 compile_error(self->m_context, "internal error: trying to generate a variable of TYPE_NIL");
1396 if (self->m_hasvalue && self->m_vtype == TYPE_FUNCTION)
1398 ir_function *func = ir_builder_create_function(ir, self->m_name, self->m_next->m_vtype);
1401 func->m_context = self->m_context;
1402 func->m_value->m_context = self->m_context;
1404 self->m_constval.vfunc->m_ir_func = func;
1405 self->m_ir_v = func->m_value;
1406 if (self->m_flags & AST_FLAG_INCLUDE_DEF)
1407 self->m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
1408 if (self->m_flags & AST_FLAG_ERASEABLE)
1409 self->m_ir_v->m_flags |= IR_FLAG_ERASABLE;
1410 if (self->m_flags & AST_FLAG_BLOCK_COVERAGE)
1411 func->m_flags |= IR_FLAG_BLOCK_COVERAGE;
1412 /* The function is filled later on ast_function_codegen... */
1416 if (isfield && self->m_vtype == TYPE_FIELD) {
1417 ast_expression *fieldtype = self->m_next;
1419 if (self->m_hasvalue) {
1420 compile_error(self->m_context, "TODO: constant field pointers with value");
1424 if (fieldtype->m_vtype == TYPE_ARRAY) {
1429 ast_expression *elemtype;
1431 ast_value *array = (ast_value*)fieldtype;
1433 if (!ast_istype(fieldtype, ast_value)) {
1434 compile_error(self->m_context, "internal error: ast_value required");
1438 if (!check_array(self, array))
1441 elemtype = array->m_next;
1442 vtype = elemtype->m_vtype;
1444 v = ir_builder_create_field(ir, self->m_name, vtype);
1446 compile_error(self->m_context, "ir_builder_create_global failed on `%s`", self->m_name);
1449 v->m_context = self->m_context;
1450 v->m_unique_life = true;
1452 array->m_ir_v = self->m_ir_v = v;
1454 if (self->m_flags & AST_FLAG_INCLUDE_DEF)
1455 self->m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
1456 if (self->m_flags & AST_FLAG_ERASEABLE)
1457 self->m_ir_v->m_flags |= IR_FLAG_ERASABLE;
1459 namelen = strlen(self->m_name);
1460 name = (char*)mem_a(namelen + 16);
1461 util_strncpy(name, self->m_name, namelen);
1463 array->m_ir_values = (ir_value**)mem_a(sizeof(array->m_ir_values[0]) * array->m_count);
1464 array->m_ir_values[0] = v;
1465 for (ai = 1; ai < array->m_count; ++ai) {
1466 util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
1467 array->m_ir_values[ai] = ir_builder_create_field(ir, name, vtype);
1468 if (!array->m_ir_values[ai]) {
1470 compile_error(self->m_context, "ir_builder_create_global failed on `%s`", name);
1473 array->m_ir_values[ai]->m_context = self->m_context;
1474 array->m_ir_values[ai]->m_unique_life = true;
1475 array->m_ir_values[ai]->m_locked = true;
1476 if (self->m_flags & AST_FLAG_INCLUDE_DEF)
1477 self->m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF;
1483 v = ir_builder_create_field(ir, self->m_name, self->m_next->m_vtype);
1486 v->m_context = self->m_context;
1488 if (self->m_flags & AST_FLAG_INCLUDE_DEF)
1489 self->m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
1491 if (self->m_flags & AST_FLAG_ERASEABLE)
1492 self->m_ir_v->m_flags |= IR_FLAG_ERASABLE;
1497 if (self->m_vtype == TYPE_ARRAY) {
1502 ast_expression *elemtype = self->m_next;
1503 qc_type vtype = elemtype->m_vtype;
1505 if (self->m_flags & AST_FLAG_ARRAY_INIT && !self->m_count) {
1506 compile_error(self->m_context, "array `%s' has no size", self->m_name);
1510 /* same as with field arrays */
1511 if (!check_array(self, self))
1514 v = ir_builder_create_global(ir, self->m_name, vtype);
1516 compile_error(self->m_context, "ir_builder_create_global failed `%s`", self->m_name);
1519 v->m_context = self->m_context;
1520 v->m_unique_life = true;
1523 if (self->m_flags & AST_FLAG_INCLUDE_DEF)
1524 v->m_flags |= IR_FLAG_INCLUDE_DEF;
1525 if (self->m_flags & AST_FLAG_ERASEABLE)
1526 self->m_ir_v->m_flags |= IR_FLAG_ERASABLE;
1528 namelen = strlen(self->m_name);
1529 name = (char*)mem_a(namelen + 16);
1530 util_strncpy(name, self->m_name, namelen);
1532 self->m_ir_values = (ir_value**)mem_a(sizeof(self->m_ir_values[0]) * self->m_count);
1533 self->m_ir_values[0] = v;
1534 for (ai = 1; ai < self->m_count; ++ai) {
1535 util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
1536 self->m_ir_values[ai] = ir_builder_create_global(ir, name, vtype);
1537 if (!self->m_ir_values[ai]) {
1539 compile_error(self->m_context, "ir_builder_create_global failed `%s`", name);
1542 self->m_ir_values[ai]->m_context = self->m_context;
1543 self->m_ir_values[ai]->m_unique_life = true;
1544 self->m_ir_values[ai]->m_locked = true;
1545 if (self->m_flags & AST_FLAG_INCLUDE_DEF)
1546 self->m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF;
1552 /* Arrays don't do this since there's no "array" value which spans across the
1555 v = ir_builder_create_global(ir, self->m_name, self->m_vtype);
1557 compile_error(self->m_context, "ir_builder_create_global failed on `%s`", self->m_name);
1560 codegen_output_type(self, v);
1561 v->m_context = self->m_context;
1564 /* link us to the ir_value */
1565 v->m_cvq = self->m_cvq;
1568 if (self->m_flags & AST_FLAG_INCLUDE_DEF)
1569 self->m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
1570 if (self->m_flags & AST_FLAG_ERASEABLE)
1571 self->m_ir_v->m_flags |= IR_FLAG_ERASABLE;
1574 if (self->m_hasvalue) {
1575 switch (self->m_vtype)
1578 if (!ir_value_set_float(v, self->m_constval.vfloat))
1582 if (!ir_value_set_vector(v, self->m_constval.vvec))
1586 if (!ir_value_set_string(v, self->m_constval.vstring))
1590 ast_global_array_set(self);
1593 compile_error(self->m_context, "global of type function not properly generated");
1595 /* Cannot generate an IR value for a function,
1596 * need a pointer pointing to a function rather.
1599 if (!self->m_constval.vfield) {
1600 compile_error(self->m_context, "field constant without vfield set");
1603 if (!self->m_constval.vfield->m_ir_v) {
1604 compile_error(self->m_context, "field constant generated before its field");
1607 if (!ir_value_set_field(v, self->m_constval.vfield->m_ir_v))
1611 compile_error(self->m_context, "TODO: global constant type %i", self->m_vtype);
1617 error: /* clean up */
1622 static bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
1624 ir_value *v = nullptr;
1626 if (self->m_vtype == TYPE_NIL) {
1627 compile_error(self->m_context, "internal error: trying to generate a variable of TYPE_NIL");
1631 if (self->m_hasvalue && self->m_vtype == TYPE_FUNCTION)
1633 /* Do we allow local functions? I think not...
1634 * this is NOT a function pointer atm.
1639 if (self->m_vtype == TYPE_ARRAY) {
1644 ast_expression *elemtype = self->m_next;
1645 qc_type vtype = elemtype->m_vtype;
1647 func->m_flags |= IR_FLAG_HAS_ARRAYS;
1649 if (param && !(self->m_flags & AST_FLAG_IS_VARARG)) {
1650 compile_error(self->m_context, "array-parameters are not supported");
1654 /* we are lame now - considering the way QC works we won't tolerate arrays > 1024 elements */
1655 if (!check_array(self, self))
1658 self->m_ir_values = (ir_value**)mem_a(sizeof(self->m_ir_values[0]) * self->m_count);
1659 if (!self->m_ir_values) {
1660 compile_error(self->m_context, "failed to allocate array values");
1664 v = ir_function_create_local(func, self->m_name, vtype, param);
1666 compile_error(self->m_context, "internal error: ir_function_create_local failed");
1669 v->m_context = self->m_context;
1670 v->m_unique_life = true;
1673 namelen = strlen(self->m_name);
1674 name = (char*)mem_a(namelen + 16);
1675 util_strncpy(name, self->m_name, namelen);
1677 self->m_ir_values[0] = v;
1678 for (ai = 1; ai < self->m_count; ++ai) {
1679 util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
1680 self->m_ir_values[ai] = ir_function_create_local(func, name, vtype, param);
1681 if (!self->m_ir_values[ai]) {
1682 compile_error(self->m_context, "internal_error: ir_builder_create_global failed on `%s`", name);
1685 self->m_ir_values[ai]->m_context = self->m_context;
1686 self->m_ir_values[ai]->m_unique_life = true;
1687 self->m_ir_values[ai]->m_locked = true;
1693 v = ir_function_create_local(func, self->m_name, self->m_vtype, param);
1696 codegen_output_type(self, v);
1697 v->m_context = self->m_context;
1700 /* A constant local... hmmm...
1701 * I suppose the IR will have to deal with this
1703 if (self->m_hasvalue) {
1704 switch (self->m_vtype)
1707 if (!ir_value_set_float(v, self->m_constval.vfloat))
1711 if (!ir_value_set_vector(v, self->m_constval.vvec))
1715 if (!ir_value_set_string(v, self->m_constval.vstring))
1719 compile_error(self->m_context, "TODO: global constant type %i", self->m_vtype);
1724 /* link us to the ir_value */
1725 v->m_cvq = self->m_cvq;
1728 if (!ast_generate_accessors(self, func->m_owner))
1732 error: /* clean up */
1737 bool ast_generate_accessors(ast_value *self, ir_builder *ir)
1740 bool warn = OPTS_WARN(WARN_USED_UNINITIALIZED);
1741 if (!self->m_setter || !self->m_getter)
1743 for (i = 0; i < self->m_count; ++i) {
1744 if (!self->m_ir_values) {
1745 compile_error(self->m_context, "internal error: no array values generated for `%s`", self->m_name);
1748 if (!self->m_ir_values[i]) {
1749 compile_error(self->m_context, "internal error: not all array values have been generated for `%s`", self->m_name);
1752 if (!self->m_ir_values[i]->m_life.empty()) {
1753 compile_error(self->m_context, "internal error: function containing `%s` already generated", self->m_name);
1758 opts_set(opts.warn, WARN_USED_UNINITIALIZED, false);
1759 if (self->m_setter) {
1760 if (!ast_global_codegen (self->m_setter, ir, false) ||
1761 !ast_function_codegen(self->m_setter->m_constval.vfunc, ir) ||
1762 !ir_function_finalize(self->m_setter->m_constval.vfunc->m_ir_func))
1764 compile_error(self->m_context, "internal error: failed to generate setter for `%s`", self->m_name);
1765 opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
1769 if (self->m_getter) {
1770 if (!ast_global_codegen (self->m_getter, ir, false) ||
1771 !ast_function_codegen(self->m_getter->m_constval.vfunc, ir) ||
1772 !ir_function_finalize(self->m_getter->m_constval.vfunc->m_ir_func))
1774 compile_error(self->m_context, "internal error: failed to generate getter for `%s`", self->m_name);
1775 opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
1779 for (i = 0; i < self->m_count; ++i)
1780 self->m_ir_values[i]->m_life.clear();
1781 opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
1785 bool ast_function_codegen(ast_function *self, ir_builder *ir)
1790 ast_expression_codegen *cgen;
1794 irf = self->m_ir_func;
1796 compile_error(self->m_context, "internal error: ast_function's related ast_value was not generated yet");
1800 /* fill the parameter list */
1801 ec = self->m_function_type;
1802 for (auto &it : ec->m_type_params) {
1803 if (it->m_vtype == TYPE_FIELD)
1804 vec_push(irf->m_params, it->m_next->m_vtype);
1806 vec_push(irf->m_params, it->m_vtype);
1807 if (!self->m_builtin) {
1808 if (!ast_local_codegen(it, self->m_ir_func, true))
1813 if (self->m_varargs) {
1814 if (!ast_local_codegen(self->m_varargs, self->m_ir_func, true))
1816 irf->m_max_varargs = self->m_varargs->m_count;
1819 if (self->m_builtin) {
1820 irf->m_builtin = self->m_builtin;
1824 /* have a local return value variable? */
1825 if (self->m_return_value) {
1826 if (!ast_local_codegen(self->m_return_value, self->m_ir_func, false))
1830 if (self->m_blocks.empty()) {
1831 compile_error(self->m_context, "function `%s` has no body", self->m_name);
1835 irf->m_first = self->m_curblock = ir_function_create_block(self->m_context, irf, "entry");
1836 if (!self->m_curblock) {
1837 compile_error(self->m_context, "failed to allocate entry block for `%s`", self->m_name);
1845 if (!ast_local_codegen(self->m_argc, self->m_ir_func, true))
1847 cgen = self->m_argc->m_codegen;
1848 if (!(*cgen)((ast_expression*)(self->m_argc), self, false, &va_count))
1850 cgen = self->m_fixedparams->m_codegen;
1851 if (!(*cgen)((ast_expression*)(self->m_fixedparams), self, false, &fixed))
1853 sub = ir_block_create_binop(self->m_curblock, self->m_context,
1854 ast_function_label(self, "va_count"), INSTR_SUB_F,
1855 ir_builder_get_va_count(ir), fixed);
1858 if (!ir_block_create_store_op(self->m_curblock, self->m_context, INSTR_STORE_F,
1865 for (auto &it : self->m_blocks) {
1866 cgen = it->m_codegen;
1867 if (!(*cgen)(it.get(), self, false, &dummy))
1871 /* TODO: check return types */
1872 if (!self->m_curblock->m_final)
1874 if (!self->m_function_type->m_next ||
1875 self->m_function_type->m_next->m_vtype == TYPE_VOID)
1877 return ir_block_create_return(self->m_curblock, self->m_context, nullptr);
1879 else if (vec_size(self->m_curblock->m_entries) || self->m_curblock == irf->m_first)
1881 if (self->m_return_value) {
1882 cgen = self->m_return_value->m_codegen;
1883 if (!(*cgen)((ast_expression*)(self->m_return_value), self, false, &dummy))
1885 return ir_block_create_return(self->m_curblock, self->m_context, dummy);
1887 else if (compile_warning(self->m_context, WARN_MISSING_RETURN_VALUES,
1888 "control reaches end of non-void function (`%s`) via %s",
1889 self->m_name, self->m_curblock->m_label.c_str()))
1893 return ir_block_create_return(self->m_curblock, self->m_context, nullptr);
1899 static bool starts_a_label(ast_expression *ex)
1901 while (ex && ast_istype(ex, ast_block)) {
1902 ast_block *b = (ast_block*)ex;
1907 return ast_istype(ex, ast_label);
1910 /* Note, you will not see ast_block_codegen generate ir_blocks.
1911 * To the AST and the IR, blocks are 2 different things.
1912 * In the AST it represents a block of code, usually enclosed in
1913 * curly braces {...}.
1914 * While in the IR it represents a block in terms of control-flow.
1916 bool ast_block_codegen(ast_block *self, ast_function *func, bool lvalue, ir_value **out)
1918 /* We don't use this
1919 * Note: an ast-representation using the comma-operator
1920 * of the form: (a, b, c) = x should not assign to c...
1923 compile_error(self->m_context, "not an l-value (code-block)");
1928 *out = self->m_outr;
1932 /* output is nullptr at first, we'll have each expression
1933 * assign to out output, thus, a comma-operator represention
1934 * using an ast_block will return the last generated value,
1935 * so: (b, c) + a executed both b and c, and returns c,
1936 * which is then added to a.
1940 /* generate locals */
1941 for (auto &it : self->m_locals) {
1942 if (!ast_local_codegen(it, func->m_ir_func, false)) {
1943 if (OPTS_OPTION_BOOL(OPTION_DEBUG))
1944 compile_error(self->m_context, "failed to generate local `%s`", it->m_name);
1949 for (auto &it : self->m_exprs) {
1950 ast_expression_codegen *gen;
1951 if (func->m_curblock->m_final && !starts_a_label(it)) {
1952 if (compile_warning(it->m_context, WARN_UNREACHABLE_CODE, "unreachable statement"))
1956 gen = it->m_codegen;
1957 if (!(*gen)(it, func, false, out))
1961 self->m_outr = *out;
1966 bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_value **out)
1968 ast_expression_codegen *cgen;
1969 ir_value *left = nullptr;
1970 ir_value *right = nullptr;
1974 ast_array_index *ai = nullptr;
1976 if (lvalue && self->m_outl) {
1977 *out = self->m_outl;
1981 if (!lvalue && self->m_outr) {
1982 *out = self->m_outr;
1986 if (ast_istype(self->m_dest, ast_array_index))
1989 ai = (ast_array_index*)self->m_dest;
1990 idx = (ast_value*)ai->m_index;
1992 if (ast_istype(ai->m_index, ast_value) && idx->m_hasvalue && idx->m_cvq == CV_CONST)
1997 /* we need to call the setter */
1998 ir_value *iridx, *funval;
2002 compile_error(self->m_context, "array-subscript assignment cannot produce lvalues");
2006 arr = (ast_value*)ai->m_array;
2007 if (!ast_istype(ai->m_array, ast_value) || !arr->m_setter) {
2008 compile_error(self->m_context, "value has no setter (%s)", arr->m_name);
2012 cgen = idx->m_codegen;
2013 if (!(*cgen)((ast_expression*)(idx), func, false, &iridx))
2016 cgen = arr->m_setter->m_codegen;
2017 if (!(*cgen)((ast_expression*)(arr->m_setter), func, true, &funval))
2020 cgen = self->m_source->m_codegen;
2021 if (!(*cgen)((ast_expression*)(self->m_source), func, false, &right))
2024 call = ir_block_create_call(func->m_curblock, self->m_context, ast_function_label(func, "store"), funval, false);
2027 ir_call_param(call, iridx);
2028 ir_call_param(call, right);
2029 self->m_outr = right;
2035 cgen = self->m_dest->m_codegen;
2037 if (!(*cgen)((ast_expression*)(self->m_dest), func, true, &left))
2039 self->m_outl = left;
2041 cgen = self->m_source->m_codegen;
2043 if (!(*cgen)((ast_expression*)(self->m_source), func, false, &right))
2046 if (!ir_block_create_store_op(func->m_curblock, self->m_context, self->m_op, left, right))
2048 self->m_outr = right;
2051 /* Theoretically, an assinment returns its left side as an
2052 * lvalue, if we don't need an lvalue though, we return
2053 * the right side as an rvalue, otherwise we have to
2054 * somehow know whether or not we need to dereference the pointer
2055 * on the left side - that is: OP_LOAD if it was an address.
2056 * Also: in original QC we cannot OP_LOADP *anyway*.
2058 *out = (lvalue ? left : right);
2063 bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_value **out)
2065 ast_expression_codegen *cgen;
2066 ir_value *left, *right;
2068 /* A binary operation cannot yield an l-value */
2070 compile_error(self->m_context, "not an l-value (binop)");
2075 *out = self->m_outr;
2079 if ((OPTS_FLAG(SHORT_LOGIC) || OPTS_FLAG(PERL_LOGIC)) &&
2080 (self->m_op == INSTR_AND || self->m_op == INSTR_OR))
2082 /* NOTE: The short-logic path will ignore right_first */
2084 /* short circuit evaluation */
2085 ir_block *other, *merge;
2086 ir_block *from_left, *from_right;
2090 /* prepare end-block */
2091 merge_id = func->m_ir_func->m_blocks.size();
2092 merge = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "sce_merge"));
2094 /* generate the left expression */
2095 cgen = self->m_left->m_codegen;
2096 if (!(*cgen)((ast_expression*)(self->m_left), func, false, &left))
2098 /* remember the block */
2099 from_left = func->m_curblock;
2101 /* create a new block for the right expression */
2102 other = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "sce_other"));
2103 if (self->m_op == INSTR_AND) {
2104 /* on AND: left==true -> other */
2105 if (!ir_block_create_if(func->m_curblock, self->m_context, left, other, merge))
2108 /* on OR: left==false -> other */
2109 if (!ir_block_create_if(func->m_curblock, self->m_context, left, merge, other))
2112 /* use the likely flag */
2113 vec_last(func->m_curblock->m_instr)->m_likely = true;
2115 /* enter the right-expression's block */
2116 func->m_curblock = other;
2118 cgen = self->m_right->m_codegen;
2119 if (!(*cgen)((ast_expression*)(self->m_right), func, false, &right))
2121 /* remember block */
2122 from_right = func->m_curblock;
2124 /* jump to the merge block */
2125 if (!ir_block_create_jump(func->m_curblock, self->m_context, merge))
2128 algo::shiftback(func->m_ir_func->m_blocks.begin() + merge_id,
2129 func->m_ir_func->m_blocks.end());
2131 //func->m_ir_func->m_blocks[merge_id].release();
2132 //func->m_ir_func->m_blocks.erase(func->m_ir_func->m_blocks.begin() + merge_id);
2133 //func->m_ir_func->m_blocks.emplace_back(merge);
2135 func->m_curblock = merge;
2136 phi = ir_block_create_phi(func->m_curblock, self->m_context,
2137 ast_function_label(func, "sce_value"),
2139 ir_phi_add(phi, from_left, left);
2140 ir_phi_add(phi, from_right, right);
2141 *out = ir_phi_value(phi);
2145 if (!OPTS_FLAG(PERL_LOGIC)) {
2147 if (OPTS_FLAG(CORRECT_LOGIC) && (*out)->m_vtype == TYPE_VECTOR) {
2148 *out = ir_block_create_unary(func->m_curblock, self->m_context,
2149 ast_function_label(func, "sce_bool_v"),
2153 *out = ir_block_create_unary(func->m_curblock, self->m_context,
2154 ast_function_label(func, "sce_bool"),
2159 else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && (*out)->m_vtype == TYPE_STRING) {
2160 *out = ir_block_create_unary(func->m_curblock, self->m_context,
2161 ast_function_label(func, "sce_bool_s"),
2165 *out = ir_block_create_unary(func->m_curblock, self->m_context,
2166 ast_function_label(func, "sce_bool"),
2172 *out = ir_block_create_binop(func->m_curblock, self->m_context,
2173 ast_function_label(func, "sce_bool"),
2174 INSTR_AND, *out, *out);
2180 self->m_outr = *out;
2181 codegen_output_type(self, *out);
2185 if (self->m_right_first) {
2186 cgen = self->m_right->m_codegen;
2187 if (!(*cgen)((ast_expression*)(self->m_right), func, false, &right))
2189 cgen = self->m_left->m_codegen;
2190 if (!(*cgen)((ast_expression*)(self->m_left), func, false, &left))
2193 cgen = self->m_left->m_codegen;
2194 if (!(*cgen)((ast_expression*)(self->m_left), func, false, &left))
2196 cgen = self->m_right->m_codegen;
2197 if (!(*cgen)((ast_expression*)(self->m_right), func, false, &right))
2201 *out = ir_block_create_binop(func->m_curblock, self->m_context, ast_function_label(func, "bin"),
2202 self->m_op, left, right);
2205 self->m_outr = *out;
2206 codegen_output_type(self, *out);
2211 bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, ir_value **out)
2213 ast_expression_codegen *cgen;
2214 ir_value *leftl = nullptr, *leftr, *right, *bin;
2218 ast_array_index *ai = nullptr;
2219 ir_value *iridx = nullptr;
2221 if (lvalue && self->m_outl) {
2222 *out = self->m_outl;
2226 if (!lvalue && self->m_outr) {
2227 *out = self->m_outr;
2231 if (ast_istype(self->m_dest, ast_array_index))
2234 ai = (ast_array_index*)self->m_dest;
2235 idx = (ast_value*)ai->m_index;
2237 if (ast_istype(ai->m_index, ast_value) && idx->m_hasvalue && idx->m_cvq == CV_CONST)
2241 /* for a binstore we need both an lvalue and an rvalue for the left side */
2242 /* rvalue of destination! */
2244 cgen = idx->m_codegen;
2245 if (!(*cgen)((ast_expression*)(idx), func, false, &iridx))
2248 cgen = self->m_dest->m_codegen;
2249 if (!(*cgen)((ast_expression*)(self->m_dest), func, false, &leftr))
2252 /* source as rvalue only */
2253 cgen = self->m_source->m_codegen;
2254 if (!(*cgen)((ast_expression*)(self->m_source), func, false, &right))
2257 /* now the binary */
2258 bin = ir_block_create_binop(func->m_curblock, self->m_context, ast_function_label(func, "binst"),
2259 self->m_opbin, leftr, right);
2263 /* we need to call the setter */
2268 compile_error(self->m_context, "array-subscript assignment cannot produce lvalues");
2272 arr = (ast_value*)ai->m_array;
2273 if (!ast_istype(ai->m_array, ast_value) || !arr->m_setter) {
2274 compile_error(self->m_context, "value has no setter (%s)", arr->m_name);
2278 cgen = arr->m_setter->m_codegen;
2279 if (!(*cgen)((ast_expression*)(arr->m_setter), func, true, &funval))
2282 call = ir_block_create_call(func->m_curblock, self->m_context, ast_function_label(func, "store"), funval, false);
2285 ir_call_param(call, iridx);
2286 ir_call_param(call, bin);
2289 /* now store them */
2290 cgen = self->m_dest->m_codegen;
2291 /* lvalue of destination */
2292 if (!(*cgen)((ast_expression*)(self->m_dest), func, true, &leftl))
2294 self->m_outl = leftl;
2296 if (!ir_block_create_store_op(func->m_curblock, self->m_context, self->m_opstore, leftl, bin))
2301 /* Theoretically, an assinment returns its left side as an
2302 * lvalue, if we don't need an lvalue though, we return
2303 * the right side as an rvalue, otherwise we have to
2304 * somehow know whether or not we need to dereference the pointer
2305 * on the left side - that is: OP_LOAD if it was an address.
2306 * Also: in original QC we cannot OP_LOADP *anyway*.
2308 *out = (lvalue ? leftl : bin);
2313 bool ast_unary_codegen(ast_unary *self, ast_function *func, bool lvalue, ir_value **out)
2315 ast_expression_codegen *cgen;
2318 /* An unary operation cannot yield an l-value */
2320 compile_error(self->m_context, "not an l-value (binop)");
2325 *out = self->m_outr;
2329 cgen = self->m_operand->m_codegen;
2331 if (!(*cgen)((ast_expression*)(self->m_operand), func, false, &operand))
2334 *out = ir_block_create_unary(func->m_curblock, self->m_context, ast_function_label(func, "unary"),
2335 self->m_op, operand);
2338 self->m_outr = *out;
2343 bool ast_return_codegen(ast_return *self, ast_function *func, bool lvalue, ir_value **out)
2345 ast_expression_codegen *cgen;
2350 /* In the context of a return operation, we don't actually return
2354 compile_error(self->m_context, "return-expression is not an l-value");
2359 compile_error(self->m_context, "internal error: ast_return cannot be reused, it bears no result!");
2362 self->m_outr = (ir_value*)1;
2364 if (self->m_operand) {
2365 cgen = self->m_operand->m_codegen;
2367 if (!(*cgen)((ast_expression*)(self->m_operand), func, false, &operand))
2370 if (!ir_block_create_return(func->m_curblock, self->m_context, operand))
2373 if (!ir_block_create_return(func->m_curblock, self->m_context, nullptr))
2380 bool ast_entfield_codegen(ast_entfield *self, ast_function *func, bool lvalue, ir_value **out)
2382 ast_expression_codegen *cgen;
2383 ir_value *ent, *field;
2385 /* This function needs to take the 'lvalue' flag into account!
2386 * As lvalue we provide a field-pointer, as rvalue we provide the
2390 if (lvalue && self->m_outl) {
2391 *out = self->m_outl;
2395 if (!lvalue && self->m_outr) {
2396 *out = self->m_outr;
2400 cgen = self->m_entity->m_codegen;
2401 if (!(*cgen)((ast_expression*)(self->m_entity), func, false, &ent))
2404 cgen = self->m_field->m_codegen;
2405 if (!(*cgen)((ast_expression*)(self->m_field), func, false, &field))
2410 *out = ir_block_create_fieldaddress(func->m_curblock, self->m_context, ast_function_label(func, "efa"),
2413 *out = ir_block_create_load_from_ent(func->m_curblock, self->m_context, ast_function_label(func, "efv"),
2414 ent, field, self->m_vtype);
2415 /* Done AFTER error checking:
2416 codegen_output_type(self, *out);
2420 compile_error(self->m_context, "failed to create %s instruction (output type %s)",
2421 (lvalue ? "ADDRESS" : "FIELD"),
2422 type_name[self->m_vtype]);
2426 codegen_output_type(self, *out);
2429 self->m_outl = *out;
2431 self->m_outr = *out;
2433 /* Hm that should be it... */
2437 bool ast_member_codegen(ast_member *self, ast_function *func, bool lvalue, ir_value **out)
2439 ast_expression_codegen *cgen;
2442 /* in QC this is always an lvalue */
2443 if (lvalue && self->m_rvalue) {
2444 compile_error(self->m_context, "not an l-value (member access)");
2448 *out = self->m_outl;
2452 cgen = self->m_owner->m_codegen;
2453 if (!(*cgen)((ast_expression*)(self->m_owner), func, false, &vec))
2456 if (vec->m_vtype != TYPE_VECTOR &&
2457 !(vec->m_vtype == TYPE_FIELD && self->m_owner->m_next->m_vtype == TYPE_VECTOR))
2462 *out = ir_value_vector_member(vec, self->m_field);
2463 self->m_outl = *out;
2465 return (*out != nullptr);
2468 bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lvalue, ir_value **out)
2473 if (!lvalue && self->m_outr) {
2474 *out = self->m_outr;
2477 if (lvalue && self->m_outl) {
2478 *out = self->m_outl;
2482 if (!ast_istype(self->m_array, ast_value)) {
2483 compile_error(self->m_context, "array indexing this way is not supported");
2484 /* note this would actually be pointer indexing because the left side is
2485 * not an actual array but (hopefully) an indexable expression.
2486 * Once we get integer arithmetic, and GADDRESS/GSTORE/GLOAD instruction
2487 * support this path will be filled.
2492 arr = (ast_value*)self->m_array;
2493 idx = (ast_value*)self->m_index;
2495 if (!ast_istype(self->m_index, ast_value) || !idx->m_hasvalue || idx->m_cvq != CV_CONST) {
2496 /* Time to use accessor functions */
2497 ast_expression_codegen *cgen;
2498 ir_value *iridx, *funval;
2502 compile_error(self->m_context, "(.2) array indexing here needs a compile-time constant");
2506 if (!arr->m_getter) {
2507 compile_error(self->m_context, "value has no getter, don't know how to index it");
2511 cgen = self->m_index->m_codegen;
2512 if (!(*cgen)((ast_expression*)(self->m_index), func, false, &iridx))
2515 cgen = arr->m_getter->m_codegen;
2516 if (!(*cgen)((ast_expression*)(arr->m_getter), func, true, &funval))
2519 call = ir_block_create_call(func->m_curblock, self->m_context, ast_function_label(func, "fetch"), funval, false);
2522 ir_call_param(call, iridx);
2524 *out = ir_call_value(call);
2525 self->m_outr = *out;
2526 (*out)->m_vtype = self->m_vtype;
2527 codegen_output_type(self, *out);
2531 if (idx->m_vtype == TYPE_FLOAT) {
2532 unsigned int arridx = idx->m_constval.vfloat;
2533 if (arridx >= self->m_array->m_count)
2535 compile_error(self->m_context, "array index out of bounds: %i", arridx);
2538 *out = arr->m_ir_values[arridx];
2540 else if (idx->m_vtype == TYPE_INTEGER) {
2541 unsigned int arridx = idx->m_constval.vint;
2542 if (arridx >= self->m_array->m_count)
2544 compile_error(self->m_context, "array index out of bounds: %i", arridx);
2547 *out = arr->m_ir_values[arridx];
2550 compile_error(self->m_context, "array indexing here needs an integer constant");
2553 (*out)->m_vtype = self->m_vtype;
2554 codegen_output_type(self, *out);
2558 bool ast_argpipe_codegen(ast_argpipe *self, ast_function *func, bool lvalue, ir_value **out)
2562 compile_error(self->m_context, "argpipe node: not an lvalue");
2567 compile_error(self->m_context, "TODO: argpipe codegen not implemented");
2571 bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_value **out)
2573 ast_expression_codegen *cgen;
2581 ir_block *ontrue_endblock = nullptr;
2582 ir_block *onfalse_endblock = nullptr;
2583 ir_block *merge = nullptr;
2586 /* We don't output any value, thus also don't care about r/lvalue */
2591 compile_error(self->m_context, "internal error: ast_ifthen cannot be reused, it bears no result!");
2594 self->m_outr = (ir_value*)1;
2596 /* generate the condition */
2597 cgen = self->m_cond->m_codegen;
2598 if (!(*cgen)((ast_expression*)(self->m_cond), func, false, &condval))
2600 /* update the block which will get the jump - because short-logic or ternaries may have changed this */
2601 cond = func->m_curblock;
2603 /* try constant folding away the condition */
2604 if ((folded = fold::cond_ifthen(condval, func, self)) != -1)
2607 if (self->m_on_true) {
2608 /* create on-true block */
2609 ontrue = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "ontrue"));
2613 /* enter the block */
2614 func->m_curblock = ontrue;
2617 cgen = self->m_on_true->m_codegen;
2618 if (!(*cgen)((ast_expression*)(self->m_on_true), func, false, &dummy))
2621 /* we now need to work from the current endpoint */
2622 ontrue_endblock = func->m_curblock;
2627 if (self->m_on_false) {
2628 /* create on-false block */
2629 onfalse = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "onfalse"));
2633 /* enter the block */
2634 func->m_curblock = onfalse;
2637 cgen = self->m_on_false->m_codegen;
2638 if (!(*cgen)((ast_expression*)(self->m_on_false), func, false, &dummy))
2641 /* we now need to work from the current endpoint */
2642 onfalse_endblock = func->m_curblock;
2646 /* Merge block were they all merge in to */
2647 if (!ontrue || !onfalse || !ontrue_endblock->m_final || !onfalse_endblock->m_final)
2649 merge = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "endif"));
2652 /* add jumps ot the merge block */
2653 if (ontrue && !ontrue_endblock->m_final && !ir_block_create_jump(ontrue_endblock, self->m_context, merge))
2655 if (onfalse && !onfalse_endblock->m_final && !ir_block_create_jump(onfalse_endblock, self->m_context, merge))
2658 /* Now enter the merge block */
2659 func->m_curblock = merge;
2662 /* we create the if here, that way all blocks are ordered :)
2664 if (!ir_block_create_if(cond, self->m_context, condval,
2665 (ontrue ? ontrue : merge),
2666 (onfalse ? onfalse : merge)))
2674 bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_value **out)
2676 ast_expression_codegen *cgen;
2679 ir_value *trueval, *falseval;
2682 ir_block *cond = func->m_curblock;
2683 ir_block *cond_out = nullptr;
2684 ir_block *ontrue, *ontrue_out = nullptr;
2685 ir_block *onfalse, *onfalse_out = nullptr;
2689 /* Ternary can never create an lvalue... */
2693 /* In theory it shouldn't be possible to pass through a node twice, but
2694 * in case we add any kind of optimization pass for the AST itself, it
2695 * may still happen, thus we remember a created ir_value and simply return one
2696 * if it already exists.
2699 *out = self->m_outr;
2703 /* In the following, contraty to ast_ifthen, we assume both paths exist. */
2705 /* generate the condition */
2706 func->m_curblock = cond;
2707 cgen = self->m_cond->m_codegen;
2708 if (!(*cgen)((ast_expression*)(self->m_cond), func, false, &condval))
2710 cond_out = func->m_curblock;
2712 /* try constant folding away the condition */
2713 if ((folded = fold::cond_ternary(condval, func, self)) != -1)
2716 /* create on-true block */
2717 ontrue = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "tern_T"));
2722 /* enter the block */
2723 func->m_curblock = ontrue;
2726 cgen = self->m_on_true->m_codegen;
2727 if (!(*cgen)((ast_expression*)(self->m_on_true), func, false, &trueval))
2730 ontrue_out = func->m_curblock;
2733 /* create on-false block */
2734 onfalse = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "tern_F"));
2739 /* enter the block */
2740 func->m_curblock = onfalse;
2743 cgen = self->m_on_false->m_codegen;
2744 if (!(*cgen)((ast_expression*)(self->m_on_false), func, false, &falseval))
2747 onfalse_out = func->m_curblock;
2750 /* create merge block */
2751 merge = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "tern_out"));
2754 /* jump to merge block */
2755 if (!ir_block_create_jump(ontrue_out, self->m_context, merge))
2757 if (!ir_block_create_jump(onfalse_out, self->m_context, merge))
2760 /* create if instruction */
2761 if (!ir_block_create_if(cond_out, self->m_context, condval, ontrue, onfalse))
2764 /* Now enter the merge block */
2765 func->m_curblock = merge;
2767 /* Here, now, we need a PHI node
2768 * but first some sanity checking...
2770 if (trueval->m_vtype != falseval->m_vtype && trueval->m_vtype != TYPE_NIL && falseval->m_vtype != TYPE_NIL) {
2771 /* error("ternary with different types on the two sides"); */
2772 compile_error(self->m_context, "internal error: ternary operand types invalid");
2777 phi = ir_block_create_phi(merge, self->m_context, ast_function_label(func, "phi"), self->m_vtype);
2779 compile_error(self->m_context, "internal error: failed to generate phi node");
2782 ir_phi_add(phi, ontrue_out, trueval);
2783 ir_phi_add(phi, onfalse_out, falseval);
2785 self->m_outr = ir_phi_value(phi);
2786 *out = self->m_outr;
2788 codegen_output_type(self, *out);
2793 bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value **out)
2795 ast_expression_codegen *cgen;
2797 ir_value *dummy = nullptr;
2798 ir_value *precond = nullptr;
2799 ir_value *postcond = nullptr;
2801 /* Since we insert some jumps "late" so we have blocks
2802 * ordered "nicely", we need to keep track of the actual end-blocks
2803 * of expressions to add the jumps to.
2805 ir_block *bbody = nullptr, *end_bbody = nullptr;
2806 ir_block *bprecond = nullptr, *end_bprecond = nullptr;
2807 ir_block *bpostcond = nullptr, *end_bpostcond = nullptr;
2808 ir_block *bincrement = nullptr, *end_bincrement = nullptr;
2809 ir_block *bout = nullptr, *bin = nullptr;
2811 /* let's at least move the outgoing block to the end */
2814 /* 'break' and 'continue' need to be able to find the right blocks */
2815 ir_block *bcontinue = nullptr;
2816 ir_block *bbreak = nullptr;
2818 ir_block *tmpblock = nullptr;
2824 compile_error(self->m_context, "internal error: ast_loop cannot be reused, it bears no result!");
2827 self->m_outr = (ir_value*)1;
2830 * Should we ever need some kind of block ordering, better make this function
2831 * move blocks around than write a block ordering algorithm later... after all
2832 * the ast and ir should work together, not against each other.
2835 /* initexpr doesn't get its own block, it's pointless, it could create more blocks
2836 * anyway if for example it contains a ternary.
2838 if (self->m_initexpr)
2840 cgen = self->m_initexpr->m_codegen;
2841 if (!(*cgen)((ast_expression*)(self->m_initexpr), func, false, &dummy))
2845 /* Store the block from which we enter this chaos */
2846 bin = func->m_curblock;
2848 /* The pre-loop condition needs its own block since we
2849 * need to be able to jump to the start of that expression.
2851 if (self->m_precond)
2853 bprecond = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "pre_loop_cond"));
2857 /* the pre-loop-condition the least important place to 'continue' at */
2858 bcontinue = bprecond;
2861 func->m_curblock = bprecond;
2864 cgen = self->m_precond->m_codegen;
2865 if (!(*cgen)((ast_expression*)(self->m_precond), func, false, &precond))
2868 end_bprecond = func->m_curblock;
2870 bprecond = end_bprecond = nullptr;
2873 /* Now the next blocks won't be ordered nicely, but we need to
2874 * generate them this early for 'break' and 'continue'.
2876 if (self->m_increment) {
2877 bincrement = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "loop_increment"));
2880 bcontinue = bincrement; /* increment comes before the pre-loop-condition */
2882 bincrement = end_bincrement = nullptr;
2885 if (self->m_postcond) {
2886 bpostcond = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "post_loop_cond"));
2889 bcontinue = bpostcond; /* postcond comes before the increment */
2891 bpostcond = end_bpostcond = nullptr;
2894 bout_id = func->m_ir_func->m_blocks.size();
2895 bout = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "after_loop"));
2900 /* The loop body... */
2901 /* if (self->m_body) */
2903 bbody = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "loop_body"));
2908 func->m_curblock = bbody;
2910 func->m_breakblocks.push_back(bbreak);
2912 func->m_continueblocks.push_back(bcontinue);
2914 func->m_continueblocks.push_back(bbody);
2918 cgen = self->m_body->m_codegen;
2919 if (!(*cgen)((ast_expression*)(self->m_body), func, false, &dummy))
2923 end_bbody = func->m_curblock;
2924 func->m_breakblocks.pop_back();
2925 func->m_continueblocks.pop_back();
2928 /* post-loop-condition */
2929 if (self->m_postcond)
2932 func->m_curblock = bpostcond;
2935 cgen = self->m_postcond->m_codegen;
2936 if (!(*cgen)((ast_expression*)(self->m_postcond), func, false, &postcond))
2939 end_bpostcond = func->m_curblock;
2942 /* The incrementor */
2943 if (self->m_increment)
2946 func->m_curblock = bincrement;
2949 cgen = self->m_increment->m_codegen;
2950 if (!(*cgen)((ast_expression*)(self->m_increment), func, false, &dummy))
2953 end_bincrement = func->m_curblock;
2956 /* In any case now, we continue from the outgoing block */
2957 func->m_curblock = bout;
2959 /* Now all blocks are in place */
2960 /* From 'bin' we jump to whatever comes first */
2961 if (bprecond) tmpblock = bprecond;
2962 else tmpblock = bbody; /* can never be null */
2965 else if (bpostcond) tmpblock = bpostcond;
2966 else tmpblock = bout;
2969 if (!ir_block_create_jump(bin, self->m_context, tmpblock))
2975 ir_block *ontrue, *onfalse;
2976 ontrue = bbody; /* can never be null */
2978 /* all of this is dead code
2979 else if (bincrement) ontrue = bincrement;
2980 else ontrue = bpostcond;
2984 if (self->m_pre_not) {
2989 if (!ir_block_create_if(end_bprecond, self->m_context, precond, ontrue, onfalse))
2996 if (bincrement) tmpblock = bincrement;
2997 else if (bpostcond) tmpblock = bpostcond;
2998 else if (bprecond) tmpblock = bprecond;
2999 else tmpblock = bbody;
3000 if (!end_bbody->m_final && !ir_block_create_jump(end_bbody, self->m_context, tmpblock))
3004 /* from increment */
3007 if (bpostcond) tmpblock = bpostcond;
3008 else if (bprecond) tmpblock = bprecond;
3009 else if (bbody) tmpblock = bbody;
3010 else tmpblock = bout;
3011 if (!ir_block_create_jump(end_bincrement, self->m_context, tmpblock))
3018 ir_block *ontrue, *onfalse;
3019 if (bprecond) ontrue = bprecond;
3020 else ontrue = bbody; /* can never be null */
3022 /* all of this is dead code
3023 else if (bincrement) ontrue = bincrement;
3024 else ontrue = bpostcond;
3028 if (self->m_post_not) {
3033 if (!ir_block_create_if(end_bpostcond, self->m_context, postcond, ontrue, onfalse))
3037 /* Move 'bout' to the end */
3038 algo::shiftback(func->m_ir_func->m_blocks.begin() + bout_id,
3039 func->m_ir_func->m_blocks.end());
3041 //func->m_ir_func->m_blocks[bout_id].release(); // it's a vector<unique_ptr<>>
3042 //func->m_ir_func->m_blocks.erase(func->m_ir_func->m_blocks.begin() + bout_id);
3043 //func->m_ir_func->m_blocks.emplace_back(bout);
3048 bool ast_breakcont_codegen(ast_breakcont *self, ast_function *func, bool lvalue, ir_value **out)
3055 compile_error(self->m_context, "break/continue expression is not an l-value");
3060 compile_error(self->m_context, "internal error: ast_breakcont cannot be reused!");
3063 self->m_outr = (ir_value*)1;
3065 if (self->m_is_continue)
3066 target = func->m_continueblocks[func->m_continueblocks.size()-1-self->m_levels];
3068 target = func->m_breakblocks[func->m_breakblocks.size()-1-self->m_levels];
3071 compile_error(self->m_context, "%s is lacking a target block", (self->m_is_continue ? "continue" : "break"));
3075 if (!ir_block_create_jump(func->m_curblock, self->m_context, target))
3080 bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_value **out)
3082 ast_expression_codegen *cgen;
3084 ast_switch_case *def_case = nullptr;
3085 ir_block *def_bfall = nullptr;
3086 ir_block *def_bfall_to = nullptr;
3087 bool set_def_bfall_to = false;
3089 ir_value *dummy = nullptr;
3090 ir_value *irop = nullptr;
3091 ir_block *bout = nullptr;
3092 ir_block *bfall = nullptr;
3099 compile_error(self->m_context, "switch expression is not an l-value");
3104 compile_error(self->m_context, "internal error: ast_switch cannot be reused!");
3107 self->m_outr = (ir_value*)1;
3112 cgen = self->m_operand->m_codegen;
3113 if (!(*cgen)((ast_expression*)(self->m_operand), func, false, &irop))
3116 if (self->m_cases.empty())
3119 cmpinstr = type_eq_instr[irop->m_vtype];
3120 if (cmpinstr >= VINSTR_END) {
3121 ast_type_to_string(self->m_operand, typestr, sizeof(typestr));
3122 compile_error(self->m_context, "invalid type to perform a switch on: %s", typestr);
3126 bout_id = func->m_ir_func->m_blocks.size();
3127 bout = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "after_switch"));
3131 /* setup the break block */
3132 func->m_breakblocks.push_back(bout);
3134 /* Now create all cases */
3135 for (auto &it : self->m_cases) {
3136 ir_value *cond, *val;
3137 ir_block *bcase, *bnot;
3140 ast_switch_case *swcase = ⁢
3142 if (swcase->m_value) {
3143 /* A regular case */
3144 /* generate the condition operand */
3145 cgen = swcase->m_value->m_codegen;
3146 if (!(*cgen)((ast_expression*)(swcase->m_value), func, false, &val))
3148 /* generate the condition */
3149 cond = ir_block_create_binop(func->m_curblock, self->m_context, ast_function_label(func, "switch_eq"), cmpinstr, irop, val);
3153 bcase = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "case"));
3154 bnot_id = func->m_ir_func->m_blocks.size();
3155 bnot = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "not_case"));
3156 if (!bcase || !bnot)
3158 if (set_def_bfall_to) {
3159 set_def_bfall_to = false;
3160 def_bfall_to = bcase;
3162 if (!ir_block_create_if(func->m_curblock, self->m_context, cond, bcase, bnot))
3165 /* Make the previous case-end fall through */
3166 if (bfall && !bfall->m_final) {
3167 if (!ir_block_create_jump(bfall, self->m_context, bcase))
3171 /* enter the case */
3172 func->m_curblock = bcase;
3173 cgen = swcase->m_code->m_codegen;
3174 if (!(*cgen)((ast_expression*)swcase->m_code, func, false, &dummy))
3177 /* remember this block to fall through from */
3178 bfall = func->m_curblock;
3180 /* enter the else and move it down */
3181 func->m_curblock = bnot;
3182 algo::shiftback(func->m_ir_func->m_blocks.begin() + bnot_id,
3183 func->m_ir_func->m_blocks.end());
3185 //func->m_ir_func->m_blocks[bnot_id].release();
3186 //func->m_ir_func->m_blocks.erase(func->m_ir_func->m_blocks.begin() + bnot_id);
3187 //func->m_ir_func->m_blocks.emplace_back(bnot);
3189 /* The default case */
3190 /* Remember where to fall through from: */
3193 /* remember which case it was */
3195 /* And the next case will be remembered */
3196 set_def_bfall_to = true;
3200 /* Jump from the last bnot to bout */
3201 if (bfall && !bfall->m_final && !ir_block_create_jump(bfall, self->m_context, bout)) {
3203 astwarning(bfall->m_context, WARN_???, "missing break after last case");
3208 /* If there was a default case, put it down here */
3212 /* No need to create an extra block */
3213 bcase = func->m_curblock;
3215 /* Insert the fallthrough jump */
3216 if (def_bfall && !def_bfall->m_final) {
3217 if (!ir_block_create_jump(def_bfall, self->m_context, bcase))
3221 /* Now generate the default code */
3222 cgen = def_case->m_code->m_codegen;
3223 if (!(*cgen)((ast_expression*)def_case->m_code, func, false, &dummy))
3226 /* see if we need to fall through */
3227 if (def_bfall_to && !func->m_curblock->m_final)
3229 if (!ir_block_create_jump(func->m_curblock, self->m_context, def_bfall_to))
3234 /* Jump from the last bnot to bout */
3235 if (!func->m_curblock->m_final && !ir_block_create_jump(func->m_curblock, self->m_context, bout))
3237 /* enter the outgoing block */
3238 func->m_curblock = bout;
3240 /* restore the break block */
3241 func->m_breakblocks.pop_back();
3243 /* Move 'bout' to the end, it's nicer */
3244 algo::shiftback(func->m_ir_func->m_blocks.begin() + bout_id,
3245 func->m_ir_func->m_blocks.end());
3247 //func->m_ir_func->m_blocks[bout_id].release();
3248 //func->m_ir_func->m_blocks.erase(func->m_ir_func->m_blocks.begin() + bout_id);
3249 //func->m_ir_func->m_blocks.emplace_back(bout);
3254 bool ast_label_codegen(ast_label *self, ast_function *func, bool lvalue, ir_value **out)
3258 if (self->m_undefined) {
3259 compile_error(self->m_context, "internal error: ast_label never defined");
3265 compile_error(self->m_context, "internal error: ast_label cannot be an lvalue");
3269 /* simply create a new block and jump to it */
3270 self->m_irblock = ir_function_create_block(self->m_context, func->m_ir_func, self->m_name);
3271 if (!self->m_irblock) {
3272 compile_error(self->m_context, "failed to allocate label block `%s`", self->m_name);
3275 if (!func->m_curblock->m_final) {
3276 if (!ir_block_create_jump(func->m_curblock, self->m_context, self->m_irblock))
3280 /* enter the new block */
3281 func->m_curblock = self->m_irblock;
3283 /* Generate all the leftover gotos */
3284 for (auto &it : self->m_gotos) {
3285 if (!ast_goto_codegen(it, func, false, &dummy))
3292 bool ast_goto_codegen(ast_goto *self, ast_function *func, bool lvalue, ir_value **out)
3296 compile_error(self->m_context, "internal error: ast_goto cannot be an lvalue");
3300 if (self->m_target->m_irblock) {
3301 if (self->m_irblock_from) {
3302 /* we already tried once, this is the callback */
3303 self->m_irblock_from->m_final = false;
3304 if (!ir_block_create_goto(self->m_irblock_from, self->m_context, self->m_target->m_irblock)) {
3305 compile_error(self->m_context, "failed to generate goto to `%s`", self->m_name);
3311 if (!ir_block_create_goto(func->m_curblock, self->m_context, self->m_target->m_irblock)) {
3312 compile_error(self->m_context, "failed to generate goto to `%s`", self->m_name);
3319 /* the target has not yet been created...
3320 * close this block in a sneaky way:
3322 func->m_curblock->m_final = true;
3323 self->m_irblock_from = func->m_curblock;
3324 ast_label_register_goto(self->m_target, self);
3331 bool ast_state_codegen(ast_state *self, ast_function *func, bool lvalue, ir_value **out)
3333 ast_expression_codegen *cgen;
3335 ir_value *frameval, *thinkval;
3338 compile_error(self->m_context, "not an l-value (state operation)");
3342 compile_error(self->m_context, "internal error: ast_state cannot be reused!");
3347 cgen = self->m_framenum->m_codegen;
3348 if (!(*cgen)((ast_expression*)(self->m_framenum), func, false, &frameval))
3353 cgen = self->m_nextthink->m_codegen;
3354 if (!(*cgen)((ast_expression*)(self->m_nextthink), func, false, &thinkval))
3359 if (!ir_block_create_state_op(func->m_curblock, self->m_context, frameval, thinkval)) {
3360 compile_error(self->m_context, "failed to create STATE instruction");
3364 self->m_outr = (ir_value*)1;
3368 bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value **out)
3370 ast_expression_codegen *cgen;
3371 std::vector<ir_value*> params;
3372 ir_instr *callinstr;
3374 ir_value *funval = nullptr;
3376 /* return values are never lvalues */
3378 compile_error(self->m_context, "not an l-value (function call)");
3383 *out = self->m_outr;
3387 cgen = self->m_func->m_codegen;
3388 if (!(*cgen)((ast_expression*)(self->m_func), func, false, &funval))
3394 for (auto &it : self->m_params) {
3396 cgen = it->m_codegen;
3397 if (!(*cgen)(it, func, false, ¶m))
3401 params.push_back(param);
3404 /* varargs counter */
3405 if (self->m_va_count) {
3407 ir_builder *builder = func->m_curblock->m_owner->m_owner;
3408 cgen = self->m_va_count->m_codegen;
3409 if (!(*cgen)((ast_expression*)(self->m_va_count), func, false, &va_count))
3411 if (!ir_block_create_store_op(func->m_curblock, self->m_context, INSTR_STORE_F,
3412 ir_builder_get_va_count(builder), va_count))
3418 callinstr = ir_block_create_call(func->m_curblock, self->m_context,
3419 ast_function_label(func, "call"),
3420 funval, !!(self->m_func->m_flags & AST_FLAG_NORETURN));
3424 for (auto &it : params)
3425 ir_call_param(callinstr, it);
3427 *out = ir_call_value(callinstr);
3428 self->m_outr = *out;
3430 codegen_output_type(self, *out);