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