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