On 22/09/16 16:04, Andre Vieira (lists) wrote: > > I reworked the patch according to the comments above. > > Is this OK? > > gcc/ChangeLog: > 2016-09-22 Andre Vieira <andre.simoesdiasvie...@arm.com> > Terry Guo <terry....@arm.com> > > * 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 <andre.simoesdiasvie...@arm.com> > Terry Guo <terry....@arm.com> > > * 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. > >
I missed this last time around, but please can you wrap references to SHF_ARM_PURECODE in the documentation with @code{...}. OK with that change. R. > 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 d0e5894dbe59ea87a3dfc9f681d5616f178ce3a7 Mon Sep 17 00:00:00 2001 > From: Andre Simoes Dias Vieira <andsi...@arm.com> > Date: Tue, 14 Jun 2016 11:17:12 +0100 > Subject: [PATCH] mpure-code for ARM > > --- > gcc/config/arm/arm.c | 145 > ++++++++++++++++++++- > gcc/config/arm/arm.h | 4 + > gcc/config/arm/arm.md | 2 +- > gcc/config/arm/arm.opt | 4 + > gcc/config/arm/elf.h | 3 +- > gcc/doc/invoke.texi | 11 +- > gcc/doc/tm.texi | 12 ++ > gcc/doc/tm.texi.in | 2 + > gcc/hooks.c | 10 ++ > gcc/target.def | 16 +++ > 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, 397 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..59dc2d3392bf375e26507041309e219215198d62 > 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,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. */ > @@ -3453,8 +3471,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 > @@ -27208,17 +27227,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 > @@ -30529,4 +30555,111 @@ 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 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 -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 > + 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" > 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..35f047e2de1659c2b426cf42dbbdae5be62cbfef > 100644 > --- a/gcc/config/arm/arm.opt > +++ b/gcc/config/arm/arm.opt > @@ -281,3 +281,7 @@ 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) > +Do not allow constant data to be placed in code sections. > 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..f673d7d2172d53422e56457c0039b96a08a526b4 > 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 > +Do not allow constant data to be placed in code sections. > +Additionally, when compiling for ELF object format give all text sections the > +ELF processor-specific section attribute SHF_ARM_PURECODE. This option is > only > +available when generating non-pic code for ARMv7-M targets. > + > @end table > > @node AVR Options > diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi > index > b318615b7b35ab93ad13e5e535a1d4e6d02cb7f7..2c717960d8cea72a93da6e23abcd01aed3b37d6e > 100644 > --- a/gcc/doc/tm.texi > +++ b/gcc/doc/tm.texi > @@ -7543,6 +7543,18 @@ 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}) > +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. > +@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..dc5a39aa724b05a3adb06c3af1b24fdff0d428c1 > 100644 > --- a/gcc/target.def > +++ b/gcc/target.def > @@ -432,6 +432,22 @@ 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, > + "This hook can be used to encode ELF section flags for which no letter\n\ > +code has been defined in the assembler. It is called by\n\ > +@code{default_asm_named_section} whenever the section flags need to be\n\ > +emitted in the assembler output. If the hook returns true, then the\n\ > +numerical value for ELF section flags should be calculated from\n\ > +@var{flags} and saved in @var{*num}; the value will be printed out\n\ > +instead of the normal sequence of letter codes. If the hook is not\n\ > +defined, or if it returns false, then @var{num} will be ignored and the\n\ > +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 <limits.h> > + > +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 > +# <http://www.gnu.org/licenses/>. > + > +# 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..c72c779484fd2ba7bdc58285437ef89ec9effbad > 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 = 0; > > /* 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); > >