]> git.xonotic.org Git - xonotic/gmqcc.git/blob - ir.c
serpate line travis-ci build url for notifications
[xonotic/gmqcc.git] / ir.c
1 /*
2  * Copyright (C) 2012, 2013
3  *     Wolfgang Bumiller
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is furnished to do
10  * so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23 #include <stdlib.h>
24 #include <string.h>
25 #include "gmqcc.h"
26 #include "ir.h"
27
28 /***********************************************************************
29  * Type sizes used at multiple points in the IR codegen
30  */
31
32 const char *type_name[TYPE_COUNT] = {
33     "void",
34     "string",
35     "float",
36     "vector",
37     "entity",
38     "field",
39     "function",
40     "pointer",
41     "integer",
42     "variant",
43     "struct",
44     "union",
45     "array",
46
47     "nil",
48     "<no-expression>"
49 };
50
51 size_t type_sizeof_[TYPE_COUNT] = {
52     1, /* TYPE_VOID     */
53     1, /* TYPE_STRING   */
54     1, /* TYPE_FLOAT    */
55     3, /* TYPE_VECTOR   */
56     1, /* TYPE_ENTITY   */
57     1, /* TYPE_FIELD    */
58     1, /* TYPE_FUNCTION */
59     1, /* TYPE_POINTER  */
60     1, /* TYPE_INTEGER  */
61     3, /* TYPE_VARIANT  */
62     0, /* TYPE_STRUCT   */
63     0, /* TYPE_UNION    */
64     0, /* TYPE_ARRAY    */
65     0, /* TYPE_NIL      */
66     0, /* TYPE_NOESPR   */
67 };
68
69 uint16_t type_store_instr[TYPE_COUNT] = {
70     INSTR_STORE_F, /* should use I when having integer support */
71     INSTR_STORE_S,
72     INSTR_STORE_F,
73     INSTR_STORE_V,
74     INSTR_STORE_ENT,
75     INSTR_STORE_FLD,
76     INSTR_STORE_FNC,
77     INSTR_STORE_ENT, /* should use I */
78 #if 0
79     INSTR_STORE_I, /* integer type */
80 #else
81     INSTR_STORE_F,
82 #endif
83
84     INSTR_STORE_V, /* variant, should never be accessed */
85
86     AINSTR_END, /* struct */
87     AINSTR_END, /* union  */
88     AINSTR_END, /* array  */
89     AINSTR_END, /* nil    */
90     AINSTR_END, /* noexpr */
91 };
92
93 uint16_t field_store_instr[TYPE_COUNT] = {
94     INSTR_STORE_FLD,
95     INSTR_STORE_FLD,
96     INSTR_STORE_FLD,
97     INSTR_STORE_V,
98     INSTR_STORE_FLD,
99     INSTR_STORE_FLD,
100     INSTR_STORE_FLD,
101     INSTR_STORE_FLD,
102 #if 0
103     INSTR_STORE_FLD, /* integer type */
104 #else
105     INSTR_STORE_FLD,
106 #endif
107
108     INSTR_STORE_V, /* variant, should never be accessed */
109
110     AINSTR_END, /* struct */
111     AINSTR_END, /* union  */
112     AINSTR_END, /* array  */
113     AINSTR_END, /* nil    */
114     AINSTR_END, /* noexpr */
115 };
116
117 uint16_t type_storep_instr[TYPE_COUNT] = {
118     INSTR_STOREP_F, /* should use I when having integer support */
119     INSTR_STOREP_S,
120     INSTR_STOREP_F,
121     INSTR_STOREP_V,
122     INSTR_STOREP_ENT,
123     INSTR_STOREP_FLD,
124     INSTR_STOREP_FNC,
125     INSTR_STOREP_ENT, /* should use I */
126 #if 0
127     INSTR_STOREP_ENT, /* integer type */
128 #else
129     INSTR_STOREP_F,
130 #endif
131
132     INSTR_STOREP_V, /* variant, should never be accessed */
133
134     AINSTR_END, /* struct */
135     AINSTR_END, /* union  */
136     AINSTR_END, /* array  */
137     AINSTR_END, /* nil    */
138     AINSTR_END, /* noexpr */
139 };
140
141 uint16_t type_eq_instr[TYPE_COUNT] = {
142     INSTR_EQ_F, /* should use I when having integer support */
143     INSTR_EQ_S,
144     INSTR_EQ_F,
145     INSTR_EQ_V,
146     INSTR_EQ_E,
147     INSTR_EQ_E, /* FLD has no comparison */
148     INSTR_EQ_FNC,
149     INSTR_EQ_E, /* should use I */
150 #if 0
151     INSTR_EQ_I,
152 #else
153     INSTR_EQ_F,
154 #endif
155
156     INSTR_EQ_V, /* variant, should never be accessed */
157
158     AINSTR_END, /* struct */
159     AINSTR_END, /* union  */
160     AINSTR_END, /* array  */
161     AINSTR_END, /* nil    */
162     AINSTR_END, /* noexpr */
163 };
164
165 uint16_t type_ne_instr[TYPE_COUNT] = {
166     INSTR_NE_F, /* should use I when having integer support */
167     INSTR_NE_S,
168     INSTR_NE_F,
169     INSTR_NE_V,
170     INSTR_NE_E,
171     INSTR_NE_E, /* FLD has no comparison */
172     INSTR_NE_FNC,
173     INSTR_NE_E, /* should use I */
174 #if 0
175     INSTR_NE_I,
176 #else
177     INSTR_NE_F,
178 #endif
179
180     INSTR_NE_V, /* variant, should never be accessed */
181
182     AINSTR_END, /* struct */
183     AINSTR_END, /* union  */
184     AINSTR_END, /* array  */
185     AINSTR_END, /* nil    */
186     AINSTR_END, /* noexpr */
187 };
188
189 uint16_t type_not_instr[TYPE_COUNT] = {
190     INSTR_NOT_F, /* should use I when having integer support */
191     INSTR_NOT_S,
192     INSTR_NOT_F,
193     INSTR_NOT_V,
194     INSTR_NOT_ENT,
195     INSTR_NOT_ENT,
196     INSTR_NOT_FNC,
197     INSTR_NOT_ENT, /* should use I */
198 #if 0
199     INSTR_NOT_I, /* integer type */
200 #else
201     INSTR_NOT_F,
202 #endif
203
204     INSTR_NOT_V, /* variant, should never be accessed */
205
206     AINSTR_END, /* struct */
207     AINSTR_END, /* union  */
208     AINSTR_END, /* array  */
209     AINSTR_END, /* nil    */
210     AINSTR_END, /* noexpr */
211 };
212
213 /* protos */
214 static ir_value* ir_gen_extparam_proto(ir_builder *ir);
215 static void      ir_gen_extparam      (ir_builder *ir);
216
217 /* error functions */
218
219 static void irerror(lex_ctx ctx, const char *msg, ...)
220 {
221     va_list ap;
222     va_start(ap, msg);
223     con_cvprintmsg((void*)&ctx, LVL_ERROR, "internal error", msg, ap);
224     va_end(ap);
225 }
226
227 static bool irwarning(lex_ctx ctx, int warntype, const char *fmt, ...)
228 {
229     bool    r;
230     va_list ap;
231     va_start(ap, fmt);
232     r = vcompile_warning(ctx, warntype, fmt, ap);
233     va_end(ap);
234     return r;
235 }
236
237 /***********************************************************************
238  * Vector utility functions
239  */
240
241 bool GMQCC_WARN vec_ir_value_find(ir_value **vec, const ir_value *what, size_t *idx)
242 {
243     size_t i;
244     size_t len = vec_size(vec);
245     for (i = 0; i < len; ++i) {
246         if (vec[i] == what) {
247             if (idx) *idx = i;
248             return true;
249         }
250     }
251     return false;
252 }
253
254 bool GMQCC_WARN vec_ir_block_find(ir_block **vec, ir_block *what, size_t *idx)
255 {
256     size_t i;
257     size_t len = vec_size(vec);
258     for (i = 0; i < len; ++i) {
259         if (vec[i] == what) {
260             if (idx) *idx = i;
261             return true;
262         }
263     }
264     return false;
265 }
266
267 bool GMQCC_WARN vec_ir_instr_find(ir_instr **vec, ir_instr *what, size_t *idx)
268 {
269     size_t i;
270     size_t len = vec_size(vec);
271     for (i = 0; i < len; ++i) {
272         if (vec[i] == what) {
273             if (idx) *idx = i;
274             return true;
275         }
276     }
277     return false;
278 }
279
280 /***********************************************************************
281  * IR Builder
282  */
283
284 static void ir_block_delete_quick(ir_block* self);
285 static void ir_instr_delete_quick(ir_instr *self);
286 static void ir_function_delete_quick(ir_function *self);
287
288 ir_builder* ir_builder_new(const char *modulename)
289 {
290     ir_builder* self;
291
292     self = (ir_builder*)mem_a(sizeof(*self));
293     if (!self)
294         return NULL;
295
296     self->functions   = NULL;
297     self->globals     = NULL;
298     self->fields      = NULL;
299     self->filenames   = NULL;
300     self->filestrings = NULL;
301     self->htglobals   = util_htnew(IR_HT_SIZE);
302     self->htfields    = util_htnew(IR_HT_SIZE);
303     self->htfunctions = util_htnew(IR_HT_SIZE);
304
305     self->extparams       = NULL;
306     self->extparam_protos = NULL;
307
308     self->first_common_globaltemp = 0;
309     self->max_globaltemps         = 0;
310     self->first_common_local      = 0;
311     self->max_locals              = 0;
312
313     self->str_immediate = 0;
314     self->name = NULL;
315     if (!ir_builder_set_name(self, modulename)) {
316         mem_d(self);
317         return NULL;
318     }
319
320     self->nil = ir_value_var("nil", store_value, TYPE_NIL);
321     self->nil->cvq = CV_CONST;
322
323     self->reserved_va_count = NULL;
324
325     return self;
326 }
327
328 void ir_builder_delete(ir_builder* self)
329 {
330     size_t i;
331     util_htdel(self->htglobals);
332     util_htdel(self->htfields);
333     util_htdel(self->htfunctions);
334     mem_d((void*)self->name);
335     for (i = 0; i != vec_size(self->functions); ++i) {
336         ir_function_delete_quick(self->functions[i]);
337     }
338     vec_free(self->functions);
339     for (i = 0; i != vec_size(self->extparams); ++i) {
340         ir_value_delete(self->extparams[i]);
341     }
342     vec_free(self->extparams);
343     for (i = 0; i != vec_size(self->globals); ++i) {
344         ir_value_delete(self->globals[i]);
345     }
346     vec_free(self->globals);
347     for (i = 0; i != vec_size(self->fields); ++i) {
348         ir_value_delete(self->fields[i]);
349     }
350     ir_value_delete(self->nil);
351     vec_free(self->fields);
352     vec_free(self->filenames);
353     vec_free(self->filestrings);
354     mem_d(self);
355 }
356
357 bool ir_builder_set_name(ir_builder *self, const char *name)
358 {
359     if (self->name)
360         mem_d((void*)self->name);
361     self->name = util_strdup(name);
362     return !!self->name;
363 }
364
365 ir_function* ir_builder_get_function(ir_builder *self, const char *name)
366 {
367     return (ir_function*)util_htget(self->htfunctions, name);
368 }
369
370 ir_function* ir_builder_create_function(ir_builder *self, const char *name, int outtype)
371 {
372     ir_function *fn = ir_builder_get_function(self, name);
373     if (fn) {
374         return NULL;
375     }
376
377     fn = ir_function_new(self, outtype);
378     if (!ir_function_set_name(fn, name))
379     {
380         ir_function_delete(fn);
381         return NULL;
382     }
383     vec_push(self->functions, fn);
384     util_htset(self->htfunctions, name, fn);
385
386     fn->value = ir_builder_create_global(self, fn->name, TYPE_FUNCTION);
387     if (!fn->value) {
388         ir_function_delete(fn);
389         return NULL;
390     }
391
392     fn->value->hasvalue = true;
393     fn->value->outtype = outtype;
394     fn->value->constval.vfunc = fn;
395     fn->value->context = fn->context;
396
397     return fn;
398 }
399
400 ir_value* ir_builder_get_global(ir_builder *self, const char *name)
401 {
402     return (ir_value*)util_htget(self->htglobals, name);
403 }
404
405 ir_value* ir_builder_create_global(ir_builder *self, const char *name, int vtype)
406 {
407     ir_value *ve;
408
409     if (name && name[0] != '#')
410     {
411         ve = ir_builder_get_global(self, name);
412         if (ve) {
413             return NULL;
414         }
415     }
416
417     ve = ir_value_var(name, store_global, vtype);
418     vec_push(self->globals, ve);
419     util_htset(self->htglobals, name, ve);
420     return ve;
421 }
422
423 ir_value* ir_builder_get_va_count(ir_builder *self)
424 {
425     if (self->reserved_va_count)
426         return self->reserved_va_count;
427     return (self->reserved_va_count = ir_builder_create_global(self, "reserved:va_count", TYPE_FLOAT));
428 }
429
430 ir_value* ir_builder_get_field(ir_builder *self, const char *name)
431 {
432     return (ir_value*)util_htget(self->htfields, name);
433 }
434
435
436 ir_value* ir_builder_create_field(ir_builder *self, const char *name, int vtype)
437 {
438     ir_value *ve = ir_builder_get_field(self, name);
439     if (ve) {
440         return NULL;
441     }
442
443     ve = ir_value_var(name, store_global, TYPE_FIELD);
444     ve->fieldtype = vtype;
445     vec_push(self->fields, ve);
446     util_htset(self->htfields, name, ve);
447     return ve;
448 }
449
450 /***********************************************************************
451  *IR Function
452  */
453
454 bool ir_function_naive_phi(ir_function*);
455 void ir_function_enumerate(ir_function*);
456 bool ir_function_calculate_liferanges(ir_function*);
457 bool ir_function_allocate_locals(ir_function*);
458
459 ir_function* ir_function_new(ir_builder* owner, int outtype)
460 {
461     ir_function *self;
462     self = (ir_function*)mem_a(sizeof(*self));
463
464     if (!self)
465         return NULL;
466
467     memset(self, 0, sizeof(*self));
468
469     self->name = NULL;
470     if (!ir_function_set_name(self, "<@unnamed>")) {
471         mem_d(self);
472         return NULL;
473     }
474     self->flags = 0;
475
476     self->owner = owner;
477     self->context.file = "<@no context>";
478     self->context.line = 0;
479     self->outtype = outtype;
480     self->value = NULL;
481     self->builtin = 0;
482
483     self->params = NULL;
484     self->blocks = NULL;
485     self->values = NULL;
486     self->locals = NULL;
487
488     self->max_varargs = 0;
489
490     self->code_function_def = -1;
491     self->allocated_locals = 0;
492     self->globaltemps      = 0;
493
494     self->run_id = 0;
495     return self;
496 }
497
498 bool ir_function_set_name(ir_function *self, const char *name)
499 {
500     if (self->name)
501         mem_d((void*)self->name);
502     self->name = util_strdup(name);
503     return !!self->name;
504 }
505
506 static void ir_function_delete_quick(ir_function *self)
507 {
508     size_t i;
509     mem_d((void*)self->name);
510
511     for (i = 0; i != vec_size(self->blocks); ++i)
512         ir_block_delete_quick(self->blocks[i]);
513     vec_free(self->blocks);
514
515     vec_free(self->params);
516
517     for (i = 0; i != vec_size(self->values); ++i)
518         ir_value_delete(self->values[i]);
519     vec_free(self->values);
520
521     for (i = 0; i != vec_size(self->locals); ++i)
522         ir_value_delete(self->locals[i]);
523     vec_free(self->locals);
524
525     /* self->value is deleted by the builder */
526
527     mem_d(self);
528 }
529
530 void ir_function_delete(ir_function *self)
531 {
532     size_t i;
533     mem_d((void*)self->name);
534
535     for (i = 0; i != vec_size(self->blocks); ++i)
536         ir_block_delete(self->blocks[i]);
537     vec_free(self->blocks);
538
539     vec_free(self->params);
540
541     for (i = 0; i != vec_size(self->values); ++i)
542         ir_value_delete(self->values[i]);
543     vec_free(self->values);
544
545     for (i = 0; i != vec_size(self->locals); ++i)
546         ir_value_delete(self->locals[i]);
547     vec_free(self->locals);
548
549     /* self->value is deleted by the builder */
550
551     mem_d(self);
552 }
553
554 void ir_function_collect_value(ir_function *self, ir_value *v)
555 {
556     vec_push(self->values, v);
557 }
558
559 ir_block* ir_function_create_block(lex_ctx ctx, ir_function *self, const char *label)
560 {
561     ir_block* bn = ir_block_new(self, label);
562     bn->context = ctx;
563     vec_push(self->blocks, bn);
564     return bn;
565 }
566
567 static bool instr_is_operation(uint16_t op)
568 {
569     return ( (op >= INSTR_MUL_F  && op <= INSTR_GT) ||
570              (op >= INSTR_LOAD_F && op <= INSTR_LOAD_FNC) ||
571              (op == INSTR_ADDRESS) ||
572              (op >= INSTR_NOT_F  && op <= INSTR_NOT_FNC) ||
573              (op >= INSTR_AND    && op <= INSTR_BITOR) ||
574              (op >= INSTR_CALL0  && op <= INSTR_CALL8) );
575 }
576
577 bool ir_function_pass_peephole(ir_function *self)
578 {
579     size_t b;
580
581     for (b = 0; b < vec_size(self->blocks); ++b) {
582         size_t    i;
583         ir_block *block = self->blocks[b];
584
585         for (i = 0; i < vec_size(block->instr); ++i) {
586             ir_instr *inst;
587             inst = block->instr[i];
588
589             if (i >= 1 &&
590                 (inst->opcode >= INSTR_STORE_F &&
591                  inst->opcode <= INSTR_STORE_FNC))
592             {
593                 ir_instr *store;
594                 ir_instr *oper;
595                 ir_value *value;
596
597                 store = inst;
598
599                 oper  = block->instr[i-1];
600                 if (!instr_is_operation(oper->opcode))
601                     continue;
602
603                 value = oper->_ops[0];
604
605                 /* only do it for SSA values */
606                 if (value->store != store_value)
607                     continue;
608
609                 /* don't optimize out the temp if it's used later again */
610                 if (vec_size(value->reads) != 1)
611                     continue;
612
613                 /* The very next store must use this value */
614                 if (value->reads[0] != store)
615                     continue;
616
617                 /* And of course the store must _read_ from it, so it's in
618                  * OP 1 */
619                 if (store->_ops[1] != value)
620                     continue;
621
622                 ++opts_optimizationcount[OPTIM_PEEPHOLE];
623                 (void)!ir_instr_op(oper, 0, store->_ops[0], true);
624
625                 vec_remove(block->instr, i, 1);
626                 ir_instr_delete(store);
627             }
628             else if (inst->opcode == VINSTR_COND)
629             {
630                 /* COND on a value resulting from a NOT could
631                  * remove the NOT and swap its operands
632                  */
633                 while (true) {
634                     ir_block *tmp;
635                     size_t    inotid;
636                     ir_instr *inot;
637                     ir_value *value;
638                     value = inst->_ops[0];
639
640                     if (value->store != store_value ||
641                         vec_size(value->reads) != 1 ||
642                         value->reads[0] != inst)
643                     {
644                         break;
645                     }
646
647                     inot = value->writes[0];
648                     if (inot->_ops[0] != value ||
649                         inot->opcode < INSTR_NOT_F ||
650                         inot->opcode > INSTR_NOT_FNC ||
651                         inot->opcode == INSTR_NOT_V || /* can't do these */
652                         inot->opcode == INSTR_NOT_S)
653                     {
654                         break;
655                     }
656
657                     /* count */
658                     ++opts_optimizationcount[OPTIM_PEEPHOLE];
659                     /* change operand */
660                     (void)!ir_instr_op(inst, 0, inot->_ops[1], false);
661                     /* remove NOT */
662                     tmp = inot->owner;
663                     for (inotid = 0; inotid < vec_size(tmp->instr); ++inotid) {
664                         if (tmp->instr[inotid] == inot)
665                             break;
666                     }
667                     if (inotid >= vec_size(tmp->instr)) {
668                         compile_error(inst->context, "sanity-check failed: failed to find instruction to optimize out");
669                         return false;
670                     }
671                     vec_remove(tmp->instr, inotid, 1);
672                     ir_instr_delete(inot);
673                     /* swap ontrue/onfalse */
674                     tmp = inst->bops[0];
675                     inst->bops[0] = inst->bops[1];
676                     inst->bops[1] = tmp;
677                 }
678                 continue;
679             }
680         }
681     }
682
683     return true;
684 }
685
686 bool ir_function_pass_tailrecursion(ir_function *self)
687 {
688     size_t b, p;
689
690     for (b = 0; b < vec_size(self->blocks); ++b) {
691         ir_value *funcval;
692         ir_instr *ret, *call, *store = NULL;
693         ir_block *block = self->blocks[b];
694
695         if (!block->final || vec_size(block->instr) < 2)
696             continue;
697
698         ret = block->instr[vec_size(block->instr)-1];
699         if (ret->opcode != INSTR_DONE && ret->opcode != INSTR_RETURN)
700             continue;
701
702         call = block->instr[vec_size(block->instr)-2];
703         if (call->opcode >= INSTR_STORE_F && call->opcode <= INSTR_STORE_FNC) {
704             /* account for the unoptimized
705              * CALL
706              * STORE %return, %tmp
707              * RETURN %tmp
708              * version
709              */
710             if (vec_size(block->instr) < 3)
711                 continue;
712
713             store = call;
714             call = block->instr[vec_size(block->instr)-3];
715         }
716
717         if (call->opcode < INSTR_CALL0 || call->opcode > INSTR_CALL8)
718             continue;
719
720         if (store) {
721             /* optimize out the STORE */
722             if (ret->_ops[0]   &&
723                 ret->_ops[0]   == store->_ops[0] &&
724                 store->_ops[1] == call->_ops[0])
725             {
726                 ++opts_optimizationcount[OPTIM_PEEPHOLE];
727                 call->_ops[0] = store->_ops[0];
728                 vec_remove(block->instr, vec_size(block->instr) - 2, 1);
729                 ir_instr_delete(store);
730             }
731             else
732                 continue;
733         }
734
735         if (!call->_ops[0])
736             continue;
737
738         funcval = call->_ops[1];
739         if (!funcval)
740             continue;
741         if (funcval->vtype != TYPE_FUNCTION || funcval->constval.vfunc != self)
742             continue;
743
744         /* now we have a CALL and a RET, check if it's a tailcall */
745         if (ret->_ops[0] && call->_ops[0] != ret->_ops[0])
746             continue;
747
748         ++opts_optimizationcount[OPTIM_TAIL_RECURSION];
749         vec_shrinkby(block->instr, 2);
750
751         block->final = false; /* open it back up */
752
753         /* emite parameter-stores */
754         for (p = 0; p < vec_size(call->params); ++p) {
755             /* assert(call->params_count <= self->locals_count); */
756             if (!ir_block_create_store(block, call->context, self->locals[p], call->params[p])) {
757                 irerror(call->context, "failed to create tailcall store instruction for parameter %i", (int)p);
758                 return false;
759             }
760         }
761         if (!ir_block_create_jump(block, call->context, self->blocks[0])) {
762             irerror(call->context, "failed to create tailcall jump");
763             return false;
764         }
765
766         ir_instr_delete(call);
767         ir_instr_delete(ret);
768     }
769
770     return true;
771 }
772
773 bool ir_function_finalize(ir_function *self)
774 {
775     size_t i;
776
777     if (self->builtin)
778         return true;
779
780     if (OPTS_OPTIMIZATION(OPTIM_PEEPHOLE)) {
781         if (!ir_function_pass_peephole(self)) {
782             irerror(self->context, "generic optimization pass broke something in `%s`", self->name);
783             return false;
784         }
785     }
786
787     if (OPTS_OPTIMIZATION(OPTIM_TAIL_RECURSION)) {
788         if (!ir_function_pass_tailrecursion(self)) {
789             irerror(self->context, "tail-recursion optimization pass broke something in `%s`", self->name);
790             return false;
791         }
792     }
793
794     if (!ir_function_naive_phi(self)) {
795         irerror(self->context, "internal error: ir_function_naive_phi failed");
796         return false;
797     }
798
799     for (i = 0; i < vec_size(self->locals); ++i) {
800         ir_value *v = self->locals[i];
801         if (v->vtype == TYPE_VECTOR ||
802             (v->vtype == TYPE_FIELD && v->outtype == TYPE_VECTOR))
803         {
804             ir_value_vector_member(v, 0);
805             ir_value_vector_member(v, 1);
806             ir_value_vector_member(v, 2);
807         }
808     }
809     for (i = 0; i < vec_size(self->values); ++i) {
810         ir_value *v = self->values[i];
811         if (v->vtype == TYPE_VECTOR ||
812             (v->vtype == TYPE_FIELD && v->outtype == TYPE_VECTOR))
813         {
814             ir_value_vector_member(v, 0);
815             ir_value_vector_member(v, 1);
816             ir_value_vector_member(v, 2);
817         }
818     }
819
820     ir_function_enumerate(self);
821
822     if (!ir_function_calculate_liferanges(self))
823         return false;
824     if (!ir_function_allocate_locals(self))
825         return false;
826     return true;
827 }
828
829 ir_value* ir_function_create_local(ir_function *self, const char *name, int vtype, bool param)
830 {
831     ir_value *ve;
832
833     if (param &&
834         vec_size(self->locals) &&
835         self->locals[vec_size(self->locals)-1]->store != store_param) {
836         irerror(self->context, "cannot add parameters after adding locals");
837         return NULL;
838     }
839
840     ve = ir_value_var(name, (param ? store_param : store_local), vtype);
841     if (param)
842         ve->locked = true;
843     vec_push(self->locals, ve);
844     return ve;
845 }
846
847 /***********************************************************************
848  *IR Block
849  */
850
851 ir_block* ir_block_new(ir_function* owner, const char *name)
852 {
853     ir_block *self;
854     self = (ir_block*)mem_a(sizeof(*self));
855     if (!self)
856         return NULL;
857
858     memset(self, 0, sizeof(*self));
859
860     self->label = NULL;
861     if (name && !ir_block_set_label(self, name)) {
862         mem_d(self);
863         return NULL;
864     }
865     self->owner = owner;
866     self->context.file = "<@no context>";
867     self->context.line = 0;
868     self->final = false;
869
870     self->instr   = NULL;
871     self->entries = NULL;
872     self->exits   = NULL;
873
874     self->eid = 0;
875     self->is_return = false;
876     self->run_id = 0;
877
878     self->living = NULL;
879
880     self->generated = false;
881
882     return self;
883 }
884
885 static void ir_block_delete_quick(ir_block* self)
886 {
887     size_t i;
888     if (self->label) mem_d(self->label);
889     for (i = 0; i != vec_size(self->instr); ++i)
890         ir_instr_delete_quick(self->instr[i]);
891     vec_free(self->instr);
892     vec_free(self->entries);
893     vec_free(self->exits);
894     vec_free(self->living);
895     mem_d(self);
896 }
897
898 void ir_block_delete(ir_block* self)
899 {
900     size_t i;
901     if (self->label) mem_d(self->label);
902     for (i = 0; i != vec_size(self->instr); ++i)
903         ir_instr_delete(self->instr[i]);
904     vec_free(self->instr);
905     vec_free(self->entries);
906     vec_free(self->exits);
907     vec_free(self->living);
908     mem_d(self);
909 }
910
911 bool ir_block_set_label(ir_block *self, const char *name)
912 {
913     if (self->label)
914         mem_d((void*)self->label);
915     self->label = util_strdup(name);
916     return !!self->label;
917 }
918
919 /***********************************************************************
920  *IR Instructions
921  */
922
923 ir_instr* ir_instr_new(lex_ctx ctx, ir_block* owner, int op)
924 {
925     ir_instr *self;
926     self = (ir_instr*)mem_a(sizeof(*self));
927     if (!self)
928         return NULL;
929
930     self->owner = owner;
931     self->context = ctx;
932     self->opcode = op;
933     self->_ops[0] = NULL;
934     self->_ops[1] = NULL;
935     self->_ops[2] = NULL;
936     self->bops[0] = NULL;
937     self->bops[1] = NULL;
938
939     self->phi    = NULL;
940     self->params = NULL;
941
942     self->eid = 0;
943
944     self->likely = true;
945     return self;
946 }
947
948 static void ir_instr_delete_quick(ir_instr *self)
949 {
950     vec_free(self->phi);
951     vec_free(self->params);
952     mem_d(self);
953 }
954
955 void ir_instr_delete(ir_instr *self)
956 {
957     size_t i;
958     /* The following calls can only delete from
959      * vectors, we still want to delete this instruction
960      * so ignore the return value. Since with the warn_unused_result attribute
961      * gcc doesn't care about an explicit: (void)foo(); to ignore the result,
962      * I have to improvise here and use if(foo());
963      */
964     for (i = 0; i < vec_size(self->phi); ++i) {
965         size_t idx;
966         if (vec_ir_instr_find(self->phi[i].value->writes, self, &idx))
967             vec_remove(self->phi[i].value->writes, idx, 1);
968         if (vec_ir_instr_find(self->phi[i].value->reads, self, &idx))
969             vec_remove(self->phi[i].value->reads, idx, 1);
970     }
971     vec_free(self->phi);
972     for (i = 0; i < vec_size(self->params); ++i) {
973         size_t idx;
974         if (vec_ir_instr_find(self->params[i]->writes, self, &idx))
975             vec_remove(self->params[i]->writes, idx, 1);
976         if (vec_ir_instr_find(self->params[i]->reads, self, &idx))
977             vec_remove(self->params[i]->reads, idx, 1);
978     }
979     vec_free(self->params);
980     (void)!ir_instr_op(self, 0, NULL, false);
981     (void)!ir_instr_op(self, 1, NULL, false);
982     (void)!ir_instr_op(self, 2, NULL, false);
983     mem_d(self);
984 }
985
986 bool ir_instr_op(ir_instr *self, int op, ir_value *v, bool writing)
987 {
988     if (self->_ops[op]) {
989         size_t idx;
990         if (writing && vec_ir_instr_find(self->_ops[op]->writes, self, &idx))
991             vec_remove(self->_ops[op]->writes, idx, 1);
992         else if (vec_ir_instr_find(self->_ops[op]->reads, self, &idx))
993             vec_remove(self->_ops[op]->reads, idx, 1);
994     }
995     if (v) {
996         if (writing)
997             vec_push(v->writes, self);
998         else
999             vec_push(v->reads, self);
1000     }
1001     self->_ops[op] = v;
1002     return true;
1003 }
1004
1005 /***********************************************************************
1006  *IR Value
1007  */
1008
1009 void ir_value_code_setaddr(ir_value *self, int32_t gaddr)
1010 {
1011     self->code.globaladdr = gaddr;
1012     if (self->members[0]) self->members[0]->code.globaladdr = gaddr;
1013     if (self->members[1]) self->members[1]->code.globaladdr = gaddr;
1014     if (self->members[2]) self->members[2]->code.globaladdr = gaddr;
1015 }
1016
1017 int32_t ir_value_code_addr(const ir_value *self)
1018 {
1019     if (self->store == store_return)
1020         return OFS_RETURN + self->code.addroffset;
1021     return self->code.globaladdr + self->code.addroffset;
1022 }
1023
1024 ir_value* ir_value_var(const char *name, int storetype, int vtype)
1025 {
1026     ir_value *self;
1027     self = (ir_value*)mem_a(sizeof(*self));
1028     self->vtype = vtype;
1029     self->fieldtype = TYPE_VOID;
1030     self->outtype = TYPE_VOID;
1031     self->store = storetype;
1032     self->flags = 0;
1033
1034     self->reads  = NULL;
1035     self->writes = NULL;
1036
1037     self->cvq          = CV_NONE;
1038     self->hasvalue     = false;
1039     self->context.file = "<@no context>";
1040     self->context.line = 0;
1041     self->name = NULL;
1042     if (name && !ir_value_set_name(self, name)) {
1043         irerror(self->context, "out of memory");
1044         mem_d(self);
1045         return NULL;
1046     }
1047
1048     memset(&self->constval, 0, sizeof(self->constval));
1049     memset(&self->code,     0, sizeof(self->code));
1050
1051     self->members[0] = NULL;
1052     self->members[1] = NULL;
1053     self->members[2] = NULL;
1054     self->memberof = NULL;
1055
1056     self->unique_life = false;
1057     self->locked      = false;
1058     self->callparam   = false;
1059
1060     self->life = NULL;
1061     return self;
1062 }
1063
1064 ir_value* ir_value_vector_member(ir_value *self, unsigned int member)
1065 {
1066     char     *name;
1067     size_t    len;
1068     ir_value *m;
1069     if (member >= 3)
1070         return NULL;
1071
1072     if (self->members[member])
1073         return self->members[member];
1074
1075     if (self->name) {
1076         len = strlen(self->name);
1077         name = (char*)mem_a(len + 3);
1078         memcpy(name, self->name, len);
1079         name[len+0] = '_';
1080         name[len+1] = 'x' + member;
1081         name[len+2] = '\0';
1082     }
1083     else
1084         name = NULL;
1085
1086     if (self->vtype == TYPE_VECTOR)
1087     {
1088         m = ir_value_var(name, self->store, TYPE_FLOAT);
1089         if (name)
1090             mem_d(name);
1091         if (!m)
1092             return NULL;
1093         m->context = self->context;
1094
1095         self->members[member] = m;
1096         m->code.addroffset = member;
1097     }
1098     else if (self->vtype == TYPE_FIELD)
1099     {
1100         if (self->fieldtype != TYPE_VECTOR)
1101             return NULL;
1102         m = ir_value_var(name, self->store, TYPE_FIELD);
1103         if (name)
1104             mem_d(name);
1105         if (!m)
1106             return NULL;
1107         m->fieldtype = TYPE_FLOAT;
1108         m->context = self->context;
1109
1110         self->members[member] = m;
1111         m->code.addroffset = member;
1112     }
1113     else
1114     {
1115         irerror(self->context, "invalid member access on %s", self->name);
1116         return NULL;
1117     }
1118
1119     m->memberof = self;
1120     return m;
1121 }
1122
1123 static GMQCC_INLINE size_t ir_value_sizeof(const ir_value *self)
1124 {
1125     if (self->vtype == TYPE_FIELD && self->fieldtype == TYPE_VECTOR)
1126         return type_sizeof_[TYPE_VECTOR];
1127     return type_sizeof_[self->vtype];
1128 }
1129
1130 ir_value* ir_value_out(ir_function *owner, const char *name, int storetype, int vtype)
1131 {
1132     ir_value *v = ir_value_var(name, storetype, vtype);
1133     if (!v)
1134         return NULL;
1135     ir_function_collect_value(owner, v);
1136     return v;
1137 }
1138
1139 void ir_value_delete(ir_value* self)
1140 {
1141     size_t i;
1142     if (self->name)
1143         mem_d((void*)self->name);
1144     if (self->hasvalue)
1145     {
1146         if (self->vtype == TYPE_STRING)
1147             mem_d((void*)self->constval.vstring);
1148     }
1149     for (i = 0; i < 3; ++i) {
1150         if (self->members[i])
1151             ir_value_delete(self->members[i]);
1152     }
1153     vec_free(self->reads);
1154     vec_free(self->writes);
1155     vec_free(self->life);
1156     mem_d(self);
1157 }
1158
1159 bool ir_value_set_name(ir_value *self, const char *name)
1160 {
1161     if (self->name)
1162         mem_d((void*)self->name);
1163     self->name = util_strdup(name);
1164     return !!self->name;
1165 }
1166
1167 bool ir_value_set_float(ir_value *self, float f)
1168 {
1169     if (self->vtype != TYPE_FLOAT)
1170         return false;
1171     self->constval.vfloat = f;
1172     self->hasvalue = true;
1173     return true;
1174 }
1175
1176 bool ir_value_set_func(ir_value *self, int f)
1177 {
1178     if (self->vtype != TYPE_FUNCTION)
1179         return false;
1180     self->constval.vint = f;
1181     self->hasvalue = true;
1182     return true;
1183 }
1184
1185 bool ir_value_set_vector(ir_value *self, vector v)
1186 {
1187     if (self->vtype != TYPE_VECTOR)
1188         return false;
1189     self->constval.vvec = v;
1190     self->hasvalue = true;
1191     return true;
1192 }
1193
1194 bool ir_value_set_field(ir_value *self, ir_value *fld)
1195 {
1196     if (self->vtype != TYPE_FIELD)
1197         return false;
1198     self->constval.vpointer = fld;
1199     self->hasvalue = true;
1200     return true;
1201 }
1202
1203 static char *ir_strdup(const char *str)
1204 {
1205     if (str && !*str) {
1206         /* actually dup empty strings */
1207         char *out = (char*)mem_a(1);
1208         *out = 0;
1209         return out;
1210     }
1211     return util_strdup(str);
1212 }
1213
1214 bool ir_value_set_string(ir_value *self, const char *str)
1215 {
1216     if (self->vtype != TYPE_STRING)
1217         return false;
1218     self->constval.vstring = ir_strdup(str);
1219     self->hasvalue = true;
1220     return true;
1221 }
1222
1223 #if 0
1224 bool ir_value_set_int(ir_value *self, int i)
1225 {
1226     if (self->vtype != TYPE_INTEGER)
1227         return false;
1228     self->constval.vint = i;
1229     self->hasvalue = true;
1230     return true;
1231 }
1232 #endif
1233
1234 bool ir_value_lives(ir_value *self, size_t at)
1235 {
1236     size_t i;
1237     for (i = 0; i < vec_size(self->life); ++i)
1238     {
1239         ir_life_entry_t *life = &self->life[i];
1240         if (life->start <= at && at <= life->end)
1241             return true;
1242         if (life->start > at) /* since it's ordered */
1243             return false;
1244     }
1245     return false;
1246 }
1247
1248 bool ir_value_life_insert(ir_value *self, size_t idx, ir_life_entry_t e)
1249 {
1250     size_t k;
1251     vec_push(self->life, e);
1252     for (k = vec_size(self->life)-1; k > idx; --k)
1253         self->life[k] = self->life[k-1];
1254     self->life[idx] = e;
1255     return true;
1256 }
1257
1258 bool ir_value_life_merge(ir_value *self, size_t s)
1259 {
1260     size_t i;
1261     ir_life_entry_t *life = NULL;
1262     ir_life_entry_t *before = NULL;
1263     ir_life_entry_t new_entry;
1264
1265     /* Find the first range >= s */
1266     for (i = 0; i < vec_size(self->life); ++i)
1267     {
1268         before = life;
1269         life = &self->life[i];
1270         if (life->start > s)
1271             break;
1272     }
1273     /* nothing found? append */
1274     if (i == vec_size(self->life)) {
1275         ir_life_entry_t e;
1276         if (life && life->end+1 == s)
1277         {
1278             /* previous life range can be merged in */
1279             life->end++;
1280             return true;
1281         }
1282         if (life && life->end >= s)
1283             return false;
1284         e.start = e.end = s;
1285         vec_push(self->life, e);
1286         return true;
1287     }
1288     /* found */
1289     if (before)
1290     {
1291         if (before->end + 1 == s &&
1292             life->start - 1 == s)
1293         {
1294             /* merge */
1295             before->end = life->end;
1296             vec_remove(self->life, i, 1);
1297             return true;
1298         }
1299         if (before->end + 1 == s)
1300         {
1301             /* extend before */
1302             before->end++;
1303             return true;
1304         }
1305         /* already contained */
1306         if (before->end >= s)
1307             return false;
1308     }
1309     /* extend */
1310     if (life->start - 1 == s)
1311     {
1312         life->start--;
1313         return true;
1314     }
1315     /* insert a new entry */
1316     new_entry.start = new_entry.end = s;
1317     return ir_value_life_insert(self, i, new_entry);
1318 }
1319
1320 bool ir_value_life_merge_into(ir_value *self, const ir_value *other)
1321 {
1322     size_t i, myi;
1323
1324     if (!vec_size(other->life))
1325         return true;
1326
1327     if (!vec_size(self->life)) {
1328         size_t count = vec_size(other->life);
1329         ir_life_entry_t *life = vec_add(self->life, count);
1330         memcpy(life, other->life, count * sizeof(*life));
1331         return true;
1332     }
1333
1334     myi = 0;
1335     for (i = 0; i < vec_size(other->life); ++i)
1336     {
1337         const ir_life_entry_t *life = &other->life[i];
1338         while (true)
1339         {
1340             ir_life_entry_t *entry = &self->life[myi];
1341
1342             if (life->end+1 < entry->start)
1343             {
1344                 /* adding an interval before entry */
1345                 if (!ir_value_life_insert(self, myi, *life))
1346                     return false;
1347                 ++myi;
1348                 break;
1349             }
1350
1351             if (life->start <  entry->start &&
1352                 life->end+1 >= entry->start)
1353             {
1354                 /* starts earlier and overlaps */
1355                 entry->start = life->start;
1356             }
1357
1358             if (life->end   >  entry->end &&
1359                 life->start <= entry->end+1)
1360             {
1361                 /* ends later and overlaps */
1362                 entry->end = life->end;
1363             }
1364
1365             /* see if our change combines it with the next ranges */
1366             while (myi+1 < vec_size(self->life) &&
1367                    entry->end+1 >= self->life[1+myi].start)
1368             {
1369                 /* overlaps with (myi+1) */
1370                 if (entry->end < self->life[1+myi].end)
1371                     entry->end = self->life[1+myi].end;
1372                 vec_remove(self->life, myi+1, 1);
1373                 entry = &self->life[myi];
1374             }
1375
1376             /* see if we're after the entry */
1377             if (life->start > entry->end)
1378             {
1379                 ++myi;
1380                 /* append if we're at the end */
1381                 if (myi >= vec_size(self->life)) {
1382                     vec_push(self->life, *life);
1383                     break;
1384                 }
1385                 /* otherweise check the next range */
1386                 continue;
1387             }
1388             break;
1389         }
1390     }
1391     return true;
1392 }
1393
1394 bool ir_values_overlap(const ir_value *a, const ir_value *b)
1395 {
1396     /* For any life entry in A see if it overlaps with
1397      * any life entry in B.
1398      * Note that the life entries are orderes, so we can make a
1399      * more efficient algorithm there than naively translating the
1400      * statement above.
1401      */
1402
1403     ir_life_entry_t *la, *lb, *enda, *endb;
1404
1405     /* first of all, if either has no life range, they cannot clash */
1406     if (!vec_size(a->life) || !vec_size(b->life))
1407         return false;
1408
1409     la = a->life;
1410     lb = b->life;
1411     enda = la + vec_size(a->life);
1412     endb = lb + vec_size(b->life);
1413     while (true)
1414     {
1415         /* check if the entries overlap, for that,
1416          * both must start before the other one ends.
1417          */
1418         if (la->start < lb->end &&
1419             lb->start < la->end)
1420         {
1421             return true;
1422         }
1423
1424         /* entries are ordered
1425          * one entry is earlier than the other
1426          * that earlier entry will be moved forward
1427          */
1428         if (la->start < lb->start)
1429         {
1430             /* order: A B, move A forward
1431              * check if we hit the end with A
1432              */
1433             if (++la == enda)
1434                 break;
1435         }
1436         else /* if (lb->start < la->start)  actually <= */
1437         {
1438             /* order: B A, move B forward
1439              * check if we hit the end with B
1440              */
1441             if (++lb == endb)
1442                 break;
1443         }
1444     }
1445     return false;
1446 }
1447
1448 /***********************************************************************
1449  *IR main operations
1450  */
1451
1452 static bool ir_check_unreachable(ir_block *self)
1453 {
1454     /* The IR should never have to deal with unreachable code */
1455     if (!self->final/* || OPTS_FLAG(ALLOW_UNREACHABLE_CODE)*/)
1456         return true;
1457     irerror(self->context, "unreachable statement (%s)", self->label);
1458     return false;
1459 }
1460
1461 bool ir_block_create_store_op(ir_block *self, lex_ctx ctx, int op, ir_value *target, ir_value *what)
1462 {
1463     ir_instr *in;
1464     if (!ir_check_unreachable(self))
1465         return false;
1466
1467     if (target->store == store_value &&
1468         (op < INSTR_STOREP_F || op > INSTR_STOREP_FNC))
1469     {
1470         irerror(self->context, "cannot store to an SSA value");
1471         irerror(self->context, "trying to store: %s <- %s", target->name, what->name);
1472         irerror(self->context, "instruction: %s", asm_instr[op].m);
1473         return false;
1474     }
1475
1476     in = ir_instr_new(ctx, self, op);
1477     if (!in)
1478         return false;
1479
1480     if (!ir_instr_op(in, 0, target, (op < INSTR_STOREP_F || op > INSTR_STOREP_FNC)) ||
1481         !ir_instr_op(in, 1, what, false))
1482     {
1483         ir_instr_delete(in);
1484         return false;
1485     }
1486     vec_push(self->instr, in);
1487     return true;
1488 }
1489
1490 bool ir_block_create_store(ir_block *self, lex_ctx ctx, ir_value *target, ir_value *what)
1491 {
1492     int op = 0;
1493     int vtype;
1494     if (target->vtype == TYPE_VARIANT)
1495         vtype = what->vtype;
1496     else
1497         vtype = target->vtype;
1498
1499 #if 0
1500     if      (vtype == TYPE_FLOAT   && what->vtype == TYPE_INTEGER)
1501         op = INSTR_CONV_ITOF;
1502     else if (vtype == TYPE_INTEGER && what->vtype == TYPE_FLOAT)
1503         op = INSTR_CONV_FTOI;
1504 #endif
1505         op = type_store_instr[vtype];
1506
1507     if (OPTS_FLAG(ADJUST_VECTOR_FIELDS)) {
1508         if (op == INSTR_STORE_FLD && what->fieldtype == TYPE_VECTOR)
1509             op = INSTR_STORE_V;
1510     }
1511
1512     return ir_block_create_store_op(self, ctx, op, target, what);
1513 }
1514
1515 bool ir_block_create_storep(ir_block *self, lex_ctx ctx, ir_value *target, ir_value *what)
1516 {
1517     int op = 0;
1518     int vtype;
1519
1520     if (target->vtype != TYPE_POINTER)
1521         return false;
1522
1523     /* storing using pointer - target is a pointer, type must be
1524      * inferred from source
1525      */
1526     vtype = what->vtype;
1527
1528     op = type_storep_instr[vtype];
1529     if (OPTS_FLAG(ADJUST_VECTOR_FIELDS)) {
1530         if (op == INSTR_STOREP_FLD && what->fieldtype == TYPE_VECTOR)
1531             op = INSTR_STOREP_V;
1532     }
1533
1534     return ir_block_create_store_op(self, ctx, op, target, what);
1535 }
1536
1537 bool ir_block_create_return(ir_block *self, lex_ctx ctx, ir_value *v)
1538 {
1539     ir_instr *in;
1540     if (!ir_check_unreachable(self))
1541         return false;
1542     self->final = true;
1543     self->is_return = true;
1544     in = ir_instr_new(ctx, self, INSTR_RETURN);
1545     if (!in)
1546         return false;
1547
1548     if (v && !ir_instr_op(in, 0, v, false)) {
1549         ir_instr_delete(in);
1550         return false;
1551     }
1552
1553     vec_push(self->instr, in);
1554     return true;
1555 }
1556
1557 bool ir_block_create_if(ir_block *self, lex_ctx ctx, ir_value *v,
1558                         ir_block *ontrue, ir_block *onfalse)
1559 {
1560     ir_instr *in;
1561     if (!ir_check_unreachable(self))
1562         return false;
1563     self->final = true;
1564     /*in = ir_instr_new(ctx, self, (v->vtype == TYPE_STRING ? INSTR_IF_S : INSTR_IF_F));*/
1565     in = ir_instr_new(ctx, self, VINSTR_COND);
1566     if (!in)
1567         return false;
1568
1569     if (!ir_instr_op(in, 0, v, false)) {
1570         ir_instr_delete(in);
1571         return false;
1572     }
1573
1574     in->bops[0] = ontrue;
1575     in->bops[1] = onfalse;
1576
1577     vec_push(self->instr, in);
1578
1579     vec_push(self->exits, ontrue);
1580     vec_push(self->exits, onfalse);
1581     vec_push(ontrue->entries,  self);
1582     vec_push(onfalse->entries, self);
1583     return true;
1584 }
1585
1586 bool ir_block_create_jump(ir_block *self, lex_ctx ctx, ir_block *to)
1587 {
1588     ir_instr *in;
1589     if (!ir_check_unreachable(self))
1590         return false;
1591     self->final = true;
1592     in = ir_instr_new(ctx, self, VINSTR_JUMP);
1593     if (!in)
1594         return false;
1595
1596     in->bops[0] = to;
1597     vec_push(self->instr, in);
1598
1599     vec_push(self->exits, to);
1600     vec_push(to->entries, self);
1601     return true;
1602 }
1603
1604 bool ir_block_create_goto(ir_block *self, lex_ctx ctx, ir_block *to)
1605 {
1606     self->owner->flags |= IR_FLAG_HAS_GOTO;
1607     return ir_block_create_jump(self, ctx, to);
1608 }
1609
1610 ir_instr* ir_block_create_phi(ir_block *self, lex_ctx ctx, const char *label, int ot)
1611 {
1612     ir_value *out;
1613     ir_instr *in;
1614     if (!ir_check_unreachable(self))
1615         return NULL;
1616     in = ir_instr_new(ctx, self, VINSTR_PHI);
1617     if (!in)
1618         return NULL;
1619     out = ir_value_out(self->owner, label, store_value, ot);
1620     if (!out) {
1621         ir_instr_delete(in);
1622         return NULL;
1623     }
1624     if (!ir_instr_op(in, 0, out, true)) {
1625         ir_instr_delete(in);
1626         ir_value_delete(out);
1627         return NULL;
1628     }
1629     vec_push(self->instr, in);
1630     return in;
1631 }
1632
1633 ir_value* ir_phi_value(ir_instr *self)
1634 {
1635     return self->_ops[0];
1636 }
1637
1638 void ir_phi_add(ir_instr* self, ir_block *b, ir_value *v)
1639 {
1640     ir_phi_entry_t pe;
1641
1642     if (!vec_ir_block_find(self->owner->entries, b, NULL)) {
1643         /* Must not be possible to cause this, otherwise the AST
1644          * is doing something wrong.
1645          */
1646         irerror(self->context, "Invalid entry block for PHI");
1647         abort();
1648     }
1649
1650     pe.value = v;
1651     pe.from = b;
1652     vec_push(v->reads, self);
1653     vec_push(self->phi, pe);
1654 }
1655
1656 /* call related code */
1657 ir_instr* ir_block_create_call(ir_block *self, lex_ctx ctx, const char *label, ir_value *func, bool noreturn)
1658 {
1659     ir_value *out;
1660     ir_instr *in;
1661     if (!ir_check_unreachable(self))
1662         return NULL;
1663     in = ir_instr_new(ctx, self, (noreturn ? VINSTR_NRCALL : INSTR_CALL0));
1664     if (!in)
1665         return NULL;
1666     if (noreturn) {
1667         self->final = true;
1668         self->is_return = true;
1669     }
1670     out = ir_value_out(self->owner, label, (func->outtype == TYPE_VOID) ? store_return : store_value, func->outtype);
1671     if (!out) {
1672         ir_instr_delete(in);
1673         return NULL;
1674     }
1675     if (!ir_instr_op(in, 0, out, true) ||
1676         !ir_instr_op(in, 1, func, false))
1677     {
1678         ir_instr_delete(in);
1679         ir_value_delete(out);
1680         return NULL;
1681     }
1682     vec_push(self->instr, in);
1683     /*
1684     if (noreturn) {
1685         if (!ir_block_create_return(self, ctx, NULL)) {
1686             compile_error(ctx, "internal error: failed to generate dummy-return instruction");
1687             ir_instr_delete(in);
1688             return NULL;
1689         }
1690     }
1691     */
1692     return in;
1693 }
1694
1695 ir_value* ir_call_value(ir_instr *self)
1696 {
1697     return self->_ops[0];
1698 }
1699
1700 void ir_call_param(ir_instr* self, ir_value *v)
1701 {
1702     vec_push(self->params, v);
1703     vec_push(v->reads, self);
1704 }
1705
1706 /* binary op related code */
1707
1708 ir_value* ir_block_create_binop(ir_block *self, lex_ctx ctx,
1709                                 const char *label, int opcode,
1710                                 ir_value *left, ir_value *right)
1711 {
1712     int ot = TYPE_VOID;
1713     switch (opcode) {
1714         case INSTR_ADD_F:
1715         case INSTR_SUB_F:
1716         case INSTR_DIV_F:
1717         case INSTR_MUL_F:
1718         case INSTR_MUL_V:
1719         case INSTR_AND:
1720         case INSTR_OR:
1721 #if 0
1722         case INSTR_AND_I:
1723         case INSTR_AND_IF:
1724         case INSTR_AND_FI:
1725         case INSTR_OR_I:
1726         case INSTR_OR_IF:
1727         case INSTR_OR_FI:
1728 #endif
1729         case INSTR_BITAND:
1730         case INSTR_BITOR:
1731 #if 0
1732         case INSTR_SUB_S: /* -- offset of string as float */
1733         case INSTR_MUL_IF:
1734         case INSTR_MUL_FI:
1735         case INSTR_DIV_IF:
1736         case INSTR_DIV_FI:
1737         case INSTR_BITOR_IF:
1738         case INSTR_BITOR_FI:
1739         case INSTR_BITAND_FI:
1740         case INSTR_BITAND_IF:
1741         case INSTR_EQ_I:
1742         case INSTR_NE_I:
1743 #endif
1744             ot = TYPE_FLOAT;
1745             break;
1746 #if 0
1747         case INSTR_ADD_I:
1748         case INSTR_ADD_IF:
1749         case INSTR_ADD_FI:
1750         case INSTR_SUB_I:
1751         case INSTR_SUB_FI:
1752         case INSTR_SUB_IF:
1753         case INSTR_MUL_I:
1754         case INSTR_DIV_I:
1755         case INSTR_BITAND_I:
1756         case INSTR_BITOR_I:
1757         case INSTR_XOR_I:
1758         case INSTR_RSHIFT_I:
1759         case INSTR_LSHIFT_I:
1760             ot = TYPE_INTEGER;
1761             break;
1762 #endif
1763         case INSTR_ADD_V:
1764         case INSTR_SUB_V:
1765         case INSTR_MUL_VF:
1766         case INSTR_MUL_FV:
1767 #if 0
1768         case INSTR_DIV_VF:
1769         case INSTR_MUL_IV:
1770         case INSTR_MUL_VI:
1771 #endif
1772             ot = TYPE_VECTOR;
1773             break;
1774 #if 0
1775         case INSTR_ADD_SF:
1776             ot = TYPE_POINTER;
1777             break;
1778 #endif
1779         default:
1780             /* ranges: */
1781             /* boolean operations result in floats */
1782             if (opcode >= INSTR_EQ_F && opcode <= INSTR_GT)
1783                 ot = TYPE_FLOAT;
1784             else if (opcode >= INSTR_LE && opcode <= INSTR_GT)
1785                 ot = TYPE_FLOAT;
1786 #if 0
1787             else if (opcode >= INSTR_LE_I && opcode <= INSTR_EQ_FI)
1788                 ot = TYPE_FLOAT;
1789 #endif
1790             break;
1791     };
1792     if (ot == TYPE_VOID) {
1793         /* The AST or parser were supposed to check this! */
1794         return NULL;
1795     }
1796
1797     return ir_block_create_general_instr(self, ctx, label, opcode, left, right, ot);
1798 }
1799
1800 ir_value* ir_block_create_unary(ir_block *self, lex_ctx ctx,
1801                                 const char *label, int opcode,
1802                                 ir_value *operand)
1803 {
1804     int ot = TYPE_FLOAT;
1805     switch (opcode) {
1806         case INSTR_NOT_F:
1807         case INSTR_NOT_V:
1808         case INSTR_NOT_S:
1809         case INSTR_NOT_ENT:
1810         case INSTR_NOT_FNC:
1811 #if 0
1812         case INSTR_NOT_I:
1813 #endif
1814             ot = TYPE_FLOAT;
1815             break;
1816         /* QC doesn't have other unary operations. We expect extensions to fill
1817          * the above list, otherwise we assume out-type = in-type, eg for an
1818          * unary minus
1819          */
1820         default:
1821             ot = operand->vtype;
1822             break;
1823     };
1824     if (ot == TYPE_VOID) {
1825         /* The AST or parser were supposed to check this! */
1826         return NULL;
1827     }
1828
1829     /* let's use the general instruction creator and pass NULL for OPB */
1830     return ir_block_create_general_instr(self, ctx, label, opcode, operand, NULL, ot);
1831 }
1832
1833 ir_value* ir_block_create_general_instr(ir_block *self, lex_ctx ctx, const char *label,
1834                                         int op, ir_value *a, ir_value *b, int outype)
1835 {
1836     ir_instr *instr;
1837     ir_value *out;
1838
1839     out = ir_value_out(self->owner, label, store_value, outype);
1840     if (!out)
1841         return NULL;
1842
1843     instr = ir_instr_new(ctx, self, op);
1844     if (!instr) {
1845         ir_value_delete(out);
1846         return NULL;
1847     }
1848
1849     if (!ir_instr_op(instr, 0, out, true) ||
1850         !ir_instr_op(instr, 1, a, false) ||
1851         !ir_instr_op(instr, 2, b, false) )
1852     {
1853         goto on_error;
1854     }
1855
1856     vec_push(self->instr, instr);
1857
1858     return out;
1859 on_error:
1860     ir_instr_delete(instr);
1861     ir_value_delete(out);
1862     return NULL;
1863 }
1864
1865 ir_value* ir_block_create_fieldaddress(ir_block *self, lex_ctx ctx, const char *label, ir_value *ent, ir_value *field)
1866 {
1867     ir_value *v;
1868
1869     /* Support for various pointer types todo if so desired */
1870     if (ent->vtype != TYPE_ENTITY)
1871         return NULL;
1872
1873     if (field->vtype != TYPE_FIELD)
1874         return NULL;
1875
1876     v = ir_block_create_general_instr(self, ctx, label, INSTR_ADDRESS, ent, field, TYPE_POINTER);
1877     v->fieldtype = field->fieldtype;
1878     return v;
1879 }
1880
1881 ir_value* ir_block_create_load_from_ent(ir_block *self, lex_ctx ctx, const char *label, ir_value *ent, ir_value *field, int outype)
1882 {
1883     int op;
1884     if (ent->vtype != TYPE_ENTITY)
1885         return NULL;
1886
1887     /* at some point we could redirect for TYPE_POINTER... but that could lead to carelessness */
1888     if (field->vtype != TYPE_FIELD)
1889         return NULL;
1890
1891     switch (outype)
1892     {
1893         case TYPE_FLOAT:    op = INSTR_LOAD_F;   break;
1894         case TYPE_VECTOR:   op = INSTR_LOAD_V;   break;
1895         case TYPE_STRING:   op = INSTR_LOAD_S;   break;
1896         case TYPE_FIELD:    op = INSTR_LOAD_FLD; break;
1897         case TYPE_ENTITY:   op = INSTR_LOAD_ENT; break;
1898         case TYPE_FUNCTION: op = INSTR_LOAD_FNC; break;
1899 #if 0
1900         case TYPE_POINTER: op = INSTR_LOAD_I;   break;
1901         case TYPE_INTEGER: op = INSTR_LOAD_I;   break;
1902 #endif
1903         default:
1904             irerror(self->context, "invalid type for ir_block_create_load_from_ent: %s", type_name[outype]);
1905             return NULL;
1906     }
1907
1908     return ir_block_create_general_instr(self, ctx, label, op, ent, field, outype);
1909 }
1910
1911 /* PHI resolving breaks the SSA, and must thus be the last
1912  * step before life-range calculation.
1913  */
1914
1915 static bool ir_block_naive_phi(ir_block *self);
1916 bool ir_function_naive_phi(ir_function *self)
1917 {
1918     size_t i;
1919
1920     for (i = 0; i < vec_size(self->blocks); ++i)
1921     {
1922         if (!ir_block_naive_phi(self->blocks[i]))
1923             return false;
1924     }
1925     return true;
1926 }
1927
1928 static bool ir_block_naive_phi(ir_block *self)
1929 {
1930     size_t i, p; /*, w;*/
1931     /* FIXME: optionally, create_phi can add the phis
1932      * to a list so we don't need to loop through blocks
1933      * - anyway: "don't optimize YET"
1934      */
1935     for (i = 0; i < vec_size(self->instr); ++i)
1936     {
1937         ir_instr *instr = self->instr[i];
1938         if (instr->opcode != VINSTR_PHI)
1939             continue;
1940
1941         vec_remove(self->instr, i, 1);
1942         --i; /* NOTE: i+1 below */
1943
1944         for (p = 0; p < vec_size(instr->phi); ++p)
1945         {
1946             ir_value *v = instr->phi[p].value;
1947             ir_block *b = instr->phi[p].from;
1948
1949             if (v->store == store_value &&
1950                 vec_size(v->reads) == 1 &&
1951                 vec_size(v->writes) == 1)
1952             {
1953                 /* replace the value */
1954                 if (!ir_instr_op(v->writes[0], 0, instr->_ops[0], true))
1955                     return false;
1956             }
1957             else
1958             {
1959                 /* force a move instruction */
1960                 ir_instr *prevjump = vec_last(b->instr);
1961                 vec_pop(b->instr);
1962                 b->final = false;
1963                 instr->_ops[0]->store = store_global;
1964                 if (!ir_block_create_store(b, instr->context, instr->_ops[0], v))
1965                     return false;
1966                 instr->_ops[0]->store = store_value;
1967                 vec_push(b->instr, prevjump);
1968                 b->final = true;
1969             }
1970         }
1971         ir_instr_delete(instr);
1972     }
1973     return true;
1974 }
1975
1976 /***********************************************************************
1977  *IR Temp allocation code
1978  * Propagating value life ranges by walking through the function backwards
1979  * until no more changes are made.
1980  * In theory this should happen once more than once for every nested loop
1981  * level.
1982  * Though this implementation might run an additional time for if nests.
1983  */
1984
1985 /* Enumerate instructions used by value's life-ranges
1986  */
1987 static void ir_block_enumerate(ir_block *self, size_t *_eid)
1988 {
1989     size_t i;
1990     size_t eid = *_eid;
1991     for (i = 0; i < vec_size(self->instr); ++i)
1992     {
1993         self->instr[i]->eid = eid++;
1994     }
1995     *_eid = eid;
1996 }
1997
1998 /* Enumerate blocks and instructions.
1999  * The block-enumeration is unordered!
2000  * We do not really use the block enumreation, however
2001  * the instruction enumeration is important for life-ranges.
2002  */
2003 void ir_function_enumerate(ir_function *self)
2004 {
2005     size_t i;
2006     size_t instruction_id = 0;
2007     for (i = 0; i < vec_size(self->blocks); ++i)
2008     {
2009         /* each block now gets an additional "entry" instruction id
2010          * we can use to avoid point-life issues
2011          */
2012         self->blocks[i]->entry_id = instruction_id;
2013         ++instruction_id;
2014
2015         self->blocks[i]->eid = i;
2016         self->blocks[i]->run_id = 0;
2017         ir_block_enumerate(self->blocks[i], &instruction_id);
2018     }
2019 }
2020
2021 static bool ir_block_life_propagate(ir_block *b, ir_block *prev, bool *changed);
2022 bool ir_function_calculate_liferanges(ir_function *self)
2023 {
2024     size_t i, s;
2025     bool changed;
2026
2027     /* parameters live at 0 */
2028     for (i = 0; i < vec_size(self->params); ++i)
2029         ir_value_life_merge(self->locals[i], 0);
2030
2031     do {
2032         self->run_id++;
2033         changed = false;
2034         for (i = 0; i != vec_size(self->blocks); ++i)
2035         {
2036             if (self->blocks[i]->is_return)
2037             {
2038                 vec_free(self->blocks[i]->living);
2039                 if (!ir_block_life_propagate(self->blocks[i], NULL, &changed))
2040                     return false;
2041             }
2042         }
2043     } while (changed);
2044     if (vec_size(self->blocks)) {
2045         ir_block *block = self->blocks[0];
2046         for (i = 0; i < vec_size(block->living); ++i) {
2047             ir_value *v = block->living[i];
2048             if (v->store != store_local)
2049                 continue;
2050             if (v->vtype == TYPE_VECTOR)
2051                 continue;
2052             self->flags |= IR_FLAG_HAS_UNINITIALIZED;
2053             /* find the instruction reading from it */
2054             for (s = 0; s < vec_size(v->reads); ++s) {
2055                 if (v->reads[s]->eid == v->life[0].end)
2056                     break;
2057             }
2058             if (s < vec_size(v->reads)) {
2059                 if (irwarning(v->context, WARN_USED_UNINITIALIZED,
2060                               "variable `%s` may be used uninitialized in this function\n"
2061                               " -> %s:%i",
2062                               v->name,
2063                               v->reads[s]->context.file, v->reads[s]->context.line)
2064                    )
2065                 {
2066                     return false;
2067                 }
2068                 continue;
2069             }
2070             if (v->memberof) {
2071                 ir_value *vec = v->memberof;
2072                 for (s = 0; s < vec_size(vec->reads); ++s) {
2073                     if (vec->reads[s]->eid == v->life[0].end)
2074                         break;
2075                 }
2076                 if (s < vec_size(vec->reads)) {
2077                     if (irwarning(v->context, WARN_USED_UNINITIALIZED,
2078                                   "variable `%s` may be used uninitialized in this function\n"
2079                                   " -> %s:%i",
2080                                   v->name,
2081                                   vec->reads[s]->context.file, vec->reads[s]->context.line)
2082                        )
2083                     {
2084                         return false;
2085                     }
2086                     continue;
2087                 }
2088             }
2089             if (irwarning(v->context, WARN_USED_UNINITIALIZED,
2090                           "variable `%s` may be used uninitialized in this function", v->name))
2091             {
2092                 return false;
2093             }
2094         }
2095     }
2096     return true;
2097 }
2098
2099 /* Local-value allocator
2100  * After finishing creating the liferange of all values used in a function
2101  * we can allocate their global-positions.
2102  * This is the counterpart to register-allocation in register machines.
2103  */
2104 typedef struct {
2105     ir_value **locals;
2106     size_t    *sizes;
2107     size_t    *positions;
2108     bool      *unique;
2109 } function_allocator;
2110
2111 static bool function_allocator_alloc(function_allocator *alloc, ir_value *var)
2112 {
2113     ir_value *slot;
2114     size_t vsize = ir_value_sizeof(var);
2115
2116     var->code.local = vec_size(alloc->locals);
2117
2118     slot = ir_value_var("reg", store_global, var->vtype);
2119     if (!slot)
2120         return false;
2121
2122     if (!ir_value_life_merge_into(slot, var))
2123         goto localerror;
2124
2125     vec_push(alloc->locals, slot);
2126     vec_push(alloc->sizes, vsize);
2127     vec_push(alloc->unique, var->unique_life);
2128
2129     return true;
2130
2131 localerror:
2132     ir_value_delete(slot);
2133     return false;
2134 }
2135
2136 static bool ir_function_allocator_assign(ir_function *self, function_allocator *alloc, ir_value *v)
2137 {
2138     size_t a;
2139     ir_value *slot;
2140
2141     if (v->unique_life)
2142         return function_allocator_alloc(alloc, v);
2143
2144     for (a = 0; a < vec_size(alloc->locals); ++a)
2145     {
2146         /* if it's reserved for a unique liferange: skip */
2147         if (alloc->unique[a])
2148             continue;
2149
2150         slot = alloc->locals[a];
2151
2152         /* never resize parameters
2153          * will be required later when overlapping temps + locals
2154          */
2155         if (a < vec_size(self->params) &&
2156             alloc->sizes[a] < ir_value_sizeof(v))
2157         {
2158             continue;
2159         }
2160
2161         if (ir_values_overlap(v, slot))
2162             continue;
2163
2164         if (!ir_value_life_merge_into(slot, v))
2165             return false;
2166
2167         /* adjust size for this slot */
2168         if (alloc->sizes[a] < ir_value_sizeof(v))
2169             alloc->sizes[a] = ir_value_sizeof(v);
2170
2171         v->code.local = a;
2172         return true;
2173     }
2174     if (a >= vec_size(alloc->locals)) {
2175         if (!function_allocator_alloc(alloc, v))
2176             return false;
2177     }
2178     return true;
2179 }
2180
2181 bool ir_function_allocate_locals(ir_function *self)
2182 {
2183     size_t i;
2184     bool   retval = true;
2185     size_t pos;
2186     bool   opt_gt = OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS);
2187
2188     ir_value *v;
2189
2190     function_allocator lockalloc, globalloc;
2191
2192     if (!vec_size(self->locals) && !vec_size(self->values))
2193         return true;
2194
2195     globalloc.locals    = NULL;
2196     globalloc.sizes     = NULL;
2197     globalloc.positions = NULL;
2198     globalloc.unique    = NULL;
2199     lockalloc.locals    = NULL;
2200     lockalloc.sizes     = NULL;
2201     lockalloc.positions = NULL;
2202     lockalloc.unique    = NULL;
2203
2204     for (i = 0; i < vec_size(self->locals); ++i)
2205     {
2206         v = self->locals[i];
2207         if ((self->flags & IR_FLAG_MASK_NO_LOCAL_TEMPS) || !OPTS_OPTIMIZATION(OPTIM_LOCAL_TEMPS)) {
2208             v->locked      = true;
2209             v->unique_life = true;
2210         }
2211         else if (i >= vec_size(self->params))
2212             break;
2213         else
2214             v->locked = true; /* lock parameters locals */
2215         if (!function_allocator_alloc((v->locked || !opt_gt ? &lockalloc : &globalloc), v))
2216             goto error;
2217     }
2218     for (; i < vec_size(self->locals); ++i)
2219     {
2220         v = self->locals[i];
2221         if (!vec_size(v->life))
2222             continue;
2223         if (!ir_function_allocator_assign(self, (v->locked || !opt_gt ? &lockalloc : &globalloc), v))
2224             goto error;
2225     }
2226
2227     /* Allocate a slot for any value that still exists */
2228     for (i = 0; i < vec_size(self->values); ++i)
2229     {
2230         v = self->values[i];
2231
2232         if (!vec_size(v->life))
2233             continue;
2234
2235         /* CALL optimization:
2236          * If the value is a parameter-temp: 1 write, 1 read from a CALL
2237          * and it's not "locked", write it to the OFS_PARM directly.
2238          */
2239         if (OPTS_OPTIMIZATION(OPTIM_CALL_STORES) && !v->locked && !v->unique_life) {
2240             if (vec_size(v->reads) == 1 && vec_size(v->writes) == 1 &&
2241                 (v->reads[0]->opcode == VINSTR_NRCALL ||
2242                  (v->reads[0]->opcode >= INSTR_CALL0 && v->reads[0]->opcode <= INSTR_CALL8)
2243                 )
2244                )
2245             {
2246                 size_t    param;
2247                 ir_instr *call = v->reads[0];
2248                 if (!vec_ir_value_find(call->params, v, &param)) {
2249                     irerror(call->context, "internal error: unlocked parameter %s not found", v->name);
2250                     goto error;
2251                 }
2252
2253                 ++opts_optimizationcount[OPTIM_CALL_STORES];
2254                 v->callparam = true;
2255                 if (param < 8)
2256                     ir_value_code_setaddr(v, OFS_PARM0 + 3*param);
2257                 else {
2258                     ir_value *ep;
2259                     param -= 8;
2260                     if (vec_size(self->owner->extparam_protos) <= param)
2261                         ep = ir_gen_extparam_proto(self->owner);
2262                     else
2263                         ep = self->owner->extparam_protos[param];
2264                     ir_instr_op(v->writes[0], 0, ep, true);
2265                     call->params[param+8] = ep;
2266                 }
2267                 continue;
2268             }
2269             if (vec_size(v->writes) == 1 && v->writes[0]->opcode == INSTR_CALL0)
2270             {
2271                 v->store = store_return;
2272                 if (v->members[0]) v->members[0]->store = store_return;
2273                 if (v->members[1]) v->members[1]->store = store_return;
2274                 if (v->members[2]) v->members[2]->store = store_return;
2275                 ++opts_optimizationcount[OPTIM_CALL_STORES];
2276                 continue;
2277             }
2278         }
2279
2280         if (!ir_function_allocator_assign(self, (v->locked || !opt_gt ? &lockalloc : &globalloc), v))
2281             goto error;
2282     }
2283
2284     if (!lockalloc.sizes && !globalloc.sizes) {
2285         goto cleanup;
2286     }
2287     vec_push(lockalloc.positions, 0);
2288     vec_push(globalloc.positions, 0);
2289
2290     /* Adjust slot positions based on sizes */
2291     if (lockalloc.sizes) {
2292         pos = (vec_size(lockalloc.sizes) ? lockalloc.positions[0] : 0);
2293         for (i = 1; i < vec_size(lockalloc.sizes); ++i)
2294         {
2295             pos = lockalloc.positions[i-1] + lockalloc.sizes[i-1];
2296             vec_push(lockalloc.positions, pos);
2297         }
2298         self->allocated_locals = pos + vec_last(lockalloc.sizes);
2299     }
2300     if (globalloc.sizes) {
2301         pos = (vec_size(globalloc.sizes) ? globalloc.positions[0] : 0);
2302         for (i = 1; i < vec_size(globalloc.sizes); ++i)
2303         {
2304             pos = globalloc.positions[i-1] + globalloc.sizes[i-1];
2305             vec_push(globalloc.positions, pos);
2306         }
2307         self->globaltemps = pos + vec_last(globalloc.sizes);
2308     }
2309
2310     /* Locals need to know their new position */
2311     for (i = 0; i < vec_size(self->locals); ++i) {
2312         v = self->locals[i];
2313         if (v->locked || !opt_gt)
2314             v->code.local = lockalloc.positions[v->code.local];
2315         else
2316             v->code.local = globalloc.positions[v->code.local];
2317     }
2318     /* Take over the actual slot positions on values */
2319     for (i = 0; i < vec_size(self->values); ++i) {
2320         v = self->values[i];
2321         if (v->locked || !opt_gt)
2322             v->code.local = lockalloc.positions[v->code.local];
2323         else
2324             v->code.local = globalloc.positions[v->code.local];
2325     }
2326
2327     goto cleanup;
2328
2329 error:
2330     retval = false;
2331 cleanup:
2332     for (i = 0; i < vec_size(lockalloc.locals); ++i)
2333         ir_value_delete(lockalloc.locals[i]);
2334     for (i = 0; i < vec_size(globalloc.locals); ++i)
2335         ir_value_delete(globalloc.locals[i]);
2336     vec_free(globalloc.unique);
2337     vec_free(globalloc.locals);
2338     vec_free(globalloc.sizes);
2339     vec_free(globalloc.positions);
2340     vec_free(lockalloc.unique);
2341     vec_free(lockalloc.locals);
2342     vec_free(lockalloc.sizes);
2343     vec_free(lockalloc.positions);
2344     return retval;
2345 }
2346
2347 /* Get information about which operand
2348  * is read from, or written to.
2349  */
2350 static void ir_op_read_write(int op, size_t *read, size_t *write)
2351 {
2352     switch (op)
2353     {
2354     case VINSTR_JUMP:
2355     case INSTR_GOTO:
2356         *write = 0;
2357         *read = 0;
2358         break;
2359     case INSTR_IF:
2360     case INSTR_IFNOT:
2361 #if 0
2362     case INSTR_IF_S:
2363     case INSTR_IFNOT_S:
2364 #endif
2365     case INSTR_RETURN:
2366     case VINSTR_COND:
2367         *write = 0;
2368         *read = 1;
2369         break;
2370     case INSTR_STOREP_F:
2371     case INSTR_STOREP_V:
2372     case INSTR_STOREP_S:
2373     case INSTR_STOREP_ENT:
2374     case INSTR_STOREP_FLD:
2375     case INSTR_STOREP_FNC:
2376         *write = 0;
2377         *read  = 7;
2378         break;
2379     default:
2380         *write = 1;
2381         *read = 6;
2382         break;
2383     };
2384 }
2385
2386 static bool ir_block_living_add_instr(ir_block *self, size_t eid)
2387 {
2388     size_t i;
2389     bool changed = false;
2390     bool tempbool;
2391     for (i = 0; i != vec_size(self->living); ++i)
2392     {
2393         tempbool = ir_value_life_merge(self->living[i], eid);
2394         changed = changed || tempbool;
2395     }
2396     return changed;
2397 }
2398
2399 static bool ir_block_living_lock(ir_block *self)
2400 {
2401     size_t i;
2402     bool changed = false;
2403     for (i = 0; i != vec_size(self->living); ++i)
2404     {
2405         if (!self->living[i]->locked) {
2406             self->living[i]->locked = true;
2407             changed = true;
2408         }
2409     }
2410     return changed;
2411 }
2412
2413 static bool ir_block_life_prop_previous(ir_block* self, ir_block *prev, bool *changed)
2414 {
2415     size_t i;
2416
2417     (void)changed;
2418
2419     /* values which have been read in a previous iteration are now
2420      * in the "living" array even if the previous block doesn't use them.
2421      * So we have to remove whatever does not exist in the previous block.
2422      * They will be re-added on-read, but the liferange merge won't cause
2423      * a change.
2424     for (i = 0; i < vec_size(self->living); ++i)
2425     {
2426         if (!vec_ir_value_find(prev->living, self->living[i], NULL)) {
2427             vec_remove(self->living, i, 1);
2428             --i;
2429         }
2430     }
2431      */
2432
2433     /* Whatever the previous block still has in its living set
2434      * must now be added to ours as well.
2435      */
2436     for (i = 0; i < vec_size(prev->living); ++i)
2437     {
2438         if (vec_ir_value_find(self->living, prev->living[i], NULL))
2439             continue;
2440         vec_push(self->living, prev->living[i]);
2441         /*
2442         irerror(self->contextt from prev: %s", self->label, prev->living[i]->_name);
2443         */
2444     }
2445     return true;
2446 }
2447
2448 static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *changed)
2449 {
2450     ir_instr *instr;
2451     ir_value *value;
2452     bool  tempbool;
2453     size_t i, o, p, mem;
2454     /* bitmasks which operands are read from or written to */
2455     size_t read, write;
2456     char dbg_ind[16];
2457     dbg_ind[0] = '#';
2458     dbg_ind[1] = '0';
2459     (void)dbg_ind;
2460
2461     if (prev)
2462     {
2463         if (!ir_block_life_prop_previous(self, prev, changed))
2464             return false;
2465     }
2466
2467     i = vec_size(self->instr);
2468     while (i)
2469     { --i;
2470         instr = self->instr[i];
2471
2472         /* See which operands are read and write operands */
2473         ir_op_read_write(instr->opcode, &read, &write);
2474
2475         /* Go through the 3 main operands
2476          * writes first, then reads
2477          */
2478         for (o = 0; o < 3; ++o)
2479         {
2480             if (!instr->_ops[o]) /* no such operand */
2481                 continue;
2482
2483             value = instr->_ops[o];
2484
2485             /* We only care about locals */
2486             /* we also calculate parameter liferanges so that locals
2487              * can take up parameter slots */
2488             if (value->store != store_value &&
2489                 value->store != store_local &&
2490                 value->store != store_param)
2491                 continue;
2492
2493             /* write operands */
2494             /* When we write to a local, we consider it "dead" for the
2495              * remaining upper part of the function, since in SSA a value
2496              * can only be written once (== created)
2497              */
2498             if (write & (1<<o))
2499             {
2500                 size_t idx;
2501                 bool in_living = vec_ir_value_find(self->living, value, &idx);
2502                 if (!in_living)
2503                 {
2504                     /* If the value isn't alive it hasn't been read before... */
2505                     /* TODO: See if the warning can be emitted during parsing or AST processing
2506                      * otherwise have warning printed here.
2507                      * IF printing a warning here: include filecontext_t,
2508                      * and make sure it's only printed once
2509                      * since this function is run multiple times.
2510                      */
2511                     /* con_err( "Value only written %s\n", value->name); */
2512                     tempbool = ir_value_life_merge(value, instr->eid);
2513                     *changed = *changed || tempbool;
2514                 } else {
2515                     /* since 'living' won't contain it
2516                      * anymore, merge the value, since
2517                      * (A) doesn't.
2518                      */
2519                     tempbool = ir_value_life_merge(value, instr->eid);
2520                     *changed = *changed || tempbool;
2521                     /* Then remove */
2522                     vec_remove(self->living, idx, 1);
2523                 }
2524                 /* Removing a vector removes all members */
2525                 for (mem = 0; mem < 3; ++mem) {
2526                     if (value->members[mem] && vec_ir_value_find(self->living, value->members[mem], &idx)) {
2527                         tempbool = ir_value_life_merge(value->members[mem], instr->eid);
2528                         *changed = *changed || tempbool;
2529                         vec_remove(self->living, idx, 1);
2530                     }
2531                 }
2532                 /* Removing the last member removes the vector */
2533                 if (value->memberof) {
2534                     value = value->memberof;
2535                     for (mem = 0; mem < 3; ++mem) {
2536                         if (value->members[mem] && vec_ir_value_find(self->living, value->members[mem], NULL))
2537                             break;
2538                     }
2539                     if (mem == 3 && vec_ir_value_find(self->living, value, &idx)) {
2540                         tempbool = ir_value_life_merge(value, instr->eid);
2541                         *changed = *changed || tempbool;
2542                         vec_remove(self->living, idx, 1);
2543                     }
2544                 }
2545             }
2546         }
2547
2548         if (instr->opcode == INSTR_MUL_VF)
2549         {
2550             value = instr->_ops[2];
2551             /* the float source will get an additional lifetime */
2552             if (ir_value_life_merge(value, instr->eid+1))
2553                 *changed = true;
2554             if (value->memberof && ir_value_life_merge(value->memberof, instr->eid+1))
2555                 *changed = true;
2556         }
2557         else if (instr->opcode == INSTR_MUL_FV)
2558         {
2559             value = instr->_ops[1];
2560             /* the float source will get an additional lifetime */
2561             if (ir_value_life_merge(value, instr->eid+1))
2562                 *changed = true;
2563             if (value->memberof && ir_value_life_merge(value->memberof, instr->eid+1))
2564                 *changed = true;
2565         }
2566
2567         for (o = 0; o < 3; ++o)
2568         {
2569             if (!instr->_ops[o]) /* no such operand */
2570                 continue;
2571
2572             value = instr->_ops[o];
2573
2574             /* We only care about locals */
2575             /* we also calculate parameter liferanges so that locals
2576              * can take up parameter slots */
2577             if (value->store != store_value &&
2578                 value->store != store_local &&
2579                 value->store != store_param)
2580                 continue;
2581
2582             /* read operands */
2583             if (read & (1<<o))
2584             {
2585                 if (!vec_ir_value_find(self->living, value, NULL))
2586                     vec_push(self->living, value);
2587                 /* reading adds the full vector */
2588                 if (value->memberof && !vec_ir_value_find(self->living, value->memberof, NULL))
2589                     vec_push(self->living, value->memberof);
2590                 for (mem = 0; mem < 3; ++mem) {
2591                     if (value->members[mem] && !vec_ir_value_find(self->living, value->members[mem], NULL))
2592                         vec_push(self->living, value->members[mem]);
2593                 }
2594             }
2595         }
2596         /* PHI operands are always read operands */
2597         for (p = 0; p < vec_size(instr->phi); ++p)
2598         {
2599             value = instr->phi[p].value;
2600             if (!vec_ir_value_find(self->living, value, NULL))
2601                 vec_push(self->living, value);
2602             /* reading adds the full vector */
2603             if (value->memberof && !vec_ir_value_find(self->living, value->memberof, NULL))
2604                 vec_push(self->living, value->memberof);
2605             for (mem = 0; mem < 3; ++mem) {
2606                 if (value->members[mem] && !vec_ir_value_find(self->living, value->members[mem], NULL))
2607                     vec_push(self->living, value->members[mem]);
2608             }
2609         }
2610
2611         /* on a call, all these values must be "locked" */
2612         if (instr->opcode >= INSTR_CALL0 && instr->opcode <= INSTR_CALL8) {
2613             if (ir_block_living_lock(self))
2614                 *changed = true;
2615         }
2616         /* call params are read operands too */
2617         for (p = 0; p < vec_size(instr->params); ++p)
2618         {
2619             value = instr->params[p];
2620             if (!vec_ir_value_find(self->living, value, NULL))
2621                 vec_push(self->living, value);
2622             /* reading adds the full vector */
2623             if (value->memberof && !vec_ir_value_find(self->living, value->memberof, NULL))
2624                 vec_push(self->living, value->memberof);
2625             for (mem = 0; mem < 3; ++mem) {
2626                 if (value->members[mem] && !vec_ir_value_find(self->living, value->members[mem], NULL))
2627                     vec_push(self->living, value->members[mem]);
2628             }
2629         }
2630
2631         /* (A) */
2632         tempbool = ir_block_living_add_instr(self, instr->eid);
2633         /*con_err( "living added values\n");*/
2634         *changed = *changed || tempbool;
2635     }
2636     /* the "entry" instruction ID */
2637     tempbool = ir_block_living_add_instr(self, self->entry_id);
2638     *changed = *changed || tempbool;
2639
2640     if (self->run_id == self->owner->run_id)
2641         return true;
2642
2643     self->run_id = self->owner->run_id;
2644
2645     for (i = 0; i < vec_size(self->entries); ++i)
2646     {
2647         ir_block *entry = self->entries[i];
2648         ir_block_life_propagate(entry, self, changed);
2649     }
2650
2651     return true;
2652 }
2653
2654 /***********************************************************************
2655  *IR Code-Generation
2656  *
2657  * Since the IR has the convention of putting 'write' operands
2658  * at the beginning, we have to rotate the operands of instructions
2659  * properly in order to generate valid QCVM code.
2660  *
2661  * Having destinations at a fixed position is more convenient. In QC
2662  * this is *mostly* OPC,  but FTE adds at least 2 instructions which
2663  * read from from OPA,  and store to OPB rather than OPC.   Which is
2664  * partially the reason why the implementation of these instructions
2665  * in darkplaces has been delayed for so long.
2666  *
2667  * Breaking conventions is annoying...
2668  */
2669 static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool islocal);
2670
2671 static bool gen_global_field(ir_value *global)
2672 {
2673     if (global->hasvalue)
2674     {
2675         ir_value *fld = global->constval.vpointer;
2676         if (!fld) {
2677             irerror(global->context, "Invalid field constant with no field: %s", global->name);
2678             return false;
2679         }
2680
2681         /* copy the field's value */
2682         ir_value_code_setaddr(global, vec_size(code_globals));
2683         vec_push(code_globals, fld->code.fieldaddr);
2684         if (global->fieldtype == TYPE_VECTOR) {
2685             vec_push(code_globals, fld->code.fieldaddr+1);
2686             vec_push(code_globals, fld->code.fieldaddr+2);
2687         }
2688     }
2689     else
2690     {
2691         ir_value_code_setaddr(global, vec_size(code_globals));
2692         vec_push(code_globals, 0);
2693         if (global->fieldtype == TYPE_VECTOR) {
2694             vec_push(code_globals, 0);
2695             vec_push(code_globals, 0);
2696         }
2697     }
2698     if (global->code.globaladdr < 0)
2699         return false;
2700     return true;
2701 }
2702
2703 static bool gen_global_pointer(ir_value *global)
2704 {
2705     if (global->hasvalue)
2706     {
2707         ir_value *target = global->constval.vpointer;
2708         if (!target) {
2709             irerror(global->context, "Invalid pointer constant: %s", global->name);
2710             /* NULL pointers are pointing to the NULL constant, which also
2711              * sits at address 0, but still has an ir_value for itself.
2712              */
2713             return false;
2714         }
2715
2716         /* Here, relocations ARE possible - in fteqcc-enhanced-qc:
2717          * void() foo; <- proto
2718          * void() *fooptr = &foo;
2719          * void() foo = { code }
2720          */
2721         if (!target->code.globaladdr) {
2722             /* FIXME: Check for the constant nullptr ir_value!
2723              * because then code.globaladdr being 0 is valid.
2724              */
2725             irerror(global->context, "FIXME: Relocation support");
2726             return false;
2727         }
2728
2729         ir_value_code_setaddr(global, vec_size(code_globals));
2730         vec_push(code_globals, target->code.globaladdr);
2731     }
2732     else
2733     {
2734         ir_value_code_setaddr(global, vec_size(code_globals));
2735         vec_push(code_globals, 0);
2736     }
2737     if (global->code.globaladdr < 0)
2738         return false;
2739     return true;
2740 }
2741
2742 static bool gen_blocks_recursive(ir_function *func, ir_block *block)
2743 {
2744     prog_section_statement stmt;
2745     ir_instr *instr;
2746     ir_block *target;
2747     ir_block *ontrue;
2748     ir_block *onfalse;
2749     size_t    stidx;
2750     size_t    i;
2751
2752     block->generated = true;
2753     block->code_start = vec_size(code_statements);
2754     for (i = 0; i < vec_size(block->instr); ++i)
2755     {
2756         instr = block->instr[i];
2757
2758         if (instr->opcode == VINSTR_PHI) {
2759             irerror(block->context, "cannot generate virtual instruction (phi)");
2760             return false;
2761         }
2762
2763         if (instr->opcode == VINSTR_JUMP) {
2764             target = instr->bops[0];
2765             /* for uncoditional jumps, if the target hasn't been generated
2766              * yet, we generate them right here.
2767              */
2768             if (!target->generated)
2769                 return gen_blocks_recursive(func, target);
2770
2771             /* otherwise we generate a jump instruction */
2772             stmt.opcode = INSTR_GOTO;
2773             stmt.o1.s1 = (target->code_start) - vec_size(code_statements);
2774             stmt.o2.s1 = 0;
2775             stmt.o3.s1 = 0;
2776             if (stmt.o1.s1 != 1)
2777                 code_push_statement(&stmt, instr->context.line);
2778
2779             /* no further instructions can be in this block */
2780             return true;
2781         }
2782
2783         if (instr->opcode == VINSTR_COND) {
2784             ontrue  = instr->bops[0];
2785             onfalse = instr->bops[1];
2786             /* TODO: have the AST signal which block should
2787              * come first: eg. optimize IFs without ELSE...
2788              */
2789
2790             stmt.o1.u1 = ir_value_code_addr(instr->_ops[0]);
2791             stmt.o2.u1 = 0;
2792             stmt.o3.s1 = 0;
2793
2794             if (ontrue->generated) {
2795                 stmt.opcode = INSTR_IF;
2796                 stmt.o2.s1 = (ontrue->code_start) - vec_size(code_statements);
2797                 if (stmt.o2.s1 != 1)
2798                     code_push_statement(&stmt, instr->context.line);
2799             }
2800             if (onfalse->generated) {
2801                 stmt.opcode = INSTR_IFNOT;
2802                 stmt.o2.s1 = (onfalse->code_start) - vec_size(code_statements);
2803                 if (stmt.o2.s1 != 1)
2804                     code_push_statement(&stmt, instr->context.line);
2805             }
2806             if (!ontrue->generated) {
2807                 if (onfalse->generated)
2808                     return gen_blocks_recursive(func, ontrue);
2809             }
2810             if (!onfalse->generated) {
2811                 if (ontrue->generated)
2812                     return gen_blocks_recursive(func, onfalse);
2813             }
2814             /* neither ontrue nor onfalse exist */
2815             stmt.opcode = INSTR_IFNOT;
2816             if (!instr->likely) {
2817                 /* Honor the likelyhood hint */
2818                 ir_block *tmp = onfalse;
2819                 stmt.opcode = INSTR_IF;
2820                 onfalse = ontrue;
2821                 ontrue = tmp;
2822             }
2823             stidx = vec_size(code_statements);
2824             code_push_statement(&stmt, instr->context.line);
2825             /* on false we jump, so add ontrue-path */
2826             if (!gen_blocks_recursive(func, ontrue))
2827                 return false;
2828             /* fixup the jump address */
2829             code_statements[stidx].o2.s1 = vec_size(code_statements) - stidx;
2830             /* generate onfalse path */
2831             if (onfalse->generated) {
2832                 /* fixup the jump address */
2833                 code_statements[stidx].o2.s1 = (onfalse->code_start) - (stidx);
2834                 if (stidx+2 == vec_size(code_statements) && code_statements[stidx].o2.s1 == 1) {
2835                     code_statements[stidx] = code_statements[stidx+1];
2836                     if (code_statements[stidx].o1.s1 < 0)
2837                         code_statements[stidx].o1.s1++;
2838                     code_pop_statement();
2839                 }
2840                 stmt.opcode = vec_last(code_statements).opcode;
2841                 if (stmt.opcode == INSTR_GOTO ||
2842                     stmt.opcode == INSTR_IF ||
2843                     stmt.opcode == INSTR_IFNOT ||
2844                     stmt.opcode == INSTR_RETURN ||
2845                     stmt.opcode == INSTR_DONE)
2846                 {
2847                     /* no use jumping from here */
2848                     return true;
2849                 }
2850                 /* may have been generated in the previous recursive call */
2851                 stmt.opcode = INSTR_GOTO;
2852                 stmt.o1.s1 = (onfalse->code_start) - vec_size(code_statements);
2853                 stmt.o2.s1 = 0;
2854                 stmt.o3.s1 = 0;
2855                 if (stmt.o1.s1 != 1)
2856                     code_push_statement(&stmt, instr->context.line);
2857                 return true;
2858             }
2859             else if (stidx+2 == vec_size(code_statements) && code_statements[stidx].o2.s1 == 1) {
2860                 code_statements[stidx] = code_statements[stidx+1];
2861                 if (code_statements[stidx].o1.s1 < 0)
2862                     code_statements[stidx].o1.s1++;
2863                 code_pop_statement();
2864             }
2865             /* if not, generate now */
2866             return gen_blocks_recursive(func, onfalse);
2867         }
2868
2869         if ( (instr->opcode >= INSTR_CALL0 && instr->opcode <= INSTR_CALL8)
2870            || instr->opcode == VINSTR_NRCALL)
2871         {
2872             size_t p, first;
2873             ir_value *retvalue;
2874
2875             first = vec_size(instr->params);
2876             if (first > 8)
2877                 first = 8;
2878             for (p = 0; p < first; ++p)
2879             {
2880                 ir_value *param = instr->params[p];
2881                 if (param->callparam)
2882                     continue;
2883
2884                 stmt.opcode = INSTR_STORE_F;
2885                 stmt.o3.u1 = 0;
2886
2887                 if (param->vtype == TYPE_FIELD)
2888                     stmt.opcode = field_store_instr[param->fieldtype];
2889                 else if (param->vtype == TYPE_NIL)
2890                     stmt.opcode = INSTR_STORE_V;
2891                 else
2892                     stmt.opcode = type_store_instr[param->vtype];
2893                 stmt.o1.u1 = ir_value_code_addr(param);
2894                 stmt.o2.u1 = OFS_PARM0 + 3 * p;
2895                 code_push_statement(&stmt, instr->context.line);
2896             }
2897             /* Now handle extparams */
2898             first = vec_size(instr->params);
2899             for (; p < first; ++p)
2900             {
2901                 ir_builder *ir = func->owner;
2902                 ir_value *param = instr->params[p];
2903                 ir_value *targetparam;
2904
2905                 if (param->callparam)
2906                     continue;
2907
2908                 if (p-8 >= vec_size(ir->extparams))
2909                     ir_gen_extparam(ir);
2910
2911                 targetparam = ir->extparams[p-8];
2912
2913                 stmt.opcode = INSTR_STORE_F;
2914                 stmt.o3.u1 = 0;
2915
2916                 if (param->vtype == TYPE_FIELD)
2917                     stmt.opcode = field_store_instr[param->fieldtype];
2918                 else if (param->vtype == TYPE_NIL)
2919                     stmt.opcode = INSTR_STORE_V;
2920                 else
2921                     stmt.opcode = type_store_instr[param->vtype];
2922                 stmt.o1.u1 = ir_value_code_addr(param);
2923                 stmt.o2.u1 = ir_value_code_addr(targetparam);
2924                 code_push_statement(&stmt, instr->context.line);
2925             }
2926
2927             stmt.opcode = INSTR_CALL0 + vec_size(instr->params);
2928             if (stmt.opcode > INSTR_CALL8)
2929                 stmt.opcode = INSTR_CALL8;
2930             stmt.o1.u1 = ir_value_code_addr(instr->_ops[1]);
2931             stmt.o2.u1 = 0;
2932             stmt.o3.u1 = 0;
2933             code_push_statement(&stmt, instr->context.line);
2934
2935             retvalue = instr->_ops[0];
2936             if (retvalue && retvalue->store != store_return &&
2937                 (retvalue->store == store_global || vec_size(retvalue->life)))
2938             {
2939                 /* not to be kept in OFS_RETURN */
2940                 if (retvalue->vtype == TYPE_FIELD && OPTS_FLAG(ADJUST_VECTOR_FIELDS))
2941                     stmt.opcode = field_store_instr[retvalue->fieldtype];
2942                 else
2943                     stmt.opcode = type_store_instr[retvalue->vtype];
2944                 stmt.o1.u1 = OFS_RETURN;
2945                 stmt.o2.u1 = ir_value_code_addr(retvalue);
2946                 stmt.o3.u1 = 0;
2947                 code_push_statement(&stmt, instr->context.line);
2948             }
2949             continue;
2950         }
2951
2952         if (instr->opcode == INSTR_STATE) {
2953             irerror(block->context, "TODO: state instruction");
2954             return false;
2955         }
2956
2957         stmt.opcode = instr->opcode;
2958         stmt.o1.u1 = 0;
2959         stmt.o2.u1 = 0;
2960         stmt.o3.u1 = 0;
2961
2962         /* This is the general order of operands */
2963         if (instr->_ops[0])
2964             stmt.o3.u1 = ir_value_code_addr(instr->_ops[0]);
2965
2966         if (instr->_ops[1])
2967             stmt.o1.u1 = ir_value_code_addr(instr->_ops[1]);
2968
2969         if (instr->_ops[2])
2970             stmt.o2.u1 = ir_value_code_addr(instr->_ops[2]);
2971
2972         if (stmt.opcode == INSTR_RETURN || stmt.opcode == INSTR_DONE)
2973         {
2974             stmt.o1.u1 = stmt.o3.u1;
2975             stmt.o3.u1 = 0;
2976         }
2977         else if ((stmt.opcode >= INSTR_STORE_F &&
2978                   stmt.opcode <= INSTR_STORE_FNC) ||
2979                  (stmt.opcode >= INSTR_STOREP_F &&
2980                   stmt.opcode <= INSTR_STOREP_FNC))
2981         {
2982             /* 2-operand instructions with A -> B */
2983             stmt.o2.u1 = stmt.o3.u1;
2984             stmt.o3.u1 = 0;
2985
2986             /* tiny optimization, don't output
2987              * STORE a, a
2988              */
2989             if (stmt.o2.u1 == stmt.o1.u1 &&
2990                 OPTS_OPTIMIZATION(OPTIM_PEEPHOLE))
2991             {
2992                 ++opts_optimizationcount[OPTIM_PEEPHOLE];
2993                 continue;
2994             }
2995         }
2996
2997         code_push_statement(&stmt, instr->context.line);
2998     }
2999     return true;
3000 }
3001
3002 static bool gen_function_code(ir_function *self)
3003 {
3004     ir_block *block;
3005     prog_section_statement stmt, *retst;
3006
3007     /* Starting from entry point, we generate blocks "as they come"
3008      * for now. Dead blocks will not be translated obviously.
3009      */
3010     if (!vec_size(self->blocks)) {
3011         irerror(self->context, "Function '%s' declared without body.", self->name);
3012         return false;
3013     }
3014
3015     block = self->blocks[0];
3016     if (block->generated)
3017         return true;
3018
3019     if (!gen_blocks_recursive(self, block)) {
3020         irerror(self->context, "failed to generate blocks for '%s'", self->name);
3021         return false;
3022     }
3023
3024     /* code_write and qcvm -disasm need to know that the function ends here */
3025     retst = &vec_last(code_statements);
3026     if (OPTS_OPTIMIZATION(OPTIM_VOID_RETURN) &&
3027         self->outtype == TYPE_VOID &&
3028         retst->opcode == INSTR_RETURN &&
3029         !retst->o1.u1 && !retst->o2.u1 && !retst->o3.u1)
3030     {
3031         retst->opcode = INSTR_DONE;
3032         ++opts_optimizationcount[OPTIM_VOID_RETURN];
3033     } else {
3034         stmt.opcode = INSTR_DONE;
3035         stmt.o1.u1 = 0;
3036         stmt.o2.u1 = 0;
3037         stmt.o3.u1 = 0;
3038         code_push_statement(&stmt, vec_last(code_linenums));
3039     }
3040     return true;
3041 }
3042
3043 static qcint ir_builder_filestring(ir_builder *ir, const char *filename)
3044 {
3045     /* NOTE: filename pointers are copied, we never strdup them,
3046      * thus we can use pointer-comparison to find the string.
3047      */
3048     size_t i;
3049     qcint  str;
3050
3051     for (i = 0; i < vec_size(ir->filenames); ++i) {
3052         if (ir->filenames[i] == filename)
3053             return ir->filestrings[i];
3054     }
3055
3056     str = code_genstring(filename);
3057     vec_push(ir->filenames, filename);
3058     vec_push(ir->filestrings, str);
3059     return str;
3060 }
3061
3062 static bool gen_global_function(ir_builder *ir, ir_value *global)
3063 {
3064     prog_section_function fun;
3065     ir_function          *irfun;
3066
3067     size_t i;
3068
3069     if (!global->hasvalue || (!global->constval.vfunc))
3070     {
3071         irerror(global->context, "Invalid state of function-global: not constant: %s", global->name);
3072         return false;
3073     }
3074
3075     irfun = global->constval.vfunc;
3076
3077     fun.name    = global->code.name;
3078     fun.file    = ir_builder_filestring(ir, global->context.file);
3079     fun.profile = 0; /* always 0 */
3080     fun.nargs   = vec_size(irfun->params);
3081     if (fun.nargs > 8)
3082         fun.nargs = 8;
3083
3084     for (i = 0;i < 8; ++i) {
3085         if ((int32_t)i >= fun.nargs)
3086             fun.argsize[i] = 0;
3087         else
3088             fun.argsize[i] = type_sizeof_[irfun->params[i]];
3089     }
3090
3091     fun.firstlocal = 0;
3092     fun.locals     = irfun->allocated_locals;
3093
3094     if (irfun->builtin)
3095         fun.entry = irfun->builtin+1;
3096     else {
3097         irfun->code_function_def = vec_size(code_functions);
3098         fun.entry = vec_size(code_statements);
3099     }
3100
3101     vec_push(code_functions, fun);
3102     return true;
3103 }
3104
3105 static ir_value* ir_gen_extparam_proto(ir_builder *ir)
3106 {
3107     ir_value *global;
3108     char      name[128];
3109
3110     snprintf(name, sizeof(name), "EXTPARM#%i", (int)(vec_size(ir->extparam_protos)+8));
3111     global = ir_value_var(name, store_global, TYPE_VECTOR);
3112
3113     vec_push(ir->extparam_protos, global);
3114     return global;
3115 }
3116
3117 static void ir_gen_extparam(ir_builder *ir)
3118 {
3119     prog_section_def def;
3120     ir_value        *global;
3121
3122     if (vec_size(ir->extparam_protos) < vec_size(ir->extparams)+1)
3123         global = ir_gen_extparam_proto(ir);
3124     else
3125         global = ir->extparam_protos[vec_size(ir->extparams)];
3126
3127     def.name = code_genstring(global->name);
3128     def.type = TYPE_VECTOR;
3129     def.offset = vec_size(code_globals);
3130
3131     vec_push(code_defs, def);
3132     ir_value_code_setaddr(global, def.offset);
3133     vec_push(code_globals, 0);
3134     vec_push(code_globals, 0);
3135     vec_push(code_globals, 0);
3136
3137     vec_push(ir->extparams, global);
3138 }
3139
3140 static bool gen_function_extparam_copy(ir_function *self)
3141 {
3142     size_t i, ext, numparams;
3143
3144     ir_builder *ir = self->owner;
3145     ir_value   *ep;
3146     prog_section_statement stmt;
3147
3148     numparams = vec_size(self->params);
3149     if (!numparams)
3150         return true;
3151
3152     stmt.opcode = INSTR_STORE_F;
3153     stmt.o3.s1 = 0;
3154     for (i = 8; i < numparams; ++i) {
3155         ext = i - 8;
3156         if (ext >= vec_size(ir->extparams))
3157             ir_gen_extparam(ir);
3158
3159         ep = ir->extparams[ext];
3160
3161         stmt.opcode = type_store_instr[self->locals[i]->vtype];
3162         if (self->locals[i]->vtype == TYPE_FIELD &&
3163             self->locals[i]->fieldtype == TYPE_VECTOR)
3164         {
3165             stmt.opcode = INSTR_STORE_V;
3166         }
3167         stmt.o1.u1 = ir_value_code_addr(ep);
3168         stmt.o2.u1 = ir_value_code_addr(self->locals[i]);
3169         code_push_statement(&stmt, self->context.line);
3170     }
3171
3172     return true;
3173 }
3174
3175 static bool gen_function_varargs_copy(ir_function *self)
3176 {
3177     size_t i, ext, numparams, maxparams;
3178
3179     ir_builder *ir = self->owner;
3180     ir_value   *ep;
3181     prog_section_statement stmt;
3182
3183     numparams = vec_size(self->params);
3184     if (!numparams)
3185         return true;
3186
3187     stmt.opcode = INSTR_STORE_V;
3188     stmt.o3.s1 = 0;
3189     maxparams = numparams + self->max_varargs;
3190     for (i = numparams; i < maxparams; ++i) {
3191         if (i <= 8) {
3192             stmt.o1.u1 = OFS_PARM0 + 3*i;
3193             stmt.o2.u1 = ir_value_code_addr(self->locals[i]);
3194             code_push_statement(&stmt, self->context.line);
3195             continue;
3196         }
3197         ext = i - 8;
3198         if (ext >= vec_size(ir->extparams))
3199             ir_gen_extparam(ir);
3200
3201         ep = ir->extparams[ext];
3202
3203         stmt.o1.u1 = ir_value_code_addr(ep);
3204         stmt.o2.u1 = ir_value_code_addr(self->locals[i]);
3205         code_push_statement(&stmt, self->context.line);
3206     }
3207
3208     return true;
3209 }
3210
3211 static bool gen_function_locals(ir_builder *ir, ir_value *global)
3212 {
3213     prog_section_function *def;
3214     ir_function           *irfun;
3215     size_t                 i;
3216     uint32_t               firstlocal, firstglobal;
3217
3218     irfun = global->constval.vfunc;
3219     def   = code_functions + irfun->code_function_def;
3220
3221     if (opts.g || !OPTS_OPTIMIZATION(OPTIM_OVERLAP_LOCALS) || (irfun->flags & IR_FLAG_MASK_NO_OVERLAP))
3222         firstlocal = def->firstlocal = vec_size(code_globals);
3223     else {
3224         firstlocal = def->firstlocal = ir->first_common_local;
3225         ++opts_optimizationcount[OPTIM_OVERLAP_LOCALS];
3226     }
3227
3228     firstglobal = (OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS) ? ir->first_common_globaltemp : firstlocal);
3229
3230     for (i = vec_size(code_globals); i < firstlocal + irfun->allocated_locals; ++i)
3231         vec_push(code_globals, 0);
3232     for (i = 0; i < vec_size(irfun->locals); ++i) {
3233         ir_value *v = irfun->locals[i];
3234         if (v->locked || !OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS)) {
3235             ir_value_code_setaddr(v, firstlocal + v->code.local);
3236             if (!ir_builder_gen_global(ir, irfun->locals[i], true)) {
3237                 irerror(irfun->locals[i]->context, "failed to generate local %s", irfun->locals[i]->name);
3238                 return false;
3239             }
3240         }
3241         else
3242             ir_value_code_setaddr(v, firstglobal + v->code.local);
3243     }
3244     for (i = 0; i < vec_size(irfun->values); ++i)
3245     {
3246         ir_value *v = irfun->values[i];
3247         if (v->callparam)
3248             continue;
3249         if (v->locked)
3250             ir_value_code_setaddr(v, firstlocal + v->code.local);
3251         else
3252             ir_value_code_setaddr(v, firstglobal + v->code.local);
3253     }
3254     return true;
3255 }
3256
3257 static bool gen_global_function_code(ir_builder *ir, ir_value *global)
3258 {
3259     prog_section_function *fundef;
3260     ir_function           *irfun;
3261
3262     (void)ir;
3263
3264     irfun = global->constval.vfunc;
3265     if (!irfun) {
3266         if (global->cvq == CV_NONE) {
3267             irwarning(global->context, WARN_IMPLICIT_FUNCTION_POINTER,
3268                       "function `%s` has no body and in QC implicitly becomes a function-pointer", global->name);
3269         }
3270         /* this was a function pointer, don't generate code for those */
3271         return true;
3272     }
3273
3274     if (irfun->builtin)
3275         return true;
3276
3277     if (irfun->code_function_def < 0) {
3278         irerror(irfun->context, "`%s`: IR global wasn't generated, failed to access function-def", irfun->name);
3279         return false;
3280     }
3281     fundef = &code_functions[irfun->code_function_def];
3282
3283     fundef->entry = vec_size(code_statements);
3284     if (!gen_function_locals(ir, global)) {
3285         irerror(irfun->context, "Failed to generate locals for function %s", irfun->name);
3286         return false;
3287     }
3288     if (!gen_function_extparam_copy(irfun)) {
3289         irerror(irfun->context, "Failed to generate extparam-copy code for function %s", irfun->name);
3290         return false;
3291     }
3292     if (irfun->max_varargs && !gen_function_varargs_copy(irfun)) {
3293         irerror(irfun->context, "Failed to generate vararg-copy code for function %s", irfun->name);
3294         return false;
3295     }
3296     if (!gen_function_code(irfun)) {
3297         irerror(irfun->context, "Failed to generate code for function %s", irfun->name);
3298         return false;
3299     }
3300     return true;
3301 }
3302
3303 static void gen_vector_defs(prog_section_def def, const char *name)
3304 {
3305     char  *component;
3306     size_t len, i;
3307
3308     if (!name || name[0] == '#' || OPTS_FLAG(SINGLE_VECTOR_DEFS))
3309         return;
3310
3311     def.type = TYPE_FLOAT;
3312
3313     len = strlen(name);
3314
3315     component = (char*)mem_a(len+3);
3316     memcpy(component, name, len);
3317     len += 2;
3318     component[len-0] = 0;
3319     component[len-2] = '_';
3320
3321     component[len-1] = 'x';
3322
3323     for (i = 0; i < 3; ++i) {
3324         def.name = code_genstring(component);
3325         vec_push(code_defs, def);
3326         def.offset++;
3327         component[len-1]++;
3328     }
3329 }
3330
3331 static void gen_vector_fields(prog_section_field fld, const char *name)
3332 {
3333     char  *component;
3334     size_t len, i;
3335
3336     if (!name || OPTS_FLAG(SINGLE_VECTOR_DEFS))
3337         return;
3338
3339     fld.type = TYPE_FLOAT;
3340
3341     len = strlen(name);
3342
3343     component = (char*)mem_a(len+3);
3344     memcpy(component, name, len);
3345     len += 2;
3346     component[len-0] = 0;
3347     component[len-2] = '_';
3348
3349     component[len-1] = 'x';
3350
3351     for (i = 0; i < 3; ++i) {
3352         fld.name = code_genstring(component);
3353         vec_push(code_fields, fld);
3354         fld.offset++;
3355         component[len-1]++;
3356     }
3357 }
3358
3359 static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool islocal)
3360 {
3361     size_t           i;
3362     int32_t         *iptr;
3363     prog_section_def def;
3364     bool             pushdef = false;
3365
3366     def.type   = global->vtype;
3367     def.offset = vec_size(code_globals);
3368     def.name   = 0;
3369     if (opts.g || !islocal)
3370     {
3371         pushdef = true;
3372
3373         if (OPTS_OPTIMIZATION(OPTIM_STRIP_CONSTANT_NAMES) &&
3374             !(global->flags & IR_FLAG_INCLUDE_DEF) &&
3375             (global->name[0] == '#' || global->cvq == CV_CONST))
3376         {
3377             pushdef = false;
3378         }
3379
3380         if (pushdef && global->name) {
3381             if (global->name[0] == '#') {
3382                 if (!self->str_immediate)
3383                     self->str_immediate = code_genstring("IMMEDIATE");
3384                 def.name = global->code.name = self->str_immediate;
3385             }
3386             else
3387                 def.name = global->code.name = code_genstring(global->name);
3388         }
3389         else
3390             def.name   = 0;
3391         if (islocal) {
3392             def.offset = ir_value_code_addr(global);
3393             vec_push(code_defs, def);
3394             if (global->vtype == TYPE_VECTOR)
3395                 gen_vector_defs(def, global->name);
3396             else if (global->vtype == TYPE_FIELD && global->fieldtype == TYPE_VECTOR)
3397                 gen_vector_defs(def, global->name);
3398             return true;
3399         }
3400     }
3401     if (islocal)
3402         return true;
3403
3404     switch (global->vtype)
3405     {
3406     case TYPE_VOID:
3407         if (!strcmp(global->name, "end_sys_globals")) {
3408             /* TODO: remember this point... all the defs before this one
3409              * should be checksummed and added to progdefs.h when we generate it.
3410              */
3411         }
3412         else if (!strcmp(global->name, "end_sys_fields")) {
3413             /* TODO: same as above but for entity-fields rather than globsl
3414              */
3415         }
3416         else
3417             irwarning(global->context, WARN_VOID_VARIABLES, "unrecognized variable of type void `%s`",
3418                       global->name);
3419         /* I'd argue setting it to 0 is sufficient, but maybe some depend on knowing how far
3420          * the system fields actually go? Though the engine knows this anyway...
3421          * Maybe this could be an -foption
3422          * fteqcc creates data for end_sys_* - of size 1, so let's do the same
3423          */
3424         ir_value_code_setaddr(global, vec_size(code_globals));
3425         vec_push(code_globals, 0);
3426         /* Add the def */
3427         if (pushdef) vec_push(code_defs, def);
3428         return true;
3429     case TYPE_POINTER:
3430         if (pushdef) vec_push(code_defs, def);
3431         return gen_global_pointer(global);
3432     case TYPE_FIELD:
3433         if (pushdef) {
3434             vec_push(code_defs, def);
3435             if (global->fieldtype == TYPE_VECTOR)
3436                 gen_vector_defs(def, global->name);
3437         }
3438         return gen_global_field(global);
3439     case TYPE_ENTITY:
3440         /* fall through */
3441     case TYPE_FLOAT:
3442     {
3443         ir_value_code_setaddr(global, vec_size(code_globals));
3444         if (global->hasvalue) {
3445             iptr = (int32_t*)&global->constval.ivec[0];
3446             vec_push(code_globals, *iptr);
3447         } else {
3448             vec_push(code_globals, 0);
3449         }
3450         if (!islocal && global->cvq != CV_CONST)
3451             def.type |= DEF_SAVEGLOBAL;
3452         if (pushdef) vec_push(code_defs, def);
3453
3454         return global->code.globaladdr >= 0;
3455     }
3456     case TYPE_STRING:
3457     {
3458         ir_value_code_setaddr(global, vec_size(code_globals));
3459         if (global->hasvalue) {
3460             vec_push(code_globals, code_genstring(global->constval.vstring));
3461         } else {
3462             vec_push(code_globals, 0);
3463         }
3464         if (!islocal && global->cvq != CV_CONST)
3465             def.type |= DEF_SAVEGLOBAL;
3466         if (pushdef) vec_push(code_defs, def);
3467         return global->code.globaladdr >= 0;
3468     }
3469     case TYPE_VECTOR:
3470     {
3471         size_t d;
3472         ir_value_code_setaddr(global, vec_size(code_globals));
3473         if (global->hasvalue) {
3474             iptr = (int32_t*)&global->constval.ivec[0];
3475             vec_push(code_globals, iptr[0]);
3476             if (global->code.globaladdr < 0)
3477                 return false;
3478             for (d = 1; d < type_sizeof_[global->vtype]; ++d) {
3479                 vec_push(code_globals, iptr[d]);
3480             }
3481         } else {
3482             vec_push(code_globals, 0);
3483             if (global->code.globaladdr < 0)
3484                 return false;
3485             for (d = 1; d < type_sizeof_[global->vtype]; ++d) {
3486                 vec_push(code_globals, 0);
3487             }
3488         }
3489         if (!islocal && global->cvq != CV_CONST)
3490             def.type |= DEF_SAVEGLOBAL;
3491
3492         if (pushdef) {
3493             vec_push(code_defs, def);
3494             def.type &= ~DEF_SAVEGLOBAL;
3495             gen_vector_defs(def, global->name);
3496         }
3497         return global->code.globaladdr >= 0;
3498     }
3499     case TYPE_FUNCTION:
3500         ir_value_code_setaddr(global, vec_size(code_globals));
3501         if (!global->hasvalue) {
3502             vec_push(code_globals, 0);
3503             if (global->code.globaladdr < 0)
3504                 return false;
3505         } else {
3506             vec_push(code_globals, vec_size(code_functions));
3507             if (!gen_global_function(self, global))
3508                 return false;
3509         }
3510         if (!islocal && global->cvq != CV_CONST)
3511             def.type |= DEF_SAVEGLOBAL;
3512         if (pushdef) vec_push(code_defs, def);
3513         return true;
3514     case TYPE_VARIANT:
3515         /* assume biggest type */
3516             ir_value_code_setaddr(global, vec_size(code_globals));
3517             vec_push(code_globals, 0);
3518             for (i = 1; i < type_sizeof_[TYPE_VARIANT]; ++i)
3519                 vec_push(code_globals, 0);
3520             return true;
3521     default:
3522         /* refuse to create 'void' type or any other fancy business. */
3523         irerror(global->context, "Invalid type for global variable `%s`: %s",
3524                 global->name, type_name[global->vtype]);
3525         return false;
3526     }
3527 }
3528
3529 static void ir_builder_prepare_field(ir_value *field)
3530 {
3531     field->code.fieldaddr = code_alloc_field(type_sizeof_[field->fieldtype]);
3532 }
3533
3534 static bool ir_builder_gen_field(ir_builder *self, ir_value *field)
3535 {
3536     prog_section_def def;
3537     prog_section_field fld;
3538
3539     (void)self;
3540
3541     def.type   = (uint16_t)field->vtype;
3542     def.offset = (uint16_t)vec_size(code_globals);
3543
3544     /* create a global named the same as the field */
3545     if (opts.standard == COMPILER_GMQCC) {
3546         /* in our standard, the global gets a dot prefix */
3547         size_t len = strlen(field->name);
3548         char name[1024];
3549
3550         /* we really don't want to have to allocate this, and 1024
3551          * bytes is more than enough for a variable/field name
3552          */
3553         if (len+2 >= sizeof(name)) {
3554             irerror(field->context, "invalid field name size: %u", (unsigned int)len);
3555             return false;
3556         }
3557
3558         name[0] = '.';
3559         memcpy(name+1, field->name, len); /* no strncpy - we used strlen above */
3560         name[len+1] = 0;
3561
3562         def.name = code_genstring(name);
3563         fld.name = def.name + 1; /* we reuse that string table entry */
3564     } else {
3565         /* in plain QC, there cannot be a global with the same name,
3566          * and so we also name the global the same.
3567          * FIXME: fteqcc should create a global as well
3568          * check if it actually uses the same name. Probably does
3569          */
3570         def.name = code_genstring(field->name);
3571         fld.name = def.name;
3572     }
3573
3574     field->code.name = def.name;
3575
3576     vec_push(code_defs, def);
3577
3578     fld.type = field->fieldtype;
3579
3580     if (fld.type == TYPE_VOID) {
3581         irerror(field->context, "field is missing a type: %s - don't know its size", field->name);
3582         return false;
3583     }
3584
3585     fld.offset = field->code.fieldaddr;
3586
3587     vec_push(code_fields, fld);
3588
3589     ir_value_code_setaddr(field, vec_size(code_globals));
3590     vec_push(code_globals, fld.offset);
3591     if (fld.type == TYPE_VECTOR) {
3592         vec_push(code_globals, fld.offset+1);
3593         vec_push(code_globals, fld.offset+2);
3594     }
3595
3596     if (field->fieldtype == TYPE_VECTOR) {
3597         gen_vector_defs(def, field->name);
3598         gen_vector_fields(fld, field->name);
3599     }
3600
3601     return field->code.globaladdr >= 0;
3602 }
3603
3604 bool ir_builder_generate(ir_builder *self, const char *filename)
3605 {
3606     prog_section_statement stmt;
3607     size_t i;
3608     char  *lnofile = NULL;
3609
3610     code_init();
3611
3612     for (i = 0; i < vec_size(self->fields); ++i)
3613     {
3614         ir_builder_prepare_field(self->fields[i]);
3615     }
3616
3617     for (i = 0; i < vec_size(self->globals); ++i)
3618     {
3619         if (!ir_builder_gen_global(self, self->globals[i], false)) {
3620             return false;
3621         }
3622         if (self->globals[i]->vtype == TYPE_FUNCTION) {
3623             ir_function *func = self->globals[i]->constval.vfunc;
3624             if (func && self->max_locals < func->allocated_locals &&
3625                 !(func->flags & IR_FLAG_MASK_NO_OVERLAP))
3626             {
3627                 self->max_locals = func->allocated_locals;
3628             }
3629             if (func && self->max_globaltemps < func->globaltemps)
3630                 self->max_globaltemps = func->globaltemps;
3631         }
3632     }
3633
3634     for (i = 0; i < vec_size(self->fields); ++i)
3635     {
3636         if (!ir_builder_gen_field(self, self->fields[i])) {
3637             return false;
3638         }
3639     }
3640
3641     /* generate nil */
3642     ir_value_code_setaddr(self->nil, vec_size(code_globals));
3643     vec_push(code_globals, 0);
3644     vec_push(code_globals, 0);
3645     vec_push(code_globals, 0);
3646
3647     /* generate global temps */
3648     self->first_common_globaltemp = vec_size(code_globals);
3649     for (i = 0; i < self->max_globaltemps; ++i) {
3650         vec_push(code_globals, 0);
3651     }
3652     /* generate common locals */
3653     self->first_common_local = vec_size(code_globals);
3654     for (i = 0; i < self->max_locals; ++i) {
3655         vec_push(code_globals, 0);
3656     }
3657
3658     /* generate function code */
3659     for (i = 0; i < vec_size(self->globals); ++i)
3660     {
3661         if (self->globals[i]->vtype == TYPE_FUNCTION) {
3662             if (!gen_global_function_code(self, self->globals[i])) {
3663                 return false;
3664             }
3665         }
3666     }
3667
3668     if (vec_size(code_globals) >= 65536) {
3669         irerror(vec_last(self->globals)->context, "This progs file would require more globals than the metadata can handle. Bailing out.");
3670         return false;
3671     }
3672
3673     /* DP errors if the last instruction is not an INSTR_DONE. */
3674     if (vec_last(code_statements).opcode != INSTR_DONE)
3675     {
3676         stmt.opcode = INSTR_DONE;
3677         stmt.o1.u1 = 0;
3678         stmt.o2.u1 = 0;
3679         stmt.o3.u1 = 0;
3680         code_push_statement(&stmt, vec_last(code_linenums));
3681     }
3682
3683     if (opts.pp_only)
3684         return true;
3685
3686     if (vec_size(code_statements) != vec_size(code_linenums)) {
3687         con_err("Linecounter wrong: %lu != %lu\n",
3688                 (unsigned long)vec_size(code_statements),
3689                 (unsigned long)vec_size(code_linenums));
3690     } else if (OPTS_FLAG(LNO)) {
3691         char *dot;
3692         size_t filelen = strlen(filename);
3693
3694         memcpy(vec_add(lnofile, filelen+1), filename, filelen+1);
3695         dot = strrchr(lnofile, '.');
3696         if (!dot) {
3697             vec_pop(lnofile);
3698         } else {
3699             vec_shrinkto(lnofile, dot - lnofile);
3700         }
3701         memcpy(vec_add(lnofile, 5), ".lno", 5);
3702     }
3703
3704     if (!opts.quiet) {
3705         if (lnofile)
3706             con_out("writing '%s' and '%s'...\n", filename, lnofile);
3707         else
3708             con_out("writing '%s'\n", filename);
3709     }
3710     if (!code_write(filename, lnofile)) {
3711         vec_free(lnofile);
3712         return false;
3713     }
3714     vec_free(lnofile);
3715     return true;
3716 }
3717
3718 /***********************************************************************
3719  *IR DEBUG Dump functions...
3720  */
3721
3722 #define IND_BUFSZ 1024
3723
3724 #ifdef _MSC_VER
3725 #   define strncat(dst, src, sz) strncat_s(dst, sz, src, _TRUNCATE)
3726 #endif
3727
3728 const char *qc_opname(int op)
3729 {
3730     if (op < 0) return "<INVALID>";
3731     if (op < (int)( sizeof(asm_instr) / sizeof(asm_instr[0]) ))
3732         return asm_instr[op].m;
3733     switch (op) {
3734         case VINSTR_PHI:  return "PHI";
3735         case VINSTR_JUMP: return "JUMP";
3736         case VINSTR_COND: return "COND";
3737         default:          return "<UNK>";
3738     }
3739 }
3740
3741 void ir_builder_dump(ir_builder *b, int (*oprintf)(const char*, ...))
3742 {
3743     size_t i;
3744     char indent[IND_BUFSZ];
3745     indent[0] = '\t';
3746     indent[1] = 0;
3747
3748     oprintf("module %s\n", b->name);
3749     for (i = 0; i < vec_size(b->globals); ++i)
3750     {
3751         oprintf("global ");
3752         if (b->globals[i]->hasvalue)
3753             oprintf("%s = ", b->globals[i]->name);
3754         ir_value_dump(b->globals[i], oprintf);
3755         oprintf("\n");
3756     }
3757     for (i = 0; i < vec_size(b->functions); ++i)
3758         ir_function_dump(b->functions[i], indent, oprintf);
3759     oprintf("endmodule %s\n", b->name);
3760 }
3761
3762 static const char *storenames[] = {
3763     "[global]", "[local]", "[param]", "[value]", "[return]"
3764 };
3765
3766 void ir_function_dump(ir_function *f, char *ind,
3767                       int (*oprintf)(const char*, ...))
3768 {
3769     size_t i;
3770     if (f->builtin != 0) {
3771         oprintf("%sfunction %s = builtin %i\n", ind, f->name, -f->builtin);
3772         return;
3773     }
3774     oprintf("%sfunction %s\n", ind, f->name);
3775     strncat(ind, "\t", IND_BUFSZ);
3776     if (vec_size(f->locals))
3777     {
3778         oprintf("%s%i locals:\n", ind, (int)vec_size(f->locals));
3779         for (i = 0; i < vec_size(f->locals); ++i) {
3780             oprintf("%s\t", ind);
3781             ir_value_dump(f->locals[i], oprintf);
3782             oprintf("\n");
3783         }
3784     }
3785     oprintf("%sliferanges:\n", ind);
3786     for (i = 0; i < vec_size(f->locals); ++i) {
3787         const char *attr = "";
3788         size_t l, m;
3789         ir_value *v = f->locals[i];
3790         if (v->unique_life && v->locked)
3791             attr = "unique,locked ";
3792         else if (v->unique_life)
3793             attr = "unique ";
3794         else if (v->locked)
3795             attr = "locked ";
3796         oprintf("%s\t%s: %s %s %s%s@%i ", ind, v->name, type_name[v->vtype],
3797                 storenames[v->store],
3798                 attr, (v->callparam ? "callparam " : ""),
3799                 (int)v->code.local);
3800         if (!v->life)
3801             oprintf("[null]");
3802         for (l = 0; l < vec_size(v->life); ++l) {
3803             oprintf("[%i,%i] ", v->life[l].start, v->life[l].end);
3804         }
3805         oprintf("\n");
3806         for (m = 0; m < 3; ++m) {
3807             ir_value *vm = v->members[m];
3808             if (!vm)
3809                 continue;
3810             oprintf("%s\t%s: @%i ", ind, vm->name, (int)vm->code.local);
3811             for (l = 0; l < vec_size(vm->life); ++l) {
3812                 oprintf("[%i,%i] ", vm->life[l].start, vm->life[l].end);
3813             }
3814             oprintf("\n");
3815         }
3816     }
3817     for (i = 0; i < vec_size(f->values); ++i) {
3818         const char *attr = "";
3819         size_t l, m;
3820         ir_value *v = f->values[i];
3821         if (v->unique_life && v->locked)
3822             attr = "unique,locked ";
3823         else if (v->unique_life)
3824             attr = "unique ";
3825         else if (v->locked)
3826             attr = "locked ";
3827         oprintf("%s\t%s: %s %s %s%s@%i ", ind, v->name, type_name[v->vtype],
3828                 storenames[v->store],
3829                 attr, (v->callparam ? "callparam " : ""),
3830                 (int)v->code.local);
3831         if (!v->life)
3832             oprintf("[null]");
3833         for (l = 0; l < vec_size(v->life); ++l) {
3834             oprintf("[%i,%i] ", v->life[l].start, v->life[l].end);
3835         }
3836         oprintf("\n");
3837         for (m = 0; m < 3; ++m) {
3838             ir_value *vm = v->members[m];
3839             if (!vm)
3840                 continue;
3841             if (vm->unique_life && vm->locked)
3842                 attr = "unique,locked ";
3843             else if (vm->unique_life)
3844                 attr = "unique ";
3845             else if (vm->locked)
3846                 attr = "locked ";
3847             oprintf("%s\t%s: %s@%i ", ind, vm->name, attr, (int)vm->code.local);
3848             for (l = 0; l < vec_size(vm->life); ++l) {
3849                 oprintf("[%i,%i] ", vm->life[l].start, vm->life[l].end);
3850             }
3851             oprintf("\n");
3852         }
3853     }
3854     if (vec_size(f->blocks))
3855     {
3856         oprintf("%slife passes (check): %i\n", ind, (int)f->run_id);
3857         for (i = 0; i < vec_size(f->blocks); ++i) {
3858             if (f->blocks[i]->run_id != f->run_id) {
3859                 oprintf("%slife pass check fail! %i != %i\n", ind, (int)f->blocks[i]->run_id, (int)f->run_id);
3860             }
3861             ir_block_dump(f->blocks[i], ind, oprintf);
3862         }
3863
3864     }
3865     ind[strlen(ind)-1] = 0;
3866     oprintf("%sendfunction %s\n", ind, f->name);
3867 }
3868
3869 void ir_block_dump(ir_block* b, char *ind,
3870                    int (*oprintf)(const char*, ...))
3871 {
3872     size_t i;
3873     oprintf("%s:%s\n", ind, b->label);
3874     strncat(ind, "\t", IND_BUFSZ);
3875
3876     if (b->instr && b->instr[0])
3877         oprintf("%s (%i) [entry]\n", ind, (int)(b->instr[0]->eid-1));
3878     for (i = 0; i < vec_size(b->instr); ++i)
3879         ir_instr_dump(b->instr[i], ind, oprintf);
3880     ind[strlen(ind)-1] = 0;
3881 }
3882
3883 void dump_phi(ir_instr *in, int (*oprintf)(const char*, ...))
3884 {
3885     size_t i;
3886     oprintf("%s <- phi ", in->_ops[0]->name);
3887     for (i = 0; i < vec_size(in->phi); ++i)
3888     {
3889         oprintf("([%s] : %s) ", in->phi[i].from->label,
3890                                 in->phi[i].value->name);
3891     }
3892     oprintf("\n");
3893 }
3894
3895 void ir_instr_dump(ir_instr *in, char *ind,
3896                        int (*oprintf)(const char*, ...))
3897 {
3898     size_t i;
3899     const char *comma = NULL;
3900
3901     oprintf("%s (%i) ", ind, (int)in->eid);
3902
3903     if (in->opcode == VINSTR_PHI) {
3904         dump_phi(in, oprintf);
3905         return;
3906     }
3907
3908     strncat(ind, "\t", IND_BUFSZ);
3909
3910     if (in->_ops[0] && (in->_ops[1] || in->_ops[2])) {
3911         ir_value_dump(in->_ops[0], oprintf);
3912         if (in->_ops[1] || in->_ops[2])
3913             oprintf(" <- ");
3914     }
3915     if (in->opcode == INSTR_CALL0 || in->opcode == VINSTR_NRCALL) {
3916         oprintf("CALL%i\t", vec_size(in->params));
3917     } else
3918         oprintf("%s\t", qc_opname(in->opcode));
3919
3920     if (in->_ops[0] && !(in->_ops[1] || in->_ops[2])) {
3921         ir_value_dump(in->_ops[0], oprintf);
3922         comma = ",\t";
3923     }
3924     else
3925     {
3926         for (i = 1; i != 3; ++i) {
3927             if (in->_ops[i]) {
3928                 if (comma)
3929                     oprintf(comma);
3930                 ir_value_dump(in->_ops[i], oprintf);
3931                 comma = ",\t";
3932             }
3933         }
3934     }
3935     if (in->bops[0]) {
3936         if (comma)
3937             oprintf(comma);
3938         oprintf("[%s]", in->bops[0]->label);
3939         comma = ",\t";
3940     }
3941     if (in->bops[1])
3942         oprintf("%s[%s]", comma, in->bops[1]->label);
3943     if (vec_size(in->params)) {
3944         oprintf("\tparams: ");
3945         for (i = 0; i != vec_size(in->params); ++i) {
3946             oprintf("%s, ", in->params[i]->name);
3947         }
3948     }
3949     oprintf("\n");
3950     ind[strlen(ind)-1] = 0;
3951 }
3952
3953 void ir_value_dump_string(const char *str, int (*oprintf)(const char*, ...))
3954 {
3955     oprintf("\"");
3956     for (; *str; ++str) {
3957         switch (*str) {
3958             case '\n': oprintf("\\n"); break;
3959             case '\r': oprintf("\\r"); break;
3960             case '\t': oprintf("\\t"); break;
3961             case '\v': oprintf("\\v"); break;
3962             case '\f': oprintf("\\f"); break;
3963             case '\b': oprintf("\\b"); break;
3964             case '\a': oprintf("\\a"); break;
3965             case '\\': oprintf("\\\\"); break;
3966             case '"': oprintf("\\\""); break;
3967             default: oprintf("%c", *str); break;
3968         }
3969     }
3970     oprintf("\"");
3971 }
3972
3973 void ir_value_dump(ir_value* v, int (*oprintf)(const char*, ...))
3974 {
3975     if (v->hasvalue) {
3976         switch (v->vtype) {
3977             default:
3978             case TYPE_VOID:
3979                 oprintf("(void)");
3980                 break;
3981             case TYPE_FUNCTION:
3982                 oprintf("fn:%s", v->name);
3983                 break;
3984             case TYPE_FLOAT:
3985                 oprintf("%g", v->constval.vfloat);
3986                 break;
3987             case TYPE_VECTOR:
3988                 oprintf("'%g %g %g'",
3989                         v->constval.vvec.x,
3990                         v->constval.vvec.y,
3991                         v->constval.vvec.z);
3992                 break;
3993             case TYPE_ENTITY:
3994                 oprintf("(entity)");
3995                 break;
3996             case TYPE_STRING:
3997                 ir_value_dump_string(v->constval.vstring, oprintf);
3998                 break;
3999 #if 0
4000             case TYPE_INTEGER:
4001                 oprintf("%i", v->constval.vint);
4002                 break;
4003 #endif
4004             case TYPE_POINTER:
4005                 oprintf("&%s",
4006                     v->constval.vpointer->name);
4007                 break;
4008         }
4009     } else {
4010         oprintf("%s", v->name);
4011     }
4012 }
4013
4014 void ir_value_dump_life(const ir_value *self, int (*oprintf)(const char*,...))
4015 {
4016     size_t i;
4017     oprintf("Life of %12s:", self->name);
4018     for (i = 0; i < vec_size(self->life); ++i)
4019     {
4020         oprintf(" + [%i, %i]\n", self->life[i].start, self->life[i].end);
4021     }
4022 }