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