make testapp deterministic
[libfirm] / ir / be / ia32 / ia32_gen_decls.c
1 /**
2  * Dumps global variables and constants as ia32 assembler.
3  * @author Christian Wuerdig
4  * @date 04.11.2005
5  * @version $Id$
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include <stdlib.h>
13 #include <string.h>
14 #include <ctype.h>
15 #include <assert.h>
16
17 #include "obst.h"
18 #include "tv.h"
19 #include "irnode.h"
20 #include "entity.h"
21 #include "irprog.h"
22 #include "error.h"
23
24 #include "../be.h"
25
26 #include "ia32_emitter.h"
27 #include "ia32_gen_decls.h"
28
29 typedef struct obstack obstack_t;
30
31 typedef struct _ia32_decl_env {
32         obstack_t *rodata_obst;
33         obstack_t *data_obst;
34         obstack_t *bss_obst;
35         obstack_t *ctor_obst;
36         const be_main_env_t *main_env;
37 } ia32_decl_env_t;
38
39 /************************************************************************/
40
41 /**
42  * output a tarval
43  */
44 static void dump_arith_tarval(obstack_t *obst, tarval *tv, int bytes)
45 {
46         switch (bytes) {
47
48         case 1:
49                 obstack_printf(obst, "0x%02x", get_tarval_sub_bits(tv, 0));
50                 break;
51
52         case 2:
53                 obstack_printf(obst, "0x%02x%02x", get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
54                 break;
55
56         case 4:
57                 obstack_printf(obst, "0x%02x%02x%02x%02x",
58                         get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
59                 break;
60
61         case 8:
62                 obstack_printf(obst, "0x%02x%02x%02x%02x%02x%02x%02x%02x",
63                         get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6), get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4),
64                         get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
65                 break;
66
67         case 10:
68         case 12:
69                 break;
70
71         default:
72                 fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
73                 assert(0);
74         }
75 }
76
77 /**
78  * Return the tarval of an atomic initializer.
79  */
80 static tarval *get_atomic_init_tv(ir_node *init)
81 {
82         for (;;) {
83                 ir_mode *mode = get_irn_mode(init);
84
85                 switch (get_irn_opcode(init)) {
86
87                 case iro_Cast:
88                         init = get_Cast_op(init);
89                         continue;
90
91                 case iro_Conv:
92                         init = get_Conv_op(init);
93                         continue;
94
95                 case iro_Const:
96                         return get_Const_tarval(init);
97
98                 case iro_SymConst:
99                         switch (get_SymConst_kind(init)) {
100                         case symconst_ofs_ent:
101                                 return new_tarval_from_long(get_entity_offset(get_SymConst_entity(init)), mode);
102
103                         case symconst_type_size:
104                                 return new_tarval_from_long(get_type_size_bytes(get_SymConst_type(init)), mode);
105
106                         case symconst_type_align:
107                                 return new_tarval_from_long(get_type_alignment_bytes(get_SymConst_type(init)), mode);
108
109                         case symconst_enum_const:
110                                 return get_enumeration_value(get_SymConst_enum(init));
111
112                         default:
113                                 return NULL;
114                         }
115
116                 default:
117                         return NULL;
118                 }
119         }
120 }
121
122 /**
123  * dump an atomic value
124  */
125 static void do_dump_atomic_init(obstack_t *obst, ir_node *init)
126 {
127         ir_mode *mode = get_irn_mode(init);
128         int bytes     = get_mode_size_bytes(mode);
129         tarval *tv;
130
131         switch (get_irn_opcode(init)) {
132
133         case iro_Cast:
134                 do_dump_atomic_init(obst, get_Cast_op(init));
135                 return;
136
137         case iro_Conv:
138                 do_dump_atomic_init(obst, get_Conv_op(init));
139                 return;
140
141         case iro_Const:
142                 tv = get_Const_tarval(init);
143
144                 /* it's a arithmetic value */
145                 dump_arith_tarval(obst, tv, bytes);
146                 return;
147
148         case iro_SymConst:
149                 switch (get_SymConst_kind(init)) {
150                 case symconst_addr_name:
151                         obstack_printf(obst, "%s", get_id_str(get_SymConst_name(init)));
152                         break;
153
154                 case symconst_addr_ent:
155                         obstack_printf(obst, "%s", get_entity_ld_name(get_SymConst_entity(init)));
156                         break;
157
158                 case symconst_ofs_ent:
159                         obstack_printf(obst, "%d", get_entity_offset(get_SymConst_entity(init)));
160                         break;
161
162                 case symconst_type_size:
163                         obstack_printf(obst, "%d", get_type_size_bytes(get_SymConst_type(init)));
164                         break;
165
166                 case symconst_type_align:
167                         obstack_printf(obst, "%d", get_type_alignment_bytes(get_SymConst_type(init)));
168                         break;
169
170                 case symconst_enum_const:
171                         tv = get_enumeration_value(get_SymConst_enum(init));
172                         dump_arith_tarval(obst, tv, bytes);
173                         break;
174
175                 default:
176                         assert(!"dump_atomic_init(): don't know how to init from this SymConst");
177                 }
178                 return;
179
180                 case iro_Add:
181                         do_dump_atomic_init(obst, get_Add_left(init));
182                         obstack_printf(obst, " + ");
183                         do_dump_atomic_init(obst, get_Add_right(init));
184                         return;
185
186                 case iro_Sub:
187                         do_dump_atomic_init(obst, get_Sub_left(init));
188                         obstack_printf(obst, " - ");
189                         do_dump_atomic_init(obst, get_Sub_right(init));
190                         return;
191
192                 case iro_Mul:
193                         do_dump_atomic_init(obst, get_Mul_left(init));
194                         obstack_printf(obst, " * ");
195                         do_dump_atomic_init(obst, get_Mul_right(init));
196                         return;
197
198                 default:
199                         assert(0 && "dump_atomic_init(): unknown IR-node");
200         }
201 }
202
203 /**
204  * dumps the type for given size (.byte, .long, ...)
205  */
206 static void dump_size_type(obstack_t *obst, int size) {
207         switch (size) {
208
209         case 1:
210                 obstack_printf(obst, "\t.byte\t");
211                 break;
212
213         case 2:
214                 obstack_printf(obst, "\t.value\t");
215                 break;
216
217         case 4:
218                 obstack_printf(obst, "\t.long\t");
219                 break;
220
221         case 8:
222                 obstack_printf(obst, "\t.quad\t");
223                 break;
224
225         case 10:
226         case 12:
227                 /* handled in arith */
228                 break;
229
230         default:
231                 fprintf(stderr, "Try to dump a type with %d bytes\n", size);
232                 assert(0);
233         }
234 }
235
236 /**
237  * dump an atomic value to an obstack
238  */
239 static void dump_atomic_init(obstack_t *obst, ir_node *init)
240 {
241         ir_mode *mode = get_irn_mode(init);
242         int bytes     = get_mode_size_bytes(mode);
243
244         dump_size_type(obst, bytes);
245         do_dump_atomic_init(obst, init);
246         obstack_printf(obst, "\n");
247 }
248
249 /************************************************************************/
250 /* Routines to dump global variables                                    */
251 /************************************************************************/
252
253 /**
254  * Determine if an entity is a string constant
255  * @param ent The entity
256  * @return 1 if it is a string constant, 0 otherwise
257  */
258 static int ent_is_string_const(ir_entity *ent)
259 {
260         ir_type *type, *element_type;
261         ir_mode *mode;
262         int i, c, n;
263
264         type = get_entity_type(ent);
265
266         /* if it's an array */
267         if (!is_Array_type(type))
268                 return 0;
269
270         element_type = get_array_element_type(type);
271
272         /* and the array's element type is primitive */
273         if (!is_Primitive_type(element_type))
274                 return 0;
275
276         /* and the mode of the element type is an int of
277          * the same size as the byte mode */
278         mode = get_type_mode(element_type);
279         if (!mode_is_int(mode)
280                 || get_mode_size_bits(mode) != get_mode_size_bits(mode_Bs))
281                 return 0;
282
283         /* if it contains only printable chars and a 0 at the end */
284         n = get_compound_ent_n_values(ent);
285         for (i = 0; i < n; ++i) {
286                 ir_node *irn = get_compound_ent_value(ent, i);
287                 if(get_irn_opcode(irn) != iro_Const)
288                         return 0;
289
290                 c = (int) get_tarval_long(get_Const_tarval(irn));
291
292                 if((i < n - 1 && !(isgraph(c) || isspace(c)))
293                                 || (i == n - 1 && c != '\0'))
294                         return 0;
295         }
296
297         /* then we can emit it as a string constant */
298         return 1;
299 }
300
301 /**
302  * Dump a string constant.
303  * No checks are made!!
304  * @param obst The obst to dump on.
305  * @param ent The entity to dump.
306  */
307 static void dump_string_cst(obstack_t *obst, ir_entity *ent)
308 {
309         int i, n;
310
311         obstack_printf(obst, "\t.string \"");
312         n = get_compound_ent_n_values(ent);
313
314         for (i = 0; i < n-1; ++i) {
315                 ir_node *irn;
316                 int c;
317
318                 irn = get_compound_ent_value(ent, i);
319                 c = (int) get_tarval_long(get_Const_tarval(irn));
320
321                 switch (c) {
322                 case '"' : obstack_printf(obst, "\\\""); break;
323                 case '\n': obstack_printf(obst, "\\n"); break;
324                 case '\r': obstack_printf(obst, "\\r"); break;
325                 case '\t': obstack_printf(obst, "\\t"); break;
326                 case '\\': obstack_printf(obst, "\\\\"); break;
327                 default  :
328                         if (isprint(c))
329                                 obstack_printf(obst, "%c", c);
330                         else
331                                 obstack_printf(obst, "\\%o", c);
332                         break;
333                 }
334         }
335         obstack_printf(obst, "\"\n");
336 }
337
338 static void dump_array_init(obstack_t *obst, ir_entity *ent)
339 {
340         const ir_type *ty = get_entity_type(ent);
341         int i;
342         int filler;
343         int size = 0;
344
345         /* potential spare values should be already included! */
346         for (i = 0; i < get_compound_ent_n_values(ent); ++i) {
347                 ir_entity *step = get_compound_ent_value_member(ent, i);
348                 ir_type *stype = get_entity_type(step);
349
350                 if (get_type_mode(stype)) {
351                         int align = (get_type_alignment_bits(stype) + 7) >> 3;
352                         int n     = size % align;
353
354                         if (n > 0) {
355                                 obstack_printf(obst, "\t.zero\t%d\n", align - n);
356                                 size += align - n;
357                         }
358                 }
359                 dump_atomic_init(obst, get_compound_ent_value(ent, i));
360                 size += get_type_size_bytes(stype);
361         }
362         filler = get_type_size_bytes(ty) - size;
363
364         if (filler > 0)
365                 obstack_printf(obst, "\t.skip\t%d\n", filler);
366 }
367
368 enum normal_or_bitfield_kind {
369         NORMAL = 0,
370         BITFIELD
371 };
372
373 typedef struct {
374         enum normal_or_bitfield_kind kind;
375         union {
376                 ir_node *value;
377                 unsigned char bf_val;
378         } v;
379 } normal_or_bitfield;
380
381 /**
382  * Dump an initializer for a compound entity.
383  */
384 static void dump_compound_init(obstack_t *obst, ir_entity *ent)
385 {
386         normal_or_bitfield *vals;
387         int i, j, n = get_compound_ent_n_values(ent);
388         int last_ofs;
389
390         /* Find the initializer size. Sorrily gcc support a nasty feature:
391            The last field of a compound may be a flexible array. This allows
392            initializers bigger than the type size. */
393         last_ofs = 0;
394         for (i = 0; i < n; ++i) {
395                 int offset = get_compound_ent_value_offset_bytes(ent, i);
396                 int bits_remainder = get_compound_ent_value_offset_bit_remainder(ent, i);
397                 const compound_graph_path *path = get_compound_ent_value_path(ent, i);
398                 int path_len = get_compound_graph_path_length(path);
399                 ir_entity *last_ent = get_compound_graph_path_node(path, path_len - 1);
400                 int value_len = get_type_size_bits(get_entity_type(last_ent));
401
402                 offset += (value_len + bits_remainder + 7) >> 3;
403
404                 if (offset > last_ofs) {
405                         last_ofs = offset;
406                 }
407         }
408
409         /*
410          * In the worst case, every initializer allocates one byte.
411          * Moreover, initializer might be big, do not allocate an stack.
412          */
413         vals = xcalloc(last_ofs, sizeof(vals[0]));
414
415         /* collect the values and store them at the offsets */
416         for (i = 0; i < n; ++i) {
417                 const compound_graph_path *path = get_compound_ent_value_path(ent, i);
418                 int path_len = get_compound_graph_path_length(path);
419                 int offset = get_compound_ent_value_offset_bytes(ent, i);
420                 int offset_bits = get_compound_ent_value_offset_bit_remainder(ent, i);
421                 ir_node *value = get_compound_ent_value(ent, i);
422                 ir_entity *last_ent = get_compound_graph_path_node(path, path_len - 1);
423                 int value_len = get_type_size_bits(get_entity_type(last_ent));
424                 assert(offset >= 0);
425                 assert(offset_bits >= 0);
426
427                 if (offset_bits != 0 ||
428                         (value_len != 8 && value_len != 16 && value_len != 32 && value_len != 64)) {
429                         tarval *shift, *shifted;
430                         tarval *tv = get_atomic_init_tv(value);
431                         if (tv == NULL) {
432                                 panic("Couldn't get numeric value for bitfield initializer '%s'\n",
433                                       get_entity_ld_name(ent));
434                         }
435                         tv = tarval_convert_to(tv, mode_Lu);
436                         shift = new_tarval_from_long(offset_bits, mode_Is);
437                         shifted = tarval_shl(tv, shift);
438                         if (shifted == tarval_bad || shifted == tarval_undefined) {
439                                 panic("Couldn't shift numeric value for bitfield initializer '%s'\n",
440                                       get_entity_ld_name(ent));
441                         }
442
443                         for (j = 0; value_len > 0; ++j) {
444                                 assert(offset + j < last_ofs);
445                                 assert(vals[offset + j].kind == BITFIELD || vals[offset + j].v.value == NULL);
446                                 vals[offset + j].kind = BITFIELD;
447                                 vals[offset + j].v.bf_val |= get_tarval_sub_bits(shifted, j);
448                                 value_len -= 8 - offset_bits;
449                                 offset_bits = 0;
450                         }
451                 } else {
452                         assert(offset < last_ofs);
453                         assert(vals[offset].kind == NORMAL);
454                         assert(vals[offset].v.value == NULL);
455                         vals[offset].v.value = value;
456                 }
457         }
458
459         /* now write them sorted */
460         for (i = 0; i < last_ofs; ) {
461                 int space = 0, skip = 0;
462                 if (vals[i].kind == NORMAL) {
463                         if(vals[i].v.value != NULL) {
464                                 dump_atomic_init(obst, vals[i].v.value);
465                                 skip = get_mode_size_bytes(get_irn_mode(vals[i].v.value)) - 1;
466                         } else {
467                                 space = 1;
468                         }
469                 } else {
470                         assert(vals[i].kind == BITFIELD);
471                         obstack_printf(obst, "\t.byte\t%d\n", vals[i].v.bf_val);
472                 }
473
474                 ++i;
475                 space = 0;
476                 while (i < last_ofs && vals[i].kind == NORMAL && vals[i].v.value == NULL) {
477                         ++space;
478                         ++i;
479                 }
480                 space -= skip;
481                 assert(space >= 0);
482
483                 /* a gap */
484                 if (space > 0)
485                         obstack_printf(obst, "\t.skip\t%d\n", space);
486         }
487         xfree(vals);
488 }
489
490 /**
491  * Dump a global entity.
492  */
493 static void dump_global(ia32_decl_env_t *env, ir_entity *ent)
494 {
495         obstack_t *obst;
496         ir_type *type = get_entity_type(ent);
497         const char *ld_name = get_entity_ld_name(ent);
498         ir_variability variability = get_entity_variability(ent);
499         ir_visibility visibility = get_entity_visibility(ent);
500         int align = get_type_alignment_bytes(type);
501
502         obst = env->data_obst;
503         if (is_Method_type(type)) {
504                 if (get_method_img_section(ent) == section_constructors) {
505                         obst = env->ctor_obst;
506                         obstack_printf(obst, ".balign\t%d\n", align);
507                         dump_size_type(obst, align);
508                         obstack_printf(obst, "%s\n", ld_name);
509                 }
510                 return;
511         } else if (variability == variability_constant) {
512                 /* a constant entity, put it on the rdata */
513                 obst = env->rodata_obst;
514         } else if (variability == variability_uninitialized) {
515                 /* uninitialized entity put it in bss segment */
516                 obst = env->bss_obst;
517         }
518
519         be_dbg_variable(env->main_env->db_handle, obst, ent);
520
521         /* global or not global */
522         if(visibility == visibility_external_visible) {
523                 obstack_printf(obst, ".global\t%s\n", ld_name);
524         } else if(visibility == visibility_external_allocated) {
525                 obstack_printf(obst, ".global\t%s\n", ld_name);
526                 /* we can return now... */
527                 return;
528         }
529         /* alignment */
530         if(align > 1) {
531                 obstack_printf(obst, ".balign\t%d\n", align);
532         }
533
534         obstack_printf(obst, "%s:\n", ld_name);
535
536         if (variability == variability_uninitialized) {
537                 obstack_printf(obst, "\t.zero %d\n", get_type_size_bytes(type));
538         } else if (is_atomic_type(type)) {
539                 dump_atomic_init(obst, get_atomic_ent_value(ent));
540         } else if (ent_is_string_const(ent)) {
541                 dump_string_cst(obst, ent);
542         } else if (is_Array_type(type)) {
543                 dump_array_init(obst, ent);
544         } else if (is_compound_type(type)) {
545                 dump_compound_init(obst, ent);
546         } else
547                 assert(0 && "unsupported type");
548 }
549
550 /**
551  * Dumps declarations of global variables and the initialization code.
552  */
553 static void ia32_dump_globals(ir_type *gt, ia32_decl_env_t *env)
554 {
555         int i, n = get_compound_n_members(gt);
556
557         for (i = 0; i < n; i++) {
558                 ir_entity *ent = get_compound_member(gt, i);
559                 dump_global(env, ent);
560         }
561 }
562
563 /************************************************************************/
564
565 void ia32_gen_decls(FILE *out, const be_main_env_t *main_env) {
566         ia32_decl_env_t env;
567         obstack_t rodata, data, bss, ctor;
568         int    size;
569         char   *cp;
570
571         /* dump the global type */
572         obstack_init(&rodata);
573         obstack_init(&data);
574         obstack_init(&bss);
575
576         if (main_env->options->opt_profile)
577                 obstack_init(&ctor);
578
579         env.rodata_obst = &rodata;
580         env.data_obst   = &data;
581         env.bss_obst    = &bss;
582         env.ctor_obst   = main_env->options->opt_profile ? &ctor : NULL;
583         env.main_env    = main_env;
584
585         ia32_dump_globals(get_glob_type(), &env);
586
587         size = obstack_object_size(&data);
588         cp   = obstack_finish(&data);
589         if (size > 0) {
590                 ia32_switch_section(out, SECTION_DATA);
591                 fwrite(cp, 1, size, out);
592         }
593
594         size = obstack_object_size(&rodata);
595         cp   = obstack_finish(&rodata);
596         if (size > 0) {
597                 ia32_switch_section(out, SECTION_RODATA);
598                 fwrite(cp, 1, size, out);
599         }
600
601         size = obstack_object_size(&bss);
602         cp   = obstack_finish(&bss);
603         if (size > 0) {
604                 ia32_switch_section(out, SECTION_COMMON);
605                 fwrite(cp, 1, size, out);
606         }
607
608         if (main_env->options->opt_profile) {
609                 size = obstack_object_size(&ctor);
610                 cp   = obstack_finish(&ctor);
611                 if (size > 0) {
612                         ia32_switch_section(out, SECTION_CTOR);
613                         fwrite(cp, 1, size, out);
614                 }
615                 obstack_free(&ctor, NULL);
616         }
617
618         obstack_free(&rodata, NULL);
619         obstack_free(&data, NULL);
620         obstack_free(&bss, NULL);
621
622         /* dump the Thread Local Storage */
623         obstack_init(&data);
624
625         env.rodata_obst = &data;
626         env.data_obst   = &data;
627         env.bss_obst   = &data;
628         env.ctor_obst   = NULL;
629
630         ia32_dump_globals(get_tls_type(), &env);
631
632         size = obstack_object_size(&data);
633         cp   = obstack_finish(&data);
634         if (size > 0) {
635                 ia32_switch_section(out, SECTION_TLS);
636                 fprintf(out, ".balign\t%d\n", 32);
637                 fwrite(cp, 1, size, out);
638         }
639
640         obstack_free(&data, NULL);
641 }