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