aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/arm/arm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/arm/arm.c')
-rw-r--r--gcc/config/arm/arm.c145
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"