From: Matthias Braun Date: Wed, 10 Feb 2010 23:05:45 +0000 (+0000) Subject: support for local common symbols (whatever that is good for); introduce ir_visibility... X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=bfd8bf38d1e4fb790fdc9300cb00c9ae9af0857a;p=libfirm support for local common symbols (whatever that is good for); introduce ir_visibility_private (not tested yet as they don't occur in C) [r27109] --- diff --git a/include/libfirm/typerep.h b/include/libfirm/typerep.h index bf7d74ae5..3f1512d78 100644 --- a/include/libfirm/typerep.h +++ b/include/libfirm/typerep.h @@ -94,7 +94,15 @@ typedef enum { * The entity is defined outside the compilation unit but potentially used * here. */ - ir_visibility_external + ir_visibility_external, + /** + * This has the same semantic as visibility_local. Additionally the symbol is + * completely hidden from the linker (it only appears in the assembly). + * While visibility_local is probably still visible to debuggers, + * visibility_private symbols aren't and probably won't appear in the object + * files + */ + ir_visibility_private } ir_visibility; /** diff --git a/ir/be/begnuas.c b/ir/be/begnuas.c index b96355817..ec190b4a4 100644 --- a/ir/be/begnuas.c +++ b/ir/be/begnuas.c @@ -480,7 +480,8 @@ static void do_dump_atomic_init(be_gas_decl_env_t *env, ir_node *init) * * @param size the size in bytes */ -static void dump_size_type(size_t size) { +static void dump_size_type(size_t size) +{ switch (size) { case 1: be_emit_cstring("\t.byte\t"); @@ -1218,11 +1219,22 @@ static be_gas_section_t determine_section(be_gas_decl_env_t *env, panic("Couldn't determine section for %+F?!?", entity); } -static void emit_common(const ir_entity *ent) +static void emit_common(const ir_entity *entity) { - const char *name = get_entity_ld_name(ent); - unsigned size = get_type_size_bytes(get_entity_type(ent)); - unsigned alignment = get_effective_entity_alignment(ent); + const char *name = get_entity_ld_name(entity); + unsigned size = get_type_size_bytes(get_entity_type(entity)); + unsigned alignment = get_effective_entity_alignment(entity); + ir_visibility visibility = get_entity_visibility(entity); + + if (visibility == ir_visibility_local + || visibility == ir_visibility_private) { + /* counter the visibility_global effect of .comm + * ... and to be honest I have no idea what local common symbols + * are good for... + */ + be_emit_irprintf("\t.local %s\n", name); + be_emit_write_line(); + } switch (be_gas_object_file_format) { case OBJECT_FILE_FORMAT_MACH_O: @@ -1272,10 +1284,11 @@ static void dump_indirect_symbol(const ir_entity *entity, be_gas_section_t secti */ static void dump_global(be_gas_decl_env_t *env, const ir_entity *ent) { - ir_type *type = get_entity_type(ent); - ident *ld_ident = get_entity_ld_ident(ent); - unsigned alignment = get_effective_entity_alignment(ent); - be_gas_section_t section = determine_section(env, ent); + ir_type *type = get_entity_type(ent); + ident *ld_ident = get_entity_ld_ident(ent); + unsigned alignment = get_effective_entity_alignment(ent); + be_gas_section_t section = determine_section(env, ent); + ir_visibility visibility = get_entity_visibility(ent); /* we already emitted all methods. Except for the trampolines which * the assembler/linker generates */ @@ -1288,17 +1301,29 @@ static void dump_global(be_gas_decl_env_t *env, const ir_entity *ent) be_dbg_variable(ent); - /* nothing to do for externally defined values */ - if (get_entity_visibility(ent) == ir_visibility_external) + switch (visibility) { + case ir_visibility_external: + /* nothing to do for externally defined values */ return; + case ir_visibility_private: + /* mangle name so the assembler doesn't export the symbol + * TODO: this is probably a bit broken, since the backends probably don't + * mangle themselfes when outputting these symbols... */ + ld_ident = id_mangle3(".L", ld_ident, ""); + break; + case ir_visibility_local: + case ir_visibility_default: + /* nothing todo (leave the cases here to avoid compiler warnings) */ + break; + } if (!is_po2(alignment)) panic("alignment not a power of 2"); if (section == GAS_SECTION_BSS && (get_entity_linkage(ent) & IR_LINKAGE_MERGE)) { - if (get_entity_visibility(ent) != ir_visibility_default) { - panic("merge link semantic not supported for local/extern entities"); + if (get_entity_visibility(ent) == ir_visibility_external) { + panic("merge link semantic not supported for extern entities"); } emit_common(ent); return; @@ -1334,7 +1359,7 @@ static void dump_global(be_gas_decl_env_t *env, const ir_entity *ent) be_emit_write_line(); } - if (section == GAS_SECTION_BSS || section == GAS_SECTION_TLS_BSS) { + if (entity_is_null(ent)) { be_emit_irprintf("\t.zero %u\n", get_type_size_bytes(type)); be_emit_write_line(); } else if(entity_has_compound_ent_values(ent)) { diff --git a/ir/tr/trvrfy.c b/ir/tr/trvrfy.c index 1d11b46ef..2ab9d9cf6 100644 --- a/ir/tr/trvrfy.c +++ b/ir/tr/trvrfy.c @@ -417,6 +417,7 @@ int tr_vrfy(void) int res = no_error; ir_type *constructors; ir_type *destructors; + ir_type *thread_locals; int i; static ident *empty = NULL; @@ -427,23 +428,32 @@ int tr_vrfy(void) constructors = get_segment_type(IR_SEGMENT_CONSTRUCTORS); for (i = get_compound_n_members(constructors)-1; i >= 0; --i) { - ir_entity *entity = get_compound_member(constructors, i); + const ir_entity *entity = get_compound_member(constructors, i); ASSERT_AND_RET(get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER, "entity without LINKAGE_HIDDEN_USER in constructors is pointless", 1); /* Mach-O doesn't like labels in this section */ ASSERT_AND_RET(get_entity_ld_ident(entity), - "entity in constructors should have ld_ident ''", 1); + "entity in constructors should have ld_ident=''", 1); } destructors = get_segment_type(IR_SEGMENT_DESTRUCTORS); for (i = get_compound_n_members(destructors)-1; i >= 0; --i) { - ir_entity *entity = get_compound_member(destructors, i); + const ir_entity *entity = get_compound_member(destructors, i); ASSERT_AND_RET(get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER, "entity without LINKAGE_HIDDEN_USER in destructors is pointless", 1); /* Mach-O doesn't like labels in this section */ ASSERT_AND_RET(get_entity_ld_ident(entity), - "entity in destructors should have ld_ident ''", 1); + "entity in destructors should have ld_ident=''", 1); + } + thread_locals = get_segment_type(IR_SEGMENT_THREAD_LOCAL); + for (i = get_compound_n_members(thread_locals)-1; i >= 0; --i) { + const ir_entity *entity = get_compound_member(thread_locals, i); + /* this is odd and should not be allowed I think */ + ASSERT_AND_RET(!is_method_entity(entity), + "method in THREAD_LOCAL segment", 1); + ASSERT_AND_RET(!(get_entity_linkage(entity) & IR_LINKAGE_MERGE), + "IR_LINKAGE_MERGE currently not support for thread locals", 1); } return res;