[PATCHv3][ARM] -mpure-code option for ARM

Richard Earnshaw (lists) Richard.Earnshaw@arm.com
Thu Sep 22 15:47:00 GMT 2016


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);
>  
> 



More information about the Gcc-patches mailing list