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