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