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