summaryrefslogtreecommitdiffhomepage
path: root/ir/be/begnuas.c
diff options
context:
space:
mode:
authorMatthias Braun <matze@braunis.de>2015-05-26 00:40:26 +0200
committerMatthias Braun <matze@braunis.de>2015-05-26 00:46:39 +0200
commitd8d48197a502e6445a3a51aa1fcfb8a092dfb84f (patch)
tree2633289769615fe5457bbae64b1533649a9dbec6 /ir/be/begnuas.c
parent708a3f7ebf36cbb2dfe1336f6b1b9ce5723fdc92 (diff)
begnuas: Refactor the way common globals are emitted to share some more code
Diffstat (limited to 'ir/be/begnuas.c')
-rw-r--r--ir/be/begnuas.c198
1 files changed, 81 insertions, 117 deletions
diff --git a/ir/be/begnuas.c b/ir/be/begnuas.c
index f2fecde..10ab734 100644
--- a/ir/be/begnuas.c
+++ b/ir/be/begnuas.c
@@ -470,16 +470,23 @@ static void emit_weak(const ir_entity *entity)
emit_symbol_directive(directive, entity);
}
-static void emit_visibility(const ir_entity *entity)
+static void emit_visibility(const ir_entity *entity, bool implicit_globl)
{
ir_linkage const linkage = get_entity_linkage(entity);
- if (linkage & IR_LINKAGE_WEAK) {
+ if (linkage & IR_LINKAGE_WEAK)
emit_weak(entity);
- /* Note: .weak seems to imply .globl so no need to output .globl */
- } else if (get_entity_visibility(entity) == ir_visibility_external
- && entity_has_definition(entity)) {
- emit_symbol_directive(".globl", entity);
+
+ if (entity_has_definition(entity)) {
+ switch (get_entity_visibility(entity)) {
+ case ir_visibility_external:
+ if (!implicit_globl)
+ emit_symbol_directive(".globl", entity);
+ break;
+ case ir_visibility_local:
+ case ir_visibility_private:
+ break;
+ }
}
if (be_gas_object_file_format == OBJECT_FILE_FORMAT_MACH_O
@@ -517,7 +524,7 @@ void be_gas_emit_function_prolog(const ir_entity *entity, unsigned po2alignment,
be_emit_irprintf("%u,%s,%u\n", po2alignment, fill_byte, maximum_skip);
be_emit_write_line();
}
- emit_visibility(entity);
+ emit_visibility(entity, false);
switch (be_gas_object_file_format) {
case OBJECT_FILE_FORMAT_ELF:
@@ -1114,63 +1121,28 @@ static unsigned get_effective_entity_alignment(const ir_entity *entity)
return alignment;
}
-static void emit_common(const ir_entity *entity)
+static void emit_common(const ir_entity *entity, bool is_local)
{
- unsigned size = get_type_size_bytes(get_entity_type(entity));
- unsigned alignment = get_effective_entity_alignment(entity);
-
- if (get_entity_linkage(entity) & IR_LINKAGE_WEAK) {
- emit_weak(entity);
- }
+ unsigned const size = get_type_size_bytes(get_entity_type(entity));
+ unsigned const alignment = get_effective_entity_alignment(entity);
switch (be_gas_object_file_format) {
case OBJECT_FILE_FORMAT_MACH_O:
- be_emit_cstring("\t.comm ");
+ be_emit_string(is_local ? "\t.lcomm " : "\t.comm ");
be_gas_emit_entity(entity);
be_emit_irprintf(",%u,%u\n", size, log2_floor(alignment));
be_emit_write_line();
return;
case OBJECT_FILE_FORMAT_ELF:
+ if (is_local)
+ emit_symbol_directive(".local", entity);
be_emit_cstring("\t.comm ");
be_gas_emit_entity(entity);
be_emit_irprintf(",%u,%u\n", size, alignment);
be_emit_write_line();
return;
case OBJECT_FILE_FORMAT_COFF:
- be_emit_cstring("\t.comm ");
- be_gas_emit_entity(entity);
- be_emit_irprintf(",%u # %u\n", size, alignment);
- be_emit_write_line();
- return;
- }
- panic("invalid object file format");
-}
-
-static void emit_local_common(const ir_entity *entity)
-{
- unsigned size = get_type_size_bytes(get_entity_type(entity));
- unsigned alignment = get_effective_entity_alignment(entity);
-
- if (get_entity_linkage(entity) & IR_LINKAGE_WEAK) {
- emit_weak(entity);
- }
-
- switch (be_gas_object_file_format) {
- case OBJECT_FILE_FORMAT_MACH_O:
- be_emit_cstring("\t.lcomm ");
- be_gas_emit_entity(entity);
- be_emit_irprintf(",%u,%u\n", size, log2_floor(alignment));
- be_emit_write_line();
- return;
- case OBJECT_FILE_FORMAT_ELF:
- emit_symbol_directive(".local", entity);
- be_emit_cstring("\t.comm ");
- be_gas_emit_entity(entity);
- be_emit_irprintf(",%u,%u\n", size, alignment);
- be_emit_write_line();
- return;
- case OBJECT_FILE_FORMAT_COFF:
- be_emit_cstring("\t.lcomm ");
+ be_emit_cstring(is_local ? "\t.lcomm " : "\t.comm ");
be_gas_emit_entity(entity);
be_emit_irprintf(",%u # %u\n", size, alignment);
be_emit_write_line();
@@ -1182,8 +1154,8 @@ static void emit_local_common(const ir_entity *entity)
static void emit_indirect_symbol(const ir_entity *entity,
be_gas_section_t section)
{
- /* we can only do PIC code on macho so far */
- assert(be_gas_object_file_format == OBJECT_FILE_FORMAT_MACH_O);
+ if (be_gas_object_file_format != OBJECT_FILE_FORMAT_MACH_O)
+ panic("indirect_symbol entities only supported for ELF");
be_gas_emit_entity(entity);
be_emit_cstring(":\n");
@@ -1202,7 +1174,6 @@ static void emit_indirect_symbol(const ir_entity *entity,
static void emit_alias(const ir_entity *entity)
{
- /* no support on other object file formats (yet) */
if (be_gas_object_file_format != OBJECT_FILE_FORMAT_ELF)
panic("alias entities only supported for ELF");
@@ -1310,10 +1281,9 @@ void be_gas_begin_block(const ir_node *block, bool needs_label)
/**
* Dump a global entity.
- *
- * @param ent the entity to be dumped
*/
-static void emit_global(be_main_env_t const *const main_env, ir_entity const *const entity)
+static void emit_global(be_main_env_t const *const main_env,
+ ir_entity const *const entity)
{
ir_entity_kind kind = get_entity_kind(entity);
@@ -1327,82 +1297,76 @@ static void emit_global(be_main_env_t const *const main_env, ir_entity const *co
/* we already emitted all methods with graphs in other functions like
* be_gas_emit_function_prolog(). All others don't need to be emitted. */
be_gas_section_t const section = determine_section(main_env, entity);
- if (kind == IR_ENTITY_METHOD && section != GAS_SECTION_PIC_TRAMPOLINES) {
+ if (kind == IR_ENTITY_METHOD && section != GAS_SECTION_PIC_TRAMPOLINES)
return;
- }
be_dwarf_variable(entity);
ir_visibility visibility = get_entity_visibility(entity);
ir_linkage linkage = get_entity_linkage(entity);
- if (section == GAS_SECTION_BSS) {
- switch (visibility) {
- case ir_visibility_local:
- case ir_visibility_private:
- emit_local_common(entity);
- return;
- case ir_visibility_external:
- if (linkage & IR_LINKAGE_MERGE) {
- emit_common(entity);
- return;
- }
- break;
- }
- }
+ bool use_common_directive = section == GAS_SECTION_BSS
+ && (visibility == ir_visibility_local
+ || visibility == ir_visibility_private
+ || (linkage & IR_LINKAGE_MERGE));
- emit_visibility(entity);
+ emit_visibility(entity, use_common_directive);
- emit_section(section, entity);
-
- if (section == GAS_SECTION_PIC_TRAMPOLINES
- || section == GAS_SECTION_PIC_SYMBOLS) {
- emit_indirect_symbol(entity, section);
- return;
- } else if (kind == IR_ENTITY_ALIAS) {
- emit_alias(entity);
- return;
- }
+ if (use_common_directive) {
+ emit_common(entity, visibility == ir_visibility_local
+ || visibility == ir_visibility_private);
+ } else {
+ emit_section(section, entity);
- /* nothing left to do without an initializer */
- if (!entity_has_definition(entity))
- return;
+ if (section == GAS_SECTION_PIC_TRAMPOLINES
+ || section == GAS_SECTION_PIC_SYMBOLS) {
+ emit_indirect_symbol(entity, section);
+ return;
+ } else if (kind == IR_ENTITY_ALIAS) {
+ emit_alias(entity);
+ return;
+ }
- /* alignment */
- unsigned alignment = get_effective_entity_alignment(entity);
- if (!is_po2(alignment))
- panic("alignment not a power of 2");
- if (alignment > 1) {
- emit_align(alignment);
- }
- if (be_gas_object_file_format == OBJECT_FILE_FORMAT_ELF
- && be_gas_emit_types && visibility != ir_visibility_private) {
- be_emit_cstring("\t.type\t");
- be_gas_emit_entity(entity);
- be_emit_cstring(", ");
- be_emit_char(be_gas_elf_type_char);
- be_emit_cstring("object\n\t.size\t");\
- be_gas_emit_entity(entity);
- ir_type *const type = get_entity_type(entity);
- be_emit_irprintf(", %u\n", get_type_size_bytes(type));
- }
+ /* nothing left to do without an initializer */
+ if (!entity_has_definition(entity))
+ return;
- ident *ld_ident = get_entity_ld_ident(entity);
- if (get_id_str(ld_ident)[0] != '\0') {
- be_gas_emit_entity(entity);
- be_emit_cstring(":\n");
- be_emit_write_line();
- }
+ /* alignment */
+ unsigned alignment = get_effective_entity_alignment(entity);
+ if (!is_po2(alignment))
+ panic("alignment not a power of 2");
+ if (alignment > 1) {
+ emit_align(alignment);
+ }
+ if (be_gas_object_file_format == OBJECT_FILE_FORMAT_ELF
+ && be_gas_emit_types && visibility != ir_visibility_private) {
+ be_emit_cstring("\t.type\t");
+ be_gas_emit_entity(entity);
+ be_emit_cstring(", ");
+ be_emit_char(be_gas_elf_type_char);
+ be_emit_cstring("object\n\t.size\t");\
+ be_gas_emit_entity(entity);
+ ir_type *const type = get_entity_type(entity);
+ be_emit_irprintf(", %u\n", get_type_size_bytes(type));
+ }
- if (entity_is_null(entity)) {
- /* we should use .space for stuff in the bss segment */
- ir_type *const type = get_entity_type(entity);
- unsigned const size = get_type_size_bytes(type);
- if (size > 0) {
- be_emit_irprintf("\t.space %u, 0\n", size);
+ ident *ld_ident = get_entity_ld_ident(entity);
+ if (get_id_str(ld_ident)[0] != '\0') {
+ be_gas_emit_entity(entity);
+ be_emit_cstring(":\n");
be_emit_write_line();
}
- } else {
- emit_initializer(entity);
+
+ if (entity_is_null(entity)) {
+ /* we should use .space for stuff in the bss segment */
+ ir_type *const type = get_entity_type(entity);
+ unsigned const size = get_type_size_bytes(type);
+ if (size > 0) {
+ be_emit_irprintf("\t.space %u, 0\n", size);
+ be_emit_write_line();
+ }
+ } else {
+ emit_initializer(entity);
+ }
}
}