On Tue, Jul 04, 2017 at 12:02:47PM +0100, Richard Earnshaw (lists) wrote:
> On 13/06/17 18:00, Torsten Duwe wrote:
> > Changes since v8:
> > 
> >   * Documentation changes as requested by Sandra
> >   * 3 functional test cases added
> > 
> >     Torsten
> > 
> > 
> > gcc/c-family/ChangeLog
> > 2017-06-13  Torsten Duwe  <d...@suse.de>
> > 
> >     * c-attribs.c (c_common_attribute_table): Add entry for
> >     "patchable_function_entry".
> > 
> > gcc/lto/ChangeLog
> > 2017-06-13  Torsten Duwe  <d...@suse.de>
> > 
> >     * lto-lang.c (lto_attribute_table): Add entry for
> >     "patchable_function_entry".
> > 
> > gcc/ChangeLog
> > 2017-06-13  Torsten Duwe  <d...@suse.de>
> > 
> >     * common.opt: Introduce -fpatchable-function-entry
> >     command line option, and its variables function_entry_patch_area_size
> >     and function_entry_patch_area_start.
> >     * opts.c (common_handle_option): Add -fpatchable_function_entry_ case,
> >     including a two-value parser.
> >     * target.def (print_patchable_function_entry): New target hook.
> >     * targhooks.h (default_print_patchable_function_entry): New function.
> >     * targhooks.c (default_print_patchable_function_entry): Likewise.
> >     * toplev.c (process_options): Switch off IPA-RA if
> >     patchable function entries are being generated.
> >     * varasm.c (assemble_start_function): Look at the
> >     patchable-function-entry command line switch and current
> >     function attributes and maybe generate NOP instructions by
> >     calling the print_patchable_function_entry hook.
> >     * doc/extend.texi: Document patchable_function_entry attribute.
> >     * doc/invoke.texi: Document -fpatchable_function_entry
> >     command line option.
> >     * doc/tm.texi.in (TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY):
> >     New target hook.
> >     * doc/tm.texi: Likewise.
> > 
> > gcc/testsuite/ChangeLog
> > 2017-06-13  Torsten Duwe  <d...@suse.de>
> > 
> >     * c-c++-common/patchable_function_entry-default.c: New test.
> >     * c-c++-common/patchable_function_entry-decl.c: Likewise.
> >     * c-c++-common/patchable_function_entry-definition.c: Likewise.
> 
> I think we're nearly there with this one, but there are a couple of nits
> still to sort out.
> 
> I can't see anything in the patch to deal with targets that set
> TARGET_HAVE_NAMED_SECTIONS to false.  We'll probably ICE in that case
> since the compiler will be unable to record the location of the patch
> region in the explicitly named section.  I think the correct thing to do
> there is to reject the option during option validation when we can't
> support it properly.

How about omitting the recording step and document that? This way the
instrumentation can still be useful on e.g. a.out format; the framework
would then have to check around each function entry whether the NOPs are
there.

> The template NOP in default_print_patchable_function_entry needs to be
> added as a GC root to prevent it being discarded during garbage collection.

Are you sure? For the nop_templ I'm only digging my way to the platform-
dependent constant string, which I find amongst the constant strings in
.rodata (or .text, for platforms without named sections ;-).
Is the memory region pointed to by nop_templ really endangered?

> There are a couple of documentation tweaks, which I think help make the
> text a little more comprehensible.  See inline.

Ack for those, in toto. I wrote this stuff, and am actively using it.
I find it sort of hard to imagine to have 0 knowledge about it, and phrase
documentation accordingly. I'd add the half-sentence for non named sections,
see below.

