On 22/09/16 14:52, Richard Earnshaw (lists) wrote: > On 11/07/16 17:56, Andre Vieira (lists) wrote: >> On 07/07/16 13:30, mickael guene wrote: >>> Hi Andre, >>> >>> Another feedback on your purecode patch. >>> You have to disable casesi pattern since then it will >>> generate wrong code with -mpure-code option. >>> Indeed it will generate an 'adr rx, .Lx' (aka >>> 'subs rx, PC, #offset') which will not work in our >>> case since 'Lx' label is put in an .rodata section. >>> So offset value is unknown and can be impossible >>> to encode correctly. >>> >>> Regards >>> Mickael >>> >>> On 06/30/2016 04:32 PM, Andre Vieira (lists) wrote: >>>> Hello, >>>> >>>> This patch adds the -mpure-code option for ARM. This option ensures >>>> functions are put into sections that contain only code and no data. To >>>> ensure this throughout compilation we give these sections the ARM >>>> processor-specific ELF section attribute "SHF_ARM_PURECODE". This option >>>> is only supported for non-pic code for armv7-m targets. >>>> >>>> This patch introduces a new target hook 'TARGET_ASM_ELF_FLAGS_NUMERIC'. >>>> This target hook enables a target to use the numeric value for elf >>>> section attributes rather than their alphabetical representation. If >>>> TARGET_ASM_ELF_FLAGS_NUMERIC returns TRUE, the existing >>>> 'default_elf_asm_named_section', will print the numeric value of the >>>> section attributes for the current section. This target hook has two >>>> parameters: >>>> unsigned int FLAGS, the input parameter that tells the function the >>>> current section's attributes; >>>> unsigned int *NUM, used to pass down the numerical representation of the >>>> section's attributes. >>>> >>>> The default implementation for TARGET_ASM_ELF_FLAGS_NUMERIC will return >>>> false, so existing behavior is not changed. >>>> >>>> Bootstrapped and tested for arm-none-linux-gnueabihf. Further tested for >>>> arm-none-eabi with a Cortex-M3 target. >>>> >>>> >>>> gcc/ChangeLog: >>>> 2016-06-30 Andre Vieira >>>> Terry Guo >>>> >>>> * target.def (elf_flags_numeric): New target hook. >>>> * targhooks.h (default_asm_elf_flags_numeric): New. >>>> * varasm.c (default_asm_elf_flags_numeric): New. >>>> (default_elf_asm_named_section): Use new target hook. >>>> * config/arm/arm.opt (mpure-code): New. >>>> * config/arm/arm.h (SECTION_ARM_PURECODE): New. >>>> * config/arm/arm.c (arm_asm_init_sections): Add section >>>> attribute to default text section if -mpure-code. >>>> (arm_option_check_internal): Diagnose use of option with >>>> non supported targets and/or options. >>>> (arm_asm_elf_flags_numeric): New. >>>> (arm_function_section): New. >>>> (arm_elf_section_type_flags): New. >>>> * config/arm/elf.h (JUMP_TABLES_IN_TEXT_SECTION): Disable >>>> for -mpure-code. >>>> * gcc/doc/texi (TARGET_ASM_ELF_FLAGS_NUMERIC): New. >>>> * gcc/doc/texi.in (TARGET_ASM_ELF_FLAGS_NUMERIC): Likewise. >>>> >>>> >>>> >>>> gcc/testsuite/ChangeLog: >>>> 2016-06-30 Andre Vieira >>>> Terry Guo >>>> >>>> * gcc.target/arm/pure-code/ffunction-sections.c: New. >>>> * gcc.target/arm/pure-code/no-literal-pool.c: New. >>>> * gcc.target/arm/pure-code/pure-code.exp: New. >>>> >>> >> Hi Sandra, Mickael, >> >> Thank you for your comments. I changed the description of -mpure-code in >> invoke.texi to better reflect the error message you get wrt supported >> targets. >> >> As for the target hook description, I hope the text is clearer now. Let >> me know if you think it needs further explanation. >> >> I also fixed the double '%' in the text string for unnamed text sections >> and disabled the casesi pattern. >> >> I duplicated the original casesi test >> 'gcc/testsuite/gcc.c-torture/compile/pr46934.c' for pure-code to make >> sure the casesi was disabled and other patterns were selected instead. >> >> Reran regressions for pure-code.exp for Cortex-M3. >> >> Cheers, >> Andre >> >> >> gcc/ChangeLog: >> 2016-07-11 Andre Vieira >> Terry Guo >> >> * target.def (elf_flags_numeric): New target hook. >> * hooks.c (hook_uint_uintp_false): New generic hook. >> * varasm.c (default_elf_asm_named_section): Use new target hook. >> * config/arm/arm.opt (mpure-code): New. >> * config/arm/arm.h (SECTION_ARM_PURECODE): New. >> * config/arm/arm.c (arm_asm_init_sections): Add section >> attribute to default text section if -mpure-code. >> (arm_option_check_internal): Diagnose use of option with >> non supported targets and/or options. >> (arm_asm_elf_flags_numeric): New. >> (arm_function_section): New. >> (arm_elf_section_type_flags): New. >> * config/arm/elf.h (JUMP_TABLES_IN_TEXT_SECTION): Disable >> for -mpure-code. >> * config/arm/arm.md (casesi): Disable pattern for >> -mpure-code. >> * gcc/doc/texi (TARGET_ASM_ELF_FLAGS_NUMERIC): New. >> * gcc/doc/texi.in (TARGET_ASM_ELF_FLAGS_NUMERIC): Likewise. >> >> >> >> gcc/testsuite/ChangeLog: >> 2016-07-11 Andre Vieira >> Terry Guo >> >> * gcc.target/arm/pure-code/ffunction-sections.c: New. >> * gcc.target/arm/pure-code/no-literal-pool.c: New. >> * gcc.target/arm/pure-code/no-casesi.c: New. >> * gcc.target/arm/pure-code/pure-code.exp: New. >> >> >> 0001-mpure-code-for-ARM.patch >> >> >> diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h >> index f0cdd669191689bc5dcf3a7c2b60da5a2d201e3f..d10605cee0e6e0e07bbb4e1910d30c91443f8d17 100644 >> --- a/gcc/config/arm/arm.h >> +++ b/gcc/config/arm/arm.h >> @@ -2263,4 +2263,8 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); >> /* For switching between functions with different target attributes. */ >> #define SWITCHABLE_TARGET 1 >> >> +/* Define SECTION_ARM_PURECODE as the ARM specific section attribute >> + representation for SHF_ARM_PURECODE in GCC. */ >> +#define SECTION_ARM_PURECODE SECTION_MACH_DEP >> + >> #endif /* ! GCC_ARM_H */ >> From b35a27e363a6123c6c50bd29e284c89f6ae434a5 Mon Sep 17 00:00:00 2001 >> From: Andre Simoes Dias Vieira >> Date: Tue, 14 Jun 2016 11:17:12 +0100 >> Subject: [PATCH] -mpure-code for ARM >> >> --- >> gcc/config/arm/arm.c | 150 ++++++++++++++++++++- >> gcc/config/arm/arm.h | 4 + >> gcc/config/arm/arm.md | 2 +- >> gcc/config/arm/arm.opt | 6 + >> gcc/config/arm/elf.h | 3 +- >> gcc/doc/invoke.texi | 11 +- >> gcc/doc/tm.texi | 9 ++ >> gcc/doc/tm.texi.in | 2 + >> gcc/hooks.c | 10 ++ >> gcc/target.def | 13 ++ >> gcc/targhooks.h | 1 - >> .../gcc.target/arm/pure-code/ffunction-sections.c | 17 +++ >> gcc/testsuite/gcc.target/arm/pure-code/no-casesi.c | 29 ++++ >> .../gcc.target/arm/pure-code/no-literal-pool.c | 68 ++++++++++ >> .../gcc.target/arm/pure-code/pure-code.exp | 54 ++++++++ >> gcc/varasm.c | 50 ++++--- >> 16 files changed, 398 insertions(+), 31 deletions(-) >> create mode 100644 gcc/testsuite/gcc.target/arm/pure-code/ffunction-sections.c >> create mode 100644 gcc/testsuite/gcc.target/arm/pure-code/no-casesi.c >> create mode 100644 gcc/testsuite/gcc.target/arm/pure-code/no-literal-pool.c >> create mode 100644 gcc/testsuite/gcc.target/arm/pure-code/pure-code.exp >> >> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c >> index f60955438d6f1cc5d996e7eacd4b453213044181..9b5013a069235d18eebc10a312e364de9f756906 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[] = >> @@ -587,8 +590,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 >> @@ -729,6 +732,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. */ >> @@ -2815,6 +2827,17 @@ 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"); >> + >> +#ifdef OBJECT_FORMAT_ELF >> + /* We only support -mpure-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"); >> +#else >> + if (target_pure_code) >> + error ("-mpure-code is only available for the ELF object format."); >> +#endif > > It looks to me as though the only reason for restricting this to ELF is > that only that object format supports a PURECODE section flag. However, > that's not a reason to restrict the behaviour to ELF-only. Please can > we change this to be enabled for all object formats, even if they don't > have a special marker flag. > >> + >> } >> >> /* Recompute the global settings depending on target attribute options. */ >> @@ -3453,8 +3476,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 -mpure-code. */ > > Better to just refer to 'pure code' and not directly to the option name. > This applies elsewhere, too. > >> + if (target_slow_flash_data || target_pure_code) >> arm_disable_literal_pool = true; >> >> /* Disable scheduling fusion by default if it's not armv7 processor >> @@ -27208,17 +27232,22 @@ 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 */ >> >> + if (target_pure_code) >> + text_section->unnamed.data = "\t.section .text,\"0x20000006\",%progbits"; >> +} >> + >> /* Output unwind directives for the start/end of a function. */ >> >> void >> @@ -30529,4 +30558,113 @@ arm_can_output_mi_thunk (const_tree, HOST_WIDE_INT, HOST_WIDE_INT vcall_offset, >> return true; >> } >> >> +/* Implement the TARGET_ASM_ELF_FLAGS_NUMERIC hook. >> + >> + For sections with SECTION_ARM_PURECODE flag set, make sure you pass the >> + machine specific flag attribute when printing the numeric value. */ > > The comment is confusing. Perhaps it's better to write: > > 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 defined (HAVE_GAS_SECTION_EXCLUDE) && HAVE_GAS_SECTION_EXCLUDE == 1 >> + if (flags & SECTION_EXCLUDE) >> + *num |= 0x80000000; >> +#endif > > Do we really need this ifdef? Can't we assume that if our assembler > supports pure-code then it also supports the exclude attribute? > >> + 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 -mpure_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 > > Two spaces after a full stop. There are other instances of this as well. > > >> + 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 > > Like here. > >> + same section to preserve behavior. */ > > Preserve what behaviour? Existing? Or some other? > >> + 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 name section to > > s/name section/section name/ ? > >> + 'get_named_section' will create a section with the declarations >> + 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 -mpure-code is passed as an option >> + then add the SFH_ARM_PURECODE attribute to the section flags. NAME is the >> + sections name and RELOC indicates whether the declarations initializer may > > section's > >> + 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" >> diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md >> index 16498316bee9f19baff414885efe1e78191da047..9f49ab6014e61e7b49972f29c96ad03c11101aa1 100644 >> --- a/gcc/config/arm/arm.md >> +++ b/gcc/config/arm/arm.md >> @@ -8180,7 +8180,7 @@ >> (match_operand:SI 2 "const_int_operand" "") ; total range >> (match_operand:SI 3 "" "") ; table label >> (match_operand:SI 4 "" "")] ; Out of range label >> - "TARGET_32BIT || optimize_size || flag_pic" >> + "(TARGET_32BIT || optimize_size || flag_pic) && !target_pure_code" >> " >> { >> enum insn_code code; >> diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt >> index 0ebe0174390167b79a64583c35a3f8fb018f6538..6c142d9fc6bee9d5ec30f7a25bd017e8bc02b801 100644 >> --- a/gcc/config/arm/arm.opt >> +++ b/gcc/config/arm/arm.opt >> @@ -281,3 +281,9 @@ Assume loading data from flash is slower than fetching instructions. >> masm-syntax-unified >> Target Report Var(inline_asm_unified) Init(0) Save >> Assume unified syntax for inline assembly code. >> + >> +mpure-code >> +Target Report Var(target_pure_code) Init(0) >> +Generate assembly which places functions in sections that contain only code. >> +This requires that no literal pools are generated for such >> +functions and that jump tables are not put in the same section. > > I think this should read something like: > > Do not allow constant data to placed in code sections. > > For the short help from the compiler that's more than enough to remind a > user what the option does. > >> diff --git a/gcc/config/arm/elf.h b/gcc/config/arm/elf.h >> index 77f30554d5286bd83aeab0c8dc308cfd44e732dc..395a22282be0cd2edc9459e1ba14d7848073fa5d 100644 >> --- a/gcc/config/arm/elf.h >> +++ b/gcc/config/arm/elf.h >> @@ -104,7 +104,8 @@ >> the code more efficient, but for Thumb-1 it's better to put them out of >> band unless we are generating compressed tables. */ >> #define JUMP_TABLES_IN_TEXT_SECTION \ >> - (TARGET_32BIT || (TARGET_THUMB && (optimize_size || flag_pic))) >> + ((TARGET_32BIT || (TARGET_THUMB && (optimize_size || flag_pic))) \ >> + && !target_pure_code) >> >> #ifndef LINK_SPEC >> #define LINK_SPEC "%{mbig-endian:-EB} %{mlittle-endian:-EL} -X" >> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi >> index 4f24daebc01f0fd006540df8d863014aa864d060..faeb4299acc1f0859eafa3e13cf4b24c4d0224d6 100644 >> --- a/gcc/doc/invoke.texi >> +++ b/gcc/doc/invoke.texi >> @@ -639,7 +639,8 @@ Objective-C and Objective-C++ Dialects}. >> -mneon-for-64bits @gol >> -mslow-flash-data @gol >> -masm-syntax-unified @gol >> --mrestrict-it} >> +-mrestrict-it @gol >> +-mpure-code} >> >> @emph{AVR Options} >> @gccoptlist{-mmcu=@var{mcu} -maccumulate-args -mbranch-cost=@var{cost} @gol >> @@ -14498,6 +14499,14 @@ Print CPU tuning information as comment in assembler file. This is >> an option used only for regression testing of the compiler and not >> intended for ordinary use in compiling code. This option is disabled >> by default. >> + >> +@item -mpure-code >> +@opindex mpure-code >> +Generate assembly where instructions and data are in separate sections. > > This should probably be the same text as the help option. > >> +Additionally, give all text sections the ELF processor-specific section >> +attribute SHF_ARM_PURECODE. This option is only available when generating >> +non-pic code in ELF object format for ARMv7-M targets. > > And this bit will need re-wording for the other changes. > >> + >> @end table >> >> @node AVR Options >> diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi >> index b318615b7b35ab93ad13e5e535a1d4e6d02cb7f7..c9e1489a0453845a2bffb2df514cc3b5b73933dc 100644 >> --- a/gcc/doc/tm.texi >> +++ b/gcc/doc/tm.texi >> @@ -7543,6 +7543,15 @@ is non-NULL, it is the @code{VAR_DECL} or @code{FUNCTION_DECL} with which >> this section is associated. >> @end deftypefn >> >> +@deftypefn {Target Hook} bool TARGET_ASM_ELF_FLAGS_NUMERIC (unsigned int @var{flags}, unsigned int *@var{num}) >> +If the target needs to represent ELF section attributes using their >> +numerical value, then this hook should be implemented to return true and >> +write the numerical value of @var{flags} in @var{num}. This function is >> +called by @code{default_elf_asm_named_section}, which prints @var{num} >> +as the value representing the ELF section attributes if this function >> +returns true. >> +@end deftypefn >> + >> @deftypefn {Target Hook} {section *} TARGET_ASM_FUNCTION_SECTION (tree @var{decl}, enum node_frequency @var{freq}, bool @var{startup}, bool @var{exit}) >> Return preferred text (sub)section for function @var{decl}. >> Main purpose of this function is to separate cold, normal and hot >> diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in >> index 1e8423cb4e255acd8144e4b105186cee3d1d04fd..17a2ca73f07516526543253c77c088c73326af2c 100644 >> --- a/gcc/doc/tm.texi.in >> +++ b/gcc/doc/tm.texi.in >> @@ -5229,6 +5229,8 @@ of the filename using this macro. >> >> @hook TARGET_ASM_NAMED_SECTION >> >> +@hook TARGET_ASM_ELF_FLAGS_NUMERIC >> + >> @hook TARGET_ASM_FUNCTION_SECTION >> >> @hook TARGET_ASM_FUNCTION_SWITCHED_TEXT_SECTIONS >> diff --git a/gcc/hooks.c b/gcc/hooks.c >> index 99ec4014adb6fcbb073bf538dd00fe8695ee6cb2..1e925645c3173f8d97e104b9b2f480fca2ede438 100644 >> --- a/gcc/hooks.c >> +++ b/gcc/hooks.c >> @@ -481,3 +481,13 @@ void >> hook_void_gcc_optionsp (struct gcc_options *opts ATTRIBUTE_UNUSED) >> { >> } >> + >> +/* Generic hook that takes an unsigned int, an unsigned int pointer and >> + returns false. */ >> + >> +bool >> +hook_uint_uintp_false (unsigned int, unsigned int *) >> +{ >> + return false; >> +} >> + >> diff --git a/gcc/target.def b/gcc/target.def >> index a4df363698ce776b51d11c187baed2069ba88a52..a3d46fa48d919a16699c33b2b78236e62a33e025 100644 >> --- a/gcc/target.def >> +++ b/gcc/target.def >> @@ -432,6 +432,19 @@ this section is associated.", >> void, (const char *name, unsigned int flags, tree decl), >> default_no_named_section) >> >> +/* Tell assembler what section attributes to assign this elf section >> + declaration, using their numerical value. */ >> +DEFHOOK >> +(elf_flags_numeric, >> + "If the target needs to represent ELF section attributes using their\n\ >> +numerical value, then this hook should be implemented to return true and\n\ >> +write the numerical value of @var{flags} in @var{num}. This function is\n\ >> +called by @code{default_elf_asm_named_section}, which prints @var{num}\n\ >> +as the value representing the ELF section attributes if this function\n\ >> +returns true.", > > > I think this should read something like. > > This hook can be used to encode ELF section flags for which no letter > code has been defined in the assembler. It is called by > @code{default_asm_named_section} whenever the section flags need to be > emitted in the assembler output. If the hook returns true, then the > numerical value for ELF section flags should be calculated from > @var{flags} and saved in @var{*num}; the value will be printed out > instead of the normal sequence of letter codes. If the hook is not > defined, or if it returns false, then @var{num} will be ignored and the > traditional letter sequence will be emitted. > > >> + bool, (unsigned int flags, unsigned int *num), >> + hook_uint_uintp_false) >> + >> /* Return preferred text (sub)section for function DECL. >> Main purpose of this function is to separate cold, normal and hot >> functions. STARTUP is true when function is known to be used only >> diff --git a/gcc/targhooks.h b/gcc/targhooks.h >> index d6581cfab893e0da619c6bc0f98ff722a7ab4404..19ad97fa453cf6102b1502f97d8b66fe413284ee 100644 >> --- a/gcc/targhooks.h >> +++ b/gcc/targhooks.h >> @@ -254,5 +254,4 @@ extern void default_setup_incoming_vararg_bounds (cumulative_args_t ca ATTRIBUTE >> int second_time ATTRIBUTE_UNUSED); >> extern bool default_optab_supported_p (int, machine_mode, machine_mode, >> optimization_type); >> - >> #endif /* GCC_TARGHOOKS_H */ >> diff --git a/gcc/testsuite/gcc.target/arm/pure-code/ffunction-sections.c b/gcc/testsuite/gcc.target/arm/pure-code/ffunction-sections.c >> new file mode 100644 >> index 0000000000000000000000000000000000000000..26fe38c05295b70ccc35ed900d41b34aae2c87a8 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/arm/pure-code/ffunction-sections.c >> @@ -0,0 +1,17 @@ >> +/* { dg-do compile } */ >> +/* { dg-skip-if "" { *-*-* } { "-fpic" "-fPIC" } { "" } } */ >> +/* { dg-options "-ffunction-sections -mpure-code" } */ >> +#include >> + >> +char * foo (void) >> +{ >> + return "foo"; >> +} >> + >> +unsigned int bar (unsigned int b) >> +{ >> + return UINT_MAX - b; >> +} >> + >> +/* { dg-final { scan-assembler {\.section\t\.text\.foo[^\n]*\"0x20000006\"} } } */ >> +/* { dg-final { scan-assembler {\.section\t\.text\.bar[^\n]*\"0x20000006\"} } } */ >> diff --git a/gcc/testsuite/gcc.target/arm/pure-code/no-casesi.c b/gcc/testsuite/gcc.target/arm/pure-code/no-casesi.c >> new file mode 100644 >> index 0000000000000000000000000000000000000000..ba116a8261b16610e6af47d26a6e1a07b0127561 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/arm/pure-code/no-casesi.c >> @@ -0,0 +1,29 @@ >> +/* { dg-do compile } */ >> +/* { dg-options "-mpure-code" } */ >> +/* { dg-skip-if "" { *-*-* } { "-g" "-fpic" "-fPIC" } { "" } } */ >> + >> +extern int foo (void); >> +extern int bar (void); >> +extern int baz (void); >> +extern int fooz (void); >> + >> +int caller (unsigned int reg_type) >> +{ >> + switch (reg_type) >> + { >> + case 0x80000000: >> + return (int) foo (); >> + >> + case 0x80000003: >> + return (int) bar (); >> + >> + case 0x80000001: >> + return (int) baz (); >> + >> + case 0x80000004: >> + return (int) fooz (); >> + } >> +} >> + >> +/* { dg-final { scan-assembler-not "\\.(float|l\\?double|\d?byte|short|int|long|quad|word)\\s+\[^.\]" } } */ >> +/* { dg-final { scan-assembler "text,\"0x20000006\"" } } */ >> diff --git a/gcc/testsuite/gcc.target/arm/pure-code/no-literal-pool.c b/gcc/testsuite/gcc.target/arm/pure-code/no-literal-pool.c >> new file mode 100644 >> index 0000000000000000000000000000000000000000..4b893fd32f722e6cd7dfde5c8542ab98327ba375 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/arm/pure-code/no-literal-pool.c >> @@ -0,0 +1,68 @@ >> +/* { dg-do compile } */ >> +/* { dg-options "-mpure-code" } */ >> +/* { dg-skip-if "" { *-*-* } { "-g" "-fpic" "-fPIC" } { "" } } */ >> + >> +float sf; >> +double df; >> +long long l; >> +static char *p = "Hello World"; >> + >> +float >> +testsf (float *p) >> +{ >> + if (*p > 1.1234f) >> + return 2.1234f; >> + else >> + return 3.1234f; >> +} >> + >> +double >> +testdf (double *p) >> +{ >> + if (*p > 4.1234) >> + return 2.1234; >> + else >> + return 3.1234; >> +} >> + >> +long long >> +testll (long long *p) >> +{ >> + if (*p > 0x123456789ABCDEFll) >> + return 0x111111111ll; >> + else >> + return 0x222222222ll; >> +} >> + >> +char * >> +testchar () >> +{ >> + return p + 4; >> +} >> + >> +int >> +foo (int a, int b) >> +{ >> + int i; >> + volatile int *labelref = &&label1; >> + >> + if (a > b) >> + { >> + while (i < b) >> + { >> + a += *labelref; >> + i += 1; >> + } >> + goto *labelref; >> + } >> + else >> + b = b + 3; >> + >> + a = a * b; >> + >> +label1: >> + return a + b; >> +} >> + >> +/* { dg-final { scan-assembler-not "\\.(float|l\\?double|\d?byte|short|int|long|quad|word)\\s+\[^.\]" } } */ >> +/* { dg-final { scan-assembler "text,\"0x20000006\"" } } */ >> diff --git a/gcc/testsuite/gcc.target/arm/pure-code/pure-code.exp b/gcc/testsuite/gcc.target/arm/pure-code/pure-code.exp >> new file mode 100644 >> index 0000000000000000000000000000000000000000..1abe7782c0e5dbb6e2deef25f4bea9415664f942 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/arm/pure-code/pure-code.exp >> @@ -0,0 +1,54 @@ >> +# Copyright (C) 1997-2016 Free Software Foundation, Inc. >> + >> +# This program is free software; you can redistribute it and/or modify >> +# it under the terms of the GNU General Public License as published by >> +# the Free Software Foundation; either version 3 of the License, or >> +# (at your option) any later version. >> +# >> +# This program is distributed in the hope that it will be useful, >> +# but WITHOUT ANY WARRANTY; without even the implied warranty of >> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> +# GNU General Public License for more details. >> +# >> +# You should have received a copy of the GNU General Public License >> +# along with GCC; see the file COPYING3. If not see >> +# . >> + >> +# GCC testsuite for ARM's -mpure-code option, using the `dg.exp' driver. >> + >> +# Load support procs. >> +load_lib gcc-dg.exp >> + >> +# If a testcase doesn't have special options, use these. >> +global DEFAULT_CFLAGS >> +if ![info exists DEFAULT_CFLAGS] then { >> + set DEFAULT_CFLAGS " -ansi -pedantic-errors" >> +} >> + >> +# The -mpure-code option is only available for M-profile targets that support >> +# thumb2. >> +if {[check_effective_target_arm_thumb2_ok] >> + && ![check_effective_target_arm_arm_ok]} then { >> +# Initialize `dg'. >> +dg-init >> + >> +set saved-dg-do-what-default ${dg-do-what-default} >> +set dg-do-what-default "assemble" >> + >> +set saved-lto_torture_options ${LTO_TORTURE_OPTIONS} >> + >> +# Add -ffat-lto-objects option to all LTO options such that we can do assembly >> +# scans. >> +proc add_fat_objects { list } { >> + set res {} >> + foreach el $list {set res [lappend res [concat $el " -ffat-lto-objects"]]} >> + return $res >> +}; >> +set LTO_TORTURE_OPTIONS [add_fat_objects ${LTO_TORTURE_OPTIONS}] >> + >> +gcc-dg-runtest [lsort [glob $srcdir/$subdir/*.c]] \ >> + "" $DEFAULT_CFLAGS >> + >> +# All done. >> +dg-finish >> +} >> diff --git a/gcc/varasm.c b/gcc/varasm.c >> index de8bcd6f20c823acd03991f813da3521b80547ff..13007d8c1ce2d094633422abeb01d91b1e986ac4 100644 >> --- a/gcc/varasm.c >> +++ b/gcc/varasm.c >> @@ -6244,6 +6244,7 @@ default_elf_asm_named_section (const char *name, unsigned int flags, >> tree decl) >> { >> char flagchars[11], *f = flagchars; >> + unsigned int numeric_value; > > I think this should be initialized to zero, rather than assuming the > hook caller will do that for you. > >> >> /* If we have already declared this section, we can use an >> abbreviated form to switch back to it -- unless this section is >> @@ -6256,31 +6257,38 @@ default_elf_asm_named_section (const char *name, unsigned int flags, >> return; >> } >> >> - if (!(flags & SECTION_DEBUG)) >> - *f++ = 'a'; >> + /* If we have a machine specific flag, then use the numeric value to pass >> + this on to GAS. */ >> + if (targetm.asm_out.elf_flags_numeric (flags, &numeric_value)) >> + snprintf (f, sizeof (flagchars), "0x%08x", numeric_value); >> + else >> + { >> + if (!(flags & SECTION_DEBUG)) >> + *f++ = 'a'; >> #if defined (HAVE_GAS_SECTION_EXCLUDE) && HAVE_GAS_SECTION_EXCLUDE == 1 >> - if (flags & SECTION_EXCLUDE) >> - *f++ = 'e'; >> + if (flags & SECTION_EXCLUDE) >> + *f++ = 'e'; >> #endif >> - if (flags & SECTION_WRITE) >> - *f++ = 'w'; >> - if (flags & SECTION_CODE) >> - *f++ = 'x'; >> - if (flags & SECTION_SMALL) >> - *f++ = 's'; >> - if (flags & SECTION_MERGE) >> - *f++ = 'M'; >> - if (flags & SECTION_STRINGS) >> - *f++ = 'S'; >> - if (flags & SECTION_TLS) >> - *f++ = TLS_SECTION_ASM_FLAG; >> - if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE)) >> - *f++ = 'G'; >> + if (flags & SECTION_WRITE) >> + *f++ = 'w'; >> + if (flags & SECTION_CODE) >> + *f++ = 'x'; >> + if (flags & SECTION_SMALL) >> + *f++ = 's'; >> + if (flags & SECTION_MERGE) >> + *f++ = 'M'; >> + if (flags & SECTION_STRINGS) >> + *f++ = 'S'; >> + if (flags & SECTION_TLS) >> + *f++ = TLS_SECTION_ASM_FLAG; >> + if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE)) >> + *f++ = 'G'; >> #ifdef MACH_DEP_SECTION_ASM_FLAG >> - if (flags & SECTION_MACH_DEP) >> - *f++ = MACH_DEP_SECTION_ASM_FLAG; >> + if (flags & SECTION_MACH_DEP) >> + *f++ = MACH_DEP_SECTION_ASM_FLAG; >> #endif >> - *f = '\0'; >> + *f = '\0'; >> + } >> >> fprintf (asm_out_file, "\t.section\t%s,\"%s\"", name, flagchars); >> >> > > R. > I reworked the patch according to the comments above. Is this OK? gcc/ChangeLog: 2016-09-22 Andre Vieira Terry Guo * target.def (elf_flags_numeric): New target hook. * targhooks.h (default_asm_elf_flags_numeric): New. * varasm.c (default_asm_elf_flags_numeric): New. (default_elf_asm_named_section): Use new target hook. * config/arm/arm.opt (mpure-code): New. * config/arm/arm.h (SECTION_ARM_PURECODE): New. * config/arm/arm.c (arm_asm_init_sections): Add section attribute to default text section if -mpure-code. (arm_option_check_internal): Diagnose use of option with non supported targets and/or options. (arm_asm_elf_flags_numeric): New. (arm_function_section): New. (arm_elf_section_type_flags): New. * config/arm/elf.h (JUMP_TABLES_IN_TEXT_SECTION): Disable for -mpure-code. * gcc/doc/texi (TARGET_ASM_ELF_FLAGS_NUMERIC): New. * gcc/doc/texi.in (TARGET_ASM_ELF_FLAGS_NUMERIC): Likewise. gcc/testsuite/ChangeLog: 2016-09-22 Andre Vieira Terry Guo * gcc.target/arm/pure-code/ffunction-sections.c: New. * gcc.target/arm/pure-code/no-literal-pool.c: New. * gcc.target/arm/pure-code/pure-code.exp: New.