]> de.git.xonotic.org Git - xonotic/gmqcc.git/blob - ast.h
sanitize: shift 1u (unsigned) for flag bits
[xonotic/gmqcc.git] / ast.h
1 #ifndef GMQCC_AST_HDR
2 #define GMQCC_AST_HDR
3 #include <vector>
4 #include "ir.h"
5
6 typedef uint16_t ast_flag_t;
7
8 /* Note: I will not be using a _t suffix for the
9  * "main" ast node types for now.
10  */
11
12 struct ast_node;
13 struct ast_expression;
14 struct ast_value;
15 struct ast_function;
16 struct ast_block;
17 struct ast_binary;
18 struct ast_store;
19 struct ast_binstore;
20 struct ast_entfield;
21 struct ast_ifthen;
22 struct ast_ternary;
23 struct ast_loop;
24 struct ast_call;
25 struct ast_unary;
26 struct ast_return;
27 struct ast_member;
28 struct ast_array_index;
29 struct ast_breakcont;
30 struct ast_switch;
31 struct ast_label;
32 struct ast_goto;
33 struct ast_argpipe;
34 struct ast_state;
35
36 enum {
37     AST_FLAG_VARIADIC       = 1 << 0,
38     AST_FLAG_NORETURN       = 1 << 1,
39     AST_FLAG_INLINE         = 1 << 2,
40     AST_FLAG_INITIALIZED    = 1 << 3,
41     AST_FLAG_DEPRECATED     = 1 << 4,
42     AST_FLAG_INCLUDE_DEF    = 1 << 5,
43     AST_FLAG_IS_VARARG      = 1 << 6,
44     AST_FLAG_ALIAS          = 1 << 7,
45     AST_FLAG_ERASEABLE      = 1 << 8,
46     AST_FLAG_ACCUMULATE     = 1 << 9,
47
48     /* An array declared as []
49      * so that the size is taken from the initializer
50      */
51     AST_FLAG_ARRAY_INIT     = 1 << 10,
52
53     AST_FLAG_FINAL_DECL     = 1 << 11,
54
55     /* Several coverage options
56      * AST_FLAG_COVERAGE means there was an explicit [[coverage]] attribute,
57      * which will overwrite the default set via the commandline switches.
58      * BLOCK_COVERAGE inserts coverage() calls into every basic block.
59      * In the future there might be more options like tracking variable access
60      * by creating get/set wrapper functions.
61      */
62     AST_FLAG_COVERAGE       = 1 << 12,
63     AST_FLAG_BLOCK_COVERAGE = 1 << 13,
64
65     /*
66      * Propagates norefness to the IR so the unused (read/write) check can be
67      * more intelligently done.
68      */
69     AST_FLAG_NOREF          = 1 << 14,
70
71     AST_FLAG_LAST,
72     AST_FLAG_TYPE_MASK      = (AST_FLAG_VARIADIC | AST_FLAG_NORETURN),
73     AST_FLAG_COVERAGE_MASK  = (AST_FLAG_BLOCK_COVERAGE)
74 };
75
76 enum {
77     TYPE_ast_node,        /*  0 */
78     TYPE_ast_expression,  /*  1 */
79     TYPE_ast_value,       /*  2 */
80     TYPE_ast_function,    /*  3 */
81     TYPE_ast_block,       /*  4 */
82     TYPE_ast_binary,      /*  5 */
83     TYPE_ast_store,       /*  6 */
84     TYPE_ast_binstore,    /*  7 */
85     TYPE_ast_entfield,    /*  8 */
86     TYPE_ast_ifthen,      /*  9 */
87     TYPE_ast_ternary,     /* 10 */
88     TYPE_ast_loop,        /* 11 */
89     TYPE_ast_call,        /* 12 */
90     TYPE_ast_unary,       /* 13 */
91     TYPE_ast_return,      /* 14 */
92     TYPE_ast_member,      /* 15 */
93     TYPE_ast_array_index, /* 16 */
94     TYPE_ast_breakcont,   /* 17 */
95     TYPE_ast_switch,      /* 18 */
96     TYPE_ast_label,       /* 19 */
97     TYPE_ast_goto,        /* 20 */
98     TYPE_ast_argpipe,     /* 21 */
99     TYPE_ast_state        /* 22 */
100 };
101
102 #define ast_istype(x, t) ( (x)->m_node_type == (TYPE_##t) )
103
104 struct ast_node
105 {
106     ast_node() = delete;
107     ast_node(lex_ctx_t, int nodetype);
108     virtual ~ast_node();
109
110     lex_ctx_t m_context;
111     /* I don't feel comfortable using keywords like 'delete' as names... */
112     int              m_node_type;
113     /* keep_node: if a node contains this node, 'keep_node'
114      * prevents its dtor from destroying this node as well.
115      */
116     bool             m_keep_node;
117     bool             m_side_effects;
118
119     void propagateSideEffects(const ast_node *other);
120 };
121
122 #define ast_unref(x) do        \
123 {                              \
124     if (! (x)->m_keep_node ) { \
125         delete (x);            \
126     }                          \
127 } while(0)
128
129 enum class ast_copy_type_t { value };
130 static const ast_copy_type_t ast_copy_type = ast_copy_type_t::value;
131
132 /* TODO: the codegen function should take an output-type parameter
133  * indicating whether a variable, type, label etc. is expected, and
134  * an environment!
135  * Then later an ast_ident could have a codegen using this to figure
136  * out what to look for.
137  * eg. in code which uses a not-yet defined variable, the expression
138  * would take an ast_ident, and the codegen would be called with
139  * type `expression`, so the ast_ident's codegen would search for
140  * variables through the environment (or functions, constants...).
141  */
142 struct ast_expression : ast_node {
143     ast_expression() = delete;
144     ast_expression(lex_ctx_t ctx, int nodetype, qc_type vtype);
145     ast_expression(lex_ctx_t ctx, int nodetype);
146     ~ast_expression();
147
148     ast_expression(ast_copy_type_t, const ast_expression&);
149     ast_expression(ast_copy_type_t, lex_ctx_t ctx, const ast_expression&);
150     ast_expression(ast_copy_type_t, int nodetype, const ast_expression&);
151     ast_expression(ast_copy_type_t, int nodetype, lex_ctx_t ctx, const ast_expression&);
152
153     static ast_expression *shallowType(lex_ctx_t ctx, qc_type vtype);
154
155     bool compareType(const ast_expression &other) const;
156     void adoptType(const ast_expression &other);
157
158     qc_type                 m_vtype = TYPE_VOID;
159     ast_expression         *m_next = nullptr;
160     /* arrays get a member-count */
161     size_t                  m_count = 0;
162     std::vector<std::unique_ptr<ast_value>> m_type_params;
163
164     ast_flag_t              m_flags = 0;
165     /* void foo(string...) gets varparam set as a restriction
166      * for variadic parameters
167      */
168     ast_expression         *m_varparam = nullptr;
169     /* The codegen functions should store their output values
170      * so we can call it multiple times without re-evaluating.
171      * Store lvalue and rvalue seperately though. So that
172      * ast_entfield for example can generate both if required.
173      */
174     ir_value               *m_outl = nullptr;
175     ir_value               *m_outr = nullptr;
176
177     virtual bool codegen(ast_function *current, bool lvalue, ir_value **out);
178 };
179
180 /* Value
181  *
182  * Types are also values, both have a type and a name.
183  * especially considering possible constructs like typedefs.
184  * typedef float foo;
185  * is like creating a 'float foo', foo serving as the type's name.
186  */
187 union basic_value_t {
188     qcfloat_t     vfloat;
189     int           vint;
190     vec3_t        vvec;
191     const char   *vstring;
192     int           ventity;
193     ast_function *vfunc;
194     ast_value    *vfield;
195 };
196
197 struct ast_value : ast_expression
198 {
199     ast_value() = delete;
200     ast_value(lex_ctx_t ctx, const std::string &name, qc_type qctype);
201     ~ast_value();
202
203     ast_value(ast_copy_type_t, const ast_expression&, const std::string&);
204     ast_value(ast_copy_type_t, const ast_value&);
205     ast_value(ast_copy_type_t, const ast_value&, const std::string&);
206
207     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
208
209     void addParam(ast_value*);
210
211     bool generateGlobal(ir_builder*, bool isfield);
212     bool generateLocal(ir_function*, bool param);
213     bool generateAccessors(ir_builder*);
214
215     std::string m_name;
216     std::string m_desc;
217
218     const char *m_argcounter = nullptr;
219
220     int m_cvq = CV_NONE;     /* const/var qualifier */
221     bool m_isfield = false; /* this declares a field */
222     bool m_isimm = false;   /* an immediate, not just const */
223     bool m_hasvalue = false;
224     bool m_inexact = false; /* inexact coming from folded expression */
225     basic_value_t m_constval;
226     /* for TYPE_ARRAY we have an optional vector
227      * of constants when an initializer list
228      * was provided.
229      */
230     std::vector<basic_value_t> m_initlist;
231
232     ir_value *m_ir_v = nullptr;
233     std::vector<ir_value*> m_ir_values;
234     size_t m_ir_value_count = 0;
235
236     /* ONLY for arrays in progs version up to 6 */
237     ast_value *m_setter = nullptr;
238     ast_value *m_getter = nullptr;
239
240     bool m_intrinsic = false; /* true if associated with intrinsic */
241
242 private:
243     bool generateGlobalFunction(ir_builder*);
244     bool generateGlobalField(ir_builder*);
245     ir_value *prepareGlobalArray(ir_builder*);
246     bool setGlobalArray();
247     bool checkArray(const ast_value &array) const;
248 };
249
250 void ast_type_to_string(const ast_expression *e, char *buf, size_t bufsize);
251
252 enum ast_binary_ref {
253     AST_REF_NONE  = 0,
254     AST_REF_LEFT  = 1 << 1,
255     AST_REF_RIGHT = 1 << 2,
256     AST_REF_ALL   = (AST_REF_LEFT | AST_REF_RIGHT)
257 };
258
259
260 /* Binary
261  *
262  * A value-returning binary expression.
263  */
264 struct ast_binary : ast_expression
265 {
266     ast_binary() = delete;
267     ast_binary(lex_ctx_t ctx, int op, ast_expression *l, ast_expression *r);
268     ~ast_binary();
269
270     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
271
272     int m_op;
273     ast_expression *m_left;
274     ast_expression *m_right;
275     ast_binary_ref m_refs;
276     bool m_right_first;
277 };
278
279 /* Binstore
280  *
281  * An assignment including a binary expression with the source as left operand.
282  * Eg. a += b; is a binstore { INSTR_STORE, INSTR_ADD, a, b }
283  */
284 struct ast_binstore : ast_expression
285 {
286     ast_binstore() = delete;
287     ast_binstore(lex_ctx_t ctx, int storeop, int mathop, ast_expression *l, ast_expression *r);
288     ~ast_binstore();
289
290     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
291
292     int m_opstore;
293     int m_opbin;
294     ast_expression *m_dest;
295     ast_expression *m_source;
296     /* for &~= which uses the destination in a binary in source we can use this */
297     bool m_keep_dest;
298 };
299
300 /* Unary
301  *
302  * Regular unary expressions: not,neg
303  */
304 struct ast_unary : ast_expression
305 {
306     ast_unary() = delete;
307     ~ast_unary();
308
309     static ast_unary* make(lex_ctx_t ctx, int op, ast_expression *expr);
310
311     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
312
313     int m_op;
314     ast_expression *m_operand;
315
316 private:
317     ast_unary(lex_ctx_t ctx, int op, ast_expression *expr);
318 };
319
320 /* Return
321  *
322  * Make sure 'return' only happens at the end of a block, otherwise the IR
323  * will refuse to create further instructions.
324  * This should be honored by the parser.
325  */
326 struct ast_return : ast_expression
327 {
328     ast_return() = delete;
329     ast_return(lex_ctx_t ctx, ast_expression *expr);
330     ~ast_return();
331
332     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
333
334     ast_expression *m_operand;
335 };
336
337 /* Entity-field
338  *
339  * This must do 2 things:
340  * -) Provide a way to fetch an entity field value. (Rvalue)
341  * -) Provide a pointer to an entity field. (Lvalue)
342  * The problem:
343  * In original QC, there's only a STORE via pointer, but
344  * no LOAD via pointer.
345  * So we must know beforehand if we are going to read or assign
346  * the field.
347  * For this we will have to extend the codegen() functions with
348  * a flag saying whether or not we need an L or an R-value.
349  */
350 struct ast_entfield : ast_expression
351 {
352     ast_entfield() = delete;
353     ast_entfield(lex_ctx_t ctx, ast_expression *entity, ast_expression *field);
354     ast_entfield(lex_ctx_t ctx, ast_expression *entity, ast_expression *field, const ast_expression *outtype);
355     ~ast_entfield();
356
357     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
358
359     // The entity can come from an expression of course.
360     ast_expression *m_entity;
361     // As can the field, it just must result in a value of TYPE_FIELD
362     ast_expression *m_field;
363 };
364
365 /* Member access:
366  *
367  * For now used for vectors. If we get structs or unions
368  * we can have them handled here as well.
369  */
370 struct ast_member : ast_expression
371 {
372     static ast_member *make(lex_ctx_t ctx, ast_expression *owner, unsigned int field, const std::string &name);
373     ~ast_member();
374
375     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
376
377     ast_expression *m_owner;
378     unsigned int m_field;
379     std::string m_name;
380     bool m_rvalue;
381
382 private:
383     ast_member() = delete;
384     ast_member(lex_ctx_t ctx, ast_expression *owner, unsigned int field, const std::string &name);
385 };
386
387 /* Array index access:
388  *
389  * QC forces us to take special action on arrays:
390  * an ast_store on an ast_array_index must not codegen the index,
391  * but call its setter - unless we have an instruction set which supports
392  * what we need.
393  * Any other array index access will be codegened to a call to the getter.
394  * In any case, accessing an element via a compiletime-constant index will
395  * result in quick access to that variable.
396  */
397 struct ast_array_index : ast_expression
398 {
399     static ast_array_index* make(lex_ctx_t ctx, ast_expression *array, ast_expression *index);
400     ~ast_array_index();
401
402     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
403
404     ast_expression *m_array;
405     ast_expression *m_index;
406 private:
407     ast_array_index() = delete;
408     ast_array_index(lex_ctx_t ctx, ast_expression *array, ast_expression *index);
409 };
410
411 /* Vararg pipe node:
412  *
413  * copy all varargs starting from a specific index
414  */
415 struct ast_argpipe : ast_expression
416 {
417     ast_argpipe() = delete;
418     ast_argpipe(lex_ctx_t ctx, ast_expression *index);
419
420     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
421
422     ~ast_argpipe();
423     ast_expression *m_index;
424 };
425
426 /* Store
427  *
428  * Stores left<-right and returns left.
429  * Specialized binary expression node
430  */
431 struct ast_store : ast_expression
432 {
433     ast_store() = delete;
434     ast_store(lex_ctx_t ctx, int op, ast_expression *d, ast_expression *s);
435     ~ast_store();
436
437     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
438
439     int m_op;
440     ast_expression *m_dest;
441     ast_expression *m_source;
442 };
443
444 /* If
445  *
446  * A general 'if then else' statement, either side can be nullptr and will
447  * thus be omitted. It is an error for *both* cases to be nullptr at once.
448  *
449  * During its 'codegen' it'll be changing the ast_function's block.
450  *
451  * An if is also an "expression". Its codegen will put nullptr into the
452  * output field though. For ternary expressions an ast_ternary will be
453  * added.
454  */
455 struct ast_ifthen : ast_expression
456 {
457     ast_ifthen() = delete;
458     ast_ifthen(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse);
459     ~ast_ifthen();
460
461     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
462
463     ast_expression *m_cond;
464     /* It's all just 'expressions', since an ast_block is one too. */
465     ast_expression *m_on_true;
466     ast_expression *m_on_false;
467 };
468
469 /* Ternary expressions...
470  *
471  * Contrary to 'if-then-else' nodes, ternary expressions actually
472  * return a value, otherwise they behave the very same way.
473  * The difference in 'codegen' is that it'll return the value of
474  * a PHI node.
475  *
476  * The other difference is that in an ast_ternary, NEITHER side
477  * must be nullptr, there's ALWAYS an else branch.
478  *
479  * This is the only ast_node beside ast_value which contains
480  * an ir_value. Theoretically we don't need to remember it though.
481  */
482 struct ast_ternary : ast_expression
483 {
484     ast_ternary() = delete;
485     ast_ternary(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse);
486     ~ast_ternary();
487
488     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
489
490     ast_expression *m_cond;
491     /* It's all just 'expressions', since an ast_block is one too. */
492     ast_expression *m_on_true;
493     ast_expression *m_on_false;
494 };
495
496 /* A general loop node
497  *
498  * For convenience it contains 4 parts:
499  * -) (ini) = initializing expression
500  * -) (pre) = pre-loop condition
501  * -) (pst) = post-loop condition
502  * -) (inc) = "increment" expression
503  * The following is a psudo-representation of this loop
504  * note that '=>' bears the logical meaning of "implies".
505  * (a => b) equals (!a || b)
506
507 {ini};
508 while (has_pre => {pre})
509 {
510     {body};
511
512 continue:      // a 'continue' will jump here
513     if (has_pst => {pst})
514         break;
515
516     {inc};
517 }
518  */
519 struct ast_loop : ast_expression
520 {
521     ast_loop() = delete;
522     ast_loop(lex_ctx_t ctx,
523              ast_expression *initexpr,
524              ast_expression *precond, bool pre_not,
525              ast_expression *postcond, bool post_not,
526              ast_expression *increment,
527              ast_expression *body);
528     ~ast_loop();
529
530     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
531
532     ast_expression *m_initexpr;
533     ast_expression *m_precond;
534     ast_expression *m_postcond;
535     ast_expression *m_increment;
536     ast_expression *m_body;
537     /* For now we allow a seperate flag on whether or not the condition
538      * is supposed to be true or false.
539      * That way, the parser can generate a 'while not(!x)' for `while(x)`
540      * if desired, which is useful for the new -f{true,false}-empty-strings
541      * flag.
542      */
543     bool m_pre_not;
544     bool m_post_not;
545 };
546
547 /* Break/Continue
548  */
549 struct ast_breakcont : ast_expression
550 {
551     ast_breakcont() = delete;
552     ast_breakcont(lex_ctx_t ctx, bool iscont, unsigned int levels);
553     ~ast_breakcont();
554
555     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
556
557
558     bool         m_is_continue;
559     unsigned int m_levels;
560 };
561
562 /* Switch Statements
563  *
564  * A few notes about this: with the original QCVM, no real optimization
565  * is possible. The SWITCH instruction set isn't really helping a lot, since
566  * it only collapes the EQ and IF instructions into one.
567  * Note: Declaring local variables inside caseblocks is normal.
568  * Since we don't have to deal with a stack there's no unnatural behaviour to
569  * be expected from it.
570  * TODO: Ticket #20
571  */
572 struct ast_switch_case {
573     ast_expression *m_value; /* #20 will replace this */
574     ast_expression *m_code;
575 };
576
577 struct ast_switch : ast_expression
578 {
579     ast_switch() = delete;
580     ast_switch(lex_ctx_t ctx, ast_expression *op);
581     ~ast_switch();
582
583     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
584
585     ast_expression *m_operand;
586     std::vector<ast_switch_case> m_cases;
587 };
588
589
590 /* Label nodes
591  *
592  * Introduce a label which can be used together with 'goto'
593  */
594 struct ast_label : ast_expression
595 {
596     ast_label() = delete;
597     ast_label(lex_ctx_t ctx, const std::string &name, bool undefined);
598     ~ast_label();
599
600     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
601
602     std::string m_name;
603     ir_block *m_irblock;
604     std::vector<ast_goto*> m_gotos;
605
606     /* means it has not yet been defined */
607     bool m_undefined;
608
609 private:
610     void registerGoto(ast_goto*);
611     friend struct ast_goto;
612 };
613
614 /* GOTO nodes
615  *
616  * Go to a label, the label node is filled in at a later point!
617  */
618 struct ast_goto : ast_expression
619 {
620     ast_goto() = delete;
621     ast_goto(lex_ctx_t ctx, const std::string &name);
622     ~ast_goto();
623
624     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
625
626     void setLabel(ast_label*);
627
628     std::string m_name;
629     ast_label *m_target;
630     ir_block *m_irblock_from;
631 };
632
633 /* STATE node
634  *
635  * For frame/think state updates: void foo() [framenum, nextthink] {}
636  */
637 struct ast_state : ast_expression
638 {
639     ast_state() = delete;
640     ast_state(lex_ctx_t ctx, ast_expression *frame, ast_expression *think);
641     ~ast_state();
642
643     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
644
645     ast_expression *m_framenum;
646     ast_expression *m_nextthink;
647 };
648
649 /* CALL node
650  *
651  * Contains an ast_expression as target, rather than an ast_function/value.
652  * Since it's how QC works, every ast_function has an ast_value
653  * associated anyway - in other words, the VM contains function
654  * pointers for every function anyway. Thus, this node will call
655  * expression.
656  * Additionally it contains a list of ast_expressions as parameters.
657  * Since calls can return values, an ast_call is also an ast_expression.
658  */
659 struct ast_call : ast_expression
660 {
661     ast_call() = delete;
662     static ast_call *make(lex_ctx_t, ast_expression*);
663     ~ast_call();
664
665     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
666
667     bool checkTypes(ast_expression *this_func_va_type) const;
668
669     ast_expression *m_func;
670     std::vector<ast_expression *> m_params;
671     ast_expression *m_va_count;
672
673 private:
674     ast_call(lex_ctx_t ctx, ast_expression *funcexpr);
675     bool checkVararg(ast_expression *va_type, ast_expression *exp_type) const;
676 };
677
678 /* Blocks
679  *
680  */
681 struct ast_block : ast_expression
682 {
683     ast_block() = delete;
684     ast_block(lex_ctx_t ctx);
685     ~ast_block();
686
687     bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
688
689     std::vector<ast_value*>      m_locals;
690     std::vector<ast_expression*> m_exprs;
691     std::vector<ast_expression*> m_collect;
692
693     void setType(const ast_expression &from);
694     bool GMQCC_WARN addExpr(ast_expression*);
695     void collect(ast_expression*);
696 };
697
698 /* Function
699  *
700  * Contains a list of blocks... at least in theory.
701  * Usually there's just the main block, other blocks are inside that.
702  *
703  * Technically, functions don't need to be an AST node, since we have
704  * neither functions inside functions, nor lambdas, and function
705  * pointers could just work with a name. However, this way could be
706  * more flexible, and adds no real complexity.
707  *
708  * The destructor will NOT delete the underlying ast_value
709  *
710  */
711 struct ast_function : ast_node
712 {
713     ast_function() = delete;
714     static ast_function *make(lex_ctx_t ctx, const std::string &name, ast_value *vtype);
715     ~ast_function();
716
717     const char* makeLabel(const char *prefix);
718     virtual bool generateFunction(ir_builder*);
719
720     ast_value  *m_function_type = nullptr;
721     std::string m_name;
722
723     int m_builtin = 0;
724
725     /* list of used-up names for statics without the count suffix */
726     std::vector<std::string> m_static_names;
727     /* number of static variables, by convention this includes the
728      * ones without the count-suffix - remember this when dealing
729      * with savegames. uint instead of size_t as %zu in printf is
730      * C99, so no windows support. */
731     unsigned int m_static_count = 0;
732
733     ir_function *m_ir_func = nullptr;
734     ir_block *m_curblock = nullptr;
735     std::vector<ir_block*> m_breakblocks;
736     std::vector<ir_block*> m_continueblocks;
737
738     size_t m_labelcount = 0;
739     /* in order for thread safety - for the optional
740      * channel abesed multithreading... keeping a buffer
741      * here to use in ast_function_label.
742      */
743     std::vector<std::unique_ptr<ast_block>> m_blocks;
744     std::unique_ptr<ast_value> m_varargs;
745     std::unique_ptr<ast_value> m_argc;
746     ast_value *m_fixedparams = nullptr; // these use unref()
747     ast_value *m_return_value = nullptr;
748
749 private:
750     ast_function(lex_ctx_t ctx, const std::string &name, ast_value *vtype);
751
752     char m_labelbuf[64];
753 };
754
755 /*
756  * If the condition creates a situation where this becomes -1 size it means there are
757  * more AST_FLAGs than the type ast_flag_t is capable of holding. So either eliminate
758  * the AST flag count or change the ast_flag_t typedef to a type large enough to accomodate
759  * all the flags.
760  */
761 typedef int static_assert_is_ast_flag_safe [((AST_FLAG_LAST) <= (ast_flag_t)(-1)) ? 1 : -1];
762 #endif