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