2 * Dumps global variables and constants as ia32 assembler.
3 * @author Christian Wuerdig
21 #include "ia32_emitter.h"
22 #include "ia32_gen_decls.h"
24 typedef struct obstack obstack_t;
26 typedef struct _ia32_decl_env {
27 obstack_t *rodata_obst;
31 const be_main_env_t *main_env;
34 /************************************************************************/
37 * returns the highest bit value
39 static unsigned highest_bit(unsigned v)
43 if (v >= (1U << 16U)) {
47 if (v >= (1U << 8U)) {
51 if (v >= (1U << 4U)) {
55 if (v >= (1U << 2U)) {
59 if (v >= (1U << 1U)) {
69 static void ia32_dump_comm(obstack_t *obst, const char *name, visibility vis, int size, int align) {
70 switch (asm_flavour) {
72 if (vis == visibility_local)
73 obstack_printf(obst, "\t.local\t%s\n", name);
74 obstack_printf(obst, "\t.comm\t%s,%d,%d\n", name, size, align);
77 if (vis == visibility_local)
78 obstack_printf(obst, "\t.lcomm\t%s,%d\n", name, size);
80 obstack_printf(obst, "\t.comm\t%s,%d\n", name, size);
86 * output the alignment to an obstack
88 static void ia32_dump_align(obstack_t *obst, int align)
90 int h = highest_bit(align);
97 obstack_printf(obst, "\t.align %d\n", align);
101 * output the alignment to a FILE
103 static void ia32_dump_align_f(FILE *f, int align)
105 int h = highest_bit(align);
107 if ((1 << h) < align)
112 fprintf(f, "\t.align %d\n", align);
118 static void dump_arith_tarval(obstack_t *obst, tarval *tv, int bytes)
123 obstack_printf(obst, "0x%02x", get_tarval_sub_bits(tv, 0));
127 obstack_printf(obst, "0x%02x%02x", get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
131 obstack_printf(obst, "0x%02x%02x%02x%02x",
132 get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
136 obstack_printf(obst, "0x%02x%02x%02x%02x%02x%02x%02x%02x",
137 get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6), get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4),
138 get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
146 fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
152 * dump an atomic value
154 static void do_dump_atomic_init(obstack_t *obst, ir_node *init)
156 ir_mode *mode = get_irn_mode(init);
157 int bytes = get_mode_size_bytes(mode);
160 switch (get_irn_opcode(init)) {
163 do_dump_atomic_init(obst, get_Cast_op(init));
167 do_dump_atomic_init(obst, get_Conv_op(init));
171 tv = get_Const_tarval(init);
173 /* beware of old stuff */
174 //assert(! mode_is_reference(mode));
176 /* it's a arithmetic value */
177 dump_arith_tarval(obst, tv, bytes);
181 switch (get_SymConst_kind(init)) {
182 case symconst_addr_name:
183 obstack_printf(obst, "%s", get_id_str(get_SymConst_name(init)));
186 case symconst_addr_ent:
187 obstack_printf(obst, "%s", get_entity_ld_name(get_SymConst_entity(init)));
190 case symconst_type_size:
191 obstack_printf(obst, "%d", get_type_size_bytes(get_SymConst_type(init)));
194 case symconst_type_align:
195 obstack_printf(obst, "%d", get_type_alignment_bytes(get_SymConst_type(init)));
198 case symconst_enum_const:
199 tv = get_enumeration_value(get_SymConst_enum(init));
200 dump_arith_tarval(obst, tv, bytes);
204 assert(0 && "dump_atomic_init(): don't know how to init from this SymConst");
209 do_dump_atomic_init(obst, get_Add_left(init));
210 obstack_printf(obst, " + ");
211 do_dump_atomic_init(obst, get_Add_right(init));
215 do_dump_atomic_init(obst, get_Sub_left(init));
216 obstack_printf(obst, " - ");
217 do_dump_atomic_init(obst, get_Sub_right(init));
221 do_dump_atomic_init(obst, get_Mul_left(init));
222 obstack_printf(obst, " * ");
223 do_dump_atomic_init(obst, get_Mul_right(init));
227 assert(0 && "dump_atomic_init(): unknown IR-node");
232 * dumps the type for given size (.byte, .long, ...)
234 static void dump_size_type(obstack_t *obst, int size) {
238 obstack_printf(obst, "\t.byte\t");
242 obstack_printf(obst, "\t.value\t");
246 obstack_printf(obst, "\t.long\t");
250 obstack_printf(obst, "\t.quad\t");
255 /* handled in arith */
259 fprintf(stderr, "Try to dump a type with %d bytes\n", size);
265 * dump an atomic value
267 static void dump_atomic_init(obstack_t *obst, ir_node *init)
269 ir_mode *mode = get_irn_mode(init);
270 int bytes = get_mode_size_bytes(mode);
272 dump_size_type(obst, bytes);
273 do_dump_atomic_init(obst, init);
274 obstack_printf(obst, "\n");
277 /************************************************************************/
278 /* Routines to dump global variables */
279 /************************************************************************/
282 * Determine if an entity is a string constant
283 * @param ent The entity
284 * @return 1 if it is a string constant, 0 otherwise
286 static int ent_is_string_const(entity *ent)
291 ty = get_entity_type(ent);
293 /* if it's an array */
294 if (is_Array_type(ty)) {
295 ir_type *elm_ty = get_array_element_type(ty);
297 /* and the array's element type is primitive */
298 if (is_Primitive_type(elm_ty)) {
299 ir_mode *mode = get_type_mode(elm_ty);
302 * and the mode of the element type is an int of
303 * the same size as the byte mode
305 if (mode_is_int(mode)
306 && get_mode_size_bits(mode) == get_mode_size_bits(mode_Bs))
310 n = get_compound_ent_n_values(ent);
311 for (i = 0; i < n; ++i) {
312 ir_node *irn = get_compound_ent_value(ent, i);
313 if(get_irn_opcode(irn) != iro_Const)
316 c = (int) get_tarval_long(get_Const_tarval(irn));
318 if((i < n - 1 && !(isgraph(c) || isspace(c)))
319 || (i == n - 1 && c != '\0'))
332 * Dump a atring constant.
333 * No checks are made!!
334 * @param obst The obst to dump on.
335 * @param ent The entity to dump.
337 static void dump_string_cst(obstack_t *obst, entity *ent)
341 obstack_printf(obst, "\t.string \"");
342 n = get_compound_ent_n_values(ent);
344 for (i = 0; i < n-1; ++i) {
348 irn = get_compound_ent_value(ent, i);
349 c = (int) get_tarval_long(get_Const_tarval(irn));
352 case '"' : obstack_printf(obst, "\\\""); break;
353 case '\n': obstack_printf(obst, "\\n"); break;
354 case '\r': obstack_printf(obst, "\\r"); break;
355 case '\t': obstack_printf(obst, "\\t"); break;
356 case '\\': obstack_printf(obst, "\\\\"); break;
359 obstack_printf(obst, "%c", c);
361 obstack_printf(obst, "%O", c);
365 obstack_printf(obst, "\"\n");
375 * Dump the size of an object
377 static void dump_object_size(obstack_t *obst, const char *name, int size) {
378 switch (asm_flavour) {
380 obstack_printf(obst, "\t.type\t%s,@object\n", name);
381 obstack_printf(obst, "\t.size\t%s,%d\n", name, size);
387 * Dumps the initialization of global variables that are not
390 static void dump_global(const arch_env_t *arch_env,
391 obstack_t *rdata_obstack, obstack_t *data_obstack,
392 obstack_t *comm_obstack, obstack_t *ctor_obstack,
395 ir_type *ty = get_entity_type(ent);
396 const char *ld_name = get_entity_ld_name(ent);
397 obstack_t *obst = data_obstack;
401 * FIXME: did NOT work for partly constant values
403 if (! is_Method_type(ty)) {
404 ent_variability variability = get_entity_variability(ent);
405 visibility visibility = get_entity_visibility(ent);
407 if (variability == variability_constant) {
408 /* a constant entity, put it on the rdata */
409 obst = rdata_obstack;
412 /* check, whether it is initialized, if yes create data */
413 if (variability != variability_uninitialized) {
414 if (visibility == visibility_external_visible) {
415 obstack_printf(obst, ".globl\t%s\n", ld_name);
417 dump_object_size(obst, ld_name, get_type_size_bytes(ty));
419 align = get_type_alignment_bytes(ty);
420 ia32_dump_align(obst, align);
422 obstack_printf(obst, "%s:\n", ld_name);
424 if (is_atomic_type(ty)) {
425 if (get_entity_visibility(ent) != visibility_external_allocated)
426 dump_atomic_init(obst, get_atomic_ent_value(ent));
431 if (ent_is_string_const(ent)) {
432 dump_string_cst(obst, ent);
434 else if (is_Array_type(ty)) {
437 /* potential spare values should be already included! */
438 for (i = 0; i < get_compound_ent_n_values(ent); ++i) {
439 entity *step = get_compound_ent_value_member(ent, i);
440 ir_type *stype = get_entity_type(step);
442 if (get_type_mode(stype)) {
443 int align = (get_type_alignment_bits(stype) + 7) >> 3;
444 int n = size % align;
447 obstack_printf(obst, "\t.zero\t%d\n", align - n);
451 dump_atomic_init(obst, get_compound_ent_value(ent, i));
452 size += get_type_size_bytes(stype);
454 filler = get_type_size_bytes(ty) - size;
457 obstack_printf(obst, "\t.zero\t%d\n", filler);
459 else if (is_compound_type(ty)) {
463 /* Compound entities are NOT sorted.
464 * The sorting strategy used doesn't work for `value' compound fields nor
465 * for partially_constant entities.
469 * in the worst case, every entity allocates one byte, so the type
470 * size should be equal or bigger the number of fields
472 type_size = get_type_size_bytes(ty);
473 vals = xcalloc(type_size, sizeof(*vals));
475 /* collect the values and store them at the offsets */
476 for(i = 0; i < get_compound_ent_n_values(ent); ++i) {
477 int graph_length, aipos, offset;
480 compound_graph_path *path = get_compound_ent_value_path(ent, i);
482 /* get the access path to the costant value */
483 graph_length = get_compound_graph_path_length(path);
484 ai = xcalloc(graph_length, sizeof(struct arr_info));
486 /* We wanna know how many arrays are on the path to the entity. We also have to know how
487 * many elements each array holds to calculate the offset for the entity. */
488 for (j = 0; j < graph_length; j++) {
489 entity *step = get_compound_graph_path_node(path, j);
490 ir_type *step_type = get_entity_type(step);
491 int ty_size = (get_type_size_bits(step_type) + 7) >> 3;
494 if (is_Array_type(step_type))
495 for (k = 0; k < get_array_n_dimensions(step_type); k++)
496 n += get_tarval_long(get_Const_tarval(get_array_upper_bound(step_type, k)));
498 ai[j].n_elems = n ? all_n + 1 : 0;
500 ai[j].size = ty_size;
503 aipos = graph_length - 1;
506 for (offset = j = 0; j < graph_length; j++) {
507 entity *step = get_compound_graph_path_node(path, j);
508 ir_type *step_type = get_entity_type(step);
509 int ent_ofs = get_entity_offset_bytes(step);
512 /* add all positive offsets (= offsets in structs) */
513 if (ent_ofs >= 0) offset += ent_ofs;
515 if (j == graph_length - 1) {
516 stepsize = (get_type_size_bits(step_type) + 7) >> 3;
518 /* Search the next free position in vals depending on the information from above (ai). */
519 while (vals[offset] && aipos >= 0) {
520 if (ai[aipos].visit_cnt < ai[aipos].n_elems) {
522 ai[aipos].visit_cnt++;
525 while (aipos >= 0 && ai[aipos].visit_cnt == ai[aipos].n_elems) {
526 stepsize = ai[aipos--].size;
531 assert(aipos >= 0 && "couldn't store entity");
532 vals[offset] = get_compound_ent_value(ent, i);
539 /* now write them sorted */
540 for(i = 0; i < type_size; ) {
542 dump_atomic_init(obst, vals[i]);
543 i += (get_mode_size_bytes(get_irn_mode(vals[i])));
547 obstack_printf(obst, "\t.byte\t0\n");
554 assert(0 && "unsupported type");
557 obstack_printf(obst, "\n");
559 else if (visibility != visibility_external_allocated) {
560 /* uninitialized and NOT external */
561 if (get_entity_owner(ent) != get_tls_type()) {
562 /* calculate the alignment */
563 align = get_type_alignment_bytes(ty);
564 h = highest_bit(align);
566 if ((1 << h) < align)
573 ia32_dump_comm(comm_obstack, ld_name, visibility,
574 get_type_size_bytes(ty), align);
577 if (visibility == visibility_external_visible) {
578 obstack_printf(obst, ".globl\t%s\n", ld_name);
580 dump_object_size(comm_obstack, ld_name, get_type_size_bytes(ty));
581 align = get_type_alignment_bytes(ty);
582 ia32_dump_align(obst, align);
583 obstack_printf(comm_obstack, "%s:\n\t.zero %d\n", ld_name, get_type_size_bytes(ty));
586 } /* ! is method type */
587 else if (ctor_obstack && arch_ent_is_constructor(arch_env, ent)) {
588 ia32_dump_align(ctor_obstack, get_type_alignment_bytes(ty));
589 dump_size_type(ctor_obstack, get_type_alignment_bytes(ty));
590 obstack_printf(ctor_obstack, "%s\n", ld_name);
595 * Dumps declarations of global variables and the initialization code.
597 static void ia32_dump_globals(ir_type *gt, ia32_decl_env_t *env)
599 int i, n = get_compound_n_members(gt);
601 for (i = 0; i < n; i++)
602 dump_global(env->main_env->arch_env, env->rodata_obst, env->data_obst, env->comm_obst, env->ctor_obst,
603 get_compound_member(gt, i));
606 /************************************************************************/
608 void ia32_gen_decls(FILE *out, const be_main_env_t *main_env) {
610 obstack_t rodata, data, comm, ctor;
614 /* dump the global type */
615 obstack_init(&rodata);
619 if (main_env->options->opt_profile)
622 env.rodata_obst = &rodata;
623 env.data_obst = &data;
624 env.comm_obst = &comm;
625 env.ctor_obst = main_env->options->opt_profile ? &ctor : NULL;
626 env.main_env = main_env;
628 ia32_dump_globals(get_glob_type(), &env);
630 size = obstack_object_size(&data);
631 cp = obstack_finish(&data);
633 ia32_switch_section(out, SECTION_DATA);
634 fwrite(cp, 1, size, out);
637 size = obstack_object_size(&rodata);
638 cp = obstack_finish(&rodata);
640 ia32_switch_section(out, SECTION_RODATA);
641 fwrite(cp, 1, size, out);
644 size = obstack_object_size(&comm);
645 cp = obstack_finish(&comm);
647 ia32_switch_section(out, SECTION_COMMON);
648 fwrite(cp, 1, size, out);
651 if (main_env->options->opt_profile) {
652 size = obstack_object_size(&ctor);
653 cp = obstack_finish(&ctor);
655 ia32_switch_section(out, SECTION_CTOR);
656 fwrite(cp, 1, size, out);
658 obstack_free(&ctor, NULL);
661 obstack_free(&rodata, NULL);
662 obstack_free(&data, NULL);
663 obstack_free(&comm, NULL);
665 /* dump the Thread Local Storage */
668 env.rodata_obst = &data;
669 env.data_obst = &data;
670 env.comm_obst = &data;
671 env.ctor_obst = NULL;
673 ia32_dump_globals(get_tls_type(), &env);
675 size = obstack_object_size(&data);
676 cp = obstack_finish(&data);
678 ia32_switch_section(out, SECTION_TLS);
679 ia32_dump_align_f(out, 32);
680 fwrite(cp, 1, size, out);
683 obstack_free(&data, NULL);