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