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