From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 72820 invoked by alias); 20 Jul 2017 10:58:16 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 72806 invoked by uid 89); 20 Jul 2017 10:58:15 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.2 spammy=colleagues, H*r:ip*192.168.1.65, U** X-HELO: mail-lf0-f45.google.com Received: from mail-lf0-f45.google.com (HELO mail-lf0-f45.google.com) (209.85.215.45) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 20 Jul 2017 10:58:11 +0000 Received: by mail-lf0-f45.google.com with SMTP id g25so6783468lfh.1 for ; Thu, 20 Jul 2017 03:58:11 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:subject:from:in-reply-to:date:cc :content-transfer-encoding:message-id:references:to; bh=4Li/xL4yGNKkD0WSS+SYRpLyeocR+m4Fna83pfTlxR0=; b=VWLK6WWn00H4OLnQqr7xkE9Dk3i7FOCKQGksxrOMXgvlw4bD5bjjm2XeiR+2IzbcWm 6i8JSy1DorRktZOx6hdEUJAa8oOQZdgPQDvk5lNNkh3K+HnitcxJVPLmW3FtCAbO7QRj FLY/e70qd0+ti+bolQhLP+CS4gL8vJAh0CD175MN7gR1Wae5U92Hfu7vbMPOAsg0FJp9 yITj4AGkYo7Uk0I7y1owi31OHI0lgqd5+iyaAbWLHM9moX129pQACBdkNfXw6wsTNYZo EKkKMyvNXIQOlPxdIbpATZjWVxEb91lfDsrPwqEK8w9WjZMeQdAPYjU7MdVtSOrZ+cQC 3NyQ== X-Gm-Message-State: AIVw113jeCdxz+epSgardEr5b/AswCmBTPRLxlW8p/tjSKsXzaMeuIOT Dmjyu0ngMz/SIp4H X-Received: by 10.25.15.103 with SMTP id e100mr241464lfi.62.1500548288997; Thu, 20 Jul 2017 03:58:08 -0700 (PDT) Received: from [192.168.1.65] (ppp109-252-218-78.pppoe.spdop.ru. [109.252.218.78]) by smtp.gmail.com with ESMTPSA id t7sm424489lfi.53.2017.07.20.03.58.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 20 Jul 2017 03:58:07 -0700 (PDT) Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 10.3 \(3273\)) Subject: Re: [PATCH v12] add -fpatchable-function-entry=N,M option From: Maxim Kuvyrkov In-Reply-To: <20170717121046.GA22056@suse.de> Date: Thu, 20 Jul 2017 10:58:00 -0000 Cc: "Richard Earnshaw (lists)" , Sandra Loosemore , Marek Polacek , GCC Patches , Szabolcs Nagy , nd@arm.com, Li Bin , Jiri Kosina , Marcus Shawcroft , Takahiro Akashi , Andrew Wafaa Content-Transfer-Encoding: quoted-printable Message-Id: <09075950-0C9D-4B43-B9BB-971A0F57B03E@linaro.org> References: <20170706140311.GA20710@suse.de> <20170707193028.GA17752@suse.de> <20170717121046.GA22056@suse.de> To: Torsten Duwe , Richard Biener , Jan Hubicka X-SW-Source: 2017-07/txt/msg01221.txt.bz2 > On Jul 17, 2017, at 3:10 PM, Torsten Duwe wrote: >=20 > What is the next step now? Is anybody going to commit that patch? >=20 > Torsten >=20 > On Fri, Jul 07, 2017 at 02:57:55PM +0100, Richard Earnshaw (lists) wrote: >> On 06/07/17 15:03, Torsten Duwe wrote: >> +#if TARGET_HAVE_NAMED_SECTIONS >=20 > No, this is a hook. You need to test targetm_common.have_named_sections. >=20 > OK with that change. Torsten, if you prefer I can commit your patch (after bootstrap and a regte= st on aarch64-linux-gnu and x86_64-linux-gnu). There is one last hurdle to sort out with the FSF copyright assignment. Lo= oking at FSF's list I don't see SuSe's copyright assignment for your contri= butions to FSF projects, of which GCC is one. You can either request SuSe = to file a copyright assignment for you, or, probably simpler, ask one of yo= ur SuSe colleagues (Richard B., Jan H.) to commit under their assignment. -- Maxim Kuvyrkov www.linaro.org >=20 > R. >=20 > On Fri, Jul 07, 2017 at 09:30:28PM +0200, Torsten Duwe wrote: >> Change since v11: >>=20 >> < +#if TARGET_HAVE_NAMED_SECTIONS >>=20 >>> + if (record_p && targetm_common.have_named_sections) >>=20 >> (plus > +#include "common/common-target.h" ) >>=20 >> Torsten >>=20 >>=20 >> gcc/c-family/ChangeLog >> 2017-07-07 Torsten Duwe >>=20 >> * c-attribs.c (c_common_attribute_table): Add entry for >> "patchable_function_entry". >>=20 >> gcc/lto/ChangeLog >> 2017-07-07 Torsten Duwe >>=20 >> * lto-lang.c (lto_attribute_table): Add entry for >> "patchable_function_entry". >>=20 >> gcc/ChangeLog >> 2017-07-07 Torsten Duwe >>=20 >> * 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. >>=20 >> gcc/testsuite/ChangeLog >> 2017-07-07 Torsten Duwe >>=20 >> * 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. >>=20 >> diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c >> index 626ffa1cde7..ecb00c1d5b9 100644 >> --- a/gcc/c-family/c-attribs.c >> +++ b/gcc/c-family/c-attribs.c >> @@ -142,6 +142,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, tr= ee, >> + int, bool *); >>=20 >> /* Table of machine-independent attributes common to all C-like language= s. >>=20 >> @@ -351,6 +353,9 @@ const struct attribute_spec c_common_attribute_table= [] =3D >> 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 } >> }; >>=20 >> @@ -3260,3 +3265,10 @@ handle_fallthrough_attribute (tree *, tree name, = tree, int, >> *no_add_attrs =3D true; >> return NULL_TREE; >> } >> + >> +static tree >> +handle_patchable_function_entry_attribute (tree *, tree, tree, int, boo= l *) >> +{ >> + /* Nothing to be done here. */ >> + return NULL_TREE; >> +} >> diff --git a/gcc/common.opt b/gcc/common.opt >> index e81165c488b..78cfa568a95 100644 >> --- a/gcc/common.opt >> +++ b/gcc/common.opt >> @@ -163,6 +163,13 @@ bool flag_stack_usage_info =3D false >> Variable >> int flag_debug_asm >>=20 >> +; 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 >>=20 >> ; Balance between GNAT encodings and standard DWARF to emit. >> Variable >> @@ -2030,6 +2037,10 @@ fprofile-reorder-functions >> Common Report Var(flag_profile_reorder_functions) >> Enable function reordering that improves code placement. >>=20 >> +fpatchable-function-entry=3D >> +Common Joined Optimization >> +Insert NOP instructions at each function entry. >> + >> frandom-seed >> Common Var(common_deferred_options) Defer >>=20 >> diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi >> index 5cb512fe575..9c171abc121 100644 >> --- a/gcc/doc/extend.texi >> +++ b/gcc/doc/extend.texi >> @@ -3105,6 +3105,27 @@ that affect more than one function. >> This attribute should be used for debugging purposes only. It is not >> suitable in production code. >>=20 >> +@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. >> + >> +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=3DN,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. >> + >> +If patchable function entries are enabled globally using the command-li= ne >> +option @option{-fpatchable-function-entry=3DN,M}, then you must disable >> +instrumentation on all functions that are part of the instrumentation >> +framework with the attribute @code{patchable_function_entry (0)} >> +to prevent recursion. >> + >> @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 d0b90503ced..dc93f0ccd50 100644 >> --- a/gcc/doc/invoke.texi >> +++ b/gcc/doc/invoke.texi >> @@ -11520,6 +11520,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. >>=20 >> +@item -fpatchable-function-entry=3D@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 NO= P. >> +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 instruc= tion >> +emitted by the internal GCC back-end interface @code{gen_nop}. This be= havior >> +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. >> + >> +Note that the value of @code{__attribute__ ((patchable_function_entry >> +(N,M)))} takes precedence over command-line option >> +@option{-fpatchable-function-entry=3DN,M}. This can be used to increase >> +the area size or to remove it completely on a single function. >> +If @code{N=3D0}, 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 >>=20 >>=20 >> diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi >> index 795e49246af..23e85c7afea 100644 >> --- a/gcc/doc/tm.texi >> +++ b/gcc/doc/tm.texi >> @@ -4573,6 +4573,15 @@ will select the smallest suitable mode. >> This section describes the macros that output function entry >> (@dfn{prologue}) and exit (@dfn{epilogue}) code. >>=20 >> +@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 the function start, consisting of >> +@var{patch_area_size} NOP instructions. If the target supports named >> +sections and if @var{record_p} is true, insert a pointer to the current >> +location in the table of patchable functions. The default implementati= on >> +of the hook places the table of pointers in the special section named >> +@code{__patchable_function_entries}. >> +@end deftypefn >> + >> @deftypefn {Target Hook} void TARGET_ASM_FUNCTION_PROLOGUE (FILE *@var{f= ile}, 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 98f2e6bce5f..6df08a2c477 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. >>=20 >> +@hook TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY >> + >> @hook TARGET_ASM_FUNCTION_PROLOGUE >>=20 >> @hook TARGET_ASM_FUNCTION_END_PROLOGUE >> diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c >> index 58935172b2c..6e9a138fa3b 100644 >> --- a/gcc/lto/lto-lang.c >> +++ b/gcc/lto/lto-lang.c >> @@ -48,6 +48,8 @@ static tree handle_sentinel_attribute (tree *, tree, t= ree, 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, boo= l *); >> +static tree handle_patchable_function_entry_attribute (tree *, tree, tr= ee, >> + int, bool *); >> static tree ignore_attribute (tree *, tree, tree, int, bool *); >>=20 >> static tree handle_format_attribute (tree *, tree, tree, int, bool *); >> @@ -76,6 +78,9 @@ const struct attribute_spec lto_attribute_table[] =3D >> 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 AR= G_UNUSED (name), >> return NULL_TREE; >> } >>=20 >> +static tree >> +handle_patchable_function_entry_attribute (tree *, tree, tree, int, boo= l *) >> +{ >> + /* 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. */ >>=20 >> diff --git a/gcc/opts.c b/gcc/opts.c >> index 7555ed55434..fecf97978fc 100644 >> --- a/gcc/opts.c >> +++ b/gcc/opts.c >> @@ -2199,6 +2199,33 @@ common_handle_option (struct gcc_options *opts, >> opts->x_flag_ipa_reference =3D false; >> break; >>=20 >> + case OPT_fpatchable_function_entry_: >> + { >> + char *patch_area_arg =3D xstrdup (arg); >> + char *comma =3D strchr (patch_area_arg, ','); >> + if (comma) >> + { >> + *comma =3D '\0'; >> + function_entry_patch_area_size =3D=20 >> + integral_argument (patch_area_arg); >> + function_entry_patch_area_start =3D >> + integral_argument (comma + 1); >> + } >> + else >> + { >> + function_entry_patch_area_size =3D >> + integral_argument (patch_area_arg); >> + function_entry_patch_area_start =3D 0; >> + } >> + if (function_entry_patch_area_size < 0 >> + || function_entry_patch_area_start < 0 >> + || function_entry_patch_area_size=20 >> + < 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 =3D value; >> diff --git a/gcc/target.def b/gcc/target.def >> index bbd9c015189..6d67b1fe8ba 100644 >> --- a/gcc/target.def >> +++ b/gcc/target.def >> @@ -288,6 +288,17 @@ hidden, protected or internal visibility as specifi= ed by @var{visibility}.", >> void, (tree decl, int visibility), >> default_assemble_visibility) >>=20 >> +DEFHOOK >> +(print_patchable_function_entry, >> + "Generate a patchable area at the function start, consisting of\n\ >> +@var{patch_area_size} NOP instructions. If the target supports named\n\ >> +sections and if @var{record_p} is true, insert a pointer to the current= \n\ >> +location in the table of patchable functions. The default implementati= on\n\ >> +of the hook places the table of pointers in the special section named\n\ >> +@code{__patchable_function_entries}.", >> + 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 940deec67f9..6a8fae656d0 100644 >> --- a/gcc/targhooks.c >> +++ b/gcc/targhooks.c >> @@ -73,6 +73,7 @@ along with GCC; see the file COPYING3. If not see >> #include "calls.h" >> #include "expr.h" >> #include "output.h" >> +#include "common/common-target.h" >> #include "reload.h" >> #include "intl.h" >> #include "opts.h" >> @@ -1610,6 +1611,51 @@ default_compare_by_pieces_branch_ratio (machine_m= ode) >> return 1; >> } >>=20 >> +/* Write PATCH_AREA_SIZE NOPs into the asm outfile FILE around a functi= on >> + entry. If RECORD_P is true and the target supports named sections, >> + the location of the NOPs will be recorded in a special object section >> + called "__patchable_function_entries". 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) >> +{ >> + const char *nop_templ =3D 0; >> + int code_num; >> + rtx_insn *my_nop =3D make_insn_raw (gen_nop ()); >> + >> + /* We use the template alone, relying on the (currently sane) assumpt= ion >> + that the NOP template does not have variable operands. */ >> + code_num =3D recog_memoized (my_nop); >> + nop_templ =3D get_insn_template (code_num, my_nop); >> + >> + if (record_p && targetm_common.have_named_sections) >> + { >> + char buf[256]; >> + static int patch_area_number; >> + section *previous_section =3D 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); >> + } >> + >> + unsigned i; >> + for (i =3D 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 1ddb8891fe4..c73ea0bda20 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); >>=20 >> +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=3D3,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=3D3,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-definit= ion.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=3D3,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 e6c69a4ba93..b28f1847c83 100644 >> --- a/gcc/toplev.c >> +++ b/gcc/toplev.c >> @@ -1630,8 +1630,10 @@ process_options (void) >> } >>=20 >> /* Do not use IPA optimizations for register allocation if profiler is = active >> + or patchable function entries are inserted for run-time instrumenta= tion >> or port does not emit prologue and epilogue as RTL. */ >> - if (profile_flag || !targetm.have_prologue () || !targetm.have_epilog= ue ()) >> + if (profile_flag || function_entry_patch_area_size >> + || !targetm.have_prologue () || !targetm.have_epilogue ()) >> flag_ipa_ra =3D 0; >>=20 >> /* Enable -Werror=3Dcoverage-mismatch when -Werror and -Wno-error >> diff --git a/gcc/varasm.c b/gcc/varasm.c >> index fbaebc1b5c0..ec1640ea378 100644 >> --- a/gcc/varasm.c >> +++ b/gcc/varasm.c >> @@ -1825,6 +1825,46 @@ assemble_start_function (tree decl, const char *f= nname) >> if (DECL_PRESERVE_P (decl)) >> targetm.asm_out.mark_decl_preserved (fnname); >>=20 >> + unsigned HOST_WIDE_INT patch_area_size =3D function_entry_patch_area_= size; >> + unsigned HOST_WIDE_INT patch_area_entry =3D function_entry_patch_area= _start; >> + >> + tree patchable_function_entry_attr >> + =3D lookup_attribute ("patchable_function_entry", DECL_ATTRIBUTES (= decl)); >> + if (patchable_function_entry_attr) >> + { >> + tree pp_val =3D TREE_VALUE (patchable_function_entry_attr); >> + tree patchable_function_entry_value1 =3D TREE_VALUE (pp_val); >> + >> + if (tree_fits_uhwi_p (patchable_function_entry_value1)) >> + patch_area_size =3D tree_to_uhwi (patchable_function_entry_value1); >> + else >> + gcc_unreachable (); >> + >> + patch_area_entry =3D 0; >> + if (list_length (pp_val) > 1) >> + { >> + tree patchable_function_entry_value2 =3D >> + TREE_VALUE (TREE_CHAIN (pp_val)); >> + >> + if (tree_fits_uhwi_p (patchable_function_entry_value2)) >> + patch_area_entry =3D 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 =3D 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= ); >> @@ -1833,6 +1873,12 @@ assemble_start_function (tree decl, const char *f= nname) >> ASM_OUTPUT_FUNCTION_LABEL (asm_out_file, fnname, current_function_decl= ); >> #endif /* ASM_DECLARE_FUNCTION_NAME */ >>=20 >> + /* 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 =3D=3D 0); >> + >> if (lookup_attribute ("no_split_stack", DECL_ATTRIBUTES (decl))) >> saw_no_split_stack =3D true; >> }