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