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