]> git.xonotic.org Git - xonotic/gmqcc.git/blob - ir.c
ast/ir support for unary instructions
[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_unary(ir_block *self,
1173                                 const char *label, int opcode,
1174                                 ir_value *operand)
1175 {
1176     int ot = TYPE_FLOAT;
1177     switch (opcode) {
1178         case INSTR_NOT_F:
1179         case INSTR_NOT_V:
1180         case INSTR_NOT_S:
1181         case INSTR_NOT_ENT:
1182         case INSTR_NOT_FNC:
1183 #if 0
1184         case INSTR_NOT_I:
1185 #endif
1186             ot = TYPE_FLOAT;
1187             break;
1188         /* QC doesn't have other unary operations. We expect extensions to fill
1189          * the above list, otherwise we assume out-type = in-type, eg for an
1190          * unary minus
1191          */
1192         default:
1193             ot = operand->vtype;
1194             break;
1195     };
1196     if (ot == TYPE_VOID) {
1197         /* The AST or parser were supposed to check this! */
1198         return NULL;
1199     }
1200
1201     /* let's use the general instruction creator and pass NULL for OPB */
1202     return ir_block_create_general_instr(self, label, opcode, operand, NULL, ot);
1203 }
1204
1205 ir_value* ir_block_create_general_instr(ir_block *self, const char *label,
1206                                         int op, ir_value *a, ir_value *b, int outype)
1207 {
1208     ir_instr *instr;
1209     ir_value *out;
1210
1211     out = ir_value_out(self->owner, label, store_value, outype);
1212     if (!out)
1213         return NULL;
1214
1215     instr = ir_instr_new(self, op);
1216     if (!instr) {
1217         ir_value_delete(out);
1218         return NULL;
1219     }
1220
1221     if (!ir_instr_op(instr, 0, out, true) ||
1222         !ir_instr_op(instr, 1, a, false) ||
1223         !ir_instr_op(instr, 2, b, false) )
1224     {
1225         goto on_error;
1226     }
1227
1228     if (!ir_block_instr_add(self, instr))
1229         goto on_error;
1230
1231     return out;
1232 on_error:
1233     ir_instr_delete(instr);
1234     ir_value_delete(out);
1235     return NULL;
1236 }
1237
1238 ir_value* ir_block_create_fieldaddress(ir_block *self, const char *label, ir_value *ent, ir_value *field)
1239 {
1240     /* Support for various pointer types todo if so desired */
1241     if (ent->vtype != TYPE_ENTITY)
1242         return NULL;
1243
1244     if (field->vtype != TYPE_FIELD)
1245         return NULL;
1246
1247     return ir_block_create_general_instr(self, label, INSTR_ADDRESS, ent, field, TYPE_POINTER);
1248 }
1249
1250 ir_value* ir_block_create_load_from_ent(ir_block *self, const char *label, ir_value *ent, ir_value *field, int outype)
1251 {
1252     int op;
1253     if (ent->vtype != TYPE_ENTITY)
1254         return NULL;
1255
1256     /* at some point we could redirect for TYPE_POINTER... but that could lead to carelessness */
1257     if (field->vtype != TYPE_FIELD)
1258         return NULL;
1259
1260     switch (outype)
1261     {
1262         case TYPE_FLOAT:   op = INSTR_LOAD_F;   break;
1263         case TYPE_VECTOR:  op = INSTR_LOAD_V;   break;
1264         case TYPE_STRING:  op = INSTR_LOAD_S;   break;
1265         case TYPE_FIELD:   op = INSTR_LOAD_FLD; break;
1266         case TYPE_ENTITY:  op = INSTR_LOAD_ENT; break;
1267 #if 0
1268         case TYPE_POINTER: op = INSTR_LOAD_I;   break;
1269         case TYPE_INTEGER: op = INSTR_LOAD_I;   break;
1270 #endif
1271         default:
1272             return NULL;
1273     }
1274
1275     return ir_block_create_general_instr(self, label, op, ent, field, outype);
1276 }
1277
1278 ir_value* ir_block_create_add(ir_block *self,
1279                               const char *label,
1280                               ir_value *left, ir_value *right)
1281 {
1282     int op = 0;
1283     int l = left->vtype;
1284     int r = right->vtype;
1285     if (l == r) {
1286         switch (l) {
1287             default:
1288                 return NULL;
1289             case TYPE_FLOAT:
1290                 op = INSTR_ADD_F;
1291                 break;
1292 #if 0
1293             case TYPE_INTEGER:
1294                 op = INSTR_ADD_I;
1295                 break;
1296 #endif
1297             case TYPE_VECTOR:
1298                 op = INSTR_ADD_V;
1299                 break;
1300         }
1301     } else {
1302 #if 0
1303         if ( (l == TYPE_FLOAT && r == TYPE_INTEGER) )
1304             op = INSTR_ADD_FI;
1305         else if ( (l == TYPE_INTEGER && r == TYPE_FLOAT) )
1306             op = INSTR_ADD_IF;
1307         else
1308 #endif
1309             return NULL;
1310     }
1311     return ir_block_create_binop(self, label, op, left, right);
1312 }
1313
1314 ir_value* ir_block_create_sub(ir_block *self,
1315                               const char *label,
1316                               ir_value *left, ir_value *right)
1317 {
1318     int op = 0;
1319     int l = left->vtype;
1320     int r = right->vtype;
1321     if (l == r) {
1322
1323         switch (l) {
1324             default:
1325                 return NULL;
1326             case TYPE_FLOAT:
1327                 op = INSTR_SUB_F;
1328                 break;
1329 #if 0
1330             case TYPE_INTEGER:
1331                 op = INSTR_SUB_I;
1332                 break;
1333 #endif
1334             case TYPE_VECTOR:
1335                 op = INSTR_SUB_V;
1336                 break;
1337         }
1338     } else {
1339 #if 0
1340         if ( (l == TYPE_FLOAT && r == TYPE_INTEGER) )
1341             op = INSTR_SUB_FI;
1342         else if ( (l == TYPE_INTEGER && r == TYPE_FLOAT) )
1343             op = INSTR_SUB_IF;
1344         else
1345 #endif
1346             return NULL;
1347     }
1348     return ir_block_create_binop(self, label, op, left, right);
1349 }
1350
1351 ir_value* ir_block_create_mul(ir_block *self,
1352                               const char *label,
1353                               ir_value *left, ir_value *right)
1354 {
1355     int op = 0;
1356     int l = left->vtype;
1357     int r = right->vtype;
1358     if (l == r) {
1359
1360         switch (l) {
1361             default:
1362                 return NULL;
1363             case TYPE_FLOAT:
1364                 op = INSTR_MUL_F;
1365                 break;
1366 #if 0
1367             case TYPE_INTEGER:
1368                 op = INSTR_MUL_I;
1369                 break;
1370 #endif
1371             case TYPE_VECTOR:
1372                 op = INSTR_MUL_V;
1373                 break;
1374         }
1375     } else {
1376         if ( (l == TYPE_VECTOR && r == TYPE_FLOAT) )
1377             op = INSTR_MUL_VF;
1378         else if ( (l == TYPE_FLOAT && r == TYPE_VECTOR) )
1379             op = INSTR_MUL_FV;
1380 #if 0
1381         else if ( (l == TYPE_VECTOR && r == TYPE_INTEGER) )
1382             op = INSTR_MUL_VI;
1383         else if ( (l == TYPE_INTEGER && r == TYPE_VECTOR) )
1384             op = INSTR_MUL_IV;
1385         else if ( (l == TYPE_FLOAT && r == TYPE_INTEGER) )
1386             op = INSTR_MUL_FI;
1387         else if ( (l == TYPE_INTEGER && r == TYPE_FLOAT) )
1388             op = INSTR_MUL_IF;
1389 #endif
1390         else
1391             return NULL;
1392     }
1393     return ir_block_create_binop(self, label, op, left, right);
1394 }
1395
1396 ir_value* ir_block_create_div(ir_block *self,
1397                               const char *label,
1398                               ir_value *left, ir_value *right)
1399 {
1400     int op = 0;
1401     int l = left->vtype;
1402     int r = right->vtype;
1403     if (l == r) {
1404
1405         switch (l) {
1406             default:
1407                 return NULL;
1408             case TYPE_FLOAT:
1409                 op = INSTR_DIV_F;
1410                 break;
1411 #if 0
1412             case TYPE_INTEGER:
1413                 op = INSTR_DIV_I;
1414                 break;
1415 #endif
1416         }
1417     } else {
1418 #if 0
1419         if ( (l == TYPE_VECTOR && r == TYPE_FLOAT) )
1420             op = INSTR_DIV_VF;
1421         else if ( (l == TYPE_FLOAT && r == TYPE_INTEGER) )
1422             op = INSTR_DIV_FI;
1423         else if ( (l == TYPE_INTEGER && r == TYPE_FLOAT) )
1424             op = INSTR_DIV_IF;
1425         else
1426 #endif
1427             return NULL;
1428     }
1429     return ir_block_create_binop(self, label, op, left, right);
1430 }
1431
1432 /* PHI resolving breaks the SSA, and must thus be the last
1433  * step before life-range calculation.
1434  */
1435
1436 static bool ir_block_naive_phi(ir_block *self);
1437 bool ir_function_naive_phi(ir_function *self)
1438 {
1439     size_t i;
1440
1441     for (i = 0; i < self->blocks_count; ++i)
1442     {
1443         if (!ir_block_naive_phi(self->blocks[i]))
1444             return false;
1445     }
1446     return true;
1447 }
1448
1449 static bool ir_naive_phi_emit_store(ir_block *block, size_t iid, ir_value *old, ir_value *what)
1450 {
1451     ir_instr *instr;
1452     size_t i;
1453
1454     /* create a store */
1455     if (!ir_block_create_store(block, old, what))
1456         return false;
1457
1458     /* we now move it up */
1459     instr = block->instr[block->instr_count-1];
1460     for (i = block->instr_count; i > iid; --i)
1461         block->instr[i] = block->instr[i-1];
1462     block->instr[i] = instr;
1463
1464     return true;
1465 }
1466
1467 static bool ir_block_naive_phi(ir_block *self)
1468 {
1469     size_t i, p, w;
1470     /* FIXME: optionally, create_phi can add the phis
1471      * to a list so we don't need to loop through blocks
1472      * - anyway: "don't optimize YET"
1473      */
1474     for (i = 0; i < self->instr_count; ++i)
1475     {
1476         ir_instr *instr = self->instr[i];
1477         if (instr->opcode != VINSTR_PHI)
1478             continue;
1479
1480         if (!ir_block_instr_remove(self, i))
1481             return false;
1482         --i; /* NOTE: i+1 below */
1483
1484         for (p = 0; p < instr->phi_count; ++p)
1485         {
1486             ir_value *v = instr->phi[p].value;
1487             for (w = 0; w < v->writes_count; ++w) {
1488                 ir_value *old;
1489
1490                 if (!v->writes[w]->_ops[0])
1491                     continue;
1492
1493                 /* When the write was to a global, we have to emit a mov */
1494                 old = v->writes[w]->_ops[0];
1495
1496                 /* The original instruction now writes to the PHI target local */
1497                 if (v->writes[w]->_ops[0] == v)
1498                     v->writes[w]->_ops[0] = instr->_ops[0];
1499
1500                 if (old->store != store_value && old->store != store_local && old->store != store_param)
1501                 {
1502                     /* If it originally wrote to a global we need to store the value
1503                      * there as welli
1504                      */
1505                     if (!ir_naive_phi_emit_store(self, i+1, old, v))
1506                         return false;
1507                     if (i+1 < self->instr_count)
1508                         instr = self->instr[i+1];
1509                     else
1510                         instr = NULL;
1511                     /* In case I forget and access instr later, it'll be NULL
1512                      * when it's a problem, to make sure we crash, rather than accessing
1513                      * invalid data.
1514                      */
1515                 }
1516                 else
1517                 {
1518                     /* If it didn't, we can replace all reads by the phi target now. */
1519                     size_t r;
1520                     for (r = 0; r < old->reads_count; ++r)
1521                     {
1522                         size_t op;
1523                         ir_instr *ri = old->reads[r];
1524                         for (op = 0; op < ri->phi_count; ++op) {
1525                             if (ri->phi[op].value == old)
1526                                 ri->phi[op].value = v;
1527                         }
1528                         for (op = 0; op < 3; ++op) {
1529                             if (ri->_ops[op] == old)
1530                                 ri->_ops[op] = v;
1531                         }
1532                     }
1533                 }
1534             }
1535         }
1536         ir_instr_delete(instr);
1537     }
1538     return true;
1539 }
1540
1541 /***********************************************************************
1542  *IR Temp allocation code
1543  * Propagating value life ranges by walking through the function backwards
1544  * until no more changes are made.
1545  * In theory this should happen once more than once for every nested loop
1546  * level.
1547  * Though this implementation might run an additional time for if nests.
1548  */
1549
1550 typedef struct
1551 {
1552     ir_value* *v;
1553     size_t    v_count;
1554     size_t    v_alloc;
1555 } new_reads_t;
1556 MEM_VEC_FUNCTIONS_ALL(new_reads_t, ir_value*, v)
1557
1558 /* Enumerate instructions used by value's life-ranges
1559  */
1560 static void ir_block_enumerate(ir_block *self, size_t *_eid)
1561 {
1562     size_t i;
1563     size_t eid = *_eid;
1564     for (i = 0; i < self->instr_count; ++i)
1565     {
1566         self->instr[i]->eid = eid++;
1567     }
1568     *_eid = eid;
1569 }
1570
1571 /* Enumerate blocks and instructions.
1572  * The block-enumeration is unordered!
1573  * We do not really use the block enumreation, however
1574  * the instruction enumeration is important for life-ranges.
1575  */
1576 void ir_function_enumerate(ir_function *self)
1577 {
1578     size_t i;
1579     size_t instruction_id = 0;
1580     for (i = 0; i < self->blocks_count; ++i)
1581     {
1582         self->blocks[i]->eid = i;
1583         self->blocks[i]->run_id = 0;
1584         ir_block_enumerate(self->blocks[i], &instruction_id);
1585     }
1586 }
1587
1588 static bool ir_block_life_propagate(ir_block *b, ir_block *prev, bool *changed);
1589 bool ir_function_calculate_liferanges(ir_function *self)
1590 {
1591     size_t i;
1592     bool changed;
1593
1594     do {
1595         self->run_id++;
1596         changed = false;
1597         for (i = 0; i != self->blocks_count; ++i)
1598         {
1599             if (self->blocks[i]->is_return)
1600             {
1601                 if (!ir_block_life_propagate(self->blocks[i], NULL, &changed))
1602                     return false;
1603             }
1604         }
1605     } while (changed);
1606     return true;
1607 }
1608
1609 /* Local-value allocator
1610  * After finishing creating the liferange of all values used in a function
1611  * we can allocate their global-positions.
1612  * This is the counterpart to register-allocation in register machines.
1613  */
1614 typedef struct {
1615     MEM_VECTOR_MAKE(ir_value*, locals);
1616     MEM_VECTOR_MAKE(size_t,    sizes);
1617     MEM_VECTOR_MAKE(size_t,    positions);
1618 } function_allocator;
1619 MEM_VEC_FUNCTIONS(function_allocator, ir_value*, locals)
1620 MEM_VEC_FUNCTIONS(function_allocator, size_t,    sizes)
1621 MEM_VEC_FUNCTIONS(function_allocator, size_t,    positions)
1622
1623 static bool function_allocator_alloc(function_allocator *alloc, const ir_value *var)
1624 {
1625     ir_value *slot;
1626     size_t vsize = type_sizeof[var->vtype];
1627
1628     slot = ir_value_var("reg", store_global, var->vtype);
1629     if (!slot)
1630         return false;
1631
1632     if (!ir_value_life_merge_into(slot, var))
1633         goto localerror;
1634
1635     if (!function_allocator_locals_add(alloc, slot))
1636         goto localerror;
1637
1638     if (!function_allocator_sizes_add(alloc, vsize))
1639         goto localerror;
1640
1641     return true;
1642
1643 localerror:
1644     ir_value_delete(slot);
1645     return false;
1646 }
1647
1648 bool ir_function_allocate_locals(ir_function *self)
1649 {
1650     size_t i, a;
1651     bool   retval = true;
1652     size_t pos;
1653
1654     ir_value *slot;
1655     const ir_value *v;
1656
1657     function_allocator alloc;
1658
1659     if (!self->locals_count)
1660         return true;
1661
1662     MEM_VECTOR_INIT(&alloc, locals);
1663     MEM_VECTOR_INIT(&alloc, sizes);
1664     MEM_VECTOR_INIT(&alloc, positions);
1665
1666     for (i = 0; i < self->locals_count; ++i)
1667     {
1668         if (!function_allocator_alloc(&alloc, self->locals[i]))
1669             goto error;
1670     }
1671
1672     /* Allocate a slot for any value that still exists */
1673     for (i = 0; i < self->values_count; ++i)
1674     {
1675         v = self->values[i];
1676
1677         if (!v->life_count)
1678             continue;
1679
1680         for (a = 0; a < alloc.locals_count; ++a)
1681         {
1682             slot = alloc.locals[a];
1683
1684             if (ir_values_overlap(v, slot))
1685                 continue;
1686
1687             if (!ir_value_life_merge_into(slot, v))
1688                 goto error;
1689
1690             /* adjust size for this slot */
1691             if (alloc.sizes[a] < type_sizeof[v->vtype])
1692                 alloc.sizes[a] = type_sizeof[v->vtype];
1693
1694             self->values[i]->code.local = a;
1695             break;
1696         }
1697         if (a >= alloc.locals_count) {
1698             self->values[i]->code.local = alloc.locals_count;
1699             if (!function_allocator_alloc(&alloc, v))
1700                 goto error;
1701         }
1702     }
1703
1704     /* Adjust slot positions based on sizes */
1705     if (!function_allocator_positions_add(&alloc, 0))
1706         goto error;
1707
1708     if (alloc.sizes_count)
1709         pos = alloc.positions[0] + alloc.sizes[0];
1710     else
1711         pos = 0;
1712     for (i = 1; i < alloc.sizes_count; ++i)
1713     {
1714         pos = alloc.positions[i-1] + alloc.sizes[i-1];
1715         if (!function_allocator_positions_add(&alloc, pos))
1716             goto error;
1717     }
1718
1719     self->allocated_locals = pos + alloc.sizes[alloc.sizes_count-1];
1720
1721     /* Take over the actual slot positions */
1722     for (i = 0; i < self->values_count; ++i)
1723         self->values[i]->code.local = alloc.positions[self->values[i]->code.local];
1724
1725     goto cleanup;
1726
1727 error:
1728     retval = false;
1729 cleanup:
1730     for (i = 0; i < alloc.locals_count; ++i)
1731         ir_value_delete(alloc.locals[i]);
1732     MEM_VECTOR_CLEAR(&alloc, locals);
1733     MEM_VECTOR_CLEAR(&alloc, sizes);
1734     MEM_VECTOR_CLEAR(&alloc, positions);
1735     return retval;
1736 }
1737
1738 /* Get information about which operand
1739  * is read from, or written to.
1740  */
1741 static void ir_op_read_write(int op, size_t *read, size_t *write)
1742 {
1743     switch (op)
1744     {
1745     case VINSTR_JUMP:
1746     case INSTR_GOTO:
1747         *write = 0;
1748         *read = 0;
1749         break;
1750     case INSTR_IF:
1751     case INSTR_IFNOT:
1752 #if 0
1753     case INSTR_IF_S:
1754     case INSTR_IFNOT_S:
1755 #endif
1756     case INSTR_RETURN:
1757     case VINSTR_COND:
1758         *write = 0;
1759         *read = 1;
1760         break;
1761     default:
1762         *write = 1;
1763         *read = 6;
1764         break;
1765     };
1766 }
1767
1768 static bool ir_block_living_add_instr(ir_block *self, size_t eid)
1769 {
1770     size_t i;
1771     bool changed = false;
1772     bool tempbool;
1773     for (i = 0; i != self->living_count; ++i)
1774     {
1775         tempbool = ir_value_life_merge(self->living[i], eid);
1776         /* debug
1777         if (tempbool)
1778             fprintf(stderr, "block_living_add_instr() value instruction added %s: %i\n", self->living[i]->_name, (int)eid);
1779         */
1780         changed = changed || tempbool;
1781     }
1782     return changed;
1783 }
1784
1785 static bool ir_block_life_prop_previous(ir_block* self, ir_block *prev, bool *changed)
1786 {
1787     size_t i;
1788     /* values which have been read in a previous iteration are now
1789      * in the "living" array even if the previous block doesn't use them.
1790      * So we have to remove whatever does not exist in the previous block.
1791      * They will be re-added on-read, but the liferange merge won't cause
1792      * a change.
1793      */
1794     for (i = 0; i < self->living_count; ++i)
1795     {
1796         if (!ir_block_living_find(prev, self->living[i], NULL)) {
1797             if (!ir_block_living_remove(self, i))
1798                 return false;
1799             --i;
1800         }
1801     }
1802
1803     /* Whatever the previous block still has in its living set
1804      * must now be added to ours as well.
1805      */
1806     for (i = 0; i < prev->living_count; ++i)
1807     {
1808         if (ir_block_living_find(self, prev->living[i], NULL))
1809             continue;
1810         if (!ir_block_living_add(self, prev->living[i]))
1811             return false;
1812         /*
1813         printf("%s got from prev: %s\n", self->label, prev->living[i]->_name);
1814         */
1815     }
1816     return true;
1817 }
1818
1819 static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *changed)
1820 {
1821     ir_instr *instr;
1822     ir_value *value;
1823     bool  tempbool;
1824     size_t i, o, p;
1825     /* bitmasks which operands are read from or written to */
1826     size_t read, write;
1827 #if defined(LIFE_RANGE_WITHOUT_LAST_READ)
1828     size_t rd;
1829     new_reads_t new_reads;
1830 #endif
1831     char dbg_ind[16] = { '#', '0' };
1832     (void)dbg_ind;
1833
1834 #if defined(LIFE_RANGE_WITHOUT_LAST_READ)
1835     MEM_VECTOR_INIT(&new_reads, v);
1836 #endif
1837
1838     if (prev)
1839     {
1840         if (!ir_block_life_prop_previous(self, prev, changed))
1841             return false;
1842     }
1843
1844     i = self->instr_count;
1845     while (i)
1846     { --i;
1847         instr = self->instr[i];
1848
1849         /* PHI operands are always read operands */
1850         for (p = 0; p < instr->phi_count; ++p)
1851         {
1852             value = instr->phi[p].value;
1853 #if ! defined(LIFE_RANGE_WITHOUT_LAST_READ)
1854             if (!ir_block_living_find(self, value, NULL) &&
1855                 !ir_block_living_add(self, value))
1856             {
1857                 goto on_error;
1858             }
1859 #else
1860             if (!new_reads_t_v_find(&new_reads, value, NULL))
1861             {
1862                 if (!new_reads_t_v_add(&new_reads, value))
1863                     goto on_error;
1864             }
1865 #endif
1866         }
1867
1868         /* See which operands are read and write operands */
1869         ir_op_read_write(instr->opcode, &read, &write);
1870
1871         /* Go through the 3 main operands */
1872         for (o = 0; o < 3; ++o)
1873         {
1874             if (!instr->_ops[o]) /* no such operand */
1875                 continue;
1876
1877             value = instr->_ops[o];
1878
1879             /* We only care about locals */
1880             /* we also calculate parameter liferanges so that locals
1881              * can take up parameter slots */
1882             if (value->store != store_value &&
1883                 value->store != store_local &&
1884                 value->store != store_param)
1885                 continue;
1886
1887             /* read operands */
1888             if (read & (1<<o))
1889             {
1890 #if ! defined(LIFE_RANGE_WITHOUT_LAST_READ)
1891                 if (!ir_block_living_find(self, value, NULL) &&
1892                     !ir_block_living_add(self, value))
1893                 {
1894                     goto on_error;
1895                 }
1896 #else
1897                 /* fprintf(stderr, "read: %s\n", value->_name); */
1898                 if (!new_reads_t_v_find(&new_reads, value, NULL))
1899                 {
1900                     if (!new_reads_t_v_add(&new_reads, value))
1901                         goto on_error;
1902                 }
1903 #endif
1904             }
1905
1906             /* write operands */
1907             /* When we write to a local, we consider it "dead" for the
1908              * remaining upper part of the function, since in SSA a value
1909              * can only be written once (== created)
1910              */
1911             if (write & (1<<o))
1912             {
1913                 size_t idx;
1914                 bool in_living = ir_block_living_find(self, value, &idx);
1915 #if defined(LIFE_RANGE_WITHOUT_LAST_READ)
1916                 size_t readidx;
1917                 bool in_reads = new_reads_t_v_find(&new_reads, value, &readidx);
1918                 if (!in_living && !in_reads)
1919 #else
1920                 if (!in_living)
1921 #endif
1922                 {
1923                     /* If the value isn't alive it hasn't been read before... */
1924                     /* TODO: See if the warning can be emitted during parsing or AST processing
1925                      * otherwise have warning printed here.
1926                      * IF printing a warning here: include filecontext_t,
1927                      * and make sure it's only printed once
1928                      * since this function is run multiple times.
1929                      */
1930                     /* For now: debug info: */
1931                     fprintf(stderr, "Value only written %s\n", value->name);
1932                     tempbool = ir_value_life_merge(value, instr->eid);
1933                     *changed = *changed || tempbool;
1934                     /*
1935                     ir_instr_dump(instr, dbg_ind, printf);
1936                     abort();
1937                     */
1938                 } else {
1939                     /* since 'living' won't contain it
1940                      * anymore, merge the value, since
1941                      * (A) doesn't.
1942                      */
1943                     tempbool = ir_value_life_merge(value, instr->eid);
1944                     /*
1945                     if (tempbool)
1946                         fprintf(stderr, "value added id %s %i\n", value->name, (int)instr->eid);
1947                     */
1948                     *changed = *changed || tempbool;
1949                     /* Then remove */
1950 #if ! defined(LIFE_RANGE_WITHOUT_LAST_READ)
1951                     if (!ir_block_living_remove(self, idx))
1952                         goto on_error;
1953 #else
1954                     if (in_reads)
1955                     {
1956                         if (!new_reads_t_v_remove(&new_reads, readidx))
1957                             goto on_error;
1958                     }
1959 #endif
1960                 }
1961             }
1962         }
1963         /* (A) */
1964         tempbool = ir_block_living_add_instr(self, instr->eid);
1965         /*fprintf(stderr, "living added values\n");*/
1966         *changed = *changed || tempbool;
1967
1968 #if defined(LIFE_RANGE_WITHOUT_LAST_READ)
1969         /* new reads: */
1970         for (rd = 0; rd < new_reads.v_count; ++rd)
1971         {
1972             if (!ir_block_living_find(self, new_reads.v[rd], NULL)) {
1973                 if (!ir_block_living_add(self, new_reads.v[rd]))
1974                     goto on_error;
1975             }
1976             if (!i && !self->entries_count) {
1977                 /* fix the top */
1978                 *changed = *changed || ir_value_life_merge(new_reads.v[rd], instr->eid);
1979             }
1980         }
1981         MEM_VECTOR_CLEAR(&new_reads, v);
1982 #endif
1983     }
1984
1985     if (self->run_id == self->owner->run_id)
1986         return true;
1987
1988     self->run_id = self->owner->run_id;
1989
1990     for (i = 0; i < self->entries_count; ++i)
1991     {
1992         ir_block *entry = self->entries[i];
1993         ir_block_life_propagate(entry, self, changed);
1994     }
1995
1996     return true;
1997 on_error:
1998 #if defined(LIFE_RANGE_WITHOUT_LAST_READ)
1999     MEM_VECTOR_CLEAR(&new_reads, v);
2000 #endif
2001     return false;
2002 }
2003
2004 /***********************************************************************
2005  *IR Code-Generation
2006  *
2007  * Since the IR has the convention of putting 'write' operands
2008  * at the beginning, we have to rotate the operands of instructions
2009  * properly in order to generate valid QCVM code.
2010  *
2011  * Having destinations at a fixed position is more convenient. In QC
2012  * this is *mostly* OPC,  but FTE adds at least 2 instructions which
2013  * read from from OPA,  and store to OPB rather than OPC.   Which is
2014  * partially the reason why the implementation of these instructions
2015  * in darkplaces has been delayed for so long.
2016  *
2017  * Breaking conventions is annoying...
2018  */
2019 static bool ir_builder_gen_global(ir_builder *self, ir_value *global);
2020
2021 static bool gen_global_field(ir_value *global)
2022 {
2023     if (global->isconst)
2024     {
2025         ir_value *fld = global->constval.vpointer;
2026         if (!fld) {
2027             printf("Invalid field constant with no field: %s\n", global->name);
2028             return false;
2029         }
2030
2031         /* Now, in this case, a relocation would be impossible to code
2032          * since it looks like this:
2033          * .vector v = origin;     <- parse error, wtf is 'origin'?
2034          * .vector origin;
2035          *
2036          * But we will need a general relocation support later anyway
2037          * for functions... might as well support that here.
2038          */
2039         if (!fld->code.globaladdr) {
2040             printf("FIXME: Relocation support\n");
2041             return false;
2042         }
2043
2044         /* copy the field's value */
2045         global->code.globaladdr = code_globals_add(code_globals_data[fld->code.globaladdr]);
2046     }
2047     else
2048     {
2049         prog_section_field fld;
2050
2051         fld.name = global->code.name;
2052         fld.offset = code_fields_elements;
2053         fld.type = global->fieldtype;
2054
2055         if (fld.type == TYPE_VOID) {
2056             printf("Field is missing a type: %s\n", global->name);
2057             return false;
2058         }
2059
2060         if (code_fields_add(fld) < 0)
2061             return false;
2062
2063         global->code.globaladdr = code_globals_add(fld.offset);
2064     }
2065     if (global->code.globaladdr < 0)
2066         return false;
2067     return true;
2068 }
2069
2070 static bool gen_global_pointer(ir_value *global)
2071 {
2072     if (global->isconst)
2073     {
2074         ir_value *target = global->constval.vpointer;
2075         if (!target) {
2076             printf("Invalid pointer constant: %s\n", global->name);
2077             /* NULL pointers are pointing to the NULL constant, which also
2078              * sits at address 0, but still has an ir_value for itself.
2079              */
2080             return false;
2081         }
2082
2083         /* Here, relocations ARE possible - in fteqcc-enhanced-qc:
2084          * void() foo; <- proto
2085          * void() *fooptr = &foo;
2086          * void() foo = { code }
2087          */
2088         if (!target->code.globaladdr) {
2089             /* FIXME: Check for the constant nullptr ir_value!
2090              * because then code.globaladdr being 0 is valid.
2091              */
2092             printf("FIXME: Relocation support\n");
2093             return false;
2094         }
2095
2096         global->code.globaladdr = code_globals_add(target->code.globaladdr);
2097     }
2098     else
2099     {
2100         global->code.globaladdr = code_globals_add(0);
2101     }
2102     if (global->code.globaladdr < 0)
2103         return false;
2104     return true;
2105 }
2106
2107 static bool gen_blocks_recursive(ir_function *func, ir_block *block)
2108 {
2109     prog_section_statement stmt;
2110     ir_instr *instr;
2111     ir_block *target;
2112     ir_block *ontrue;
2113     ir_block *onfalse;
2114     size_t    stidx;
2115     size_t    i;
2116
2117 tailcall:
2118     block->generated = true;
2119     block->code_start = code_statements_elements;
2120     for (i = 0; i < block->instr_count; ++i)
2121     {
2122         instr = block->instr[i];
2123
2124         if (instr->opcode == VINSTR_PHI) {
2125             printf("cannot generate virtual instruction (phi)\n");
2126             return false;
2127         }
2128
2129         if (instr->opcode == VINSTR_JUMP) {
2130             target = instr->bops[0];
2131             /* for uncoditional jumps, if the target hasn't been generated
2132              * yet, we generate them right here.
2133              */
2134             if (!target->generated) {
2135                 block = target;
2136                 goto tailcall;
2137             }
2138
2139             /* otherwise we generate a jump instruction */
2140             stmt.opcode = INSTR_GOTO;
2141             stmt.o1.s1 = (target->code_start) - code_statements_elements;
2142             stmt.o2.s1 = 0;
2143             stmt.o3.s1 = 0;
2144             if (code_statements_add(stmt) < 0)
2145                 return false;
2146
2147             /* no further instructions can be in this block */
2148             return true;
2149         }
2150
2151         if (instr->opcode == VINSTR_COND) {
2152             ontrue  = instr->bops[0];
2153             onfalse = instr->bops[1];
2154             /* TODO: have the AST signal which block should
2155              * come first: eg. optimize IFs without ELSE...
2156              */
2157
2158             stmt.o1.u1 = instr->_ops[0]->code.globaladdr;
2159             stmt.o2.u1 = 0;
2160             stmt.o3.s1 = 0;
2161
2162             if (ontrue->generated) {
2163                 stmt.opcode = INSTR_IF;
2164                 stmt.o2.s1 = (ontrue->code_start-1) - code_statements_elements;
2165                 if (code_statements_add(stmt) < 0)
2166                     return false;
2167             }
2168             if (onfalse->generated) {
2169                 stmt.opcode = INSTR_IFNOT;
2170                 stmt.o2.s1 = (onfalse->code_start-1) - code_statements_elements;
2171                 if (code_statements_add(stmt) < 0)
2172                     return false;
2173             }
2174             if (!ontrue->generated) {
2175                 if (onfalse->generated) {
2176                     block = ontrue;
2177                     goto tailcall;
2178                 }
2179             }
2180             if (!onfalse->generated) {
2181                 if (ontrue->generated) {
2182                     block = onfalse;
2183                     goto tailcall;
2184                 }
2185             }
2186             /* neither ontrue nor onfalse exist */
2187             stmt.opcode = INSTR_IFNOT;
2188             stidx = code_statements_elements;
2189             if (code_statements_add(stmt) < 0)
2190                 return false;
2191             /* on false we jump, so add ontrue-path */
2192             if (!gen_blocks_recursive(func, ontrue))
2193                 return false;
2194             /* fixup the jump address */
2195             code_statements_data[stidx].o2.s1 = code_statements_elements - stidx;
2196             /* generate onfalse path */
2197             if (onfalse->generated) {
2198                 /* fixup the jump address */
2199                 code_statements_data[stidx].o2.s1 = (onfalse->code_start) - (stidx);
2200                 /* may have been generated in the previous recursive call */
2201                 stmt.opcode = INSTR_GOTO;
2202                 stmt.o1.s1 = (onfalse->code_start) - code_statements_elements;
2203                 stmt.o2.s1 = 0;
2204                 stmt.o3.s1 = 0;
2205                 return (code_statements_add(stmt) >= 0);
2206             }
2207             /* if not, generate now */
2208             block = onfalse;
2209             goto tailcall;
2210         }
2211
2212         if (instr->opcode >= INSTR_CALL0 && instr->opcode <= INSTR_CALL8) {
2213             /* Trivial call translation:
2214              * copy all params to OFS_PARM*
2215              * if the output's storetype is not store_return,
2216              * add append a STORE instruction!
2217              *
2218              * NOTES on how to do it better without much trouble:
2219              * -) The liferanges!
2220              *      Simply check the liferange of all parameters for
2221              *      other CALLs. For each param with no CALL in its
2222              *      liferange, we can store it in an OFS_PARM at
2223              *      generation already. This would even include later
2224              *      reuse.... probably... :)
2225              */
2226             size_t p;
2227             ir_value *retvalue;
2228
2229             for (p = 0; p < instr->params_count; ++p)
2230             {
2231                 ir_value *param = instr->params[p];
2232
2233                 stmt.opcode = INSTR_STORE_F;
2234                 stmt.o3.u1 = 0;
2235
2236                 stmt.opcode = type_store_instr[param->vtype];
2237                 stmt.o1.u1 = param->code.globaladdr;
2238                 stmt.o2.u1 = OFS_PARM0 + 3 * p;
2239                 if (code_statements_add(stmt) < 0)
2240                     return false;
2241             }
2242             stmt.opcode = INSTR_CALL0 + instr->params_count;
2243             if (stmt.opcode > INSTR_CALL8)
2244                 stmt.opcode = INSTR_CALL8;
2245             stmt.o1.u1 = instr->_ops[1]->code.globaladdr;
2246             stmt.o2.u1 = 0;
2247             stmt.o3.u1 = 0;
2248             if (code_statements_add(stmt) < 0)
2249                 return false;
2250
2251             retvalue = instr->_ops[0];
2252             if (retvalue && retvalue->store != store_return && retvalue->life_count)
2253             {
2254                 /* not to be kept in OFS_RETURN */
2255                 stmt.opcode = type_store_instr[retvalue->vtype];
2256                 stmt.o1.u1 = OFS_RETURN;
2257                 stmt.o2.u1 = retvalue->code.globaladdr;
2258                 stmt.o3.u1 = 0;
2259                 if (code_statements_add(stmt) < 0)
2260                     return false;
2261             }
2262             continue;
2263         }
2264
2265         if (instr->opcode == INSTR_STATE) {
2266             printf("TODO: state instruction\n");
2267             return false;
2268         }
2269
2270         stmt.opcode = instr->opcode;
2271         stmt.o1.u1 = 0;
2272         stmt.o2.u1 = 0;
2273         stmt.o3.u1 = 0;
2274
2275         /* This is the general order of operands */
2276         if (instr->_ops[0])
2277             stmt.o3.u1 = instr->_ops[0]->code.globaladdr;
2278
2279         if (instr->_ops[1])
2280             stmt.o1.u1 = instr->_ops[1]->code.globaladdr;
2281
2282         if (instr->_ops[2])
2283             stmt.o2.u1 = instr->_ops[2]->code.globaladdr;
2284
2285         if (stmt.opcode == INSTR_RETURN || stmt.opcode == INSTR_DONE)
2286         {
2287             stmt.o1.u1 = stmt.o3.u1;
2288             stmt.o3.u1 = 0;
2289         }
2290         else if ((stmt.opcode >= INSTR_STORE_F    &&
2291                   stmt.opcode <= INSTR_STORE_FNC)    ||
2292                  (stmt.opcode >= INSTR_NOT_F      &&
2293                   stmt.opcode <= INSTR_NOT_FNC))
2294         {
2295             /* 2-operand instructions with A -> B */
2296             stmt.o2.u1 = stmt.o3.u1;
2297             stmt.o3.u1 = 0;
2298         }
2299
2300         if (code_statements_add(stmt) < 0)
2301             return false;
2302     }
2303     return true;
2304 }
2305
2306 static bool gen_function_code(ir_function *self)
2307 {
2308     ir_block *block;
2309     prog_section_statement stmt;
2310
2311     /* Starting from entry point, we generate blocks "as they come"
2312      * for now. Dead blocks will not be translated obviously.
2313      */
2314     if (!self->blocks_count) {
2315         printf("Function '%s' declared without body.\n", self->name);
2316         return false;
2317     }
2318
2319     block = self->blocks[0];
2320     if (block->generated)
2321         return true;
2322
2323     if (!gen_blocks_recursive(self, block)) {
2324         printf("failed to generate blocks for '%s'\n", self->name);
2325         return false;
2326     }
2327
2328     /* otherwise code_write crashes since it debug-prints functions until AINSTR_END */
2329     stmt.opcode = AINSTR_END;
2330     stmt.o1.u1 = 0;
2331     stmt.o2.u1 = 0;
2332     stmt.o3.u1 = 0;
2333     if (code_statements_add(stmt) < 0)
2334         return false;
2335     return true;
2336 }
2337
2338 static bool gen_global_function(ir_builder *ir, ir_value *global)
2339 {
2340     prog_section_function fun;
2341     ir_function          *irfun;
2342
2343     size_t i;
2344     size_t local_var_end;
2345
2346     if (!global->isconst || (!global->constval.vfunc))
2347     {
2348         printf("Invalid state of function-global: not constant: %s\n", global->name);
2349         return false;
2350     }
2351
2352     irfun = global->constval.vfunc;
2353
2354     fun.name    = global->code.name;
2355     fun.file    = code_cachedstring(global->context.file);
2356     fun.profile = 0; /* always 0 */
2357     fun.nargs   = irfun->params_count;
2358
2359     for (i = 0;i < 8; ++i) {
2360         if (i >= fun.nargs)
2361             fun.argsize[i] = 0;
2362         else
2363             fun.argsize[i] = type_sizeof[irfun->params[i]];
2364     }
2365
2366     fun.firstlocal = code_globals_elements;
2367     fun.locals     = irfun->allocated_locals + irfun->locals_count;
2368
2369     local_var_end = 0;
2370     for (i = 0; i < irfun->locals_count; ++i) {
2371         if (!ir_builder_gen_global(ir, irfun->locals[i])) {
2372             printf("Failed to generate global %s\n", irfun->locals[i]->name);
2373             return false;
2374         }
2375     }
2376     if (irfun->locals_count) {
2377         ir_value *last = irfun->locals[irfun->locals_count-1];
2378         local_var_end = last->code.globaladdr;
2379         local_var_end += type_sizeof[last->vtype];
2380     }
2381     for (i = 0; i < irfun->values_count; ++i)
2382     {
2383         /* generate code.globaladdr for ssa values */
2384         ir_value *v = irfun->values[i];
2385         v->code.globaladdr = local_var_end + v->code.local;
2386     }
2387     for (i = 0; i < irfun->locals_count; ++i) {
2388         /* fill the locals with zeros */
2389         code_globals_add(0);
2390     }
2391
2392     if (irfun->builtin)
2393         fun.entry = irfun->builtin;
2394     else {
2395         fun.entry = code_statements_elements;
2396         if (!gen_function_code(irfun)) {
2397             printf("Failed to generate code for function %s\n", irfun->name);
2398             return false;
2399         }
2400     }
2401
2402     return (code_functions_add(fun) >= 0);
2403 }
2404
2405 static bool ir_builder_gen_global(ir_builder *self, ir_value *global)
2406 {
2407     size_t           i;
2408     int32_t         *iptr;
2409     prog_section_def def;
2410
2411     def.type   = global->vtype;
2412     def.offset = code_globals_elements;
2413     def.name   = global->code.name       = code_genstring(global->name);
2414
2415     switch (global->vtype)
2416     {
2417     case TYPE_POINTER:
2418         if (code_defs_add(def) < 0)
2419             return false;
2420         return gen_global_pointer(global);
2421     case TYPE_FIELD:
2422         if (code_defs_add(def) < 0)
2423             return false;
2424         return gen_global_field(global);
2425     case TYPE_ENTITY:
2426         /* fall through */
2427     case TYPE_FLOAT:
2428     {
2429         if (code_defs_add(def) < 0)
2430             return false;
2431
2432         if (global->isconst) {
2433             iptr = (int32_t*)&global->constval.vfloat;
2434             global->code.globaladdr = code_globals_add(*iptr);
2435         } else
2436             global->code.globaladdr = code_globals_add(0);
2437
2438         return global->code.globaladdr >= 0;
2439     }
2440     case TYPE_STRING:
2441     {
2442         if (code_defs_add(def) < 0)
2443             return false;
2444         if (global->isconst)
2445             global->code.globaladdr = code_globals_add(code_cachedstring(global->constval.vstring));
2446         else
2447             global->code.globaladdr = code_globals_add(0);
2448         return global->code.globaladdr >= 0;
2449     }
2450     case TYPE_VECTOR:
2451     {
2452         size_t d;
2453         if (code_defs_add(def) < 0)
2454             return false;
2455
2456         if (global->isconst) {
2457             iptr = (int32_t*)&global->constval.vvec;
2458             global->code.globaladdr = code_globals_add(iptr[0]);
2459             if (global->code.globaladdr < 0)
2460                 return false;
2461             for (d = 1; d < type_sizeof[global->vtype]; ++d)
2462             {
2463                 if (code_globals_add(iptr[d]) < 0)
2464                     return false;
2465             }
2466         } else {
2467             global->code.globaladdr = code_globals_add(0);
2468             if (global->code.globaladdr < 0)
2469                 return false;
2470             for (d = 1; d < type_sizeof[global->vtype]; ++d)
2471             {
2472                 if (code_globals_add(0) < 0)
2473                     return false;
2474             }
2475         }
2476         return global->code.globaladdr >= 0;
2477     }
2478     case TYPE_FUNCTION:
2479         if (code_defs_add(def) < 0)
2480             return false;
2481         global->code.globaladdr = code_globals_elements;
2482         code_globals_add(code_functions_elements);
2483         return gen_global_function(self, global);
2484     case TYPE_VARIANT:
2485         /* assume biggest type */
2486             global->code.globaladdr = code_globals_add(0);
2487             for (i = 1; i < type_sizeof[TYPE_VARIANT]; ++i)
2488                 code_globals_add(0);
2489             return true;
2490     default:
2491         /* refuse to create 'void' type or any other fancy business. */
2492         printf("Invalid type for global variable %s\n", global->name);
2493         return false;
2494     }
2495 }
2496
2497 bool ir_builder_generate(ir_builder *self, const char *filename)
2498 {
2499     size_t i;
2500
2501     code_init();
2502
2503     for (i = 0; i < self->globals_count; ++i)
2504     {
2505         if (!ir_builder_gen_global(self, self->globals[i])) {
2506             return false;
2507         }
2508     }
2509
2510     printf("writing '%s'...\n", filename);
2511     return code_write(filename);
2512 }
2513
2514 /***********************************************************************
2515  *IR DEBUG Dump functions...
2516  */
2517
2518 #define IND_BUFSZ 1024
2519
2520 const char *qc_opname(int op)
2521 {
2522     if (op < 0) return "<INVALID>";
2523     if (op < ( sizeof(asm_instr) / sizeof(asm_instr[0]) ))
2524         return asm_instr[op].m;
2525     switch (op) {
2526         case VINSTR_PHI:  return "PHI";
2527         case VINSTR_JUMP: return "JUMP";
2528         case VINSTR_COND: return "COND";
2529         default:          return "<UNK>";
2530     }
2531 }
2532
2533 void ir_builder_dump(ir_builder *b, int (*oprintf)(const char*, ...))
2534 {
2535         size_t i;
2536         char indent[IND_BUFSZ];
2537         indent[0] = '\t';
2538         indent[1] = 0;
2539
2540         oprintf("module %s\n", b->name);
2541         for (i = 0; i < b->globals_count; ++i)
2542         {
2543                 oprintf("global ");
2544                 if (b->globals[i]->isconst)
2545                         oprintf("%s = ", b->globals[i]->name);
2546                 ir_value_dump(b->globals[i], oprintf);
2547                 oprintf("\n");
2548         }
2549         for (i = 0; i < b->functions_count; ++i)
2550                 ir_function_dump(b->functions[i], indent, oprintf);
2551         oprintf("endmodule %s\n", b->name);
2552 }
2553
2554 void ir_function_dump(ir_function *f, char *ind,
2555                       int (*oprintf)(const char*, ...))
2556 {
2557         size_t i;
2558         if (f->builtin != 0) {
2559             oprintf("%sfunction %s = builtin %i\n", ind, f->name, -f->builtin);
2560             return;
2561         }
2562         oprintf("%sfunction %s\n", ind, f->name);
2563         strncat(ind, "\t", IND_BUFSZ);
2564         if (f->locals_count)
2565         {
2566                 oprintf("%s%i locals:\n", ind, (int)f->locals_count);
2567                 for (i = 0; i < f->locals_count; ++i) {
2568                         oprintf("%s\t", ind);
2569                         ir_value_dump(f->locals[i], oprintf);
2570                         oprintf("\n");
2571                 }
2572         }
2573         if (f->blocks_count)
2574         {
2575                 oprintf("%slife passes (check): %i\n", ind, (int)f->run_id);
2576                 for (i = 0; i < f->blocks_count; ++i) {
2577                     if (f->blocks[i]->run_id != f->run_id) {
2578                         oprintf("%slife pass check fail! %i != %i\n", ind, (int)f->blocks[i]->run_id, (int)f->run_id);
2579                     }
2580                         ir_block_dump(f->blocks[i], ind, oprintf);
2581                 }
2582
2583         }
2584         ind[strlen(ind)-1] = 0;
2585         oprintf("%sendfunction %s\n", ind, f->name);
2586 }
2587
2588 void ir_block_dump(ir_block* b, char *ind,
2589                    int (*oprintf)(const char*, ...))
2590 {
2591         size_t i;
2592         oprintf("%s:%s\n", ind, b->label);
2593         strncat(ind, "\t", IND_BUFSZ);
2594
2595         for (i = 0; i < b->instr_count; ++i)
2596                 ir_instr_dump(b->instr[i], ind, oprintf);
2597         ind[strlen(ind)-1] = 0;
2598 }
2599
2600 void dump_phi(ir_instr *in, char *ind,
2601               int (*oprintf)(const char*, ...))
2602 {
2603         size_t i;
2604         oprintf("%s <- phi ", in->_ops[0]->name);
2605         for (i = 0; i < in->phi_count; ++i)
2606         {
2607                 oprintf("([%s] : %s) ", in->phi[i].from->label,
2608                                         in->phi[i].value->name);
2609         }
2610         oprintf("\n");
2611 }
2612
2613 void ir_instr_dump(ir_instr *in, char *ind,
2614                        int (*oprintf)(const char*, ...))
2615 {
2616         size_t i;
2617         const char *comma = NULL;
2618
2619         oprintf("%s (%i) ", ind, (int)in->eid);
2620
2621         if (in->opcode == VINSTR_PHI) {
2622                 dump_phi(in, ind, oprintf);
2623                 return;
2624         }
2625
2626         strncat(ind, "\t", IND_BUFSZ);
2627
2628         if (in->_ops[0] && (in->_ops[1] || in->_ops[2])) {
2629                 ir_value_dump(in->_ops[0], oprintf);
2630                 if (in->_ops[1] || in->_ops[2])
2631                         oprintf(" <- ");
2632         }
2633         oprintf("%s\t", qc_opname(in->opcode));
2634         if (in->_ops[0] && !(in->_ops[1] || in->_ops[2])) {
2635                 ir_value_dump(in->_ops[0], oprintf);
2636                 comma = ",\t";
2637         }
2638         else
2639         {
2640                 for (i = 1; i != 3; ++i) {
2641                         if (in->_ops[i]) {
2642                                 if (comma)
2643                                         oprintf(comma);
2644                                 ir_value_dump(in->_ops[i], oprintf);
2645                                 comma = ",\t";
2646                         }
2647                 }
2648         }
2649         if (in->bops[0]) {
2650                 if (comma)
2651                         oprintf(comma);
2652                 oprintf("[%s]", in->bops[0]->label);
2653                 comma = ",\t";
2654         }
2655         if (in->bops[1])
2656                 oprintf("%s[%s]", comma, in->bops[1]->label);
2657         oprintf("\n");
2658         ind[strlen(ind)-1] = 0;
2659 }
2660
2661 void ir_value_dump(ir_value* v, int (*oprintf)(const char*, ...))
2662 {
2663         if (v->isconst) {
2664                 switch (v->vtype) {
2665                         case TYPE_VOID:
2666                                 oprintf("(void)");
2667                                 break;
2668                         case TYPE_FLOAT:
2669                                 oprintf("%g", v->constval.vfloat);
2670                                 break;
2671                         case TYPE_VECTOR:
2672                                 oprintf("'%g %g %g'",
2673                                         v->constval.vvec.x,
2674                                         v->constval.vvec.y,
2675                                         v->constval.vvec.z);
2676                                 break;
2677                         case TYPE_ENTITY:
2678                                 oprintf("(entity)");
2679                                 break;
2680                         case TYPE_STRING:
2681                                 oprintf("\"%s\"", v->constval.vstring);
2682                                 break;
2683 #if 0
2684                         case TYPE_INTEGER:
2685                                 oprintf("%i", v->constval.vint);
2686                                 break;
2687 #endif
2688                         case TYPE_POINTER:
2689                                 oprintf("&%s",
2690                                         v->constval.vpointer->name);
2691                                 break;
2692                 }
2693         } else {
2694                 oprintf("%s", v->name);
2695         }
2696 }
2697
2698 void ir_value_dump_life(ir_value *self, int (*oprintf)(const char*,...))
2699 {
2700         size_t i;
2701         oprintf("Life of %s:\n", self->name);
2702         for (i = 0; i < self->life_count; ++i)
2703         {
2704                 oprintf(" + [%i, %i]\n", self->life[i].start, self->life[i].end);
2705         }
2706 }