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