diff options
Diffstat (limited to 'gcc/config/arm/arm.c')
-rw-r--r-- | gcc/config/arm/arm.c | 145 |
1 files changed, 139 insertions, 6 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 594dc17..b68e005 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -214,8 +214,8 @@ static bool arm_return_in_memory (const_tree, const_tree); static void arm_unwind_emit (FILE *, rtx_insn *); static bool arm_output_ttype (rtx); static void arm_asm_emit_except_personality (rtx); -static void arm_asm_init_sections (void); #endif +static void arm_asm_init_sections (void); static rtx arm_dwarf_register_span (rtx); static tree arm_cxx_guard_type (void); @@ -299,7 +299,10 @@ static unsigned HOST_WIDE_INT arm_asan_shadow_offset (void); static void arm_sched_fusion_priority (rtx_insn *, int, int *, int*); static bool arm_can_output_mi_thunk (const_tree, HOST_WIDE_INT, HOST_WIDE_INT, const_tree); - +static section *arm_function_section (tree, enum node_frequency, bool, bool); +static bool arm_asm_elf_flags_numeric (unsigned int flags, unsigned int *num); +static unsigned int arm_elf_section_type_flags (tree decl, const char *name, + int reloc); /* Table of machine attributes. */ static const struct attribute_spec arm_attribute_table[] = @@ -584,8 +587,8 @@ static const struct attribute_spec arm_attribute_table[] = #define TARGET_ASM_EMIT_EXCEPT_PERSONALITY arm_asm_emit_except_personality #undef TARGET_ASM_INIT_SECTIONS -#define TARGET_ASM_INIT_SECTIONS arm_asm_init_sections #endif /* ARM_UNWIND_INFO */ +#define TARGET_ASM_INIT_SECTIONS arm_asm_init_sections #undef TARGET_DWARF_REGISTER_SPAN #define TARGET_DWARF_REGISTER_SPAN arm_dwarf_register_span @@ -726,6 +729,15 @@ static const struct attribute_spec arm_attribute_table[] = #undef TARGET_SCHED_FUSION_PRIORITY #define TARGET_SCHED_FUSION_PRIORITY arm_sched_fusion_priority +#undef TARGET_ASM_FUNCTION_SECTION +#define TARGET_ASM_FUNCTION_SECTION arm_function_section + +#undef TARGET_ASM_ELF_FLAGS_NUMERIC +#define TARGET_ASM_ELF_FLAGS_NUMERIC arm_asm_elf_flags_numeric + +#undef TARGET_SECTION_TYPE_FLAGS +#define TARGET_SECTION_TYPE_FLAGS arm_elf_section_type_flags + struct gcc_target targetm = TARGET_INITIALIZER; /* Obstack for minipool constant handling. */ @@ -2837,6 +2849,12 @@ arm_option_check_internal (struct gcc_options *opts) && ((!(arm_arch7 && !arm_arch_notm) && !arm_arch7em) || (TARGET_THUMB1_P (flags) || flag_pic || TARGET_NEON))) error ("-mslow-flash-data only supports non-pic code on armv7-m targets"); + + /* We only support pure-code on Thumb-2 M-profile targets. */ + if (target_pure_code + && (!arm_arch_thumb2 || arm_arch_notm || flag_pic || TARGET_NEON)) + error ("-mpure-code only supports non-pic code on armv7-m targets"); + } /* Recompute the global settings depending on target attribute options. */ @@ -3487,8 +3505,9 @@ arm_option_override (void) global_options.x_param_values, global_options_set.x_param_values); - /* Currently, for slow flash data, we just disable literal pools. */ - if (target_slow_flash_data) + /* Currently, for slow flash data, we just disable literal pools. We also + disable it for pure-code. */ + if (target_slow_flash_data || target_pure_code) arm_disable_literal_pool = true; /* Disable scheduling fusion by default if it's not armv7 processor @@ -27262,17 +27281,24 @@ arm_asm_emit_except_personality (rtx personality) output_addr_const (asm_out_file, personality); fputc ('\n', asm_out_file); } +#endif /* ARM_UNWIND_INFO */ /* Implement TARGET_ASM_INITIALIZE_SECTIONS. */ static void arm_asm_init_sections (void) { +#if ARM_UNWIND_INFO exception_section = get_unnamed_section (0, output_section_asm_op, "\t.handlerdata"); -} #endif /* ARM_UNWIND_INFO */ +#ifdef OBJECT_FORMAT_ELF + if (target_pure_code) + text_section->unnamed.data = "\t.section .text,\"0x20000006\",%progbits"; +#endif +} + /* Output unwind directives for the start/end of a function. */ void @@ -30613,4 +30639,111 @@ arm_gen_unlikely_cbranch (enum rtx_code code, machine_mode cc_mode, emit_unlikely_jump (gen_rtx_SET (pc_rtx, x)); } +/* Implement the TARGET_ASM_ELF_FLAGS_NUMERIC hook. + + For pure-code sections there is no letter code for this attribute, so + output all the section flags numerically when this is needed. */ + +static bool +arm_asm_elf_flags_numeric (unsigned int flags, unsigned int *num) +{ + + if (flags & SECTION_ARM_PURECODE) + { + *num = 0x20000000; + + if (!(flags & SECTION_DEBUG)) + *num |= 0x2; + if (flags & SECTION_EXCLUDE) + *num |= 0x80000000; + if (flags & SECTION_WRITE) + *num |= 0x1; + if (flags & SECTION_CODE) + *num |= 0x4; + if (flags & SECTION_MERGE) + *num |= 0x10; + if (flags & SECTION_STRINGS) + *num |= 0x20; + if (flags & SECTION_TLS) + *num |= 0x400; + if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE)) + *num |= 0x200; + + return true; + } + + return false; +} + +/* Implement the TARGET_ASM_FUNCTION_SECTION hook. + + If pure-code is passed as an option, make sure all functions are in + sections that have the SHF_ARM_PURECODE attribute. */ + +static section * +arm_function_section (tree decl, enum node_frequency freq, + bool startup, bool exit) +{ + const char * section_name; + section * sec; + + if (!decl || TREE_CODE (decl) != FUNCTION_DECL) + return default_function_section (decl, freq, startup, exit); + + if (!target_pure_code) + return default_function_section (decl, freq, startup, exit); + + + section_name = DECL_SECTION_NAME (decl); + + /* If a function is not in a named section then it falls under the 'default' + text section, also known as '.text'. We can preserve previous behavior as + the default text section already has the SHF_ARM_PURECODE section + attribute. */ + if (!section_name) + { + section *default_sec = default_function_section (decl, freq, startup, + exit); + + /* If default_sec is not null, then it must be a special section like for + example .text.startup. We set the pure-code attribute and return the + same section to preserve existing behavior. */ + if (default_sec) + default_sec->common.flags |= SECTION_ARM_PURECODE; + return default_sec; + } + + /* Otherwise look whether a section has already been created with + 'section_name'. */ + sec = get_named_section (decl, section_name, 0); + if (!sec) + /* If that is not the case passing NULL as the section's name to + 'get_named_section' will create a section with the declaration's + section name. */ + sec = get_named_section (decl, NULL, 0); + + /* Set the SHF_ARM_PURECODE attribute. */ + sec->common.flags |= SECTION_ARM_PURECODE; + + return sec; +} + +/* Implements the TARGET_SECTION_FLAGS hook. + + If DECL is a function declaration and pure-code is passed as an option + then add the SFH_ARM_PURECODE attribute to the section flags. NAME is the + section's name and RELOC indicates whether the declarations initializer may + contain runtime relocations. */ + +static unsigned int +arm_elf_section_type_flags (tree decl, const char *name, int reloc) +{ + unsigned int flags = default_section_type_flags (decl, name, reloc); + + if (decl && TREE_CODE (decl) == FUNCTION_DECL && target_pure_code) + flags |= SECTION_ARM_PURECODE; + + return flags; +} + #include "gt-arm.h" |