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