This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCHv3][ARM] -mpure-code option for ARM
- From: "Richard Earnshaw (lists)" <Richard dot Earnshaw at arm dot com>
- To: "Andre Vieira (lists)" <Andre dot SimoesDiasVieira at arm dot com>, gcc-patches at gcc dot gnu dot org
- Date: Thu, 22 Sep 2016 16:28:59 +0100
- Subject: Re: [PATCHv3][ARM] -mpure-code option for ARM
- Authentication-results: sourceware.org; auth=none
- References: <57752D6E.9070006@arm.com> <47c8a674-3af0-afff-776b-9d71c0d1bb46@st.com> <5783CFD1.2070500@arm.com> <f5498a4d-c3ba-a13c-6a7d-06ec93c29f40@arm.com> <57E3F2F7.9000409@arm.com>
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.simoesdiasvieira@arm.com>
> Terry Guo <terry.guo@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.simoesdiasvieira@arm.com>
> Terry Guo <terry.guo@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 <andsim01@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);
>
>