> R.
> 
> > 
> > diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
> > index f2a88e147ba..31137ce0433 100644
> > --- a/gcc/c-family/c-attribs.c
> > +++ b/gcc/c-family/c-attribs.c
> > @@ -139,6 +139,8 @@ static tree handle_bnd_variable_size_attribute (tree *, 
> > tree, tree, int, bool *)
> >  static tree handle_bnd_legacy (tree *, tree, tree, int, bool *);
> >  static tree handle_bnd_instrument (tree *, tree, tree, int, bool *);
> >  static tree handle_fallthrough_attribute (tree *, tree, tree, int, bool *);
> > +static tree handle_patchable_function_entry_attribute (tree *, tree, tree,
> > +                                                  int, bool *);
> >  
> >  /* Table of machine-independent attributes common to all C-like languages.
> >  
> > @@ -345,6 +347,9 @@ const struct attribute_spec c_common_attribute_table[] =
> >                           handle_bnd_instrument, false },
> >    { "fallthrough",       0, 0, false, false, false,
> >                           handle_fallthrough_attribute, false },
> > +  { "patchable_function_entry",    1, 2, true, false, false,
> > +                         handle_patchable_function_entry_attribute,
> > +                         false },
> >    { NULL,                     0, 0, false, false, false, NULL, false }
> >  };
> >  
> > @@ -3173,3 +3178,10 @@ handle_fallthrough_attribute (tree *, tree name, 
> > tree, int,
> >    *no_add_attrs = true;
> >    return NULL_TREE;
> >  }
> > +
> > +static tree
> > +handle_patchable_function_entry_attribute (tree *, tree, tree, int, bool *)
> > +{
> > +  /* Nothing to be done here.  */
> > +  return NULL_TREE;
> > +}
> > diff --git a/gcc/common.opt b/gcc/common.opt
> > index a5c3aeaa336..f542590650c 100644
> > --- a/gcc/common.opt
> > +++ b/gcc/common.opt
> > @@ -163,6 +163,13 @@ bool flag_stack_usage_info = false
> >  Variable
> >  int flag_debug_asm
> >  
> > +; How many NOP insns to place at each function entry by default
> > +Variable
> > +HOST_WIDE_INT function_entry_patch_area_size
> > +
> > +; And how far the real asm entry point is into this area
> > +Variable
> > +HOST_WIDE_INT function_entry_patch_area_start
> >  
> >  ; Balance between GNAT encodings and standard DWARF to emit.
> >  Variable
> > @@ -2022,6 +2029,10 @@ fprofile-reorder-functions
> >  Common Report Var(flag_profile_reorder_functions)
> >  Enable function reordering that improves code placement.
> >  
> > +fpatchable-function-entry=
> > +Common Joined Optimization
> > +Insert NOP instructions at each function entry.
> > +
> >  frandom-seed
> >  Common Var(common_deferred_options) Defer
> >  
> > diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> > index 1255995eb78..d09ccd90c42 100644
> > --- a/gcc/doc/extend.texi
> > +++ b/gcc/doc/extend.texi
> > @@ -3083,6 +3083,25 @@ that affect more than one function.
> >  This attribute should be used for debugging purposes only.  It is not
> >  suitable in production code.
> >  
> > +@item patchable_function_entry
> > +@cindex @code{patchable_function_entry} function attribute
> > +@cindex extra NOP instructions at the function entry point
> > +In case the target's text segment can be made writable at run time by
> > +any means, padding the function entry with a number of NOPs can be
> > +used to provide a universal tool for instrumentation.  
> 
> 
> > +Usually,
> > +patchable function entries are enabled globally using the
> > +@option{-fpatchable-function-entry=N,M} command-line switch, and
> > +disabled with attribute @code{patchable_function_entry (0)} for
> > +functions that are part of the actual instrumentation framework.
> > +This conveniently avoids an endless recursion.
> 
> I think it would be better to use the imperative here.  Perhaps
> something like:
> 
> If patchable function entries are enabled globally using the command
> line option @option{-fpatchable-function-entry=N,M}, then all functions
> that are part of the instrumentation framework must disable
> instrumentation with the attribute @code{patchable_function_entry (0)}
> to prevent recursion.
> 
> However, I'd be inclined to put that in a separate paragraph below
> following text.
> 
> > +The @code{patchable_function_entry} function attribute can be used to
> > +change the number of NOPs to any desired value.  The two-value syntax
> > +is the same as for the command-line switch
> > +@option{-fpatchable-function-entry=N,M}, generating @var{N} NOPs, with
> > +the function entry point before the @var{M}th NOP instruction.
> > +@var{M} defaults to 0 if omitted e.g. function entry point is before
> > +the first NOP.
> > +
> >  @item pure
> >  @cindex @code{pure} function attribute
> >  @cindex functions that have no side effects
> > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> > index 68a558e9992..2e08387ad40 100644
> > --- a/gcc/doc/invoke.texi
> > +++ b/gcc/doc/invoke.texi
> > @@ -11384,6 +11384,34 @@ of the function name, it is considered to be a 
> > match.  For C99 and C++
> >  extended identifiers, the function name must be given in UTF-8, not
> >  using universal character names.
> >  
> > +@item -fpatchable-function-entry=@var{N}[,@var{M}]
> > +@opindex fpatchable-function-entry
> > +Generate @var{N} NOPs right at the beginning
> > +of each function, with the function entry point before the @var{M}th NOP.
> > +If @var{M} is omitted, it defaults to @code{0} so the
> > +function entry points to the address just at the first NOP.
> > +The NOP instructions reserve extra space which can be used to patch in
> > +any desired instrumentation at run time, provided that the code segment
> > +is writable.  The amount of space is controllable indirectly via
> > +the number of NOPs; the NOP instruction used corresponds to the instruction
> > +emitted by the internal GCC back-end interface @code{gen_nop}.  This 
> > behavior
> > +is target-specific and may also depend on the architecture variant and/or
> > +other compilation options.
> > +
> > +For run-time identification, the starting addresses of these areas,
> > +which correspond to their respective function entries minus @var{M},
> > +are additionally collected in the @code{__patchable_function_entries}
> > +section of the resulting binary

