]> git.xonotic.org Git - xonotic/gmqcc.git/blob - ir.c
use type_sizeof in another place where it wasn't
[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 size_t type_sizeof[TYPE_COUNT] = {
33     1, /* TYPE_VOID     */
34     1, /* TYPE_STRING   */
35     1, /* TYPE_FLOAT    */
36     3, /* TYPE_VECTOR   */
37     1, /* TYPE_ENTITY   */
38     1, /* TYPE_FIELD    */
39     1, /* TYPE_FUNCTION */
40     1, /* TYPE_POINTER  */
41 #if 0
42     1, /* TYPE_INTEGER  */
43 #endif
44     3, /* TYPE_VARIANT  */
45 };
46
47 uint16_t type_store_instr[TYPE_COUNT] = {
48     INSTR_STORE_F, /* should use I when having integer support */
49     INSTR_STORE_S,
50     INSTR_STORE_F,
51     INSTR_STORE_V,
52     INSTR_STORE_ENT,
53     INSTR_STORE_FLD,
54     INSTR_STORE_FNC,
55     INSTR_STORE_ENT, /* should use I */
56 #if 0
57     INSTR_STORE_ENT, /* integer type */
58 #endif
59     INSTR_STORE_V, /* variant, should never be accessed */
60 };
61
62 uint16_t type_storep_instr[TYPE_COUNT] = {
63     INSTR_STOREP_F, /* should use I when having integer support */
64     INSTR_STOREP_S,
65     INSTR_STOREP_F,
66     INSTR_STOREP_V,
67     INSTR_STOREP_ENT,
68     INSTR_STOREP_FLD,
69     INSTR_STOREP_FNC,
70     INSTR_STOREP_ENT, /* should use I */
71 #if 0
72     INSTR_STOREP_ENT, /* integer type */
73 #endif
74     INSTR_STOREP_V, /* variant, should never be accessed */
75 };
76
77 MEM_VEC_FUNCTIONS(ir_value_vector, ir_value*, v)
78
79 /***********************************************************************
80  *IR Builder
81  */
82
83 ir_builder* ir_builder_new(const char *modulename)
84 {
85     ir_builder* self;
86
87     self = (ir_builder*)mem_a(sizeof(*self));
88     if (!self)
89         return NULL;
90
91     MEM_VECTOR_INIT(self, functions);
92     MEM_VECTOR_INIT(self, globals);
93     self->name = NULL;
94     if (!ir_builder_set_name(self, modulename)) {
95         mem_d(self);
96         return NULL;
97     }
98
99     /* globals which always exist */
100
101     /* for now we give it a vector size */
102     ir_builder_create_global(self, "OFS_RETURN", TYPE_VARIANT);
103
104     return self;
105 }
106
107 MEM_VEC_FUNCTIONS(ir_builder, ir_value*, globals)
108 MEM_VEC_FUNCTIONS(ir_builder, ir_function*, functions)
109
110 void ir_builder_delete(ir_builder* self)
111 {
112     size_t i;
113     mem_d((void*)self->name);
114     for (i = 0; i != self->functions_count; ++i) {
115         ir_function_delete(self->functions[i]);
116     }
117     MEM_VECTOR_CLEAR(self, functions);
118     for (i = 0; i != self->globals_count; ++i) {
119         ir_value_delete(self->globals[i]);
120     }
121     MEM_VECTOR_CLEAR(self, globals);
122     mem_d(self);
123 }
124
125 bool ir_builder_set_name(ir_builder *self, const char *name)
126 {
127     if (self->name)
128         mem_d((void*)self->name);
129     self->name = util_strdup(name);
130     return !!self->name;
131 }
132
133 ir_function* ir_builder_get_function(ir_builder *self, const char *name)
134 {
135     size_t i;
136     for (i = 0; i < self->functions_count; ++i) {
137         if (!strcmp(name, self->functions[i]->name))
138             return self->functions[i];
139     }
140     return NULL;
141 }
142
143 ir_function* ir_builder_create_function(ir_builder *self, const char *name, int outtype)
144 {
145     ir_function *fn = ir_builder_get_function(self, name);
146     if (fn) {
147         return NULL;
148     }
149
150     fn = ir_function_new(self, outtype);
151     if (!ir_function_set_name(fn, name) ||
152         !ir_builder_functions_add(self, fn) )
153     {
154         ir_function_delete(fn);
155         return NULL;
156     }
157
158     fn->value = ir_builder_create_global(self, fn->name, TYPE_FUNCTION);
159     if (!fn->value) {
160         ir_function_delete(fn);
161         return NULL;
162     }
163
164     fn->value->isconst = true;
165     fn->value->outtype = outtype;
166     fn->value->constval.vfunc = fn;
167     fn->value->context = fn->context;
168
169     return fn;
170 }
171
172 ir_value* ir_builder_get_global(ir_builder *self, const char *name)
173 {
174     size_t i;
175     for (i = 0; i < self->globals_count; ++i) {
176         if (!strcmp(self->globals[i]->name, name))
177             return self->globals[i];
178     }
179     return NULL;
180 }
181
182 ir_value* ir_builder_create_global(ir_builder *self, const char *name, int vtype)
183 {
184     ir_value *ve = ir_builder_get_global(self, name);
185     if (ve) {
186         return NULL;
187     }
188
189     ve = ir_value_var(name, store_global, vtype);
190     if (!ir_builder_globals_add(self, ve)) {
191         ir_value_delete(ve);
192         return NULL;
193     }
194     return ve;
195 }
196
197 /***********************************************************************
198  *IR Function
199  */
200
201 bool ir_function_naive_phi(ir_function*);
202 void ir_function_enumerate(ir_function*);
203 bool ir_function_calculate_liferanges(ir_function*);
204 bool ir_function_allocate_locals(ir_function*);
205
206 ir_function* ir_function_new(ir_builder* owner, int outtype)
207 {
208     ir_function *self;
209     self = (ir_function*)mem_a(sizeof(*self));
210
211     if (!self)
212         return NULL;
213
214     self->name = NULL;
215     if (!ir_function_set_name(self, "<@unnamed>")) {
216         mem_d(self);
217         return NULL;
218     }
219     self->owner = owner;
220     self->context.file = "<@no context>";
221     self->context.line = 0;
222     self->outtype = outtype;
223     self->value = NULL;
224     self->builtin = 0;
225     MEM_VECTOR_INIT(self, params);
226     MEM_VECTOR_INIT(self, blocks);
227     MEM_VECTOR_INIT(self, values);
228     MEM_VECTOR_INIT(self, locals);
229
230     self->run_id = 0;
231     return self;
232 }
233 MEM_VEC_FUNCTIONS(ir_function, ir_value*, values)
234 MEM_VEC_FUNCTIONS(ir_function, ir_block*, blocks)
235 MEM_VEC_FUNCTIONS(ir_function, ir_value*, locals)
236 MEM_VEC_FUNCTIONS(ir_function, int,       params)
237
238 bool ir_function_set_name(ir_function *self, const char *name)
239 {
240     if (self->name)
241         mem_d((void*)self->name);
242     self->name = util_strdup(name);
243     return !!self->name;
244 }
245
246 void ir_function_delete(ir_function *self)
247 {
248     size_t i;
249     mem_d((void*)self->name);
250
251     for (i = 0; i != self->blocks_count; ++i)
252         ir_block_delete(self->blocks[i]);
253     MEM_VECTOR_CLEAR(self, blocks);
254
255     MEM_VECTOR_CLEAR(self, params);
256
257     for (i = 0; i != self->values_count; ++i)
258         ir_value_delete(self->values[i]);
259     MEM_VECTOR_CLEAR(self, values);
260
261     for (i = 0; i != self->locals_count; ++i)
262         ir_value_delete(self->locals[i]);
263     MEM_VECTOR_CLEAR(self, locals);
264
265     /* self->value is deleted by the builder */
266
267     mem_d(self);
268 }
269
270 bool GMQCC_WARN ir_function_collect_value(ir_function *self, ir_value *v)
271 {
272     return ir_function_values_add(self, v);
273 }
274
275 ir_block* ir_function_create_block(ir_function *self, const char *label)
276 {
277     ir_block* bn = ir_block_new(self, label);
278     memcpy(&bn->context, &self->context, sizeof(self->context));
279     if (!ir_function_blocks_add(self, bn)) {
280         ir_block_delete(bn);
281         return NULL;
282     }
283     return bn;
284 }
285
286 bool ir_function_finalize(ir_function *self)
287 {
288     if (self->builtin)
289         return true;
290
291     if (!ir_function_naive_phi(self))
292         return false;
293
294     ir_function_enumerate(self);
295
296     if (!ir_function_calculate_liferanges(self))
297         return false;
298
299     if (!ir_function_allocate_locals(self))
300         return false;
301     return true;
302 }
303
304 ir_value* ir_function_get_local(ir_function *self, const char *name)
305 {
306     size_t i;
307     for (i = 0; i < self->locals_count; ++i) {
308         if (!strcmp(self->locals[i]->name, name))
309             return self->locals[i];
310     }
311     return NULL;
312 }
313
314 ir_value* ir_function_create_local(ir_function *self, const char *name, int vtype, bool param)
315 {
316     ir_value *ve = ir_function_get_local(self, name);
317     if (ve) {
318         return NULL;
319     }
320
321     if (param &&
322         self->locals_count &&
323         self->locals[self->locals_count-1]->store != store_param) {
324         printf("cannot add parameters after adding locals\n");
325         return NULL;
326     }
327
328     ve = ir_value_var(name, (param ? store_param : store_local), vtype);
329     if (!ir_function_locals_add(self, ve)) {
330         ir_value_delete(ve);
331         return NULL;
332     }
333     return ve;
334 }
335
336 /***********************************************************************
337  *IR Block
338  */
339
340 ir_block* ir_block_new(ir_function* owner, const char *name)
341 {
342     ir_block *self;
343     self = (ir_block*)mem_a(sizeof(*self));
344     if (!self)
345         return NULL;
346
347     memset(self, 0, sizeof(*self));
348
349     self->label = NULL;
350     if (!ir_block_set_label(self, name)) {
351         mem_d(self);
352         return NULL;
353     }
354     self->owner = owner;
355     self->context.file = "<@no context>";
356     self->context.line = 0;
357     self->final = false;
358     MEM_VECTOR_INIT(self, instr);
359     MEM_VECTOR_INIT(self, entries);
360     MEM_VECTOR_INIT(self, exits);
361
362     self->eid = 0;
363     self->is_return = false;
364     self->run_id = 0;
365     MEM_VECTOR_INIT(self, living);
366
367     self->generated = false;
368
369     return self;
370 }
371 MEM_VEC_FUNCTIONS(ir_block, ir_instr*, instr)
372 MEM_VEC_FUNCTIONS_ALL(ir_block, ir_block*, entries)
373 MEM_VEC_FUNCTIONS_ALL(ir_block, ir_block*, exits)
374 MEM_VEC_FUNCTIONS_ALL(ir_block, ir_value*, living)
375
376 void ir_block_delete(ir_block* self)
377 {
378     size_t i;
379     mem_d(self->label);
380     for (i = 0; i != self->instr_count; ++i)
381         ir_instr_delete(self->instr[i]);
382     MEM_VECTOR_CLEAR(self, instr);
383     MEM_VECTOR_CLEAR(self, entries);
384     MEM_VECTOR_CLEAR(self, exits);
385     MEM_VECTOR_CLEAR(self, living);
386     mem_d(self);
387 }
388
389 bool ir_block_set_label(ir_block *self, const char *name)
390 {
391     if (self->label)
392         mem_d((void*)self->label);
393     self->label = util_strdup(name);
394     return !!self->label;
395 }
396
397 /***********************************************************************
398  *IR Instructions
399  */
400
401 ir_instr* ir_instr_new(ir_block* owner, int op)
402 {
403     ir_instr *self;
404     self = (ir_instr*)mem_a(sizeof(*self));
405     if (!self)
406         return NULL;
407
408     self->owner = owner;
409     self->context.file = "<@no context>";
410     self->context.line = 0;
411     self->opcode = op;
412     self->_ops[0] = NULL;
413     self->_ops[1] = NULL;
414     self->_ops[2] = NULL;
415     self->bops[0] = NULL;
416     self->bops[1] = NULL;
417     MEM_VECTOR_INIT(self, phi);
418     MEM_VECTOR_INIT(self, params);
419
420     self->eid = 0;
421     return self;
422 }
423 MEM_VEC_FUNCTIONS(ir_instr, ir_phi_entry_t, phi)
424 MEM_VEC_FUNCTIONS(ir_instr, ir_value*, params)
425
426 void ir_instr_delete(ir_instr *self)
427 {
428     size_t i;
429     /* The following calls can only delete from
430      * vectors, we still want to delete this instruction
431      * so ignore the return value. Since with the warn_unused_result attribute
432      * gcc doesn't care about an explicit: (void)foo(); to ignore the result,
433      * I have to improvise here and use if(foo());
434      */
435     for (i = 0; i < self->phi_count; ++i) {
436         size_t idx;
437         if (ir_value_writes_find(self->phi[i].value, self, &idx))
438             if (ir_value_writes_remove(self->phi[i].value, idx)) GMQCC_SUPPRESS_EMPTY_BODY;
439         if (ir_value_reads_find(self->phi[i].value, self, &idx))
440             if (ir_value_reads_remove (self->phi[i].value, idx)) GMQCC_SUPPRESS_EMPTY_BODY;
441     }
442     MEM_VECTOR_CLEAR(self, phi);
443     for (i = 0; i < self->params_count; ++i) {
444         size_t idx;
445         if (ir_value_writes_find(self->params[i], self, &idx))
446             if (ir_value_writes_remove(self->params[i], idx)) GMQCC_SUPPRESS_EMPTY_BODY;
447         if (ir_value_reads_find(self->params[i], self, &idx))
448             if (ir_value_reads_remove (self->params[i], idx)) GMQCC_SUPPRESS_EMPTY_BODY;
449     }
450     MEM_VECTOR_CLEAR(self, params);
451     if (ir_instr_op(self, 0, NULL, false)) GMQCC_SUPPRESS_EMPTY_BODY;
452     if (ir_instr_op(self, 1, NULL, false)) GMQCC_SUPPRESS_EMPTY_BODY;
453     if (ir_instr_op(self, 2, NULL, false)) GMQCC_SUPPRESS_EMPTY_BODY;
454     mem_d(self);
455 }
456
457 bool ir_instr_op(ir_instr *self, int op, ir_value *v, bool writing)
458 {
459     if (self->_ops[op]) {
460         size_t idx;
461         if (writing && ir_value_writes_find(self->_ops[op], self, &idx))
462         {
463             if (!ir_value_writes_remove(self->_ops[op], idx))
464                 return false;
465         }
466         else if (ir_value_reads_find(self->_ops[op], self, &idx))
467         {
468             if (!ir_value_reads_remove(self->_ops[op], idx))
469                 return false;
470         }
471     }
472     if (v) {
473         if (writing) {
474             if (!ir_value_writes_add(v, self))
475                 return false;
476         } else {
477             if (!ir_value_reads_add(v, self))
478                 return false;
479         }
480     }
481     self->_ops[op] = v;
482     return true;
483 }
484
485 /***********************************************************************
486  *IR Value
487  */
488
489 ir_value* ir_value_var(const char *name, int storetype, int vtype)
490 {
491     ir_value *self;
492     self = (ir_value*)mem_a(sizeof(*self));
493     self->vtype = vtype;
494     self->fieldtype = TYPE_VOID;
495     self->outtype = TYPE_VOID;
496     self->store = storetype;
497     MEM_VECTOR_INIT(self, reads);
498     MEM_VECTOR_INIT(self, writes);
499     self->isconst = false;
500     self->context.file = "<@no context>";
501     self->context.line = 0;
502     self->name = NULL;
503     ir_value_set_name(self, name);
504
505     memset(&self->constval, 0, sizeof(self->constval));
506     memset(&self->code,     0, sizeof(self->code));
507
508     MEM_VECTOR_INIT(self, life);
509     return self;
510 }
511 MEM_VEC_FUNCTIONS(ir_value, ir_life_entry_t, life)
512 MEM_VEC_FUNCTIONS_ALL(ir_value, ir_instr*, reads)
513 MEM_VEC_FUNCTIONS_ALL(ir_value, ir_instr*, writes)
514
515 ir_value* ir_value_out(ir_function *owner, const char *name, int storetype, int vtype)
516 {
517     ir_value *v = ir_value_var(name, storetype, vtype);
518     if (!v)
519         return NULL;
520     if (!ir_function_collect_value(owner, v))
521     {
522         ir_value_delete(v);
523         return NULL;
524     }
525     return v;
526 }
527
528 void ir_value_delete(ir_value* self)
529 {
530     if (self->name)
531         mem_d((void*)self->name);
532     if (self->isconst)
533     {
534         if (self->vtype == TYPE_STRING)
535             mem_d((void*)self->constval.vstring);
536     }
537     MEM_VECTOR_CLEAR(self, reads);
538     MEM_VECTOR_CLEAR(self, writes);
539     MEM_VECTOR_CLEAR(self, life);
540     mem_d(self);
541 }
542
543 void ir_value_set_name(ir_value *self, const char *name)
544 {
545     if (self->name)
546         mem_d((void*)self->name);
547     self->name = util_strdup(name);
548 }
549
550 bool ir_value_set_float(ir_value *self, float f)
551 {
552     if (self->vtype != TYPE_FLOAT)
553         return false;
554     self->constval.vfloat = f;
555     self->isconst = true;
556     return true;
557 }
558
559 bool ir_value_set_func(ir_value *self, int f)
560 {
561     if (self->vtype != TYPE_FUNCTION)
562         return false;
563     self->constval.vint = f;
564     self->isconst = true;
565     return true;
566 }
567
568 bool ir_value_set_vector(ir_value *self, vector v)
569 {
570     if (self->vtype != TYPE_VECTOR)
571         return false;
572     self->constval.vvec = v;
573     self->isconst = true;
574     return true;
575 }
576
577 bool ir_value_set_string(ir_value *self, const char *str)
578 {
579     if (self->vtype != TYPE_STRING)
580         return false;
581     self->constval.vstring = util_strdup(str);
582     self->isconst = true;
583     return true;
584 }
585
586 #if 0
587 bool ir_value_set_int(ir_value *self, int i)
588 {
589     if (self->vtype != TYPE_INTEGER)
590         return false;
591     self->constval.vint = i;
592     self->isconst = true;
593     return true;
594 }
595 #endif
596
597 bool ir_value_lives(ir_value *self, size_t at)
598 {
599     size_t i;
600     for (i = 0; i < self->life_count; ++i)
601     {
602         ir_life_entry_t *life = &self->life[i];
603         if (life->start <= at && at <= life->end)
604             return true;
605         if (life->start > at) /* since it's ordered */
606             return false;
607     }
608     return false;
609 }
610
611 bool ir_value_life_insert(ir_value *self, size_t idx, ir_life_entry_t e)
612 {
613     size_t k;
614     if (!ir_value_life_add(self, e)) /* naive... */
615         return false;
616     for (k = self->life_count-1; k > idx; --k)
617         self->life[k] = self->life[k-1];
618     self->life[idx] = e;
619     return true;
620 }
621
622 bool ir_value_life_merge(ir_value *self, size_t s)
623 {
624     size_t i;
625     ir_life_entry_t *life = NULL;
626     ir_life_entry_t *before = NULL;
627     ir_life_entry_t new_entry;
628
629     /* Find the first range >= s */
630     for (i = 0; i < self->life_count; ++i)
631     {
632         before = life;
633         life = &self->life[i];
634         if (life->start > s)
635             break;
636     }
637     /* nothing found? append */
638     if (i == self->life_count) {
639         ir_life_entry_t e;
640         if (life && life->end+1 == s)
641         {
642             /* previous life range can be merged in */
643             life->end++;
644             return true;
645         }
646         if (life && life->end >= s)
647             return false;
648         e.start = e.end = s;
649         if (!ir_value_life_add(self, e))
650             return false; /* failing */
651         return true;
652     }
653     /* found */
654     if (before)
655     {
656         if (before->end + 1 == s &&
657             life->start - 1 == s)
658         {
659             /* merge */
660             before->end = life->end;
661             if (!ir_value_life_remove(self, i))
662                 return false; /* failing */
663             return true;
664         }
665         if (before->end + 1 == s)
666         {
667             /* extend before */
668             before->end++;
669             return true;
670         }
671         /* already contained */
672         if (before->end >= s)
673             return false;
674     }
675     /* extend */
676     if (life->start - 1 == s)
677     {
678         life->start--;
679         return true;
680     }
681     /* insert a new entry */
682     new_entry.start = new_entry.end = s;
683     return ir_value_life_insert(self, i, new_entry);
684 }
685
686 bool ir_value_life_merge_into(ir_value *self, const ir_value *other)
687 {
688     size_t i, myi;
689
690     if (!other->life_count)
691         return true;
692
693     if (!self->life_count) {
694         for (i = 0; i < other->life_count; ++i) {
695             if (!ir_value_life_add(self, other->life[i]))
696                 return false;
697         }
698         return true;
699     }
700
701     myi = 0;
702     for (i = 0; i < other->life_count; ++i)
703     {
704         const ir_life_entry_t *life = &other->life[i];
705         while (true)
706         {
707             ir_life_entry_t *entry = &self->life[myi];
708
709             if (life->end+1 < entry->start)
710             {
711                 /* adding an interval before entry */
712                 if (!ir_value_life_insert(self, myi, *life))
713                     return false;
714                 ++myi;
715                 break;
716             }
717
718             if (life->start <  entry->start &&
719                 life->end   >= entry->start)
720             {
721                 /* starts earlier and overlaps */
722                 entry->start = life->start;
723             }
724
725             if (life->end     >  entry->end &&
726                 life->start-1 <= entry->end)
727             {
728                 /* ends later and overlaps */
729                 entry->end = life->end;
730             }
731
732             /* see if our change combines it with the next ranges */
733             while (myi+1 < self->life_count &&
734                    entry->end+1 >= self->life[1+myi].start)
735             {
736                 /* overlaps with (myi+1) */
737                 if (entry->end < self->life[1+myi].end)
738                     entry->end = self->life[1+myi].end;
739                 if (!ir_value_life_remove(self, myi+1))
740                     return false;
741                 entry = &self->life[myi];
742             }
743
744             /* see if we're after the entry */
745             if (life->start > entry->end)
746             {
747                 ++myi;
748                 /* append if we're at the end */
749                 if (myi >= self->life_count) {
750                     if (!ir_value_life_add(self, *life))
751                         return false;
752                     break;
753                 }
754                 /* otherweise check the next range */
755                 continue;
756             }
757             break;
758         }
759     }
760     return true;
761 }
762
763 bool ir_values_overlap(const ir_value *a, const ir_value *b)
764 {
765     /* For any life entry in A see if it overlaps with
766      * any life entry in B.
767      * Note that the life entries are orderes, so we can make a
768      * more efficient algorithm there than naively translating the
769      * statement above.
770      */
771
772     ir_life_entry_t *la, *lb, *enda, *endb;
773
774     /* first of all, if either has no life range, they cannot clash */
775     if (!a->life_count || !b->life_count)
776         return false;
777
778     la = a->life;
779     lb = b->life;
780     enda = la + a->life_count;
781     endb = lb + b->life_count;
782     while (true)
783     {
784         /* check if the entries overlap, for that,
785          * both must start before the other one ends.
786          */
787 #if defined(LIFE_RANGE_WITHOUT_LAST_READ)
788         if (la->start <= lb->end &&
789             lb->start <= la->end)
790 #else
791         if (la->start <  lb->end &&
792             lb->start <  la->end)
793 #endif
794         {
795             return true;
796         }
797
798         /* entries are ordered
799          * one entry is earlier than the other
800          * that earlier entry will be moved forward
801          */
802         if (la->start < lb->start)
803         {
804             /* order: A B, move A forward
805              * check if we hit the end with A
806              */
807             if (++la == enda)
808                 break;
809         }
810         else if (lb->start < la->start)
811         {
812             /* order: B A, move B forward
813              * check if we hit the end with B
814              */
815             if (++lb == endb)
816                 break;
817         }
818     }
819     return false;
820 }
821
822 /***********************************************************************
823  *IR main operations
824  */
825
826 bool ir_block_create_store_op(ir_block *self, int op, ir_value *target, ir_value *what)
827 {
828     if (target->store == store_value) {
829         fprintf(stderr, "cannot store to an SSA value\n");
830         fprintf(stderr, "trying to store: %s <- %s\n", target->name, what->name);
831         return false;
832     } else {
833         ir_instr *in = ir_instr_new(self, op);
834         if (!in)
835             return false;
836         if (!ir_instr_op(in, 0, target, true) ||
837             !ir_instr_op(in, 1, what, false)  ||
838             !ir_block_instr_add(self, in) )
839         {
840             return false;
841         }
842         return true;
843     }
844 }
845
846 bool ir_block_create_store(ir_block *self, ir_value *target, ir_value *what)
847 {
848     int op = 0;
849     int vtype;
850     if (target->vtype == TYPE_VARIANT)
851         vtype = what->vtype;
852     else
853         vtype = target->vtype;
854
855 #if 0
856     if      (vtype == TYPE_FLOAT   && what->vtype == TYPE_INTEGER)
857         op = INSTR_CONV_ITOF;
858     else if (vtype == TYPE_INTEGER && what->vtype == TYPE_FLOAT)
859         op = INSTR_CONV_FTOI;
860 #endif
861         op = type_store_instr[vtype];
862
863     return ir_block_create_store_op(self, op, target, what);
864 }
865
866 bool ir_block_create_storep(ir_block *self, ir_value *target, ir_value *what)
867 {
868     int op = 0;
869     int vtype;
870
871     if (target->vtype != TYPE_POINTER)
872         return false;
873
874     /* storing using pointer - target is a pointer, type must be
875      * inferred from source
876      */
877     vtype = what->vtype;
878
879     op = type_storep_instr[vtype];
880
881     return ir_block_create_store_op(self, op, target, what);
882 }
883
884 bool ir_block_create_return(ir_block *self, ir_value *v)
885 {
886     ir_instr *in;
887     if (self->final) {
888         fprintf(stderr, "block already ended (%s)\n", self->label);
889         return false;
890     }
891     self->final = true;
892     self->is_return = true;
893     in = ir_instr_new(self, INSTR_RETURN);
894     if (!in)
895         return false;
896
897     if (!ir_instr_op(in, 0, v, false) ||
898         !ir_block_instr_add(self, in) )
899     {
900         return false;
901     }
902     return true;
903 }
904
905 bool ir_block_create_if(ir_block *self, ir_value *v,
906                         ir_block *ontrue, ir_block *onfalse)
907 {
908     ir_instr *in;
909     if (self->final) {
910         fprintf(stderr, "block already ended (%s)\n", self->label);
911         return false;
912     }
913     self->final = true;
914     /*in = ir_instr_new(self, (v->vtype == TYPE_STRING ? INSTR_IF_S : INSTR_IF_F));*/
915     in = ir_instr_new(self, VINSTR_COND);
916     if (!in)
917         return false;
918
919     if (!ir_instr_op(in, 0, v, false)) {
920         ir_instr_delete(in);
921         return false;
922     }
923
924     in->bops[0] = ontrue;
925     in->bops[1] = onfalse;
926
927     if (!ir_block_instr_add(self, in))
928         return false;
929
930     if (!ir_block_exits_add(self, ontrue)    ||
931         !ir_block_exits_add(self, onfalse)   ||
932         !ir_block_entries_add(ontrue, self)  ||
933         !ir_block_entries_add(onfalse, self) )
934     {
935         return false;
936     }
937     return true;
938 }
939
940 bool ir_block_create_jump(ir_block *self, ir_block *to)
941 {
942     ir_instr *in;
943     if (self->final) {
944         fprintf(stderr, "block already ended (%s)\n", self->label);
945         return false;
946     }
947     self->final = true;
948     in = ir_instr_new(self, VINSTR_JUMP);
949     if (!in)
950         return false;
951
952     in->bops[0] = to;
953     if (!ir_block_instr_add(self, in))
954         return false;
955
956     if (!ir_block_exits_add(self, to) ||
957         !ir_block_entries_add(to, self) )
958     {
959         return false;
960     }
961     return true;
962 }
963
964 bool ir_block_create_goto(ir_block *self, ir_block *to)
965 {
966     ir_instr *in;
967     if (self->final) {
968         fprintf(stderr, "block already ended (%s)\n", self->label);
969         return false;
970     }
971     self->final = true;
972     in = ir_instr_new(self, INSTR_GOTO);
973     if (!in)
974         return false;
975
976     in->bops[0] = to;
977     if (!ir_block_instr_add(self, in))
978         return false;
979
980     if (!ir_block_exits_add(self, to) ||
981         !ir_block_entries_add(to, self) )
982     {
983         return false;
984     }
985     return true;
986 }
987
988 ir_instr* ir_block_create_phi(ir_block *self, const char *label, int ot)
989 {
990     ir_value *out;
991     ir_instr *in;
992     in = ir_instr_new(self, VINSTR_PHI);
993     if (!in)
994         return NULL;
995     out = ir_value_out(self->owner, label, store_value, ot);
996     if (!out) {
997         ir_instr_delete(in);
998         return NULL;
999     }
1000     if (!ir_instr_op(in, 0, out, true)) {
1001         ir_instr_delete(in);
1002         ir_value_delete(out);
1003         return NULL;
1004     }
1005     if (!ir_block_instr_add(self, in)) {
1006         ir_instr_delete(in);
1007         ir_value_delete(out);
1008         return NULL;
1009     }
1010     return in;
1011 }
1012
1013 ir_value* ir_phi_value(ir_instr *self)
1014 {
1015     return self->_ops[0];
1016 }
1017
1018 bool ir_phi_add(ir_instr* self, ir_block *b, ir_value *v)
1019 {
1020     ir_phi_entry_t pe;
1021
1022     if (!ir_block_entries_find(self->owner, b, NULL)) {
1023         /* Must not be possible to cause this, otherwise the AST
1024          * is doing something wrong.
1025          */
1026         fprintf(stderr, "Invalid entry block for PHI\n");
1027         abort();
1028     }
1029
1030     pe.value = v;
1031     pe.from = b;
1032     if (!ir_value_reads_add(v, self))
1033         return false;
1034     return ir_instr_phi_add(self, pe);
1035 }
1036
1037 /* call related code */
1038 ir_instr* ir_block_create_call(ir_block *self, const char *label, ir_value *func)
1039 {
1040     ir_value *out;
1041     ir_instr *in;
1042     in = ir_instr_new(self, INSTR_CALL0);
1043     if (!in)
1044         return NULL;
1045     out = ir_value_out(self->owner, label, store_return, func->outtype);
1046     if (!out) {
1047         ir_instr_delete(in);
1048         return NULL;
1049     }
1050     if (!ir_instr_op(in, 0, out, true) ||
1051         !ir_instr_op(in, 1, func, false) ||
1052         !ir_block_instr_add(self, in))
1053     {
1054         ir_instr_delete(in);
1055         ir_value_delete(out);
1056         return NULL;
1057     }
1058     return in;
1059 }
1060
1061 ir_value* ir_call_value(ir_instr *self)
1062 {
1063     return self->_ops[0];
1064 }
1065
1066 bool ir_call_param(ir_instr* self, ir_value *v)
1067 {
1068     if (!ir_instr_params_add(self, v))
1069         return false;
1070     if (!ir_value_reads_add(v, self)) {
1071         if (!ir_instr_params_remove(self, self->params_count-1))
1072             GMQCC_SUPPRESS_EMPTY_BODY;
1073         return false;
1074     }
1075     return true;
1076 }
1077
1078 /* binary op related code */
1079
1080 ir_value* ir_block_create_binop(ir_block *self,
1081                                 const char *label, int opcode,
1082                                 ir_value *left, ir_value *right)
1083 {
1084     int ot = TYPE_VOID;
1085     switch (opcode) {
1086         case INSTR_ADD_F:
1087         case INSTR_SUB_F:
1088         case INSTR_DIV_F:
1089         case INSTR_MUL_F:
1090         case INSTR_MUL_V:
1091         case INSTR_AND:
1092         case INSTR_OR:
1093 #if 0
1094         case INSTR_AND_I:
1095         case INSTR_AND_IF:
1096         case INSTR_AND_FI:
1097         case INSTR_OR_I:
1098         case INSTR_OR_IF:
1099         case INSTR_OR_FI:
1100 #endif
1101         case INSTR_BITAND:
1102         case INSTR_BITOR:
1103 #if 0
1104         case INSTR_SUB_S: /* -- offset of string as float */
1105         case INSTR_MUL_IF:
1106         case INSTR_MUL_FI:
1107         case INSTR_DIV_IF:
1108         case INSTR_DIV_FI:
1109         case INSTR_BITOR_IF:
1110         case INSTR_BITOR_FI:
1111         case INSTR_BITAND_FI:
1112         case INSTR_BITAND_IF:
1113         case INSTR_EQ_I:
1114         case INSTR_NE_I:
1115 #endif
1116             ot = TYPE_FLOAT;
1117             break;
1118 #if 0
1119         case INSTR_ADD_I:
1120         case INSTR_ADD_IF:
1121         case INSTR_ADD_FI:
1122         case INSTR_SUB_I:
1123         case INSTR_SUB_FI:
1124         case INSTR_SUB_IF:
1125         case INSTR_MUL_I:
1126         case INSTR_DIV_I:
1127         case INSTR_BITAND_I:
1128         case INSTR_BITOR_I:
1129         case INSTR_XOR_I:
1130         case INSTR_RSHIFT_I:
1131         case INSTR_LSHIFT_I:
1132             ot = TYPE_INTEGER;
1133             break;
1134 #endif
1135         case INSTR_ADD_V:
1136         case INSTR_SUB_V:
1137         case INSTR_MUL_VF:
1138         case INSTR_MUL_FV:
1139 #if 0
1140         case INSTR_DIV_VF:
1141         case INSTR_MUL_IV:
1142         case INSTR_MUL_VI:
1143 #endif
1144             ot = TYPE_VECTOR;
1145             break;
1146 #if 0
1147         case INSTR_ADD_SF:
1148             ot = TYPE_POINTER;
1149             break;
1150 #endif
1151         default:
1152             /* ranges: */
1153             /* boolean operations result in floats */
1154             if (opcode >= INSTR_EQ_F && opcode <= INSTR_GT)
1155                 ot = TYPE_FLOAT;
1156             else if (opcode >= INSTR_LE && opcode <= INSTR_GT)
1157                 ot = TYPE_FLOAT;
1158 #if 0
1159             else if (opcode >= INSTR_LE_I && opcode <= INSTR_EQ_FI)
1160                 ot = TYPE_FLOAT;
1161 #endif
1162             break;
1163     };
1164     if (ot == TYPE_VOID) {
1165         /* The AST or parser were supposed to check this! */
1166         return NULL;
1167     }
1168
1169     return ir_block_create_general_instr(self, label, opcode, left, right, ot);
1170 }
1171
1172 ir_value* ir_block_create_general_instr(ir_block *self, const char *label,
1173                                         int op, ir_value *a, ir_value *b, int outype)
1174 {
1175     ir_instr *instr;
1176     ir_value *out;
1177
1178     out = ir_value_out(self->owner, label, store_value, outype);
1179     if (!out)
1180         return NULL;
1181
1182     instr = ir_instr_new(self, op);
1183     if (!instr) {
1184         ir_value_delete(out);
1185         return NULL;
1186     }
1187
1188     if (!ir_instr_op(instr, 0, out, true) ||
1189         !ir_instr_op(instr, 1, a, false) ||
1190         !ir_instr_op(instr, 2, b, false) )
1191     {
1192         goto on_error;
1193     }
1194
1195     if (!ir_block_instr_add(self, instr))
1196         goto on_error;
1197
1198     return out;
1199 on_error:
1200     ir_instr_delete(instr);
1201     ir_value_delete(out);
1202     return NULL;
1203 }
1204
1205 ir_value* ir_block_create_fieldaddress(ir_block *self, const char *label, ir_value *ent, ir_value *field)
1206 {
1207     /* Support for various pointer types todo if so desired */
1208     if (ent->vtype != TYPE_ENTITY)
1209         return NULL;
1210
1211     if (field->vtype != TYPE_FIELD)
1212         return NULL;
1213
1214     return ir_block_create_general_instr(self, label, INSTR_ADDRESS, ent, field, TYPE_POINTER);
1215 }
1216
1217 ir_value* ir_block_create_load_from_ent(ir_block *self, const char *label, ir_value *ent, ir_value *field, int outype)
1218 {
1219     int op;
1220     if (ent->vtype != TYPE_ENTITY)
1221         return NULL;
1222
1223     /* at some point we could redirect for TYPE_POINTER... but that could lead to carelessness */
1224     if (field->vtype != TYPE_FIELD)
1225         return NULL;
1226
1227     switch (outype)
1228     {
1229         case TYPE_FLOAT:   op = INSTR_LOAD_F;   break;
1230         case TYPE_VECTOR:  op = INSTR_LOAD_V;   break;
1231         case TYPE_STRING:  op = INSTR_LOAD_S;   break;
1232         case TYPE_FIELD:   op = INSTR_LOAD_FLD; break;
1233         case TYPE_ENTITY:  op = INSTR_LOAD_ENT; break;
1234 #if 0
1235         case TYPE_POINTER: op = INSTR_LOAD_I;   break;
1236         case TYPE_INTEGER: op = INSTR_LOAD_I;   break;
1237 #endif
1238         default:
1239             return NULL;
1240     }
1241
1242     return ir_block_create_general_instr(self, label, op, ent, field, outype);
1243 }
1244
1245 ir_value* ir_block_create_add(ir_block *self,
1246                               const char *label,
1247                               ir_value *left, ir_value *right)
1248 {
1249     int op = 0;
1250     int l = left->vtype;
1251     int r = right->vtype;
1252     if (l == r) {
1253         switch (l) {
1254             default:
1255                 return NULL;
1256             case TYPE_FLOAT:
1257                 op = INSTR_ADD_F;
1258                 break;
1259 #if 0
1260             case TYPE_INTEGER:
1261                 op = INSTR_ADD_I;
1262                 break;
1263 #endif
1264             case TYPE_VECTOR:
1265                 op = INSTR_ADD_V;
1266                 break;
1267         }
1268     } else {
1269 #if 0
1270         if ( (l == TYPE_FLOAT && r == TYPE_INTEGER) )
1271             op = INSTR_ADD_FI;
1272         else if ( (l == TYPE_INTEGER && r == TYPE_FLOAT) )
1273             op = INSTR_ADD_IF;
1274         else
1275 #endif
1276             return NULL;
1277     }
1278     return ir_block_create_binop(self, label, op, left, right);
1279 }
1280
1281 ir_value* ir_block_create_sub(ir_block *self,
1282                               const char *label,
1283                               ir_value *left, ir_value *right)
1284 {
1285     int op = 0;
1286     int l = left->vtype;
1287     int r = right->vtype;
1288     if (l == r) {
1289
1290         switch (l) {
1291             default:
1292                 return NULL;
1293             case TYPE_FLOAT:
1294                 op = INSTR_SUB_F;
1295                 break;
1296 #if 0
1297             case TYPE_INTEGER:
1298                 op = INSTR_SUB_I;
1299                 break;
1300 #endif
1301             case TYPE_VECTOR:
1302                 op = INSTR_SUB_V;
1303                 break;
1304         }
1305     } else {
1306 #if 0
1307         if ( (l == TYPE_FLOAT && r == TYPE_INTEGER) )
1308             op = INSTR_SUB_FI;
1309         else if ( (l == TYPE_INTEGER && r == TYPE_FLOAT) )
1310             op = INSTR_SUB_IF;
1311         else
1312 #endif
1313             return NULL;
1314     }
1315     return ir_block_create_binop(self, label, op, left, right);
1316 }
1317
1318 ir_value* ir_block_create_mul(ir_block *self,
1319                               const char *label,
1320                               ir_value *left, ir_value *right)
1321 {
1322     int op = 0;
1323     int l = left->vtype;
1324     int r = right->vtype;
1325     if (l == r) {
1326
1327         switch (l) {
1328             default:
1329                 return NULL;
1330             case TYPE_FLOAT:
1331                 op = INSTR_MUL_F;
1332                 break;
1333 #if 0
1334             case TYPE_INTEGER:
1335                 op = INSTR_MUL_I;
1336                 break;
1337 #endif
1338             case TYPE_VECTOR:
1339                 op = INSTR_MUL_V;
1340                 break;
1341         }
1342     } else {
1343         if ( (l == TYPE_VECTOR && r == TYPE_FLOAT) )
1344             op = INSTR_MUL_VF;
1345         else if ( (l == TYPE_FLOAT && r == TYPE_VECTOR) )
1346             op = INSTR_MUL_FV;
1347 #if 0
1348         else if ( (l == TYPE_VECTOR && r == TYPE_INTEGER) )
1349             op = INSTR_MUL_VI;
1350         else if ( (l == TYPE_INTEGER && r == TYPE_VECTOR) )
1351             op = INSTR_MUL_IV;
1352         else if ( (l == TYPE_FLOAT && r == TYPE_INTEGER) )
1353             op = INSTR_MUL_FI;
1354         else if ( (l == TYPE_INTEGER && r == TYPE_FLOAT) )
1355             op = INSTR_MUL_IF;
1356 #endif
1357         else
1358             return NULL;
1359     }
1360     return ir_block_create_binop(self, label, op, left, right);
1361 }
1362
1363 ir_value* ir_block_create_div(ir_block *self,
1364                               const char *label,
1365                               ir_value *left, ir_value *right)
1366 {
1367     int op = 0;
1368     int l = left->vtype;
1369     int r = right->vtype;
1370     if (l == r) {
1371
1372         switch (l) {
1373             default:
1374                 return NULL;
1375             case TYPE_FLOAT:
1376                 op = INSTR_DIV_F;
1377                 break;
1378 #if 0
1379             case TYPE_INTEGER:
1380                 op = INSTR_DIV_I;
1381                 break;
1382 #endif
1383         }
1384     } else {
1385 #if 0
1386         if ( (l == TYPE_VECTOR && r == TYPE_FLOAT) )
1387             op = INSTR_DIV_VF;
1388         else if ( (l == TYPE_FLOAT && r == TYPE_INTEGER) )
1389             op = INSTR_DIV_FI;
1390         else if ( (l == TYPE_INTEGER && r == TYPE_FLOAT) )
1391             op = INSTR_DIV_IF;
1392         else
1393 #endif
1394             return NULL;
1395     }
1396     return ir_block_create_binop(self, label, op, left, right);
1397 }
1398
1399 /* PHI resolving breaks the SSA, and must thus be the last
1400  * step before life-range calculation.
1401  */
1402
1403 static bool ir_block_naive_phi(ir_block *self);
1404 bool ir_function_naive_phi(ir_function *self)
1405 {
1406     size_t i;
1407
1408     for (i = 0; i < self->blocks_count; ++i)
1409     {
1410         if (!ir_block_naive_phi(self->blocks[i]))
1411             return false;
1412     }
1413     return true;
1414 }
1415
1416 static bool ir_naive_phi_emit_store(ir_block *block, size_t iid, ir_value *old, ir_value *what)
1417 {
1418     ir_instr *instr;
1419     size_t i;
1420
1421     /* create a store */
1422     if (!ir_block_create_store(block, old, what))
1423         return false;
1424
1425     /* we now move it up */
1426     instr = block->instr[block->instr_count-1];
1427     for (i = block->instr_count; i > iid; --i)
1428         block->instr[i] = block->instr[i-1];
1429     block->instr[i] = instr;
1430
1431     return true;
1432 }
1433
1434 static bool ir_block_naive_phi(ir_block *self)
1435 {
1436     size_t i, p, w;
1437     /* FIXME: optionally, create_phi can add the phis
1438      * to a list so we don't need to loop through blocks
1439      * - anyway: "don't optimize YET"
1440      */
1441     for (i = 0; i < self->instr_count; ++i)
1442     {
1443         ir_instr *instr = self->instr[i];
1444         if (instr->opcode != VINSTR_PHI)
1445             continue;
1446
1447         if (!ir_block_instr_remove(self, i))
1448             return false;
1449         --i; /* NOTE: i+1 below */
1450
1451         for (p = 0; p < instr->phi_count; ++p)
1452         {
1453             ir_value *v = instr->phi[p].value;
1454             for (w = 0; w < v->writes_count; ++w) {
1455                 ir_value *old;
1456
1457                 if (!v->writes[w]->_ops[0])
1458                     continue;
1459
1460                 /* When the write was to a global, we have to emit a mov */
1461                 old = v->writes[w]->_ops[0];
1462
1463                 /* The original instruction now writes to the PHI target local */
1464                 if (v->writes[w]->_ops[0] == v)
1465                     v->writes[w]->_ops[0] = instr->_ops[0];
1466
1467                 if (old->store != store_value && old->store != store_local && old->store != store_param)
1468                 {
1469                     /* If it originally wrote to a global we need to store the value
1470                      * there as welli
1471                      */
1472                     if (!ir_naive_phi_emit_store(self, i+1, old, v))
1473                         return false;
1474                     if (i+1 < self->instr_count)
1475                         instr = self->instr[i+1];
1476                     else
1477                         instr = NULL;
1478                     /* In case I forget and access instr later, it'll be NULL
1479                      * when it's a problem, to make sure we crash, rather than accessing
1480                      * invalid data.
1481                      */
1482                 }
1483                 else
1484                 {
1485                     /* If it didn't, we can replace all reads by the phi target now. */
1486                     size_t r;
1487                     for (r = 0; r < old->reads_count; ++r)
1488                     {
1489                         size_t op;
1490                         ir_instr *ri = old->reads[r];
1491                         for (op = 0; op < ri->phi_count; ++op) {
1492                             if (ri->phi[op].value == old)
1493                                 ri->phi[op].value = v;
1494                         }
1495                         for (op = 0; op < 3; ++op) {
1496                             if (ri->_ops[op] == old)
1497                                 ri->_ops[op] = v;
1498                         }
1499                     }
1500                 }
1501             }
1502         }
1503         ir_instr_delete(instr);
1504     }
1505     return true;
1506 }
1507
1508 /***********************************************************************
1509  *IR Temp allocation code
1510  * Propagating value life ranges by walking through the function backwards
1511  * until no more changes are made.
1512  * In theory this should happen once more than once for every nested loop
1513  * level.
1514  * Though this implementation might run an additional time for if nests.
1515  */
1516
1517 typedef struct
1518 {
1519     ir_value* *v;
1520     size_t    v_count;
1521     size_t    v_alloc;
1522 } new_reads_t;
1523 MEM_VEC_FUNCTIONS_ALL(new_reads_t, ir_value*, v)
1524
1525 /* Enumerate instructions used by value's life-ranges
1526  */
1527 static void ir_block_enumerate(ir_block *self, size_t *_eid)
1528 {
1529     size_t i;
1530     size_t eid = *_eid;
1531     for (i = 0; i < self->instr_count; ++i)
1532     {
1533         self->instr[i]->eid = eid++;
1534     }
1535     *_eid = eid;
1536 }
1537
1538 /* Enumerate blocks and instructions.
1539  * The block-enumeration is unordered!
1540  * We do not really use the block enumreation, however
1541  * the instruction enumeration is important for life-ranges.
1542  */
1543 void ir_function_enumerate(ir_function *self)
1544 {
1545     size_t i;
1546     size_t instruction_id = 0;
1547     for (i = 0; i < self->blocks_count; ++i)
1548     {
1549         self->blocks[i]->eid = i;
1550         self->blocks[i]->run_id = 0;
1551         ir_block_enumerate(self->blocks[i], &instruction_id);
1552     }
1553 }
1554
1555 static bool ir_block_life_propagate(ir_block *b, ir_block *prev, bool *changed);
1556 bool ir_function_calculate_liferanges(ir_function *self)
1557 {
1558     size_t i;
1559     bool changed;
1560
1561     do {
1562         self->run_id++;
1563         changed = false;
1564         for (i = 0; i != self->blocks_count; ++i)
1565         {
1566             if (self->blocks[i]->is_return)
1567             {
1568                 if (!ir_block_life_propagate(self->blocks[i], NULL, &changed))
1569                     return false;
1570             }
1571         }
1572     } while (changed);
1573     return true;
1574 }
1575
1576 /* Local-value allocator
1577  * After finishing creating the liferange of all values used in a function
1578  * we can allocate their global-positions.
1579  * This is the counterpart to register-allocation in register machines.
1580  */
1581 typedef struct {
1582     MEM_VECTOR_MAKE(ir_value*, locals);
1583     MEM_VECTOR_MAKE(size_t,    sizes);
1584     MEM_VECTOR_MAKE(size_t,    positions);
1585 } function_allocator;
1586 MEM_VEC_FUNCTIONS(function_allocator, ir_value*, locals)
1587 MEM_VEC_FUNCTIONS(function_allocator, size_t,    sizes)
1588 MEM_VEC_FUNCTIONS(function_allocator, size_t,    positions)
1589
1590 static bool function_allocator_alloc(function_allocator *alloc, const ir_value *var)
1591 {
1592     ir_value *slot;
1593     size_t vsize = type_sizeof[var->vtype];
1594
1595     slot = ir_value_var("reg", store_global, var->vtype);
1596     if (!slot)
1597         return false;
1598
1599     if (!ir_value_life_merge_into(slot, var))
1600         goto localerror;
1601
1602     if (!function_allocator_locals_add(alloc, slot))
1603         goto localerror;
1604
1605     if (!function_allocator_sizes_add(alloc, vsize))
1606         goto localerror;
1607
1608     return true;
1609
1610 localerror:
1611     ir_value_delete(slot);
1612     return false;
1613 }
1614
1615 bool ir_function_allocate_locals(ir_function *self)
1616 {
1617     size_t i, a;
1618     bool   retval = true;
1619     size_t pos;
1620
1621     ir_value *slot;
1622     const ir_value *v;
1623
1624     function_allocator alloc;
1625
1626     if (!self->locals_count)
1627         return true;
1628
1629     MEM_VECTOR_INIT(&alloc, locals);
1630     MEM_VECTOR_INIT(&alloc, sizes);
1631     MEM_VECTOR_INIT(&alloc, positions);
1632
1633     for (i = 0; i < self->locals_count; ++i)
1634     {
1635         if (!function_allocator_alloc(&alloc, self->locals[i]))
1636             goto error;
1637     }
1638
1639     /* Allocate a slot for any value that still exists */
1640     for (i = 0; i < self->values_count; ++i)
1641     {
1642         v = self->values[i];
1643
1644         if (!v->life_count)
1645             continue;
1646
1647         for (a = 0; a < alloc.locals_count; ++a)
1648         {
1649             slot = alloc.locals[a];
1650
1651             if (ir_values_overlap(v, slot))
1652                 continue;
1653
1654             if (!ir_value_life_merge_into(slot, v))
1655                 goto error;
1656
1657             /* adjust size for this slot */
1658             if (alloc.sizes[a] < type_sizeof[v->vtype])
1659                 alloc.sizes[a] = type_sizeof[v->vtype];
1660
1661             self->values[i]->code.local = a;
1662             break;
1663         }
1664         if (a >= alloc.locals_count) {
1665             self->values[i]->code.local = alloc.locals_count;
1666             if (!function_allocator_alloc(&alloc, v))
1667                 goto error;
1668         }
1669     }
1670
1671     /* Adjust slot positions based on sizes */
1672     if (!function_allocator_positions_add(&alloc, 0))
1673         goto error;
1674
1675     if (alloc.sizes_count)
1676         pos = alloc.positions[0] + alloc.sizes[0];
1677     else
1678         pos = 0;
1679     for (i = 1; i < alloc.sizes_count; ++i)
1680     {
1681         pos = alloc.positions[i-1] + alloc.sizes[i-1];
1682         if (!function_allocator_positions_add(&alloc, pos))
1683             goto error;
1684     }
1685
1686     self->allocated_locals = pos + alloc.sizes[alloc.sizes_count-1];
1687
1688     /* Take over the actual slot positions */
1689     for (i = 0; i < self->values_count; ++i)
1690         self->values[i]->code.local = alloc.positions[self->values[i]->code.local];
1691
1692     goto cleanup;
1693
1694 error:
1695     retval = false;
1696 cleanup:
1697     for (i = 0; i < alloc.locals_count; ++i)
1698         ir_value_delete(alloc.locals[i]);
1699     MEM_VECTOR_CLEAR(&alloc, locals);
1700     MEM_VECTOR_CLEAR(&alloc, sizes);
1701     MEM_VECTOR_CLEAR(&alloc, positions);
1702     return retval;
1703 }
1704
1705 /* Get information about which operand
1706  * is read from, or written to.
1707  */
1708 static void ir_op_read_write(int op, size_t *read, size_t *write)
1709 {
1710     switch (op)
1711     {
1712     case VINSTR_JUMP:
1713     case INSTR_GOTO:
1714         *write = 0;
1715         *read = 0;
1716         break;
1717     case INSTR_IF:
1718     case INSTR_IFNOT:
1719 #if 0
1720     case INSTR_IF_S:
1721     case INSTR_IFNOT_S:
1722 #endif
1723     case INSTR_RETURN:
1724     case VINSTR_COND:
1725         *write = 0;
1726         *read = 1;
1727         break;
1728     default:
1729         *write = 1;
1730         *read = 6;
1731         break;
1732     };
1733 }
1734
1735 static bool ir_block_living_add_instr(ir_block *self, size_t eid)
1736 {
1737     size_t i;
1738     bool changed = false;
1739     bool tempbool;
1740     for (i = 0; i != self->living_count; ++i)
1741     {
1742         tempbool = ir_value_life_merge(self->living[i], eid);
1743         /* debug
1744         if (tempbool)
1745             fprintf(stderr, "block_living_add_instr() value instruction added %s: %i\n", self->living[i]->_name, (int)eid);
1746         */
1747         changed = changed || tempbool;
1748     }
1749     return changed;
1750 }
1751
1752 static bool ir_block_life_prop_previous(ir_block* self, ir_block *prev, bool *changed)
1753 {
1754     size_t i;
1755     /* values which have been read in a previous iteration are now
1756      * in the "living" array even if the previous block doesn't use them.
1757      * So we have to remove whatever does not exist in the previous block.
1758      * They will be re-added on-read, but the liferange merge won't cause
1759      * a change.
1760      */
1761     for (i = 0; i < self->living_count; ++i)
1762     {
1763         if (!ir_block_living_find(prev, self->living[i], NULL)) {
1764             if (!ir_block_living_remove(self, i))
1765                 return false;
1766             --i;
1767         }
1768     }
1769
1770     /* Whatever the previous block still has in its living set
1771      * must now be added to ours as well.
1772      */
1773     for (i = 0; i < prev->living_count; ++i)
1774     {
1775         if (ir_block_living_find(self, prev->living[i], NULL))
1776             continue;
1777         if (!ir_block_living_add(self, prev->living[i]))
1778             return false;
1779         /*
1780         printf("%s got from prev: %s\n", self->label, prev->living[i]->_name);
1781         */
1782     }
1783     return true;
1784 }
1785
1786 static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *changed)
1787 {
1788     ir_instr *instr;
1789     ir_value *value;
1790     bool  tempbool;
1791     size_t i, o, p;
1792     /* bitmasks which operands are read from or written to */
1793     size_t read, write;
1794 #if defined(LIFE_RANGE_WITHOUT_LAST_READ)
1795     size_t rd;
1796     new_reads_t new_reads;
1797 #endif
1798     char dbg_ind[16] = { '#', '0' };
1799     (void)dbg_ind;
1800
1801 #if defined(LIFE_RANGE_WITHOUT_LAST_READ)
1802     MEM_VECTOR_INIT(&new_reads, v);
1803 #endif
1804
1805     if (prev)
1806     {
1807         if (!ir_block_life_prop_previous(self, prev, changed))
1808             return false;
1809     }
1810
1811     i = self->instr_count;
1812     while (i)
1813     { --i;
1814         instr = self->instr[i];
1815
1816         /* PHI operands are always read operands */
1817         for (p = 0; p < instr->phi_count; ++p)
1818         {
1819             value = instr->phi[p].value;
1820 #if ! defined(LIFE_RANGE_WITHOUT_LAST_READ)
1821             if (!ir_block_living_find(self, value, NULL) &&
1822                 !ir_block_living_add(self, value))
1823             {
1824                 goto on_error;
1825             }
1826 #else
1827             if (!new_reads_t_v_find(&new_reads, value, NULL))
1828             {
1829                 if (!new_reads_t_v_add(&new_reads, value))
1830                     goto on_error;
1831             }
1832 #endif
1833         }
1834
1835         /* See which operands are read and write operands */
1836         ir_op_read_write(instr->opcode, &read, &write);
1837
1838         /* Go through the 3 main operands */
1839         for (o = 0; o < 3; ++o)
1840         {
1841             if (!instr->_ops[o]) /* no such operand */
1842                 continue;
1843
1844             value = instr->_ops[o];
1845
1846             /* We only care about locals */
1847             /* we also calculate parameter liferanges so that locals
1848              * can take up parameter slots */
1849             if (value->store != store_value &&
1850                 value->store != store_local &&
1851                 value->store != store_param)
1852                 continue;
1853
1854             /* read operands */
1855             if (read & (1<<o))
1856             {
1857 #if ! defined(LIFE_RANGE_WITHOUT_LAST_READ)
1858                 if (!ir_block_living_find(self, value, NULL) &&
1859                     !ir_block_living_add(self, value))
1860                 {
1861                     goto on_error;
1862                 }
1863 #else
1864                 /* fprintf(stderr, "read: %s\n", value->_name); */
1865                 if (!new_reads_t_v_find(&new_reads, value, NULL))
1866                 {
1867                     if (!new_reads_t_v_add(&new_reads, value))
1868                         goto on_error;
1869                 }
1870 #endif
1871             }
1872
1873             /* write operands */
1874             /* When we write to a local, we consider it "dead" for the
1875              * remaining upper part of the function, since in SSA a value
1876              * can only be written once (== created)
1877              */
1878             if (write & (1<<o))
1879             {
1880                 size_t idx;
1881                 bool in_living = ir_block_living_find(self, value, &idx);
1882 #if defined(LIFE_RANGE_WITHOUT_LAST_READ)
1883                 size_t readidx;
1884                 bool in_reads = new_reads_t_v_find(&new_reads, value, &readidx);
1885                 if (!in_living && !in_reads)
1886 #else
1887                 if (!in_living)
1888 #endif
1889                 {
1890                     /* If the value isn't alive it hasn't been read before... */
1891                     /* TODO: See if the warning can be emitted during parsing or AST processing
1892                      * otherwise have warning printed here.
1893                      * IF printing a warning here: include filecontext_t,
1894                      * and make sure it's only printed once
1895                      * since this function is run multiple times.
1896                      */
1897                     /* For now: debug info: */
1898                     fprintf(stderr, "Value only written %s\n", value->name);
1899                     tempbool = ir_value_life_merge(value, instr->eid);
1900                     *changed = *changed || tempbool;
1901                     /*
1902                     ir_instr_dump(instr, dbg_ind, printf);
1903                     abort();
1904                     */
1905                 } else {
1906                     /* since 'living' won't contain it
1907                      * anymore, merge the value, since
1908                      * (A) doesn't.
1909                      */
1910                     tempbool = ir_value_life_merge(value, instr->eid);
1911                     /*
1912                     if (tempbool)
1913                         fprintf(stderr, "value added id %s %i\n", value->name, (int)instr->eid);
1914                     */
1915                     *changed = *changed || tempbool;
1916                     /* Then remove */
1917 #if ! defined(LIFE_RANGE_WITHOUT_LAST_READ)
1918                     if (!ir_block_living_remove(self, idx))
1919                         goto on_error;
1920 #else
1921                     if (in_reads)
1922                     {
1923                         if (!new_reads_t_v_remove(&new_reads, readidx))
1924                             goto on_error;
1925                     }
1926 #endif
1927                 }
1928             }
1929         }
1930         /* (A) */
1931         tempbool = ir_block_living_add_instr(self, instr->eid);
1932         /*fprintf(stderr, "living added values\n");*/
1933         *changed = *changed || tempbool;
1934
1935 #if defined(LIFE_RANGE_WITHOUT_LAST_READ)
1936         /* new reads: */
1937         for (rd = 0; rd < new_reads.v_count; ++rd)
1938         {
1939             if (!ir_block_living_find(self, new_reads.v[rd], NULL)) {
1940                 if (!ir_block_living_add(self, new_reads.v[rd]))
1941                     goto on_error;
1942             }
1943             if (!i && !self->entries_count) {
1944                 /* fix the top */
1945                 *changed = *changed || ir_value_life_merge(new_reads.v[rd], instr->eid);
1946             }
1947         }
1948         MEM_VECTOR_CLEAR(&new_reads, v);
1949 #endif
1950     }
1951
1952     if (self->run_id == self->owner->run_id)
1953         return true;
1954
1955     self->run_id = self->owner->run_id;
1956
1957     for (i = 0; i < self->entries_count; ++i)
1958     {
1959         ir_block *entry = self->entries[i];
1960         ir_block_life_propagate(entry, self, changed);
1961     }
1962
1963     return true;
1964 on_error:
1965 #if defined(LIFE_RANGE_WITHOUT_LAST_READ)
1966     MEM_VECTOR_CLEAR(&new_reads, v);
1967 #endif
1968     return false;
1969 }
1970
1971 /***********************************************************************
1972  *IR Code-Generation
1973  *
1974  * Since the IR has the convention of putting 'write' operands
1975  * at the beginning, we have to rotate the operands of instructions
1976  * properly in order to generate valid QCVM code.
1977  *
1978  * Having destinations at a fixed position is more convenient. In QC
1979  * this is *mostly* OPC,  but FTE adds at least 2 instructions which
1980  * read from from OPA,  and store to OPB rather than OPC.   Which is
1981  * partially the reason why the implementation of these instructions
1982  * in darkplaces has been delayed for so long.
1983  *
1984  * Breaking conventions is annoying...
1985  */
1986 static bool ir_builder_gen_global(ir_builder *self, ir_value *global);
1987
1988 static bool gen_global_field(ir_value *global)
1989 {
1990     if (global->isconst)
1991     {
1992         ir_value *fld = global->constval.vpointer;
1993         if (!fld) {
1994             printf("Invalid field constant with no field: %s\n", global->name);
1995             return false;
1996         }
1997
1998         /* Now, in this case, a relocation would be impossible to code
1999          * since it looks like this:
2000          * .vector v = origin;     <- parse error, wtf is 'origin'?
2001          * .vector origin;
2002          *
2003          * But we will need a general relocation support later anyway
2004          * for functions... might as well support that here.
2005          */
2006         if (!fld->code.globaladdr) {
2007             printf("FIXME: Relocation support\n");
2008             return false;
2009         }
2010
2011         /* copy the field's value */
2012         global->code.globaladdr = code_globals_add(code_globals_data[fld->code.globaladdr]);
2013     }
2014     else
2015     {
2016         prog_section_field fld;
2017
2018         fld.name = global->code.name;
2019         fld.offset = code_fields_elements;
2020         fld.type = global->fieldtype;
2021
2022         if (fld.type == TYPE_VOID) {
2023             printf("Field is missing a type: %s\n", global->name);
2024             return false;
2025         }
2026
2027         if (code_fields_add(fld) < 0)
2028             return false;
2029
2030         global->code.globaladdr = code_globals_add(fld.offset);
2031     }
2032     if (global->code.globaladdr < 0)
2033         return false;
2034     return true;
2035 }
2036
2037 static bool gen_global_pointer(ir_value *global)
2038 {
2039     if (global->isconst)
2040     {
2041         ir_value *target = global->constval.vpointer;
2042         if (!target) {
2043             printf("Invalid pointer constant: %s\n", global->name);
2044             /* NULL pointers are pointing to the NULL constant, which also
2045              * sits at address 0, but still has an ir_value for itself.
2046              */
2047             return false;
2048         }
2049
2050         /* Here, relocations ARE possible - in fteqcc-enhanced-qc:
2051          * void() foo; <- proto
2052          * void() *fooptr = &foo;
2053          * void() foo = { code }
2054          */
2055         if (!target->code.globaladdr) {
2056             /* FIXME: Check for the constant nullptr ir_value!
2057              * because then code.globaladdr being 0 is valid.
2058              */
2059             printf("FIXME: Relocation support\n");
2060             return false;
2061         }
2062
2063         global->code.globaladdr = code_globals_add(target->code.globaladdr);
2064     }
2065     else
2066     {
2067         global->code.globaladdr = code_globals_add(0);
2068     }
2069     if (global->code.globaladdr < 0)
2070         return false;
2071     return true;
2072 }
2073
2074 static bool gen_blocks_recursive(ir_function *func, ir_block *block)
2075 {
2076     prog_section_statement stmt;
2077     ir_instr *instr;
2078     ir_block *target;
2079     ir_block *ontrue;
2080     ir_block *onfalse;
2081     size_t    stidx;
2082     size_t    i;
2083
2084 tailcall:
2085     block->generated = true;
2086     block->code_start = code_statements_elements;
2087     for (i = 0; i < block->instr_count; ++i)
2088     {
2089         instr = block->instr[i];
2090
2091         if (instr->opcode == VINSTR_PHI) {
2092             printf("cannot generate virtual instruction (phi)\n");
2093             return false;
2094         }
2095
2096         if (instr->opcode == VINSTR_JUMP) {
2097             target = instr->bops[0];
2098             /* for uncoditional jumps, if the target hasn't been generated
2099              * yet, we generate them right here.
2100              */
2101             if (!target->generated) {
2102                 block = target;
2103                 goto tailcall;
2104             }
2105
2106             /* otherwise we generate a jump instruction */
2107             stmt.opcode = INSTR_GOTO;
2108             stmt.o1.s1 = (target->code_start) - code_statements_elements;
2109             stmt.o2.s1 = 0;
2110             stmt.o3.s1 = 0;
2111             if (code_statements_add(stmt) < 0)
2112                 return false;
2113
2114             /* no further instructions can be in this block */
2115             return true;
2116         }
2117
2118         if (instr->opcode == VINSTR_COND) {
2119             ontrue  = instr->bops[0];
2120             onfalse = instr->bops[1];
2121             /* TODO: have the AST signal which block should
2122              * come first: eg. optimize IFs without ELSE...
2123              */
2124
2125             stmt.o1.u1 = instr->_ops[0]->code.globaladdr;
2126             stmt.o2.u1 = 0;
2127             stmt.o3.s1 = 0;
2128
2129             if (ontrue->generated) {
2130                 stmt.opcode = INSTR_IF;
2131                 stmt.o2.s1 = (ontrue->code_start-1) - code_statements_elements;
2132                 if (code_statements_add(stmt) < 0)
2133                     return false;
2134             }
2135             if (onfalse->generated) {
2136                 stmt.opcode = INSTR_IFNOT;
2137                 stmt.o2.s1 = (onfalse->code_start-1) - code_statements_elements;
2138                 if (code_statements_add(stmt) < 0)
2139                     return false;
2140             }
2141             if (!ontrue->generated) {
2142                 if (onfalse->generated) {
2143                     block = ontrue;
2144                     goto tailcall;
2145                 }
2146             }
2147             if (!onfalse->generated) {
2148                 if (ontrue->generated) {
2149                     block = onfalse;
2150                     goto tailcall;
2151                 }
2152             }
2153             /* neither ontrue nor onfalse exist */
2154             stmt.opcode = INSTR_IFNOT;
2155             stidx = code_statements_elements;
2156             if (code_statements_add(stmt) < 0)
2157                 return false;
2158             /* on false we jump, so add ontrue-path */
2159             if (!gen_blocks_recursive(func, ontrue))
2160                 return false;
2161             /* fixup the jump address */
2162             code_statements_data[stidx].o2.s1 = code_statements_elements - stidx;
2163             /* generate onfalse path */
2164             if (onfalse->generated) {
2165                 /* fixup the jump address */
2166                 code_statements_data[stidx].o2.s1 = (onfalse->code_start) - (stidx);
2167                 /* may have been generated in the previous recursive call */
2168                 stmt.opcode = INSTR_GOTO;
2169                 stmt.o1.s1 = (onfalse->code_start) - code_statements_elements;
2170                 stmt.o2.s1 = 0;
2171                 stmt.o3.s1 = 0;
2172                 return (code_statements_add(stmt) >= 0);
2173             }
2174             /* if not, generate now */
2175             block = onfalse;
2176             goto tailcall;
2177         }
2178
2179         if (instr->opcode >= INSTR_CALL0 && instr->opcode <= INSTR_CALL8) {
2180             /* Trivial call translation:
2181              * copy all params to OFS_PARM*
2182              * if the output's storetype is not store_return,
2183              * add append a STORE instruction!
2184              *
2185              * NOTES on how to do it better without much trouble:
2186              * -) The liferanges!
2187              *      Simply check the liferange of all parameters for
2188              *      other CALLs. For each param with no CALL in its
2189              *      liferange, we can store it in an OFS_PARM at
2190              *      generation already. This would even include later
2191              *      reuse.... probably... :)
2192              */
2193             size_t p;
2194             ir_value *retvalue;
2195
2196             for (p = 0; p < instr->params_count; ++p)
2197             {
2198                 ir_value *param = instr->params[p];
2199
2200                 stmt.opcode = INSTR_STORE_F;
2201                 stmt.o3.u1 = 0;
2202
2203                 stmt.opcode = type_store_instr[param->vtype];
2204                 stmt.o1.u1 = param->code.globaladdr;
2205                 stmt.o2.u1 = OFS_PARM0 + 3 * p;
2206                 if (code_statements_add(stmt) < 0)
2207                     return false;
2208             }
2209             stmt.opcode = INSTR_CALL0 + instr->params_count;
2210             if (stmt.opcode > INSTR_CALL8)
2211                 stmt.opcode = INSTR_CALL8;
2212             stmt.o1.u1 = instr->_ops[1]->code.globaladdr;
2213             stmt.o2.u1 = 0;
2214             stmt.o3.u1 = 0;
2215             if (code_statements_add(stmt) < 0)
2216                 return false;
2217
2218             retvalue = instr->_ops[0];
2219             if (retvalue && retvalue->store != store_return && retvalue->life_count)
2220             {
2221                 /* not to be kept in OFS_RETURN */
2222                 stmt.opcode = type_store_instr[retvalue->vtype];
2223                 stmt.o1.u1 = OFS_RETURN;
2224                 stmt.o2.u1 = retvalue->code.globaladdr;
2225                 stmt.o3.u1 = 0;
2226                 if (code_statements_add(stmt) < 0)
2227                     return false;
2228             }
2229             continue;
2230         }
2231
2232         if (instr->opcode == INSTR_STATE) {
2233             printf("TODO: state instruction\n");
2234             return false;
2235         }
2236
2237         stmt.opcode = instr->opcode;
2238         stmt.o1.u1 = 0;
2239         stmt.o2.u1 = 0;
2240         stmt.o3.u1 = 0;
2241
2242         /* This is the general order of operands */
2243         if (instr->_ops[0])
2244             stmt.o3.u1 = instr->_ops[0]->code.globaladdr;
2245
2246         if (instr->_ops[1])
2247             stmt.o1.u1 = instr->_ops[1]->code.globaladdr;
2248
2249         if (instr->_ops[2])
2250             stmt.o2.u1 = instr->_ops[2]->code.globaladdr;
2251
2252         if (stmt.opcode == INSTR_RETURN || stmt.opcode == INSTR_DONE)
2253         {
2254             stmt.o1.u1 = stmt.o3.u1;
2255             stmt.o3.u1 = 0;
2256         }
2257         else if ((stmt.opcode >= INSTR_STORE_F    &&
2258                   stmt.opcode <= INSTR_STORE_FNC)    ||
2259                  (stmt.opcode >= INSTR_NOT_F      &&
2260                   stmt.opcode <= INSTR_NOT_FNC))
2261         {
2262             /* 2-operand instructions with A -> B */
2263             stmt.o2.u1 = stmt.o3.u1;
2264             stmt.o3.u1 = 0;
2265         }
2266
2267         if (code_statements_add(stmt) < 0)
2268             return false;
2269     }
2270     return true;
2271 }
2272
2273 static bool gen_function_code(ir_function *self)
2274 {
2275     ir_block *block;
2276     prog_section_statement stmt;
2277
2278     /* Starting from entry point, we generate blocks "as they come"
2279      * for now. Dead blocks will not be translated obviously.
2280      */
2281     if (!self->blocks_count) {
2282         printf("Function '%s' declared without body.\n", self->name);
2283         return false;
2284     }
2285
2286     block = self->blocks[0];
2287     if (block->generated)
2288         return true;
2289
2290     if (!gen_blocks_recursive(self, block)) {
2291         printf("failed to generate blocks for '%s'\n", self->name);
2292         return false;
2293     }
2294
2295     /* otherwise code_write crashes since it debug-prints functions until AINSTR_END */
2296     stmt.opcode = AINSTR_END;
2297     stmt.o1.u1 = 0;
2298     stmt.o2.u1 = 0;
2299     stmt.o3.u1 = 0;
2300     if (code_statements_add(stmt) < 0)
2301         return false;
2302     return true;
2303 }
2304
2305 static bool gen_global_function(ir_builder *ir, ir_value *global)
2306 {
2307     prog_section_function fun;
2308     ir_function          *irfun;
2309
2310     size_t i;
2311     size_t local_var_end;
2312
2313     if (!global->isconst || (!global->constval.vfunc))
2314     {
2315         printf("Invalid state of function-global: not constant: %s\n", global->name);
2316         return false;
2317     }
2318
2319     irfun = global->constval.vfunc;
2320
2321     fun.name    = global->code.name;
2322     fun.file    = code_cachedstring(global->context.file);
2323     fun.profile = 0; /* always 0 */
2324     fun.nargs   = irfun->params_count;
2325
2326     for (i = 0;i < 8; ++i) {
2327         if (i >= fun.nargs)
2328             fun.argsize[i] = 0;
2329         else
2330             fun.argsize[i] = type_sizeof[irfun->params[i]];
2331     }
2332
2333     fun.firstlocal = code_globals_elements;
2334     fun.locals     = irfun->allocated_locals + irfun->locals_count;
2335
2336     local_var_end = 0;
2337     for (i = 0; i < irfun->locals_count; ++i) {
2338         if (!ir_builder_gen_global(ir, irfun->locals[i])) {
2339             printf("Failed to generate global %s\n", irfun->locals[i]->name);
2340             return false;
2341         }
2342     }
2343     if (irfun->locals_count) {
2344         ir_value *last = irfun->locals[irfun->locals_count-1];
2345         local_var_end = last->code.globaladdr;
2346         local_var_end += type_sizeof[last->vtype];
2347     }
2348     for (i = 0; i < irfun->values_count; ++i)
2349     {
2350         /* generate code.globaladdr for ssa values */
2351         ir_value *v = irfun->values[i];
2352         v->code.globaladdr = local_var_end + v->code.local;
2353     }
2354     for (i = 0; i < irfun->locals_count; ++i) {
2355         /* fill the locals with zeros */
2356         code_globals_add(0);
2357     }
2358
2359     if (irfun->builtin)
2360         fun.entry = irfun->builtin;
2361     else {
2362         fun.entry = code_statements_elements;
2363         if (!gen_function_code(irfun)) {
2364             printf("Failed to generate code for function %s\n", irfun->name);
2365             return false;
2366         }
2367     }
2368
2369     return (code_functions_add(fun) >= 0);
2370 }
2371
2372 static bool ir_builder_gen_global(ir_builder *self, ir_value *global)
2373 {
2374     size_t           i;
2375     int32_t         *iptr;
2376     prog_section_def def;
2377
2378     def.type   = global->vtype;
2379     def.offset = code_globals_elements;
2380     def.name   = global->code.name       = code_genstring(global->name);
2381
2382     switch (global->vtype)
2383     {
2384     case TYPE_POINTER:
2385         if (code_defs_add(def) < 0)
2386             return false;
2387         return gen_global_pointer(global);
2388     case TYPE_FIELD:
2389         if (code_defs_add(def) < 0)
2390             return false;
2391         return gen_global_field(global);
2392     case TYPE_ENTITY:
2393         /* fall through */
2394     case TYPE_FLOAT:
2395     {
2396         if (code_defs_add(def) < 0)
2397             return false;
2398
2399         if (global->isconst) {
2400             iptr = (int32_t*)&global->constval.vfloat;
2401             global->code.globaladdr = code_globals_add(*iptr);
2402         } else
2403             global->code.globaladdr = code_globals_add(0);
2404
2405         return global->code.globaladdr >= 0;
2406     }
2407     case TYPE_STRING:
2408     {
2409         if (code_defs_add(def) < 0)
2410             return false;
2411         if (global->isconst)
2412             global->code.globaladdr = code_globals_add(code_cachedstring(global->constval.vstring));
2413         else
2414             global->code.globaladdr = code_globals_add(0);
2415         return global->code.globaladdr >= 0;
2416     }
2417     case TYPE_VECTOR:
2418     {
2419         size_t d;
2420         if (code_defs_add(def) < 0)
2421             return false;
2422
2423         if (global->isconst) {
2424             iptr = (int32_t*)&global->constval.vvec;
2425             global->code.globaladdr = code_globals_add(iptr[0]);
2426             if (global->code.globaladdr < 0)
2427                 return false;
2428             for (d = 1; d < type_sizeof[global->vtype]; ++d)
2429             {
2430                 if (code_globals_add(iptr[d]) < 0)
2431                     return false;
2432             }
2433         } else {
2434             global->code.globaladdr = code_globals_add(0);
2435             if (global->code.globaladdr < 0)
2436                 return false;
2437             for (d = 1; d < type_sizeof[global->vtype]; ++d)
2438             {
2439                 if (code_globals_add(0) < 0)
2440                     return false;
2441             }
2442         }
2443         return global->code.globaladdr >= 0;
2444     }
2445     case TYPE_FUNCTION:
2446         if (code_defs_add(def) < 0)
2447             return false;
2448         global->code.globaladdr = code_globals_elements;
2449         code_globals_add(code_functions_elements);
2450         return gen_global_function(self, global);
2451     case TYPE_VARIANT:
2452         /* assume biggest type */
2453             global->code.globaladdr = code_globals_add(0);
2454             for (i = 1; i < type_sizeof[TYPE_VARIANT]; ++i)
2455                 code_globals_add(0);
2456             return true;
2457     default:
2458         /* refuse to create 'void' type or any other fancy business. */
2459         printf("Invalid type for global variable %s\n", global->name);
2460         return false;
2461     }
2462 }
2463
2464 bool ir_builder_generate(ir_builder *self, const char *filename)
2465 {
2466     size_t i;
2467
2468     code_init();
2469
2470     for (i = 0; i < self->globals_count; ++i)
2471     {
2472         if (!ir_builder_gen_global(self, self->globals[i])) {
2473             return false;
2474         }
2475     }
2476
2477     printf("writing '%s'...\n", filename);
2478     return code_write(filename);
2479 }
2480
2481 /***********************************************************************
2482  *IR DEBUG Dump functions...
2483  */
2484
2485 #define IND_BUFSZ 1024
2486
2487 const char *qc_opname(int op)
2488 {
2489     if (op < 0) return "<INVALID>";
2490     if (op < ( sizeof(asm_instr) / sizeof(asm_instr[0]) ))
2491         return asm_instr[op].m;
2492     switch (op) {
2493         case VINSTR_PHI:  return "PHI";
2494         case VINSTR_JUMP: return "JUMP";
2495         case VINSTR_COND: return "COND";
2496         default:          return "<UNK>";
2497     }
2498 }
2499
2500 void ir_builder_dump(ir_builder *b, int (*oprintf)(const char*, ...))
2501 {
2502         size_t i;
2503         char indent[IND_BUFSZ];
2504         indent[0] = '\t';
2505         indent[1] = 0;
2506
2507         oprintf("module %s\n", b->name);
2508         for (i = 0; i < b->globals_count; ++i)
2509         {
2510                 oprintf("global ");
2511                 if (b->globals[i]->isconst)
2512                         oprintf("%s = ", b->globals[i]->name);
2513                 ir_value_dump(b->globals[i], oprintf);
2514                 oprintf("\n");
2515         }
2516         for (i = 0; i < b->functions_count; ++i)
2517                 ir_function_dump(b->functions[i], indent, oprintf);
2518         oprintf("endmodule %s\n", b->name);
2519 }
2520
2521 void ir_function_dump(ir_function *f, char *ind,
2522                       int (*oprintf)(const char*, ...))
2523 {
2524         size_t i;
2525         if (f->builtin != 0) {
2526             oprintf("%sfunction %s = builtin %i\n", ind, f->name, -f->builtin);
2527             return;
2528         }
2529         oprintf("%sfunction %s\n", ind, f->name);
2530         strncat(ind, "\t", IND_BUFSZ);
2531         if (f->locals_count)
2532         {
2533                 oprintf("%s%i locals:\n", ind, (int)f->locals_count);
2534                 for (i = 0; i < f->locals_count; ++i) {
2535                         oprintf("%s\t", ind);
2536                         ir_value_dump(f->locals[i], oprintf);
2537                         oprintf("\n");
2538                 }
2539         }
2540         if (f->blocks_count)
2541         {
2542                 oprintf("%slife passes (check): %i\n", ind, (int)f->run_id);
2543                 for (i = 0; i < f->blocks_count; ++i) {
2544                     if (f->blocks[i]->run_id != f->run_id) {
2545                         oprintf("%slife pass check fail! %i != %i\n", ind, (int)f->blocks[i]->run_id, (int)f->run_id);
2546                     }
2547                         ir_block_dump(f->blocks[i], ind, oprintf);
2548                 }
2549
2550         }
2551         ind[strlen(ind)-1] = 0;
2552         oprintf("%sendfunction %s\n", ind, f->name);
2553 }
2554
2555 void ir_block_dump(ir_block* b, char *ind,
2556                    int (*oprintf)(const char*, ...))
2557 {
2558         size_t i;
2559         oprintf("%s:%s\n", ind, b->label);
2560         strncat(ind, "\t", IND_BUFSZ);
2561
2562         for (i = 0; i < b->instr_count; ++i)
2563                 ir_instr_dump(b->instr[i], ind, oprintf);
2564         ind[strlen(ind)-1] = 0;
2565 }
2566
2567 void dump_phi(ir_instr *in, char *ind,
2568               int (*oprintf)(const char*, ...))
2569 {
2570         size_t i;
2571         oprintf("%s <- phi ", in->_ops[0]->name);
2572         for (i = 0; i < in->phi_count; ++i)
2573         {
2574                 oprintf("([%s] : %s) ", in->phi[i].from->label,
2575                                         in->phi[i].value->name);
2576         }
2577         oprintf("\n");
2578 }
2579
2580 void ir_instr_dump(ir_instr *in, char *ind,
2581                        int (*oprintf)(const char*, ...))
2582 {
2583         size_t i;
2584         const char *comma = NULL;
2585
2586         oprintf("%s (%i) ", ind, (int)in->eid);
2587
2588         if (in->opcode == VINSTR_PHI) {
2589                 dump_phi(in, ind, oprintf);
2590                 return;
2591         }
2592
2593         strncat(ind, "\t", IND_BUFSZ);
2594
2595         if (in->_ops[0] && (in->_ops[1] || in->_ops[2])) {
2596                 ir_value_dump(in->_ops[0], oprintf);
2597                 if (in->_ops[1] || in->_ops[2])
2598                         oprintf(" <- ");
2599         }
2600         oprintf("%s\t", qc_opname(in->opcode));
2601         if (in->_ops[0] && !(in->_ops[1] || in->_ops[2])) {
2602                 ir_value_dump(in->_ops[0], oprintf);
2603                 comma = ",\t";
2604         }
2605         else
2606         {
2607                 for (i = 1; i != 3; ++i) {
2608                         if (in->_ops[i]) {
2609                                 if (comma)
2610                                         oprintf(comma);
2611                                 ir_value_dump(in->_ops[i], oprintf);
2612                                 comma = ",\t";
2613                         }
2614                 }
2615         }
2616         if (in->bops[0]) {
2617                 if (comma)
2618                         oprintf(comma);
2619                 oprintf("[%s]", in->bops[0]->label);
2620                 comma = ",\t";
2621         }
2622         if (in->bops[1])
2623                 oprintf("%s[%s]", comma, in->bops[1]->label);
2624         oprintf("\n");
2625         ind[strlen(ind)-1] = 0;
2626 }
2627
2628 void ir_value_dump(ir_value* v, int (*oprintf)(const char*, ...))
2629 {
2630         if (v->isconst) {
2631                 switch (v->vtype) {
2632                         case TYPE_VOID:
2633                                 oprintf("(void)");
2634                                 break;
2635                         case TYPE_FLOAT:
2636                                 oprintf("%g", v->constval.vfloat);
2637                                 break;
2638                         case TYPE_VECTOR:
2639                                 oprintf("'%g %g %g'",
2640                                         v->constval.vvec.x,
2641                                         v->constval.vvec.y,
2642                                         v->constval.vvec.z);
2643                                 break;
2644                         case TYPE_ENTITY:
2645                                 oprintf("(entity)");
2646                                 break;
2647                         case TYPE_STRING:
2648                                 oprintf("\"%s\"", v->constval.vstring);
2649                                 break;
2650 #if 0
2651                         case TYPE_INTEGER:
2652                                 oprintf("%i", v->constval.vint);
2653                                 break;
2654 #endif
2655                         case TYPE_POINTER:
2656                                 oprintf("&%s",
2657                                         v->constval.vpointer->name);
2658                                 break;
2659                 }
2660         } else {
2661                 oprintf("%s", v->name);
2662         }
2663 }
2664
2665 void ir_value_dump_life(ir_value *self, int (*oprintf)(const char*,...))
2666 {
2667         size_t i;
2668         oprintf("Life of %s:\n", self->name);
2669         for (i = 0; i < self->life_count; ++i)
2670         {
2671                 oprintf(" + [%i, %i]\n", self->life[i].start, self->life[i].end);
2672         }
2673 }