X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbegnuas.c;h=b79ba281f51e75c0f382352b6b9d44e2d711584e;hb=d300330b1e6df8c8914b8fb70cf38ee1c8ca2634;hp=af458a70d78a76c3a418869237ad6dd952192513;hpb=9e32caf2e94f99e6d057b69e5b8384e26de2e785;p=libfirm diff --git a/ir/be/begnuas.c b/ir/be/begnuas.c index af458a70d..b79ba281f 100644 --- a/ir/be/begnuas.c +++ b/ir/be/begnuas.c @@ -51,7 +51,6 @@ be_gas_flavour_t be_gas_flavour = GAS_FLAVOUR_ELF; static be_gas_section_t current_section = (be_gas_section_t) -1; -static int force_section = 0; /** * Return the pseudo-instruction to be issued for a section switch @@ -69,7 +68,8 @@ static const char *get_section_name(be_gas_section_t section) { ".section\t.rodata", ".section\t.bss", ".section\t.tbss,\"awT\",@nobits", - ".section\t.ctors,\"aw\",@progbits" + ".section\t.ctors,\"aw\",@progbits", + NULL, }, { /* GAS_FLAVOUR_MINGW */ ".section\t.text", @@ -77,7 +77,8 @@ static const char *get_section_name(be_gas_section_t section) { ".section .rdata,\"dr\"", ".section\t.bss", ".section\t.tbss,\"awT\",@nobits", - ".section\t.ctors,\"aw\",@progbits" + ".section\t.ctors,\"aw\",@progbits", + NULL, }, { /* GAS_FLAVOUR_YASM */ ".section\t.text", @@ -85,15 +86,17 @@ static const char *get_section_name(be_gas_section_t section) { ".section\t.rodata", ".section\t.bss", ".section\t.tbss,\"awT\",@nobits", - ".section\t.ctors,\"aw\",@progbits" + ".section\t.ctors,\"aw\",@progbits", + NULL }, { /* GAS_FLAVOUR_MACH_O */ ".text", ".data", ".const", ".data", - NULL, /* TLS is not supported on Mach-O */ - NULL /* constructors aren't marked with sections in Mach-O */ + NULL, /* TLS is not supported on Mach-O */ + ".mod_init_func", + ".cstring" } }; @@ -103,7 +106,7 @@ static const char *get_section_name(be_gas_section_t section) { } void be_gas_emit_switch_section(be_gas_section_t section) { - if(current_section == section || force_section) + if(current_section == section) return; be_emit_char('\t'); @@ -116,6 +119,8 @@ void be_gas_emit_switch_section(be_gas_section_t section) { void be_gas_emit_function_prolog(ir_entity *entity, unsigned alignment) { const char *name = get_entity_ld_name(entity); + const char *fill_byte = ""; + unsigned maximum_skip; be_gas_emit_switch_section(GAS_SECTION_TEXT); @@ -126,13 +131,12 @@ void be_gas_emit_function_prolog(ir_entity *entity, unsigned alignment) be_emit_char('\n'); be_emit_write_line(); - const char *fill_byte = ""; /* gcc fills space between function with 0x90, no idea if this is needed */ if(be_gas_flavour == GAS_FLAVOUR_MACH_O) { fill_byte = "0x90"; } - unsigned maximum_skip = (1 << alignment) - 1; + maximum_skip = (1 << alignment) - 1; be_emit_cstring("\t.p2align "); be_emit_irprintf("%u,%s,%u\n", alignment, fill_byte, maximum_skip); be_emit_write_line(); @@ -193,7 +197,8 @@ void be_gas_emit_function_epilog(ir_entity *entity) */ typedef struct _be_gas_decl_env { const be_main_env_t *main_env; /**< The main backend environment, used for it's debug handle. */ - waitq *worklist; /**< A worklist we use to place not yet handled entities on. */ + be_gas_section_t section; + waitq *worklist; /**< A worklist we use to place not yet handled entities on. */ } be_gas_decl_env_t; /************************************************************************/ @@ -481,6 +486,7 @@ static void dump_atomic_init(be_gas_decl_env_t *env, ir_node *init) static int initializer_is_string_const(const ir_initializer_t *initializer) { size_t i, len; + int found_printable = 0; if(initializer->kind != IR_INITIALIZER_COMPOUND) return 0; @@ -506,16 +512,16 @@ static int initializer_is_string_const(const ir_initializer_t *initializer) return 0; c = get_tarval_long(tv); - if (i < len - 1) { - if (!isgraph(c) && !isspace(c)) - return 0; - } else { - if (c != 0) - return 0; - } + if (isgraph(c) || isspace(c)) + found_printable = 1; + else if(c != 0) + return 0; + + if (i == len - 1 && c != '\0') + return 0; } - return 1; + return found_printable; } /** @@ -528,6 +534,7 @@ static int ent_is_string_const(ir_entity *ent) ir_type *type, *element_type; ir_mode *mode; int i, c, n; + int found_printable = 0; type = get_entity_type(ent); @@ -561,14 +568,18 @@ static int ent_is_string_const(ir_entity *ent) c = (int) get_tarval_long(get_Const_tarval(irn)); - if((i < n - 1 && !(isgraph(c) || isspace(c))) - || (i == n - 1 && c != '\0')) + if (isgraph(c) || isspace(c)) + found_printable = 1; + else if(c != 0) + return 0; + + if (i == n - 1 && c != '\0') return 0; } } /* then we can emit it as a string constant */ - return 1; + return found_printable; } /** @@ -584,12 +595,8 @@ static void dump_string_cst(ir_entity *ent) int type_size; int remaining_space; - be_gas_section_t last_section = current_section; len = get_compound_ent_n_values(ent); if (be_gas_flavour == GAS_FLAVOUR_MACH_O) { - if (get_entity_variability(ent) == variability_constant) { - be_gas_emit_switch_section(GAS_SECTION_CSTRING); - } be_emit_cstring("\t.ascii \""); } else { be_emit_cstring("\t.string \""); @@ -627,9 +634,6 @@ static void dump_string_cst(ir_entity *ent) if(remaining_space > 0) { be_emit_irprintf("\t.skip\t%d\n", remaining_space); } - if(be_gas_flavour == GAS_FLAVOUR_MACH_O) { - be_gas_emit_switch_section(last_section); - } } static void dump_string_initializer(const ir_initializer_t *initializer) @@ -638,10 +642,10 @@ static void dump_string_initializer(const ir_initializer_t *initializer) len = initializer->compound.n_initializers; if(be_gas_flavour == GAS_FLAVOUR_MACH_O) { + be_emit_cstring("\t.ascii \""); + } else { be_emit_cstring("\t.string \""); len -= 1; - } else { - be_emit_cstring("\t.ascii \""); } for(i = 0; i < len; ++i) { @@ -1084,42 +1088,30 @@ static void emit_align(unsigned alignment) * * @param env the gas output environment * @param ent the entity to be dumped - * @param emit_commons if non-zero, emit commons (non-local uninitialized entities) */ -static void dump_global(be_gas_decl_env_t *env, ir_entity *ent, int emit_commons) +static void dump_global(be_gas_decl_env_t *env, ir_entity *ent) { ir_type *type = get_entity_type(ent); ident *ld_ident = get_entity_ld_ident(ent); unsigned align = get_type_alignment_bytes(type); int emit_as_common = 0; - be_gas_section_t section; - ir_variability variability; - ir_visibility visibility; - - if (is_Method_type(type)) { - if (be_gas_flavour != GAS_FLAVOUR_MACH_O - && get_method_img_section(ent) == section_constructors) { - be_gas_emit_switch_section(GAS_SECTION_CTOR); - emit_align(align); - dump_size_type(align); - be_emit_ident(ld_ident); - be_emit_char('\n'); - be_emit_write_line(); - } - - return; - } + be_gas_section_t section = env->section; + ir_variability variability = get_entity_variability(ent); + ir_visibility visibility = get_entity_visibility(ent); - variability = get_entity_variability(ent); - visibility = get_entity_visibility(ent); - section = GAS_SECTION_DATA; - if (variability == variability_constant) { + if (section != (be_gas_section_t) -1) { + emit_as_common = 0; + } else if (variability == variability_constant) { /* a constant entity, put it on the rdata */ section = GAS_SECTION_RODATA; + if (be_gas_flavour == GAS_FLAVOUR_MACH_O + && ent_is_string_const(ent)) { + section = GAS_SECTION_CSTRING; + } } else if (variability == variability_uninitialized) { /* uninitialized entity put it in bss segment */ section = GAS_SECTION_COMMON; - if (emit_commons && visibility != visibility_local) + if (visibility != visibility_local) emit_as_common = 1; } @@ -1171,7 +1163,7 @@ static void dump_global(be_gas_decl_env_t *env, ir_entity *ent, int emit_commons break; } } else { - be_emit_irprintf("\t.zero %u\n", get_type_size_bytes(type)); + be_emit_irprintf("\t.space %u\n", get_type_size_bytes(type)); be_emit_write_line(); } } else { @@ -1204,12 +1196,11 @@ static void dump_global(be_gas_decl_env_t *env, ir_entity *ent, int emit_commons * * @param gt a global like type, either the global or the TLS one * @param env an environment - * @param emit_commons if non-zero, emit commons (non-local uninitialized entities) * @param only_emit_marked if non-zero, external allocated entities that do not have * its visited flag set are ignored */ static void be_gas_dump_globals(ir_type *gt, be_gas_decl_env_t *env, - int emit_commons, int only_emit_marked) + int only_emit_marked) { int i, n = get_compound_n_members(gt); waitq *worklist = new_waitq(); @@ -1236,7 +1227,7 @@ static void be_gas_dump_globals(ir_type *gt, be_gas_decl_env_t *env, while (!waitq_empty(worklist)) { ir_entity *ent = waitq_get(worklist); - dump_global(env, ent, emit_commons); + dump_global(env, ent); } del_waitq(worklist); @@ -1250,17 +1241,16 @@ void be_gas_emit_decls(const be_main_env_t *main_env, int only_emit_marked_entities) { be_gas_decl_env_t env; + memset(&env, 0, sizeof(env)); env.main_env = main_env; /* dump global type */ - be_gas_dump_globals(get_glob_type(), &env, 1, only_emit_marked_entities); - - /* dump the Thread Local Storage */ - if (be_gas_flavour != GAS_FLAVOUR_MACH_O) { - be_gas_emit_switch_section(GAS_SECTION_TLS); - force_section = 1; - be_gas_dump_globals(get_tls_type(), &env, 0, only_emit_marked_entities); - force_section = 0; - } + env.section = (be_gas_section_t) -1; + be_gas_dump_globals(get_glob_type(), &env, only_emit_marked_entities); + env.section = GAS_SECTION_TLS; + be_gas_dump_globals(get_tls_type(), &env, only_emit_marked_entities); + env.section = GAS_SECTION_CTOR; + be_gas_dump_globals(get_constructors_type(), &env, + only_emit_marked_entities); }