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