2 * Dumps global variables and constants as ia32 assembler.
3 * @author Christian Wuerdig
26 #include "ia32_emitter.h"
27 #include "ia32_gen_decls.h"
29 typedef struct obstack obstack_t;
31 typedef struct _ia32_decl_env {
32 obstack_t *rodata_obst;
36 const be_main_env_t *main_env;
39 /************************************************************************/
44 static void dump_arith_tarval(obstack_t *obst, tarval *tv, int bytes)
49 obstack_printf(obst, "0x%02x", get_tarval_sub_bits(tv, 0));
53 obstack_printf(obst, "0x%02x%02x", get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
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));
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));
72 fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
78 * Return the tarval of an atomic initializer.
80 static tarval *get_atomic_init_tv(ir_node *init)
83 ir_mode *mode = get_irn_mode(init);
85 switch (get_irn_opcode(init)) {
88 init = get_Cast_op(init);
92 init = get_Conv_op(init);
96 return get_Const_tarval(init);
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);
103 case symconst_type_size:
104 return new_tarval_from_long(get_type_size_bytes(get_SymConst_type(init)), mode);
106 case symconst_type_align:
107 return new_tarval_from_long(get_type_alignment_bytes(get_SymConst_type(init)), mode);
109 case symconst_enum_const:
110 return get_enumeration_value(get_SymConst_enum(init));
123 * dump an atomic value
125 static void do_dump_atomic_init(obstack_t *obst, ir_node *init)
127 ir_mode *mode = get_irn_mode(init);
128 int bytes = get_mode_size_bytes(mode);
131 switch (get_irn_opcode(init)) {
134 do_dump_atomic_init(obst, get_Cast_op(init));
138 do_dump_atomic_init(obst, get_Conv_op(init));
142 tv = get_Const_tarval(init);
144 /* beware of old stuff */
145 //assert(! mode_is_reference(mode));
147 /* it's a arithmetic value */
148 dump_arith_tarval(obst, tv, bytes);
152 switch (get_SymConst_kind(init)) {
153 case symconst_addr_name:
154 obstack_printf(obst, "%s", get_id_str(get_SymConst_name(init)));
157 case symconst_addr_ent:
158 obstack_printf(obst, "%s", get_entity_ld_name(get_SymConst_entity(init)));
161 case symconst_ofs_ent:
162 obstack_printf(obst, "%d", get_entity_offset(get_SymConst_entity(init)));
165 case symconst_type_size:
166 obstack_printf(obst, "%d", get_type_size_bytes(get_SymConst_type(init)));
169 case symconst_type_align:
170 obstack_printf(obst, "%d", get_type_alignment_bytes(get_SymConst_type(init)));
173 case symconst_enum_const:
174 tv = get_enumeration_value(get_SymConst_enum(init));
175 dump_arith_tarval(obst, tv, bytes);
179 assert(!"dump_atomic_init(): don't know how to init from this SymConst");
184 do_dump_atomic_init(obst, get_Add_left(init));
185 obstack_printf(obst, " + ");
186 do_dump_atomic_init(obst, get_Add_right(init));
190 do_dump_atomic_init(obst, get_Sub_left(init));
191 obstack_printf(obst, " - ");
192 do_dump_atomic_init(obst, get_Sub_right(init));
196 do_dump_atomic_init(obst, get_Mul_left(init));
197 obstack_printf(obst, " * ");
198 do_dump_atomic_init(obst, get_Mul_right(init));
202 assert(0 && "dump_atomic_init(): unknown IR-node");
207 * dumps the type for given size (.byte, .long, ...)
209 static void dump_size_type(obstack_t *obst, int size) {
213 obstack_printf(obst, "\t.byte\t");
217 obstack_printf(obst, "\t.value\t");
221 obstack_printf(obst, "\t.long\t");
225 obstack_printf(obst, "\t.quad\t");
230 /* handled in arith */
234 fprintf(stderr, "Try to dump a type with %d bytes\n", size);
240 * dump an atomic value to an obstack
242 static void dump_atomic_init(obstack_t *obst, ir_node *init)
244 ir_mode *mode = get_irn_mode(init);
245 int bytes = get_mode_size_bytes(mode);
247 dump_size_type(obst, bytes);
248 do_dump_atomic_init(obst, init);
249 obstack_printf(obst, "\n");
252 /************************************************************************/
253 /* Routines to dump global variables */
254 /************************************************************************/
257 * Determine if an entity is a string constant
258 * @param ent The entity
259 * @return 1 if it is a string constant, 0 otherwise
261 static int ent_is_string_const(ir_entity *ent)
266 ty = get_entity_type(ent);
268 /* if it's an array */
269 if (is_Array_type(ty)) {
270 ir_type *elm_ty = get_array_element_type(ty);
272 /* and the array's element type is primitive */
273 if (is_Primitive_type(elm_ty)) {
274 ir_mode *mode = get_type_mode(elm_ty);
277 * and the mode of the element type is an int of
278 * the same size as the byte mode
280 if (mode_is_int(mode)
281 && get_mode_size_bits(mode) == get_mode_size_bits(mode_Bs))
285 n = get_compound_ent_n_values(ent);
286 for (i = 0; i < n; ++i) {
287 ir_node *irn = get_compound_ent_value(ent, i);
288 if(get_irn_opcode(irn) != iro_Const)
291 c = (int) get_tarval_long(get_Const_tarval(irn));
293 if((i < n - 1 && !(isgraph(c) || isspace(c)))
294 || (i == n - 1 && c != '\0'))
307 * Dump a string constant.
308 * No checks are made!!
309 * @param obst The obst to dump on.
310 * @param ent The entity to dump.
312 static void dump_string_cst(obstack_t *obst, ir_entity *ent)
316 obstack_printf(obst, "\t.string \"");
317 n = get_compound_ent_n_values(ent);
319 for (i = 0; i < n-1; ++i) {
323 irn = get_compound_ent_value(ent, i);
324 c = (int) get_tarval_long(get_Const_tarval(irn));
327 case '"' : obstack_printf(obst, "\\\""); break;
328 case '\n': obstack_printf(obst, "\\n"); break;
329 case '\r': obstack_printf(obst, "\\r"); break;
330 case '\t': obstack_printf(obst, "\\t"); break;
331 case '\\': obstack_printf(obst, "\\\\"); break;
334 obstack_printf(obst, "%c", c);
336 obstack_printf(obst, "\\%o", c);
340 obstack_printf(obst, "\"\n");
343 static void dump_array_init(obstack_t *obst, ir_entity *ent)
345 const ir_type *ty = get_entity_type(ent);
350 /* potential spare values should be already included! */
351 for (i = 0; i < get_compound_ent_n_values(ent); ++i) {
352 ir_entity *step = get_compound_ent_value_member(ent, i);
353 ir_type *stype = get_entity_type(step);
355 if (get_type_mode(stype)) {
356 int align = (get_type_alignment_bits(stype) + 7) >> 3;
357 int n = size % align;
360 obstack_printf(obst, "\t.zero\t%d\n", align - n);
364 dump_atomic_init(obst, get_compound_ent_value(ent, i));
365 size += get_type_size_bytes(stype);
367 filler = get_type_size_bytes(ty) - size;
370 obstack_printf(obst, "\t.skip\t%d\n", filler);
373 enum normal_or_bitfield_kind {
379 enum normal_or_bitfield_kind kind;
382 unsigned char bf_val;
384 } normal_or_bitfield;
387 * Dump an initializer for a compound entity.
389 static void dump_compound_init(obstack_t *obst, ir_entity *ent)
391 normal_or_bitfield *vals;
392 int i, j, n = get_compound_ent_n_values(ent);
395 /* Find the initializer size. Sorrily gcc support a nasty feature:
396 The last filed of a compound may be a flexible array. This allows
397 initializers bigger than the type size. */
399 for (i = 0; i < n; ++i) {
400 int offset = get_compound_ent_value_offset_bytes(ent, i);
401 int bits_remainder = get_compound_ent_value_offset_bit_remainder(ent, i);
402 const compound_graph_path *path = get_compound_ent_value_path(ent, i);
403 int path_len = get_compound_graph_path_length(path);
404 ir_entity *last_ent = get_compound_graph_path_node(path, path_len - 1);
405 int value_len = get_type_size_bits(get_entity_type(last_ent));
407 offset += (value_len + bits_remainder + 7) >> 3;
409 if (offset > last_ofs) {
415 * In the worst case, every initializer allocates one byte.
416 * Moreover, initializer might be big, do not allocate an stack.
418 vals = xcalloc(last_ofs, sizeof(vals[0]));
420 /* collect the values and store them at the offsets */
421 for (i = 0; i < n; ++i) {
422 const compound_graph_path *path = get_compound_ent_value_path(ent, i);
423 int path_len = get_compound_graph_path_length(path);
424 int offset = get_compound_ent_value_offset_bytes(ent, i);
425 int offset_bits = get_compound_ent_value_offset_bit_remainder(ent, i);
426 ir_node *value = get_compound_ent_value(ent, i);
427 ir_entity *last_ent = get_compound_graph_path_node(path, path_len - 1);
428 int value_len = get_type_size_bits(get_entity_type(last_ent));
430 assert(offset_bits >= 0);
432 if (offset_bits != 0 || value_len % 8 != 0) {
433 tarval *shift, *shifted;
434 tarval *tv = get_atomic_init_tv(value);
436 panic("Couldn't get numeric value for bitfield initializer '%s'\n",
437 get_entity_ld_name(ent));
439 shift = new_tarval_from_long(offset_bits, mode_Is);
440 shifted = tarval_shl(tv, shift);
441 if (shifted == tarval_bad || shifted == tarval_undefined) {
442 panic("Couldn't shift numeric value for bitfield initializer '%s'\n",
443 get_entity_ld_name(ent));
446 for (j = 0; j < 4 && value_len > 0; ++j) {
447 assert(offset + j < last_ofs);
448 assert(vals[offset + j].kind == BITFIELD || vals[offset + j].v.value == NULL);
449 vals[offset + j].kind = BITFIELD;
450 vals[offset + j].v.bf_val |= get_tarval_sub_bits(shifted, j);
451 value_len -= 8 - offset_bits;
455 assert(offset < last_ofs);
456 assert(vals[offset].kind == NORMAL);
457 assert(vals[offset].v.value == NULL);
458 vals[offset].v.value = value;
462 /* now write them sorted */
463 for (i = 0; i < last_ofs; ) {
464 int space = 0, skip = 0;
465 if (vals[i].kind == NORMAL) {
466 if(vals[i].v.value != NULL) {
467 dump_atomic_init(obst, vals[i].v.value);
468 skip = get_mode_size_bytes(get_irn_mode(vals[i].v.value)) - 1;
473 obstack_printf(obst, "\t.byte\t%d\n", vals[i].v.bf_val);
478 while (i < last_ofs && vals[i].kind == NORMAL && vals[i].v.value == NULL) {
487 obstack_printf(obst, "\t.skip\t%d\n", space);
493 * Dump a global entity.
495 static void dump_global(ia32_decl_env_t *env, ir_entity *ent)
498 ir_type *type = get_entity_type(ent);
499 const char *ld_name = get_entity_ld_name(ent);
500 ir_variability variability = get_entity_variability(ent);
501 ir_visibility visibility = get_entity_visibility(ent);
502 int align = get_type_alignment_bytes(type);
504 obst = env->data_obst;
505 if (is_Method_type(type)) {
506 if (get_method_img_section(ent) == section_constructors) {
507 obst = env->ctor_obst;
508 obstack_printf(obst, ".balign\t%d\n", align);
509 dump_size_type(obst, align);
510 obstack_printf(obst, "%s\n", ld_name);
513 } else if (variability == variability_constant) {
514 /* a constant entity, put it on the rdata */
515 obst = env->rodata_obst;
516 } else if (variability == variability_uninitialized) {
517 /* uninitialized entity put it in bss segment */
518 obst = env->bss_obst;
521 be_dbg_variable(env->main_env->db_handle, obst, ent);
523 /* global or not global */
524 if(visibility == visibility_external_visible) {
525 obstack_printf(obst, ".global\t%s\n", ld_name);
526 } else if(visibility == visibility_external_allocated) {
527 obstack_printf(obst, ".global\t%s\n", ld_name);
528 /* we can return now... */
533 obstack_printf(obst, ".balign\t%d\n", align);
536 obstack_printf(obst, "%s:\n", ld_name);
538 if (variability == variability_uninitialized) {
539 obstack_printf(obst, "\t.zero %d\n", get_type_size_bytes(type));
540 } else if (is_atomic_type(type)) {
541 dump_atomic_init(obst, get_atomic_ent_value(ent));
542 } else if (ent_is_string_const(ent)) {
543 dump_string_cst(obst, ent);
544 } else if (is_Array_type(type)) {
545 dump_array_init(obst, ent);
546 } else if (is_compound_type(type)) {
547 dump_compound_init(obst, ent);
549 assert(0 && "unsupported type");
553 * Dumps declarations of global variables and the initialization code.
555 static void ia32_dump_globals(ir_type *gt, ia32_decl_env_t *env)
557 int i, n = get_compound_n_members(gt);
559 for (i = 0; i < n; i++) {
560 ir_entity *ent = get_compound_member(gt, i);
561 dump_global(env, ent);
565 /************************************************************************/
567 void ia32_gen_decls(FILE *out, const be_main_env_t *main_env) {
569 obstack_t rodata, data, bss, ctor;
573 /* dump the global type */
574 obstack_init(&rodata);
578 if (main_env->options->opt_profile)
581 env.rodata_obst = &rodata;
582 env.data_obst = &data;
584 env.ctor_obst = main_env->options->opt_profile ? &ctor : NULL;
585 env.main_env = main_env;
587 ia32_dump_globals(get_glob_type(), &env);
589 size = obstack_object_size(&data);
590 cp = obstack_finish(&data);
592 ia32_switch_section(out, SECTION_DATA);
593 fwrite(cp, 1, size, out);
596 size = obstack_object_size(&rodata);
597 cp = obstack_finish(&rodata);
599 ia32_switch_section(out, SECTION_RODATA);
600 fwrite(cp, 1, size, out);
603 size = obstack_object_size(&bss);
604 cp = obstack_finish(&bss);
606 ia32_switch_section(out, SECTION_COMMON);
607 fwrite(cp, 1, size, out);
610 if (main_env->options->opt_profile) {
611 size = obstack_object_size(&ctor);
612 cp = obstack_finish(&ctor);
614 ia32_switch_section(out, SECTION_CTOR);
615 fwrite(cp, 1, size, out);
617 obstack_free(&ctor, NULL);
620 obstack_free(&rodata, NULL);
621 obstack_free(&data, NULL);
622 obstack_free(&bss, NULL);
624 /* dump the Thread Local Storage */
627 env.rodata_obst = &data;
628 env.data_obst = &data;
629 env.bss_obst = &data;
630 env.ctor_obst = NULL;
632 ia32_dump_globals(get_tls_type(), &env);
634 size = obstack_object_size(&data);
635 cp = obstack_finish(&data);
637 ia32_switch_section(out, SECTION_TLS);
638 fprintf(out, ".balign\t%d\n", 32);
639 fwrite(cp, 1, size, out);
642 obstack_free(&data, NULL);