, if the target platform supports named sections.
(or the other way, for clarity: If the target..., ... the starting addrs are
collected...)

> > +
> > +Note that the value of @code{__attribute__ ((patchable_function_entry
> > +(N,M)))} takes precedence over command-line option
> > +@option{-fpatchable-function-entry=N,M}.  This can be used to increase
> > +the area size or to remove it completely on a single function.
> > +If @code{N=0}, no pad location is recorded.
> > +
> > +The NOP instructions are inserted at --- and maybe before, depending on
> > +@var{M} --- the function entry address, even before the prologue.
> > +
> >  @end table
> >  
> >  
> > diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
> > index c4f2c893c8e..0e5e20904af 100644
> > --- a/gcc/doc/tm.texi
> > +++ b/gcc/doc/tm.texi
> > @@ -4566,6 +4566,12 @@ will select the smallest suitable mode.
> >  This section describes the macros that output function entry
> >  (@dfn{prologue}) and exit (@dfn{epilogue}) code.
> >  
> > +@deftypefn {Target Hook} void TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY 
> > (FILE *@var{file}, unsigned HOST_WIDE_INT @var{patch_area_size}, bool 
> > @var{record_p})
> > +Generate a patchable area at a function start, consisting of
> > +@var{patch_area_size} NOP instructions.  Note the current location in
> > +a dedicated segment if @var{record_p} is true.   
> 
> I had to parse that final sentence twice to understand what you meant.
> The problem is that in documentation 'Note' is often used as something
> being pointed out to the reader to be of special importance.  Here, I
> think you'd be better off with
> 
> If @var{record_p} is true insert a pointer the current location in the
> table of patchable functions.
> 
> You then need to describe where that 'table' goes.
> 
> > +@end deftypefn
> > +
> >  @deftypefn {Target Hook} void TARGET_ASM_FUNCTION_PROLOGUE (FILE 
> > *@var{file}, HOST_WIDE_INT @var{size})
> >  If defined, a function that outputs the assembler code for entry to a
> >  function.  The prologue is responsible for setting up the stack frame,
> > diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
> > index 1c471d8da35..53696740f48 100644
> > --- a/gcc/doc/tm.texi.in
> > +++ b/gcc/doc/tm.texi.in
> > @@ -3650,6 +3650,8 @@ will select the smallest suitable mode.
> >  This section describes the macros that output function entry
> >  (@dfn{prologue}) and exit (@dfn{epilogue}) code.
> >  
> > +@hook TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY
> > +
> >  @hook TARGET_ASM_FUNCTION_PROLOGUE
> >  
> >  @hook TARGET_ASM_FUNCTION_END_PROLOGUE
> > diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
> > index 52ab2a8cb81..2312ada48c6 100644
> > --- a/gcc/lto/lto-lang.c
> > +++ b/gcc/lto/lto-lang.c
> > @@ -48,6 +48,8 @@ static tree handle_sentinel_attribute (tree *, tree, 
> > tree, int, bool *);
> >  static tree handle_type_generic_attribute (tree *, tree, tree, int, bool 
> > *);
> >  static tree handle_transaction_pure_attribute (tree *, tree, tree, int, 
> > bool *);
> >  static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool 
> > *);
> > +static tree handle_patchable_function_entry_attribute (tree *, tree, tree,
> > +                                                  int, bool *);
> >  static tree ignore_attribute (tree *, tree, tree, int, bool *);
> >  
> >  static tree handle_format_attribute (tree *, tree, tree, int, bool *);
> > @@ -76,6 +78,9 @@ const struct attribute_spec lto_attribute_table[] =
> >                           handle_nonnull_attribute, false },
> >    { "nothrow",                0, 0, true,  false, false,
> >                           handle_nothrow_attribute, false },
> > +  { "patchable_function_entry", 1, 2, true, false, false,
> > +                         handle_patchable_function_entry_attribute,
> > +                         false },
> >    { "returns_twice",          0, 0, true,  false, false,
> >                           handle_returns_twice_attribute, false },
> >    { "sentinel",               0, 1, false, true, true,
> > @@ -473,6 +478,13 @@ handle_returns_twice_attribute (tree *node, tree 
> > ARG_UNUSED (name),
> >    return NULL_TREE;
> >  }
> >  
> > +static tree
> > +handle_patchable_function_entry_attribute (tree *, tree, tree, int, bool *)
> > +{
> > +  /* Nothing to be done here.  */
> > +  return NULL_TREE;
> > +}
> > +
> >  /* Ignore the given attribute.  Used when this attribute may be usefully
> >     overridden by the target, but is not used generically.  */
> >  
> > diff --git a/gcc/opts.c b/gcc/opts.c
> > index ffedb10f18f..f240c01f7d9 100644
> > --- a/gcc/opts.c
> > +++ b/gcc/opts.c
> > @@ -2155,6 +2155,33 @@ common_handle_option (struct gcc_options *opts,
> >          opts->x_flag_ipa_reference = false;
> >        break;
> >  
> > +    case OPT_fpatchable_function_entry_:
> > +      {
> > +   char *patch_area_arg = xstrdup (arg);
> > +   char *comma = strchr (patch_area_arg, ',');
> > +   if (comma)
> > +     {
> > +       *comma = '\0';
> > +       function_entry_patch_area_size = 
> > +         integral_argument (patch_area_arg);
> > +       function_entry_patch_area_start =
> > +         integral_argument (comma + 1);
> > +     }
> > +   else
> > +     {
> > +       function_entry_patch_area_size =
> > +         integral_argument (patch_area_arg);
> > +       function_entry_patch_area_start = 0;
> > +     }
> > +   if (function_entry_patch_area_size < 0
> > +       || function_entry_patch_area_start < 0
> > +       || function_entry_patch_area_size 
> > +           < function_entry_patch_area_start)
> > +     error ("invalid arguments for %<-fpatchable_function_entry%>");
> > +   free (patch_area_arg);
> > +      }
> > +      break;
> > +
> >      case OPT_ftree_vectorize:
> >        if (!opts_set->x_flag_tree_loop_vectorize)
> >          opts->x_flag_tree_loop_vectorize = value;
> > diff --git a/gcc/target.def b/gcc/target.def
> > index 6bebfd5b9d6..53b60f3d276 100644
> > --- a/gcc/target.def
> > +++ b/gcc/target.def
> > @@ -288,6 +288,12 @@ hidden, protected or internal visibility as specified 
> > by @var{visibility}.",
> >   void, (tree decl, int visibility),
> >   default_assemble_visibility)
> >  
> > +DEFHOOK
> > +(print_patchable_function_entry,
> > + "Generate a patchable area at the function start",
> > + void, (FILE *file, unsigned HOST_WIDE_INT patch_area_size, bool record_p),
> > + default_print_patchable_function_entry)
> > +
> >  /* Output the assembler code for entry to a function.  */
> >  DEFHOOK
> >  (function_prologue,
> > diff --git a/gcc/targhooks.c b/gcc/targhooks.c
> > index 1cdec068ed8..f3d9edafafe 100644
> > --- a/gcc/targhooks.c
> > +++ b/gcc/targhooks.c
> > @@ -1609,6 +1609,54 @@ default_compare_by_pieces_branch_ratio (machine_mode)
> >    return 1;
> >  }
> >  
> > +/* Write PATCH_AREA_SIZE NOPs into the asm outfile FILE around a function
> > +   entry.  If RECORD_P is true, the location of the NOPs will be
> > +   recorded in a special object section called 
> > "__patchable_function_entries".

, if the target...

> > +   This routine may be called twice per function to put NOPs before
> > +   and after the function entry.  */
> > +
> > +void
> > +default_print_patchable_function_entry (FILE *file,
> > +                                   unsigned HOST_WIDE_INT patch_area_size,
> > +                                   bool record_p)
> > +{
> > +  static const char *nop_templ = 0;
> 
> You need to record this pointer as a GC root.  Otherwise garbage
> collection might destroy your template NOP.
> 
> > +
> > +  /* We use the template alone, relying on the (currently sane) assumption
> > +     that the NOP template does not have variable operands.  */
> > +  if (!nop_templ)
> > +    {
> > +      int code_num;
> > +      rtx_insn *my_nop = make_insn_raw (gen_nop ());
> > +
> > +      code_num = recog_memoized (my_nop);
> > +      nop_templ = get_insn_template (code_num, my_nop);
> > +    }
> > +

#if TARGET_HAVE_NAMED_SECTIONS
> > +  if (record_p)
> > +    {
> > +      char buf[256];
> > +      static int patch_area_number;
> > +      section *previous_section = in_section;
> > +
> > +      patch_area_number++;
> > +      ASM_GENERATE_INTERNAL_LABEL (buf, "LPFE", patch_area_number);
> > +
> > +      switch_to_section (get_section ("__patchable_function_entries",
> > +                                 0, NULL));
> > +      fputs (integer_asm_op (POINTER_SIZE_UNITS, false), file);
> > +      assemble_name_raw (file, buf);
> > +      fputc ('\n', file);
> > +
> > +      switch_to_section (previous_section);
> > +      ASM_OUTPUT_LABEL (file, buf);
> > +    }
#endif

        ?

> > +
> > +  unsigned i;
> > +  for (i = 0; i < patch_area_size; ++i)
> > +    fprintf (file, "\t%s\n", nop_templ);
> > +}
> > +
> >  bool
> >  default_profile_before_prologue (void)
> >  {
> > diff --git a/gcc/targhooks.h b/gcc/targhooks.h
> > index 18070df7839..6206fe20823 100644
> > --- a/gcc/targhooks.h
> > +++ b/gcc/targhooks.h
> > @@ -203,6 +203,9 @@ extern bool default_use_by_pieces_infrastructure_p 
> > (unsigned HOST_WIDE_INT,
> >                                                 bool);
> >  extern int default_compare_by_pieces_branch_ratio (machine_mode);
> >  
> > +extern void default_print_patchable_function_entry (FILE *,
> > +                                               unsigned HOST_WIDE_INT,
> > +                                               bool);
> >  extern bool default_profile_before_prologue (void);
> >  extern reg_class_t default_preferred_reload_class (rtx, reg_class_t);
> >  extern reg_class_t default_preferred_output_reload_class (rtx, 
> > reg_class_t);
> > diff --git a/gcc/testsuite/c-c++-common/patchable_function_entry-decl.c 
> > b/gcc/testsuite/c-c++-common/patchable_function_entry-decl.c
> > new file mode 100644
> > index 00000000000..8514b10e820
> > --- /dev/null
> > +++ b/gcc/testsuite/c-c++-common/patchable_function_entry-decl.c
> > @@ -0,0 +1,16 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -fpatchable-function-entry=3,1" } */
> > +/* { dg-final { scan-assembler-times "nop" 2 } } */
> > +
> > +extern int a;
> > +
> > +/* Respect overriding attributes in the declaration.  */
> > +int f3 (void) __attribute__((patchable_function_entry(2)));
> > +
> > +/* F3 should now get 2 NOPs.  */
> > +int
> > +__attribute__((noinline))
> > +f3 (void)
> > +{
> > +  return 5*a;
> > +}
> > diff --git a/gcc/testsuite/c-c++-common/patchable_function_entry-default.c 
> > b/gcc/testsuite/c-c++-common/patchable_function_entry-default.c
> > new file mode 100644
> > index 00000000000..0dcf1181dde
> > --- /dev/null
> > +++ b/gcc/testsuite/c-c++-common/patchable_function_entry-default.c
> > @@ -0,0 +1,16 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -fpatchable-function-entry=3,1" } */
> > +/* { dg-final { scan-assembler-times "nop" 3 } } */
> > +
> > +extern int a;
> > +
> > +/* Nothing declared must not mean anything.  */
> > +int f3 (void);
> > +
> > +/* F3 should get a default-sized NOP area.  */
> > +int
> > +__attribute__((noinline))
> > +f3 (void)
> > +{
> > +  return 5*a;
> > +}
> > diff --git 
> > a/gcc/testsuite/c-c++-common/patchable_function_entry-definition.c 
> > b/gcc/testsuite/c-c++-common/patchable_function_entry-definition.c
> > new file mode 100644
> > index 00000000000..a007867dcb0
> > --- /dev/null
> > +++ b/gcc/testsuite/c-c++-common/patchable_function_entry-definition.c
> > @@ -0,0 +1,16 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -fpatchable-function-entry=3,1" } */
> > +/* { dg-final { scan-assembler-times "nop" 1 } } */
> > +
> > +extern int a;
> > +
> > +int f3 (void);
> > +
> > +/* F3 should now get 1 NOP.  */
> > +int
> > +__attribute__((noinline))
> > +__attribute__((patchable_function_entry(1)))
> > +f3 (void)
> > +{
> > +  return 5*a;
> > +}
> > diff --git a/gcc/toplev.c b/gcc/toplev.c
> > index f1384fc2fda..84969fb8ef4 100644
> > --- a/gcc/toplev.c
> > +++ b/gcc/toplev.c
> > @@ -1612,8 +1612,10 @@ process_options (void)
> >      }
> >  
> >   /* Do not use IPA optimizations for register allocation if profiler is 
> > active
> > +    or patchable function entries are inserted for run-time instrumentation
> >      or port does not emit prologue and epilogue as RTL.  */
> > -  if (profile_flag || !targetm.have_prologue () || !targetm.have_epilogue 
> > ())
> > +  if (profile_flag || function_entry_patch_area_size
> > +      || !targetm.have_prologue () || !targetm.have_epilogue ())
> >      flag_ipa_ra = 0;
> >  
> >    /* Enable -Werror=coverage-mismatch when -Werror and -Wno-error
> > diff --git a/gcc/varasm.c b/gcc/varasm.c
> > index 05e48a5b894..6c3a56419e8 100644
> > --- a/gcc/varasm.c
> > +++ b/gcc/varasm.c
> > @@ -1830,6 +1830,46 @@ assemble_start_function (tree decl, const char 
> > *fnname)
> >    if (DECL_PRESERVE_P (decl))
> >      targetm.asm_out.mark_decl_preserved (fnname);
> >  
> > +  unsigned HOST_WIDE_INT patch_area_size = function_entry_patch_area_size;
> > +  unsigned HOST_WIDE_INT patch_area_entry = 
> > function_entry_patch_area_start;
> > +
> > +  tree patchable_function_entry_attr
> > +    = lookup_attribute ("patchable_function_entry", DECL_ATTRIBUTES 
> > (decl));
> > +  if (patchable_function_entry_attr)
> > +    {
> > +      tree pp_val = TREE_VALUE (patchable_function_entry_attr);
> > +      tree patchable_function_entry_value1 = TREE_VALUE (pp_val);
> > +
> > +      if (tree_fits_uhwi_p (patchable_function_entry_value1))
> > +   patch_area_size = tree_to_uhwi (patchable_function_entry_value1);
> > +      else
> > +   gcc_unreachable ();
> > +
> > +      patch_area_entry = 0;
> > +      if (list_length (pp_val) > 1)
> > +   {
> > +     tree patchable_function_entry_value2 =
> > +       TREE_VALUE (TREE_CHAIN (pp_val));
> > +
> > +     if (tree_fits_uhwi_p (patchable_function_entry_value2))
> > +       patch_area_entry = tree_to_uhwi (patchable_function_entry_value2);
> > +     else
> > +       gcc_unreachable ();
> > +   }
> > +    }
> > +
> > +  if (patch_area_entry > patch_area_size)
> > +    {
> > +      if (patch_area_size > 0)
> > +   warning (OPT_Wattributes, "Patchable function entry > size");
> > +      patch_area_entry = 0;
> > +    }
> > +
> > +  /* Emit the patching area before the entry label, if any.  */
> > +  if (patch_area_entry > 0)
> > +    targetm.asm_out.print_patchable_function_entry (asm_out_file,
> > +                                               patch_area_entry, true);
> > +
> >    /* Do any machine/system dependent processing of the function name.  */
> >  #ifdef ASM_DECLARE_FUNCTION_NAME
> >    ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname, current_function_decl);
> > @@ -1838,6 +1878,12 @@ assemble_start_function (tree decl, const char 
> > *fnname)
> >    ASM_OUTPUT_FUNCTION_LABEL (asm_out_file, fnname, current_function_decl);
> >  #endif /* ASM_DECLARE_FUNCTION_NAME */
> >  
> > +  /* And the area after the label.  Record it if we haven't done so yet.  
> > */
> > +  if (patch_area_size > patch_area_entry)
> > +    targetm.asm_out.print_patchable_function_entry (asm_out_file,
> > +                                        patch_area_size-patch_area_entry,
> > +                                               patch_area_entry == 0);
> > +
> >    if (lookup_attribute ("no_split_stack", DECL_ATTRIBUTES (decl)))
> >      saw_no_split_stack = true;
> >  }
> > 
> 

Reply via email to