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