Home | History | Annotate | Line # | Download | only in gcc
      1 /* strub (stack scrubbing) support.
      2    Copyright (C) 2021-2024 Free Software Foundation, Inc.
      3    Contributed by Alexandre Oliva <oliva (at) adacore.com>.
      4 
      5 This file is part of GCC.
      6 
      7 GCC is free software; you can redistribute it and/or modify it under
      8 the terms of the GNU General Public License as published by the Free
      9 Software Foundation; either version 3, or (at your option) any later
     10 version.
     11 
     12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15 for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with GCC; see the file COPYING3.  If not see
     19 <http://www.gnu.org/licenses/>.  */
     20 
     21 #include "config.h"
     22 #include "system.h"
     23 #include "coretypes.h"
     24 #include "backend.h"
     25 #include "tree.h"
     26 #include "gimple.h"
     27 #include "gimplify.h"
     28 #include "tree-pass.h"
     29 #include "ssa.h"
     30 #include "gimple-iterator.h"
     31 #include "gimplify-me.h"
     32 #include "tree-into-ssa.h"
     33 #include "tree-ssa.h"
     34 #include "tree-cfg.h"
     35 #include "cfghooks.h"
     36 #include "cfgloop.h"
     37 #include "cfgcleanup.h"
     38 #include "tree-eh.h"
     39 #include "except.h"
     40 #include "builtins.h"
     41 #include "attribs.h"
     42 #include "tree-inline.h"
     43 #include "cgraph.h"
     44 #include "alloc-pool.h"
     45 #include "symbol-summary.h"
     46 #include "sreal.h"
     47 #include "ipa-cp.h"
     48 #include "ipa-prop.h"
     49 #include "ipa-fnsummary.h"
     50 #include "gimple-fold.h"
     51 #include "fold-const.h"
     52 #include "gimple-walk.h"
     53 #include "tree-dfa.h"
     54 #include "langhooks.h"
     55 #include "calls.h"
     56 #include "vec.h"
     57 #include "stor-layout.h"
     58 #include "varasm.h"
     59 #include "alias.h"
     60 #include "diagnostic.h"
     61 #include "intl.h"
     62 #include "ipa-strub.h"
     63 #include "symtab-thunks.h"
     64 #include "attr-fnspec.h"
     65 #include "target.h"
     66 
     67 /* This file introduces two passes that, together, implement
     68    machine-independent stack scrubbing, strub for short.  It arranges
     69    for stack frames that have strub enabled to be zeroed-out after
     70    relinquishing control to a caller, whether by returning or by
     71    propagating an exception.  This admittedly unusual design decision
     72    was driven by exception support (one needs a stack frame to be
     73    active to propagate exceptions out of it), and it enabled an
     74    implementation that is entirely machine-independent (no custom
     75    epilogue code is required).
     76 
     77    Strub modes can be selected for stack frames by attaching attribute
     78    strub to functions or to variables (to their types, actually).
     79    Different strub modes, with different implementation details, are
     80    available, and they can be selected by an argument to the strub
     81    attribute.  When enabled by strub-enabled variables, whether by
     82    accessing (as in reading from) statically-allocated ones, or by
     83    introducing (as in declaring) automatically-allocated ones, a
     84    suitable mode is selected automatically.
     85 
     86    At-calls mode modifies the interface of a function, adding a stack
     87    watermark argument, that callers use to clean up the stack frame of
     88    the called function.  Because of the interface change, it can only
     89    be used when explicitly selected, or when a function is internal to
     90    a translation unit.  Strub-at-calls function types are distinct
     91    from their original types (they're not modified in-place), and they
     92    are not interchangeable with other function types.
     93 
     94    Internal mode, in turn, does not modify the type or the interface
     95    of a function.  It is currently implemented by turning the function
     96    into a wrapper, moving the function body to a separate wrapped
     97    function, and scrubbing the wrapped body's stack in the wrapper.
     98    Internal-strub function types are mostly interface-compatible with
     99    other strub modes, namely callable (from strub functions, though
    100    not strub-enabled) and disabled (not callable from strub
    101    functions).
    102 
    103    Always_inline functions can be strub functions, but they can only
    104    be called from other strub functions, because strub functions must
    105    never be inlined into non-strub functions.  Internal and at-calls
    106    modes are indistinguishable when it comes to always_inline
    107    functions: they will necessarily be inlined into another strub
    108    function, and will thus be integrated into the caller's stack
    109    frame, whatever the mode.  (Contrast with non-always_inline strub
    110    functions: an at-calls function can be called from other strub
    111    functions, ensuring no discontinuity in stack erasing, whereas an
    112    internal-strub function can only be called from other strub
    113    functions if it happens to be inlined, or if -fstrub=relaxed mode
    114    is in effect (that's the default).  In -fstrub=strict mode,
    115    internal-strub functions are not callable from strub functions,
    116    because the wrapper itself is not strubbed.
    117 
    118    The implementation involves two simple-IPA passes.  The earliest
    119    one, strub-mode, assigns strub modes to functions.  It needs to run
    120    before any inlining, so that we can prevent inlining of strub
    121    functions into non-strub functions.  It notes explicit strub mode
    122    requests, enables strub in response to strub variables and testing
    123    options, and flags unsatisfiable requests.
    124 
    125    Three possibilities of unsatisfiable requests come to mind: (a)
    126    when a strub mode is explicitly selected, but the function uses
    127    features that make it ineligible for that mode (e.g. at-calls rules
    128    out calling __builtin_apply_args, because of the interface changes,
    129    and internal mode rules out noclone or otherwise non-versionable
    130    functions, non-default varargs, non-local or forced labels, and
    131    functions with far too many arguments); (b) when some strub mode
    132    must be enabled because of a strub variable, but the function is
    133    not eligible or not viable for any mode; and (c) when
    134    -fstrub=strict is enabled, and calls are found in strub functions
    135    to functions that are not callable from strub contexts.
    136    compute_strub_mode implements (a) and (b), and verify_strub
    137    implements (c).
    138 
    139    The second IPA pass modifies interfaces of at-calls-strub functions
    140    and types, introduces strub calls in and around them. and splits
    141    internal-strub functions.  It is placed after early inlining, so
    142    that even internal-strub functions get a chance of being inlined
    143    into other strub functions, but before non-early inlining, so that
    144    internal-strub wrapper functions still get a chance of inlining
    145    after splitting.
    146 
    147    Wrappers avoid duplicating the copying of large arguments again by
    148    passing them by reference to the wrapped bodies.  This involves
    149    occasional SSA rewriting of address computations, because of the
    150    additional indirection.  Besides these changes, and the
    151    introduction of the stack watermark parameter, wrappers and wrapped
    152    functions cooperate to handle variable argument lists (performing
    153    va_start in the wrapper, passing the list as an argument, and
    154    replacing va_start calls in the wrapped body with va_copy), and
    155    __builtin_apply_args (also called in the wrapper and passed to the
    156    wrapped body as an argument).
    157 
    158    Strub bodies (both internal-mode wrapped bodies, and at-calls
    159    functions) always start by adjusting the watermark parameter, by
    160    calling __builtin___strub_update.  The compiler inserts them in the
    161    main strub pass.  Allocations of additional stack space for the
    162    frame (__builtin_alloca) are also followed by watermark updates.
    163    Stack space temporarily allocated to pass arguments to other
    164    functions, released right after the call, is not regarded as part
    165    of the frame.  Around calls to them, i.e., in internal-mode
    166    wrappers and at-calls callers (even calls through pointers), calls
    167    to __builtin___strub_enter and __builtin___strub_leave are
    168    inserted, the latter as a __finally block, so that it runs at
    169    regular and exceptional exit paths.  strub_enter only initializes
    170    the stack watermark, and strub_leave is where the scrubbing takes
    171    place, overwriting with zeros the stack space from the top of the
    172    stack to the watermark.
    173 
    174    These calls can be optimized in various cases.  In
    175    pass_ipa_strub::adjust_at_calls_call, for example, we enable
    176    tail-calling and other optimized calls from one strub body to
    177    another by passing on the watermark parameter.  The builtins
    178    themselves may undergo inline substitution during expansion,
    179    dependign on optimization levels.  This involves dealing with stack
    180    red zones (when the builtins are called out-of-line, the red zone
    181    cannot be used) and other ugly details related with inlining strub
    182    bodies into other strub bodies (see expand_builtin_strub_update).
    183    expand_builtin_strub_leave may even perform partial inline
    184    substitution.  */
    185 
    186 /* Const and pure functions that gain a watermark parameter for strub purposes
    187    are still regarded as such, which may cause the inline expansions of the
    188    __strub builtins to malfunction.  Ideally, attribute "fn spec" would enable
    189    us to inform the backend about requirements and side effects of the call, but
    190    call_fusage building in calls.c:expand_call does not even look at
    191    attr_fnspec, so we resort to asm loads and updates to attain an equivalent
    192    effect.  Once expand_call gains the ability to issue extra memory uses and
    193    clobbers based on pure/const function's fnspec, we can define this to 1.  */
    194 #define ATTR_FNSPEC_DECONST_WATERMARK 0
    195 
    196 enum strub_mode {
    197   /* This mode denotes a regular function, that does not require stack
    198      scrubbing (strubbing).  It may call any other functions, but if
    199      it calls AT_CALLS (or WRAPPED) ones, strubbing logic is
    200      automatically introduced around those calls (the latter, by
    201      inlining INTERNAL wrappers).  */
    202   STRUB_DISABLED = 0,
    203 
    204   /* This denotes a function whose signature is (to be) modified to
    205      take an extra parameter, for stack use annotation, and its
    206      callers must initialize and pass that argument, and perform the
    207      strubbing.  Functions that are explicitly marked with attribute
    208      strub must have the mark visible wherever the function is,
    209      including aliases, and overriders and overriding methods.
    210      Functions that are implicitly marked for strubbing, for accessing
    211      variables explicitly marked as such, will only select this
    212      strubbing method if they are internal to a translation unit.  It
    213      can only be inlined into other strubbing functions, i.e.,
    214      STRUB_AT_CALLS or STRUB_WRAPPED.  */
    215   STRUB_AT_CALLS = 1,
    216 
    217   /* This denotes a function that is to perform strubbing internally,
    218      without any changes to its interface (the function is turned into
    219      a strubbing wrapper, and its original body is moved to a separate
    220      STRUB_WRAPPED function, with a modified interface).  Functions
    221      may be explicitly marked with attribute strub(2), and the
    222      attribute must be visible at the point of definition.  Functions
    223      that are explicitly marked for strubbing, for accessing variables
    224      explicitly marked as such, may select this strubbing mode if
    225      their interface cannot change, e.g. because its interface is
    226      visible to other translation units, directly, by indirection
    227      (having its address taken), inheritance, etc.  Functions that use
    228      this method must not have the noclone attribute, nor the noipa
    229      one.  Functions marked as always_inline may select this mode, but
    230      they are NOT wrapped, they remain unchanged, and are only inlined
    231      into strubbed contexts.  Once non-always_inline functions are
    232      wrapped, the wrapper becomes STRUB_WRAPPER, and the wrapped becomes
    233      STRUB_WRAPPED.  */
    234   STRUB_INTERNAL = 2,
    235 
    236   /* This denotes a function whose stack is not strubbed, but that is
    237      nevertheless explicitly or implicitly marked as callable from strubbing
    238      functions.  Normally, only STRUB_AT_CALLS (and STRUB_INTERNAL ->
    239      STRUB_WRAPPED) functions can be called from strubbing contexts (bodies of
    240      STRUB_AT_CALLS, STRUB_INTERNAL and STRUB_WRAPPED functions), but attribute
    241      strub(3) enables other functions to be (indirectly) called from these
    242      contexts.  Some builtins and internal functions may be implicitly marked as
    243      STRUB_CALLABLE.  */
    244   STRUB_CALLABLE = 3,
    245 
    246   /* This denotes the function that took over the body of a
    247      STRUB_INTERNAL function.  At first, it's only called by its
    248      wrapper, but the wrapper may be inlined.  The wrapped function,
    249      in turn, can only be inlined into other functions whose stack
    250      frames are strubbed, i.e., that are STRUB_WRAPPED or
    251      STRUB_AT_CALLS.  */
    252   STRUB_WRAPPED = -1,
    253 
    254   /* This denotes the wrapper function that replaced the STRUB_INTERNAL
    255      function.  This mode overrides the STRUB_INTERNAL mode at the time the
    256      internal to-be-wrapped function becomes a wrapper, so that inlining logic
    257      can tell one from the other.  */
    258   STRUB_WRAPPER = -2,
    259 
    260   /* This denotes an always_inline function that requires strubbing.  It can
    261      only be called from, and inlined into, other strubbing contexts.  */
    262   STRUB_INLINABLE = -3,
    263 
    264   /* This denotes a function that accesses strub variables, so it would call for
    265      internal strubbing (whether or not it's eligible for that), but since
    266      at-calls strubbing is viable, that's selected as an optimization.  This
    267      mode addresses the inconvenience that such functions may have different
    268      modes selected depending on optimization flags, and get a different
    269      callable status depending on that choice: if we assigned them
    270      STRUB_AT_CALLS mode, they would be callable when optimizing, whereas
    271      STRUB_INTERNAL would not be callable.  */
    272   STRUB_AT_CALLS_OPT = -4,
    273 
    274 };
    275 
    276 /* Look up a strub attribute in TYPE, and return it.  */
    277 
    278 static tree
    279 get_strub_attr_from_type (tree type)
    280 {
    281   return lookup_attribute ("strub", TYPE_ATTRIBUTES (type));
    282 }
    283 
    284 /* Look up a strub attribute in DECL or in its type, and return it.  */
    285 
    286 static tree
    287 get_strub_attr_from_decl (tree decl)
    288 {
    289   tree ret = lookup_attribute ("strub", DECL_ATTRIBUTES (decl));
    290   if (ret)
    291     return ret;
    292   return get_strub_attr_from_type (TREE_TYPE (decl));
    293 }
    294 
    295 #define STRUB_ID_COUNT		8
    296 #define STRUB_IDENT_COUNT	3
    297 #define STRUB_TYPE_COUNT	5
    298 
    299 #define STRUB_ID_BASE		0
    300 #define STRUB_IDENT_BASE	(STRUB_ID_BASE + STRUB_ID_COUNT)
    301 #define STRUB_TYPE_BASE		(STRUB_IDENT_BASE + STRUB_IDENT_COUNT)
    302 #define STRUB_CACHE_SIZE	(STRUB_TYPE_BASE + STRUB_TYPE_COUNT)
    303 
    304 /* Keep the strub mode and temp identifiers and types from being GC'd.  */
    305 static GTY((deletable)) tree strub_cache[STRUB_CACHE_SIZE];
    306 
    307 /* Define a function to cache identifier ID, to be used as a strub attribute
    308    parameter for a strub mode named after NAME.  */
    309 #define DEF_STRUB_IDS(IDX, NAME, ID)				\
    310 static inline tree get_strub_mode_id_ ## NAME () {		\
    311   int idx = STRUB_ID_BASE + IDX;				\
    312   tree identifier = strub_cache[idx];				\
    313   if (!identifier)						\
    314     strub_cache[idx] = identifier = get_identifier (ID);	\
    315   return identifier;						\
    316 }
    317 /* Same as DEF_STRUB_IDS, but use the string expansion of NAME as ID.  */
    318 #define DEF_STRUB_ID(IDX, NAME)			\
    319   DEF_STRUB_IDS (IDX, NAME, #NAME)
    320 
    321 /* Define functions for each of the strub mode identifiers.
    322    Expose dashes rather than underscores.  */
    323 DEF_STRUB_ID (0, disabled)
    324 DEF_STRUB_IDS (1, at_calls, "at-calls")
    325 DEF_STRUB_ID (2, internal)
    326 DEF_STRUB_ID (3, callable)
    327 DEF_STRUB_ID (4, wrapped)
    328 DEF_STRUB_ID (5, wrapper)
    329 DEF_STRUB_ID (6, inlinable)
    330 DEF_STRUB_IDS (7, at_calls_opt, "at-calls-opt")
    331 
    332 /* Release the temporary macro names.  */
    333 #undef DEF_STRUB_IDS
    334 #undef DEF_STRUB_ID
    335 
    336 /* Return the identifier corresponding to strub MODE.  */
    337 
    338 static tree
    339 get_strub_mode_attr_parm (enum strub_mode mode)
    340 {
    341   switch (mode)
    342     {
    343     case STRUB_DISABLED:
    344       return get_strub_mode_id_disabled ();
    345 
    346     case STRUB_AT_CALLS:
    347       return get_strub_mode_id_at_calls ();
    348 
    349     case STRUB_INTERNAL:
    350       return get_strub_mode_id_internal ();
    351 
    352     case STRUB_CALLABLE:
    353       return get_strub_mode_id_callable ();
    354 
    355     case STRUB_WRAPPED:
    356       return get_strub_mode_id_wrapped ();
    357 
    358     case STRUB_WRAPPER:
    359       return get_strub_mode_id_wrapper ();
    360 
    361     case STRUB_INLINABLE:
    362       return get_strub_mode_id_inlinable ();
    363 
    364     case STRUB_AT_CALLS_OPT:
    365       return get_strub_mode_id_at_calls_opt ();
    366 
    367     default:
    368       gcc_unreachable ();
    369     }
    370 }
    371 
    372 /* Return the parmeters (TREE_VALUE) for a strub attribute of MODE.
    373    We know we use a single parameter, so we bypass the creation of a
    374    tree list.  */
    375 
    376 static tree
    377 get_strub_mode_attr_value (enum strub_mode mode)
    378 {
    379   return get_strub_mode_attr_parm (mode);
    380 }
    381 
    382 /* Determine whether ID is a well-formed strub mode-specifying attribute
    383    parameter for a function (type).  Only user-visible modes are accepted, and
    384    ID must be non-NULL.
    385 
    386    For unacceptable parms, return 0, otherwise a nonzero value as below.
    387 
    388    If the parm enables strub, return positive, otherwise negative.
    389 
    390    If the affected type must be a distinct, incompatible type,return an integer
    391    of absolute value 2, otherwise 1.  */
    392 
    393 int
    394 strub_validate_fn_attr_parm (tree id)
    395 {
    396   int ret;
    397   const char *s = NULL;
    398   size_t len = 0;
    399 
    400   /* do NOT test for NULL.  This is only to be called with non-NULL arguments.
    401      We assume that the strub parameter applies to a function, because only
    402      functions accept an explicit argument.  If we accepted NULL, and we
    403      happened to be called to verify the argument for a variable, our return
    404      values would be wrong.  */
    405   if (TREE_CODE (id) == STRING_CST)
    406     {
    407       s = TREE_STRING_POINTER (id);
    408       len = TREE_STRING_LENGTH (id) - 1;
    409     }
    410   else if (TREE_CODE (id) == IDENTIFIER_NODE)
    411     {
    412       s = IDENTIFIER_POINTER (id);
    413       len = IDENTIFIER_LENGTH (id);
    414     }
    415   else
    416     return 0;
    417 
    418   enum strub_mode mode;
    419 
    420   if (len != 8)
    421     return 0;
    422 
    423   switch (s[0])
    424     {
    425     case 'd':
    426       mode = STRUB_DISABLED;
    427       ret = -1;
    428       break;
    429 
    430     case 'a':
    431       mode = STRUB_AT_CALLS;
    432       ret = 2;
    433       break;
    434 
    435     case 'i':
    436       mode = STRUB_INTERNAL;
    437       ret = 1;
    438       break;
    439 
    440     case 'c':
    441       mode = STRUB_CALLABLE;
    442       ret = -2;
    443       break;
    444 
    445     default:
    446       /* Other parms are for internal use only.  */
    447       return 0;
    448     }
    449 
    450   tree mode_id = get_strub_mode_attr_parm (mode);
    451 
    452   if (TREE_CODE (id) == IDENTIFIER_NODE
    453       ? id != mode_id
    454       : strncmp (s, IDENTIFIER_POINTER (mode_id), len) != 0)
    455     return 0;
    456 
    457   return ret;
    458 }
    459 
    460 /* Return the strub mode from STRUB_ATTR.  VAR_P should be TRUE if the attribute
    461    is taken from a variable, rather than from a function, or a type thereof.  */
    462 
    463 static enum strub_mode
    464 get_strub_mode_from_attr (tree strub_attr, bool var_p = false)
    465 {
    466   enum strub_mode mode = STRUB_DISABLED;
    467 
    468   if (strub_attr)
    469     {
    470       if (!TREE_VALUE (strub_attr))
    471 	mode = !var_p ? STRUB_AT_CALLS : STRUB_INTERNAL;
    472       else
    473 	{
    474 	  gcc_checking_assert (!var_p);
    475 	  tree id = TREE_VALUE (strub_attr);
    476 	  if (TREE_CODE (id) == TREE_LIST)
    477 	    id = TREE_VALUE (id);
    478 	  const char *s = (TREE_CODE (id) == STRING_CST
    479 			   ? TREE_STRING_POINTER (id)
    480 			   : IDENTIFIER_POINTER (id));
    481 	  size_t len = (TREE_CODE (id) == STRING_CST
    482 			? TREE_STRING_LENGTH (id) - 1
    483 			: IDENTIFIER_LENGTH (id));
    484 
    485 	  switch (len)
    486 	    {
    487 	    case 7:
    488 	      switch (s[6])
    489 		{
    490 		case 'r':
    491 		  mode = STRUB_WRAPPER;
    492 		  break;
    493 
    494 		case 'd':
    495 		  mode = STRUB_WRAPPED;
    496 		  break;
    497 
    498 		default:
    499 		  gcc_unreachable ();
    500 		}
    501 	      break;
    502 
    503 	    case 8:
    504 	      switch (s[0])
    505 		{
    506 		case 'd':
    507 		  mode = STRUB_DISABLED;
    508 		  break;
    509 
    510 		case 'a':
    511 		  mode = STRUB_AT_CALLS;
    512 		  break;
    513 
    514 		case 'i':
    515 		  mode = STRUB_INTERNAL;
    516 		  break;
    517 
    518 		case 'c':
    519 		  mode = STRUB_CALLABLE;
    520 		  break;
    521 
    522 		default:
    523 		  gcc_unreachable ();
    524 		}
    525 	      break;
    526 
    527 	    case 9:
    528 	      mode = STRUB_INLINABLE;
    529 	      break;
    530 
    531 	    case 12:
    532 	      mode = STRUB_AT_CALLS_OPT;
    533 	      break;
    534 
    535 	    default:
    536 	      gcc_unreachable ();
    537 	    }
    538 
    539 	  gcc_checking_assert (TREE_CODE (id) == IDENTIFIER_NODE
    540 			       ? id == get_strub_mode_attr_parm (mode)
    541 			       : strncmp (IDENTIFIER_POINTER
    542 					  (get_strub_mode_attr_parm (mode)),
    543 					  s, len) == 0);
    544 	}
    545     }
    546 
    547   return mode;
    548 }
    549 
    550 /* Look up, decode and return the strub mode associated with FNDECL.  */
    551 
    552 static enum strub_mode
    553 get_strub_mode_from_fndecl (tree fndecl)
    554 {
    555   return get_strub_mode_from_attr (get_strub_attr_from_decl (fndecl));
    556 }
    557 
    558 /* Look up, decode and return the strub mode associated with NODE.  */
    559 
    560 static enum strub_mode
    561 get_strub_mode (cgraph_node *node)
    562 {
    563   return get_strub_mode_from_fndecl (node->decl);
    564 }
    565 
    566 /* Look up, decode and return the strub mode associated with TYPE.  */
    567 
    568 static enum strub_mode
    569 get_strub_mode_from_type (tree type)
    570 {
    571   bool var_p = !FUNC_OR_METHOD_TYPE_P (type);
    572   tree attr = get_strub_attr_from_type (type);
    573 
    574   if (attr)
    575     return get_strub_mode_from_attr (attr, var_p);
    576 
    577   if (flag_strub >= -1 && !var_p)
    578     return STRUB_CALLABLE;
    579 
    580   return STRUB_DISABLED;
    581 }
    582 
    583 
    584 /* Return TRUE iff NODE calls builtin va_start.  */
    586 
    587 static bool
    588 calls_builtin_va_start_p (cgraph_node *node)
    589 {
    590   bool result = false;
    591 
    592   for (cgraph_edge *e = node->callees; e; e = e->next_callee)
    593     {
    594       tree cdecl = e->callee->decl;
    595       if (fndecl_built_in_p (cdecl, BUILT_IN_VA_START))
    596 	return true;
    597     }
    598 
    599   return result;
    600 }
    601 
    602 /* Return TRUE iff NODE calls builtin apply_args, and optionally REPORT it.  */
    603 
    604 static bool
    605 calls_builtin_apply_args_p (cgraph_node *node, bool report = false)
    606 {
    607   bool result = false;
    608 
    609   for (cgraph_edge *e = node->callees; e; e = e->next_callee)
    610     {
    611       tree cdecl = e->callee->decl;
    612       if (!fndecl_built_in_p (cdecl, BUILT_IN_APPLY_ARGS))
    613 	continue;
    614 
    615       result = true;
    616 
    617       if (!report)
    618 	break;
    619 
    620       sorry_at (e->call_stmt
    621 		? gimple_location (e->call_stmt)
    622 		: DECL_SOURCE_LOCATION (node->decl),
    623 		"at-calls %<strub%> does not support call to %qD",
    624 		cdecl);
    625     }
    626 
    627   return result;
    628 }
    629 
    630 /* Return TRUE iff NODE carries the always_inline attribute.  */
    631 
    632 static inline bool
    633 strub_always_inline_p (cgraph_node *node)
    634 {
    635   return lookup_attribute ("always_inline", DECL_ATTRIBUTES (node->decl));
    636 }
    637 
    638 /* Return TRUE iff the target has strub support for T, a function
    639    decl, or a type used in an indirect call, and optionally REPORT the
    640    reasons for ineligibility.  If T is a type and error REPORTing is
    641    enabled, the LOCation (of the indirect call) should be provided.  */
    642 static inline bool
    643 strub_target_support_p (tree t, bool report = false,
    644 			location_t loc = UNKNOWN_LOCATION)
    645 {
    646   bool result = true;
    647 
    648   if (!targetm.have_strub_support_for (t))
    649     {
    650       result = false;
    651 
    652       if (!report)
    653 	return result;
    654 
    655       if (DECL_P (t))
    656 	sorry_at (DECL_SOURCE_LOCATION (t),
    657 		  "%qD is not eligible for %<strub%>"
    658 		  " on the target system", t);
    659       else
    660 	sorry_at (loc,
    661 		  "unsupported %<strub%> call"
    662 		  " on the target system");
    663     }
    664 
    665   return result;
    666 }
    667 
    668 /* Return TRUE iff NODE is potentially eligible for any strub-enabled mode, and
    669    optionally REPORT the reasons for ineligibility.  */
    670 
    671 static inline bool
    672 can_strub_p (cgraph_node *node, bool report = false)
    673 {
    674   bool result = strub_target_support_p (node->decl, report);
    675 
    676   if (!report && (!result || strub_always_inline_p (node)))
    677     return result;
    678 
    679   if (flag_split_stack)
    680     {
    681       result = false;
    682 
    683       if (!report)
    684 	return result;
    685 
    686       sorry_at (DECL_SOURCE_LOCATION (node->decl),
    687 		"%qD is not eligible for %<strub%>"
    688 		" because %<-fsplit-stack%> is enabled",
    689 		node->decl);
    690     }
    691 
    692   if (lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl)))
    693     {
    694       result = false;
    695 
    696       if (!report)
    697 	return result;
    698 
    699       sorry_at (DECL_SOURCE_LOCATION (node->decl),
    700 		"%qD is not eligible for %<strub%>"
    701 		" because of attribute %<noipa%>",
    702 		node->decl);
    703     }
    704 
    705   /* We can't, and don't want to vectorize the watermark and other
    706      strub-introduced parms.  */
    707   if (lookup_attribute ("simd", DECL_ATTRIBUTES (node->decl)))
    708     {
    709       result = false;
    710 
    711       if (!report)
    712 	return result;
    713 
    714       sorry_at (DECL_SOURCE_LOCATION (node->decl),
    715 		"%qD is not eligible for %<strub%>"
    716 		" because of attribute %<simd%>",
    717 		node->decl);
    718     }
    719 
    720   return result;
    721 }
    722 
    723 /* Return TRUE iff NODE is eligible for at-calls strub, and optionally REPORT
    724    the reasons for ineligibility.  Besides general non-eligibility for
    725    strub-enabled modes, at-calls rules out calling builtin apply_args.  */
    726 
    727 static bool
    728 can_strub_at_calls_p (cgraph_node *node, bool report = false)
    729 {
    730   bool result = !report || can_strub_p (node, report);
    731 
    732   if (!result && !report)
    733     return result;
    734 
    735   return !calls_builtin_apply_args_p (node, report);
    736 }
    737 
    738 /* Return TRUE iff the called function (pointer or, if available,
    739    decl) undergoes a significant type conversion for the call.  Strub
    740    mode changes between function types, and other non-useless type
    741    conversions, are regarded as significant.  When the function type
    742    is overridden, the effective strub mode for the call is that of the
    743    call fntype, rather than that of the pointer or of the decl.
    744    Functions called with type overrides cannot undergo type changes;
    745    it's as if their address was taken, so they're considered
    746    non-viable for implicit at-calls strub mode.  */
    747 
    748 static inline bool
    749 strub_call_fntype_override_p (const gcall *gs)
    750 {
    751   if (gimple_call_internal_p (gs))
    752     return false;
    753   tree fn_type = TREE_TYPE (TREE_TYPE (gimple_call_fn (gs)));
    754   if (tree decl = gimple_call_fndecl (gs))
    755     fn_type = TREE_TYPE (decl);
    756 
    757   /* We do NOT want to take the mode from the decl here.  This
    758      function is used to tell whether we can change the strub mode of
    759      a function, and whether the effective mode for the call is to be
    760      taken from the decl or from an overrider type.  When the strub
    761      mode is explicitly declared, or overridden with a type cast, the
    762      difference will be noticed in function types.  However, if the
    763      strub mode is implicit due to e.g. strub variables or -fstrub=*
    764      command-line flags, we will adjust call types along with function
    765      types.  In either case, the presence of type or strub mode
    766      overriders in calls will prevent a function from having its strub
    767      modes changed in ways that would imply type changes, but taking
    768      strub modes from decls would defeat this, since we set strub
    769      modes and then call this function to tell whether the original
    770      type was overridden to decide whether to adjust the call.  We
    771      need the answer to be about the type, not the decl.  */
    772   enum strub_mode mode = get_strub_mode_from_type (fn_type);
    773   return (get_strub_mode_from_type (gs->u.fntype) != mode
    774 	  || !useless_type_conversion_p (gs->u.fntype, fn_type));
    775 }
    776 
    777 /* Return TRUE iff NODE is called directly with a type override.  */
    778 
    779 static bool
    780 called_directly_with_type_override_p (cgraph_node *node, void *)
    781 {
    782   for (cgraph_edge *e = node->callers; e; e = e->next_caller)
    783     if (e->call_stmt && strub_call_fntype_override_p (e->call_stmt))
    784       return true;
    785 
    786   return false;
    787 }
    788 
    789 /* Return TRUE iff NODE or any other nodes aliased to it are called
    790    with type overrides.  We can't safely change the type of such
    791    functions.  */
    792 
    793 static bool
    794 called_with_type_override_p (cgraph_node *node)
    795 {
    796   return (node->call_for_symbol_thunks_and_aliases
    797 	  (called_directly_with_type_override_p, NULL, true, true));
    798 }
    799 
    800 /* Symbolic macro for the max number of arguments that internal strub may add to
    801    a function.  */
    802 
    803 #define STRUB_INTERNAL_MAX_EXTRA_ARGS 3
    804 
    805 /* We can't perform internal strubbing if the function body involves certain
    806    features:
    807 
    808    - a non-default __builtin_va_start (e.g. x86's __builtin_ms_va_start) is
    809    currently unsupported because we can't discover the corresponding va_copy and
    810    va_end decls in the wrapper, and we don't convey the alternate variable
    811    arguments ABI to the modified wrapped function.  The default
    812    __builtin_va_start is supported by calling va_start/va_end at the wrapper,
    813    that takes variable arguments, passing a pointer to the va_list object to the
    814    wrapped function, that runs va_copy from it where the original function ran
    815    va_start.
    816 
    817    __builtin_next_arg is currently unsupported because the wrapped function
    818    won't be a variable argument function.  We could process it in the wrapper,
    819    that remains a variable argument function, and replace calls in the wrapped
    820    body, but we currently don't.
    821 
    822    __builtin_return_address is rejected because it's generally used when the
    823    actual caller matters, and introducing a wrapper breaks such uses as those in
    824    the unwinder.  */
    825 
    826 static bool
    827 can_strub_internally_p (cgraph_node *node, bool report = false)
    828 {
    829   bool result = !report || can_strub_p (node, report);
    830 
    831   if (!result && !report)
    832     return result;
    833 
    834   if (!report && strub_always_inline_p (node))
    835     return result;
    836 
    837   /* Since we're not changing the function identity proper, just
    838      moving its full implementation, we *could* disable
    839      fun->cannot_be_copied_reason and/or temporarily drop a noclone
    840      attribute, but we'd have to prevent remapping of the labels.  */
    841   if (lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
    842     {
    843       result = false;
    844 
    845       if (!report)
    846 	return result;
    847 
    848       sorry_at (DECL_SOURCE_LOCATION (node->decl),
    849 		"%qD is not eligible for internal %<strub%>"
    850 		" because of attribute %<noclone%>",
    851 		node->decl);
    852     }
    853 
    854   if (node->has_gimple_body_p ())
    855     {
    856       for (cgraph_edge *e = node->callees; e; e = e->next_callee)
    857 	{
    858 	  tree cdecl = e->callee->decl;
    859 	  if (!((fndecl_built_in_p (cdecl, BUILT_IN_VA_START)
    860 		 && cdecl != builtin_decl_explicit (BUILT_IN_VA_START))
    861 		|| fndecl_built_in_p (cdecl, BUILT_IN_NEXT_ARG)
    862 		|| fndecl_built_in_p (cdecl, BUILT_IN_RETURN_ADDRESS)))
    863 	    continue;
    864 
    865 	  result = false;
    866 
    867 	  if (!report)
    868 	    return result;
    869 
    870 	  sorry_at (e->call_stmt
    871 		    ? gimple_location (e->call_stmt)
    872 		    : DECL_SOURCE_LOCATION (node->decl),
    873 		    "%qD is not eligible for internal %<strub%> "
    874 		    "because it calls %qD",
    875 		    node->decl, cdecl);
    876 	}
    877 
    878       struct function *fun = DECL_STRUCT_FUNCTION (node->decl);
    879       if (fun->has_nonlocal_label)
    880 	{
    881 	  result = false;
    882 
    883 	  if (!report)
    884 	    return result;
    885 
    886 	  sorry_at (DECL_SOURCE_LOCATION (node->decl),
    887 		    "%qD is not eligible for internal %<strub%> "
    888 		    "because it contains a non-local goto target",
    889 		    node->decl);
    890 	}
    891 
    892       if (fun->has_forced_label_in_static)
    893 	{
    894 	  result = false;
    895 
    896 	  if (!report)
    897 	    return result;
    898 
    899 	  sorry_at (DECL_SOURCE_LOCATION (node->decl),
    900 		    "%qD is not eligible for internal %<strub%> "
    901 		    "because the address of a local label escapes",
    902 		    node->decl);
    903 	}
    904 
    905       /* Catch any other case that would prevent versioning/cloning
    906 	 so as to also have it covered above.  */
    907       gcc_checking_assert (!result /* || !node->has_gimple_body_p () */
    908 			   || tree_versionable_function_p (node->decl));
    909 
    910 
    911       /* Label values references are not preserved when copying.  If referenced
    912 	 in nested functions, as in 920415-1.c and 920721-4.c their decls get
    913 	 remapped independently.  The exclusion below might be too broad, in
    914 	 that we might be able to support correctly cases in which the labels
    915 	 are only used internally in a function, but disconnecting forced labels
    916 	 from their original declarations is undesirable in general.  */
    917       basic_block bb;
    918       FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
    919 	for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
    920 	     !gsi_end_p (gsi); gsi_next (&gsi))
    921 	  {
    922 	    glabel *label_stmt = dyn_cast <glabel *> (gsi_stmt (gsi));
    923 	    tree target;
    924 
    925 	    if (!label_stmt)
    926 	      break;
    927 
    928 	    target = gimple_label_label (label_stmt);
    929 
    930 	    if (!FORCED_LABEL (target))
    931 	      continue;
    932 
    933 	    result = false;
    934 
    935 	    if (!report)
    936 	      return result;
    937 
    938 	    sorry_at (gimple_location (label_stmt),
    939 		      "internal %<strub%> does not support forced labels");
    940 	  }
    941     }
    942 
    943   if (list_length (TYPE_ARG_TYPES (TREE_TYPE (node->decl)))
    944       >= ((HOST_WIDE_INT_1 << IPA_PARAM_MAX_INDEX_BITS)
    945 	  - STRUB_INTERNAL_MAX_EXTRA_ARGS))
    946     {
    947       result = false;
    948 
    949       if (!report)
    950 	return result;
    951 
    952       sorry_at (DECL_SOURCE_LOCATION (node->decl),
    953 		"%qD has too many arguments for internal %<strub%>",
    954 		node->decl);
    955     }
    956 
    957   return result;
    958 }
    959 
    960 /* Return TRUE iff NODE has any strub-requiring local variable, or accesses (as
    961    in reading) any variable through a strub-requiring type.  */
    962 
    963 static bool
    964 strub_from_body_p (cgraph_node *node)
    965 {
    966   if (!node->has_gimple_body_p ())
    967     return false;
    968 
    969   /* If any local variable is marked for strub...  */
    970   unsigned i;
    971   tree var;
    972   FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (node->decl),
    973 		       i, var)
    974     if (get_strub_mode_from_type (TREE_TYPE (var))
    975 	!= STRUB_DISABLED)
    976       return true;
    977 
    978   /* Now scan the body for loads with strub-requiring types.
    979      ??? Compound types don't propagate the strub requirement to
    980      component types.  */
    981   basic_block bb;
    982   FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
    983     for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
    984 	 !gsi_end_p (gsi); gsi_next (&gsi))
    985       {
    986 	gimple *stmt = gsi_stmt (gsi);
    987 
    988 	if (!gimple_assign_load_p (stmt))
    989 	  continue;
    990 
    991 	tree rhs = gimple_assign_rhs1 (stmt);
    992 	if (get_strub_mode_from_type (TREE_TYPE (rhs))
    993 	    != STRUB_DISABLED)
    994 	  return true;
    995       }
    996 
    997   return false;
    998 }
    999 
   1000 /* Return TRUE iff node is associated with a builtin that should be callable
   1001    from strub contexts.  */
   1002 
   1003 static inline bool
   1004 strub_callable_builtin_p (cgraph_node *node)
   1005 {
   1006   if (DECL_BUILT_IN_CLASS (node->decl) != BUILT_IN_NORMAL)
   1007     return false;
   1008 
   1009   enum built_in_function fcode = DECL_FUNCTION_CODE (node->decl);
   1010 
   1011   switch (fcode)
   1012     {
   1013     case BUILT_IN_NONE:
   1014       gcc_unreachable ();
   1015 
   1016       /* This temporarily allocates stack for the call, and we can't reasonably
   1017 	 update the watermark for that.  Besides, we don't check the actual call
   1018 	 target, nor its signature, and it seems to be overkill to as much as
   1019 	 try to do so.  */
   1020     case BUILT_IN_APPLY:
   1021       return false;
   1022 
   1023       /* Conversely, this shouldn't be called from within strub contexts, since
   1024 	 the caller may have had its signature modified.  STRUB_INTERNAL is ok,
   1025 	 the call will remain in the STRUB_WRAPPER, and removed from the
   1026 	 STRUB_WRAPPED clone.  */
   1027     case BUILT_IN_APPLY_ARGS:
   1028       return false;
   1029 
   1030       /* ??? Make all other builtins callable.  We wish to make any builtin call
   1031 	 the compiler might introduce on its own callable.  Anything that is
   1032 	 predictable enough as to be known not to allow stack data that should
   1033 	 be strubbed to unintentionally escape to non-strub contexts can be
   1034 	 allowed, and pretty much every builtin appears to fit this description.
   1035 	 The exceptions to this rule seem to be rare, and only available as
   1036 	 explicit __builtin calls, so let's keep it simple and allow all of
   1037 	 them...  */
   1038     default:
   1039       return true;
   1040     }
   1041 }
   1042 
   1043 /* Compute the strub mode to be used for NODE.  STRUB_ATTR should be the strub
   1044    attribute,found for NODE, if any.  */
   1045 
   1046 static enum strub_mode
   1047 compute_strub_mode (cgraph_node *node, tree strub_attr)
   1048 {
   1049   enum strub_mode req_mode = get_strub_mode_from_attr (strub_attr);
   1050 
   1051   gcc_checking_assert (flag_strub >= -2 && flag_strub <= 3);
   1052 
   1053   /* Symbolic encodings of the -fstrub-* flags.  */
   1054   /* Enable strub when explicitly requested through attributes to functions or
   1055      variables, reporting errors if the requests cannot be satisfied.  */
   1056   const bool strub_flag_auto = flag_strub < 0;
   1057   /* strub_flag_auto with strub call verification; without this, functions are
   1058      implicitly callable.  */
   1059   const bool strub_flag_strict = flag_strub < -1;
   1060   /* Disable strub altogether, ignore attributes entirely.  */
   1061   const bool strub_flag_disabled = flag_strub == 0;
   1062   /* On top of _auto, also enable strub implicitly for functions that can
   1063      safely undergo at-calls strubbing.  Internal mode will still be used in
   1064      functions that request it explicitly with attribute strub(2), or when the
   1065      function body requires strubbing and at-calls strubbing is not viable.  */
   1066   const bool strub_flag_at_calls = flag_strub == 1;
   1067   /* On top of default, also enable strub implicitly for functions that can
   1068      safely undergo internal strubbing.  At-calls mode will still be used in
   1069      functions that requiest it explicitly with attribute strub() or strub(1),
   1070      or when the function body requires strubbing and internal strubbing is not
   1071      viable.  */
   1072   const bool strub_flag_internal = flag_strub == 2;
   1073   /* On top of default, also enable strub implicitly for functions that can
   1074      safely undergo strubbing in either mode.  When both modes are viable,
   1075      at-calls is preferred.  */
   1076   const bool strub_flag_either = flag_strub == 3;
   1077   /* Besides the default behavior, enable strub implicitly for all viable
   1078      functions.  */
   1079   const bool strub_flag_viable = flag_strub > 0;
   1080 
   1081   /* The consider_* variables should be TRUE if selecting the corresponding
   1082      strub modes would be consistent with requests from attributes and command
   1083      line flags.  Attributes associated with functions pretty much mandate a
   1084      selection, and should report an error if not satisfied; strub_flag_auto
   1085      implicitly enables some viable strub mode if that's required by references
   1086      to variables marked for strub; strub_flag_viable enables strub if viable
   1087      (even when favoring one mode, body-requested strub can still be satisfied
   1088      by either mode), and falls back to callable, silently unless variables
   1089      require strubbing.  */
   1090 
   1091   const bool consider_at_calls
   1092     = (!strub_flag_disabled
   1093        && (strub_attr
   1094 	   ? req_mode == STRUB_AT_CALLS
   1095 	   : true));
   1096   const bool consider_internal
   1097     = (!strub_flag_disabled
   1098        && (strub_attr
   1099 	   ? req_mode == STRUB_INTERNAL
   1100 	   : true));
   1101 
   1102   const bool consider_callable
   1103     = (!strub_flag_disabled
   1104        && (strub_attr
   1105 	   ? req_mode == STRUB_CALLABLE
   1106 	   : (!strub_flag_strict
   1107 	      || strub_callable_builtin_p (node))));
   1108 
   1109   /* This is a shorthand for either strub-enabled mode.  */
   1110   const bool consider_strub
   1111     = (consider_at_calls || consider_internal);
   1112 
   1113   /* We can cope with always_inline functions even with noipa and noclone,
   1114      because we just leave them alone.  */
   1115   const bool is_always_inline
   1116     = strub_always_inline_p (node);
   1117 
   1118   /* Strubbing in general, and each specific strub mode, may have its own set of
   1119      requirements.  We require noipa for strubbing, either because of cloning
   1120      required for internal strub, or because of caller enumeration required for
   1121      at-calls strub.  We don't consider the at-calls mode eligible if it's not
   1122      even considered, it has no further requirements.  Internal mode requires
   1123      cloning and the absence of certain features in the body and, like at-calls,
   1124      it's not eligible if it's not even under consideration.
   1125 
   1126      ??? Do we need target hooks for further constraints?  E.g., x86's
   1127      "interrupt" attribute breaks internal strubbing because the wrapped clone
   1128      carries the attribute and thus isn't callable; in this case, we could use a
   1129      target hook to adjust the clone instead.  */
   1130   const bool strub_eligible
   1131     = (consider_strub
   1132        && (is_always_inline || can_strub_p (node)));
   1133   const bool at_calls_eligible
   1134     = (consider_at_calls && strub_eligible
   1135        && can_strub_at_calls_p (node));
   1136   const bool internal_eligible
   1137     = (consider_internal && strub_eligible
   1138        && (is_always_inline
   1139 	   || can_strub_internally_p (node)));
   1140 
   1141   /* In addition to the strict eligibility requirements, some additional
   1142      constraints are placed on implicit selection of certain modes.  These do
   1143      not prevent the selection of a mode if explicitly specified as part of a
   1144      function interface (the strub attribute), but they may prevent modes from
   1145      being selected by the command line or by function bodies.  The only actual
   1146      constraint is on at-calls mode: since we change the function's exposed
   1147      signature, we won't do it implicitly if the function can possibly be used
   1148      in ways that do not expect the signature change, e.g., if the function is
   1149      available to or interposable by other units, if its address is taken,
   1150      etc.  */
   1151   const bool at_calls_viable
   1152     = (at_calls_eligible
   1153        && (strub_attr
   1154 	   || (node->has_gimple_body_p ()
   1155 	       && (!node->externally_visible
   1156 		   || (node->binds_to_current_def_p ()
   1157 		       && node->can_be_local_p ()))
   1158 	       && node->only_called_directly_p ()
   1159 	       && !called_with_type_override_p (node))));
   1160   const bool internal_viable
   1161     = (internal_eligible);
   1162 
   1163   /* Shorthand.  */
   1164   const bool strub_viable
   1165     = (at_calls_viable || internal_viable);
   1166 
   1167   /* We wish to analyze the body, to look for implicit requests for strub, both
   1168      to implicitly enable it when the body calls for it, and to report errors if
   1169      the body calls for it but neither mode is viable (even if that follows from
   1170      non-eligibility because of the explicit specification of some non-strubbing
   1171      mode).  We can refrain from scanning the body only in rare circumstances:
   1172      when strub is enabled by a function attribute (scanning might be redundant
   1173      in telling us to also enable it), and when we are enabling strub implicitly
   1174      but there are non-viable modes: we want to know whether strubbing is
   1175      required, to fallback to another mode, even if we're only enabling a
   1176      certain mode, or, when either mode would do, to report an error if neither
   1177      happens to be viable.  */
   1178   const bool analyze_body
   1179     = (strub_attr
   1180        ? !consider_strub
   1181        : (strub_flag_auto
   1182 	  || (strub_flag_viable && (!at_calls_viable && !internal_viable))
   1183 	  || (strub_flag_either && !strub_viable)));
   1184 
   1185   /* Cases in which strubbing is enabled or disabled by strub_flag_auto.
   1186      Unsatisfiable requests ought to be reported.  */
   1187   const bool strub_required
   1188     = ((strub_attr && consider_strub)
   1189        || (analyze_body && strub_from_body_p (node)));
   1190 
   1191   /* Besides the required cases, we want to abide by the requests to enabling on
   1192      an if-viable basis.  */
   1193   const bool strub_enable
   1194     = (strub_required
   1195        || (strub_flag_at_calls && at_calls_viable)
   1196        || (strub_flag_internal && internal_viable)
   1197        || (strub_flag_either && strub_viable));
   1198 
   1199   /* And now we're finally ready to select a mode that abides by the viability
   1200      and eligibility constraints, and that satisfies the strubbing requirements
   1201      and requests, subject to the constraints.  If both modes are viable and
   1202      strub is to be enabled, pick STRUB_AT_CALLS unless STRUB_INTERNAL was named
   1203      as preferred.  */
   1204   const enum strub_mode mode
   1205     = ((strub_enable && is_always_inline)
   1206        ? (strub_required ? STRUB_INLINABLE : STRUB_CALLABLE)
   1207        : (strub_enable && internal_viable
   1208 	  && (strub_flag_internal || !at_calls_viable))
   1209        ? STRUB_INTERNAL
   1210        : (strub_enable && at_calls_viable)
   1211        ? (strub_required && !strub_attr
   1212 	  ? STRUB_AT_CALLS_OPT
   1213 	  : STRUB_AT_CALLS)
   1214        : consider_callable
   1215        ? STRUB_CALLABLE
   1216        : STRUB_DISABLED);
   1217 
   1218   switch (mode)
   1219     {
   1220     case STRUB_CALLABLE:
   1221       if (is_always_inline)
   1222 	break;
   1223       /* Fall through.  */
   1224 
   1225     case STRUB_DISABLED:
   1226       if (strub_enable && !strub_attr)
   1227 	{
   1228 	  gcc_checking_assert (analyze_body);
   1229 	  error_at (DECL_SOURCE_LOCATION (node->decl),
   1230 		    "%qD requires %<strub%>,"
   1231 		    " but no viable %<strub%> mode was found",
   1232 		    node->decl);
   1233 	  break;
   1234 	}
   1235       /* Fall through.  */
   1236 
   1237     case STRUB_AT_CALLS:
   1238     case STRUB_INTERNAL:
   1239     case STRUB_INLINABLE:
   1240       /* Differences from an mode requested through a function attribute are
   1241 	 reported in set_strub_mode_to.  */
   1242       break;
   1243 
   1244     case STRUB_AT_CALLS_OPT:
   1245       /* Functions that select this mode do so because of references to strub
   1246 	 variables.  Even if we choose at-calls as an optimization, the
   1247 	 requirements for internal strub must still be satisfied.  Optimization
   1248 	 options may render implicit at-calls strub not viable (-O0 sets
   1249 	 force_output for static non-inline functions), and it would not be good
   1250 	 if changing optimization options turned a well-formed into an
   1251 	 ill-formed one.  */
   1252       if (!internal_viable)
   1253 	can_strub_internally_p (node, true);
   1254       break;
   1255 
   1256     case STRUB_WRAPPED:
   1257     case STRUB_WRAPPER:
   1258     default:
   1259       gcc_unreachable ();
   1260     }
   1261 
   1262   return mode;
   1263 }
   1264 
   1265 /* Set FNDT's strub mode to MODE; FNDT may be a function decl or
   1266    function type.  If OVERRIDE, do not check whether a mode is already
   1267    set.  */
   1268 
   1269 static void
   1270 strub_set_fndt_mode_to (tree fndt, enum strub_mode mode, bool override)
   1271 {
   1272   gcc_checking_assert (override
   1273 		       || !(DECL_P (fndt)
   1274 			    ? get_strub_attr_from_decl (fndt)
   1275 			    : get_strub_attr_from_type (fndt)));
   1276 
   1277   tree attr = tree_cons (get_identifier ("strub"),
   1278 			 get_strub_mode_attr_value (mode),
   1279 			 NULL_TREE);
   1280   tree *attrp = NULL;
   1281   if (DECL_P (fndt))
   1282     {
   1283       gcc_checking_assert (FUNC_OR_METHOD_TYPE_P (TREE_TYPE (fndt)));
   1284       attrp = &DECL_ATTRIBUTES (fndt);
   1285     }
   1286   else if (FUNC_OR_METHOD_TYPE_P (fndt))
   1287     attrp = &TYPE_ATTRIBUTES (fndt);
   1288   else
   1289     gcc_unreachable ();
   1290 
   1291   TREE_CHAIN (attr) = *attrp;
   1292   *attrp = attr;
   1293 }
   1294 
   1295 /* Set FNDT's strub mode to callable.
   1296    FNDT may be a function decl or a function type.  */
   1297 
   1298 void
   1299 strub_make_callable (tree fndt)
   1300 {
   1301   strub_set_fndt_mode_to (fndt, STRUB_CALLABLE, false);
   1302 }
   1303 
   1304 /* Set NODE to strub MODE.  Report incompatibilities between MODE and the mode
   1305    requested through explicit attributes, and cases of non-eligibility.  */
   1306 
   1307 static void
   1308 set_strub_mode_to (cgraph_node *node, enum strub_mode mode)
   1309 {
   1310   tree attr = get_strub_attr_from_decl (node->decl);
   1311   enum strub_mode req_mode = get_strub_mode_from_attr (attr);
   1312 
   1313   if (attr)
   1314     {
   1315       /* Check for and report incompatible mode changes.  */
   1316       if (mode != req_mode
   1317 	  && !(req_mode == STRUB_INTERNAL
   1318 	       && (mode == STRUB_WRAPPED
   1319 		   || mode == STRUB_WRAPPER))
   1320 	  && !((req_mode == STRUB_INTERNAL
   1321 		|| req_mode == STRUB_AT_CALLS
   1322 		|| req_mode == STRUB_CALLABLE)
   1323 	       && mode == STRUB_INLINABLE))
   1324 	{
   1325 	  error_at (DECL_SOURCE_LOCATION (node->decl),
   1326 		    "%<strub%> mode %qE selected for %qD, when %qE was requested",
   1327 		    get_strub_mode_attr_parm (mode),
   1328 		    node->decl,
   1329 		    get_strub_mode_attr_parm (req_mode));
   1330 	  if (node->alias)
   1331 	    {
   1332 	      cgraph_node *target = node->ultimate_alias_target ();
   1333 	      if (target != node)
   1334 		error_at (DECL_SOURCE_LOCATION (target->decl),
   1335 			  "the incompatible selection was determined"
   1336 			  " by ultimate alias target %qD",
   1337 			  target->decl);
   1338 	    }
   1339 
   1340 	  /* Report any incompatibilities with explicitly-requested strub.  */
   1341 	  switch (req_mode)
   1342 	    {
   1343 	    case STRUB_AT_CALLS:
   1344 	      can_strub_at_calls_p (node, true);
   1345 	      break;
   1346 
   1347 	    case STRUB_INTERNAL:
   1348 	      can_strub_internally_p (node, true);
   1349 	      break;
   1350 
   1351 	    default:
   1352 	      break;
   1353 	    }
   1354 	}
   1355 
   1356       /* Drop any incompatible strub attributes leading the decl attribute
   1357 	 chain.  Return if we find one with the mode we need.  */
   1358       for (;;)
   1359 	{
   1360 	  if (mode == req_mode)
   1361 	    return;
   1362 
   1363 	  if (DECL_ATTRIBUTES (node->decl) != attr)
   1364 	    break;
   1365 
   1366 	  DECL_ATTRIBUTES (node->decl) = TREE_CHAIN (attr);
   1367 	  attr = get_strub_attr_from_decl (node->decl);
   1368 	  if (!attr)
   1369 	    break;
   1370 
   1371 	  req_mode = get_strub_mode_from_attr (attr);
   1372 	}
   1373     }
   1374   else if (mode == req_mode)
   1375     return;
   1376 
   1377   strub_set_fndt_mode_to (node->decl, mode, attr);
   1378 }
   1379 
   1380 /* Compute and set NODE's strub mode.  */
   1381 
   1382 static void
   1383 set_strub_mode (cgraph_node *node)
   1384 {
   1385   tree attr = get_strub_attr_from_decl (node->decl);
   1386 
   1387   if (attr)
   1388     switch (get_strub_mode_from_attr (attr))
   1389       {
   1390 	/* These can't have been requested through user attributes, so we must
   1391 	   have already gone through them.  */
   1392       case STRUB_WRAPPER:
   1393       case STRUB_WRAPPED:
   1394       case STRUB_INLINABLE:
   1395       case STRUB_AT_CALLS_OPT:
   1396 	return;
   1397 
   1398       case STRUB_DISABLED:
   1399       case STRUB_AT_CALLS:
   1400       case STRUB_INTERNAL:
   1401       case STRUB_CALLABLE:
   1402 	break;
   1403 
   1404       default:
   1405 	gcc_unreachable ();
   1406       }
   1407 
   1408   cgraph_node *xnode = node;
   1409   if (node->alias)
   1410     xnode = node->ultimate_alias_target ();
   1411   /* Weakrefs may remain unresolved (the above will return node) if
   1412      their targets are not defined, so make sure we compute a strub
   1413      mode for them, instead of defaulting to STRUB_DISABLED and
   1414      rendering them uncallable.  */
   1415   enum strub_mode mode = (xnode != node && !xnode->alias
   1416 			  ? get_strub_mode (xnode)
   1417 			  : compute_strub_mode (node, attr));
   1418 
   1419   set_strub_mode_to (node, mode);
   1420 }
   1421 
   1422 
   1423 /* Non-strub functions shouldn't be called from within strub contexts,
   1425    except through callable ones.  Always inline strub functions can
   1426    only be called from strub functions.  */
   1427 
   1428 static bool
   1429 strub_callable_from_p (strub_mode caller_mode, strub_mode callee_mode)
   1430 {
   1431   switch (caller_mode)
   1432     {
   1433     case STRUB_WRAPPED:
   1434     case STRUB_AT_CALLS_OPT:
   1435     case STRUB_AT_CALLS:
   1436     case STRUB_INTERNAL:
   1437     case STRUB_INLINABLE:
   1438       break;
   1439 
   1440     case STRUB_WRAPPER:
   1441     case STRUB_DISABLED:
   1442     case STRUB_CALLABLE:
   1443       return callee_mode != STRUB_INLINABLE;
   1444 
   1445     default:
   1446       gcc_unreachable ();
   1447     }
   1448 
   1449   switch (callee_mode)
   1450     {
   1451     case STRUB_WRAPPED:
   1452     case STRUB_AT_CALLS:
   1453     case STRUB_INLINABLE:
   1454       break;
   1455 
   1456     case STRUB_AT_CALLS_OPT:
   1457     case STRUB_INTERNAL:
   1458     case STRUB_WRAPPER:
   1459       return (flag_strub >= -1);
   1460 
   1461     case STRUB_DISABLED:
   1462       return false;
   1463 
   1464     case STRUB_CALLABLE:
   1465       break;
   1466 
   1467     default:
   1468       gcc_unreachable ();
   1469     }
   1470 
   1471   return true;
   1472 }
   1473 
   1474 /* Return TRUE iff CALLEE can be inlined into CALLER.  We wish to avoid inlining
   1475    WRAPPED functions back into their WRAPPERs.  More generally, we wish to avoid
   1476    inlining strubbed functions into non-strubbed ones.  CALLER doesn't have to
   1477    be an immediate caller of CALLEE: the immediate caller may have already been
   1478    cloned for inlining, and then CALLER may be further up the original call
   1479    chain.  ???  It would be nice if our own caller would retry inlining callee
   1480    if caller gets inlined.  */
   1481 
   1482 bool
   1483 strub_inlinable_to_p (cgraph_node *callee, cgraph_node *caller)
   1484 {
   1485   strub_mode callee_mode = get_strub_mode (callee);
   1486 
   1487   switch (callee_mode)
   1488     {
   1489     case STRUB_WRAPPED:
   1490     case STRUB_AT_CALLS:
   1491     case STRUB_INTERNAL:
   1492     case STRUB_INLINABLE:
   1493     case STRUB_AT_CALLS_OPT:
   1494       break;
   1495 
   1496     case STRUB_WRAPPER:
   1497     case STRUB_DISABLED:
   1498     case STRUB_CALLABLE:
   1499       /* When we consider inlining, we've already verified callability, so we
   1500 	 can even inline callable and then disabled into a strub context.  That
   1501 	 will get strubbed along with the context, so it's hopefully not a
   1502 	 problem.  */
   1503       return true;
   1504 
   1505     default:
   1506       gcc_unreachable ();
   1507     }
   1508 
   1509   strub_mode caller_mode = get_strub_mode (caller);
   1510 
   1511   switch (caller_mode)
   1512     {
   1513     case STRUB_WRAPPED:
   1514     case STRUB_AT_CALLS:
   1515     case STRUB_INTERNAL:
   1516     case STRUB_INLINABLE:
   1517     case STRUB_AT_CALLS_OPT:
   1518       return true;
   1519 
   1520     case STRUB_WRAPPER:
   1521     case STRUB_DISABLED:
   1522     case STRUB_CALLABLE:
   1523       break;
   1524 
   1525     default:
   1526       gcc_unreachable ();
   1527     }
   1528 
   1529   return false;
   1530 }
   1531 
   1532 /* Check that types T1 and T2 are strub-compatible.  Return 1 if the strub modes
   1533    are the same, 2 if they are interchangeable, and 0 otherwise.  */
   1534 
   1535 int
   1536 strub_comptypes (tree t1, tree t2)
   1537 {
   1538   if (TREE_CODE (t1) != TREE_CODE (t2))
   1539     return 0;
   1540 
   1541   enum strub_mode m1 = get_strub_mode_from_type (t1);
   1542   enum strub_mode m2 = get_strub_mode_from_type (t2);
   1543 
   1544   if (m1 == m2)
   1545     return 1;
   1546 
   1547   /* We're dealing with types, so only strub modes that can be selected by
   1548      attributes in the front end matter.  If either mode is at-calls (for
   1549      functions) or internal (for variables), the conversion is not
   1550      compatible.  */
   1551   bool var_p = !FUNC_OR_METHOD_TYPE_P (t1);
   1552   enum strub_mode mr = var_p ? STRUB_INTERNAL : STRUB_AT_CALLS;
   1553   if (m1 == mr || m2 == mr)
   1554     return 0;
   1555 
   1556   return 2;
   1557 }
   1558 
   1559 /* Return the effective strub mode used for CALL, and set *TYPEP to
   1560    the effective type used for the call.  The effective type and mode
   1561    are those of the callee, unless the call involves a typecast.  */
   1562 
   1563 static enum strub_mode
   1564 effective_strub_mode_for_call (gcall *call, tree *typep)
   1565 {
   1566   tree type;
   1567   enum strub_mode mode;
   1568 
   1569   if (strub_call_fntype_override_p (call))
   1570     {
   1571       type = gimple_call_fntype (call);
   1572       mode = get_strub_mode_from_type (type);
   1573     }
   1574   else
   1575     {
   1576       type = TREE_TYPE (TREE_TYPE (gimple_call_fn (call)));
   1577       tree decl = gimple_call_fndecl (call);
   1578       if (decl)
   1579 	mode = get_strub_mode_from_fndecl (decl);
   1580       else
   1581 	mode = get_strub_mode_from_type (type);
   1582     }
   1583 
   1584   if (typep)
   1585     *typep = type;
   1586 
   1587   return mode;
   1588 }
   1589 
   1590 /* Create a distinct copy of the type of NODE's function, and change
   1591    the fntype of all calls to it with the same main type to the new
   1592    type.  */
   1593 
   1594 static void
   1595 distinctify_node_type (cgraph_node *node)
   1596 {
   1597   tree old_type = TREE_TYPE (node->decl);
   1598   tree new_type = build_distinct_type_copy (old_type);
   1599   tree new_ptr_type = NULL_TREE;
   1600 
   1601   /* Remap any calls to node->decl that use old_type, or a variant
   1602      thereof, to new_type as well.  We don't look for aliases, their
   1603      declarations will have their types changed independently, and
   1604      we'll adjust their fntypes then.  */
   1605   for (cgraph_edge *e = node->callers; e; e = e->next_caller)
   1606     {
   1607       if (!e->call_stmt)
   1608 	continue;
   1609       tree fnaddr = gimple_call_fn (e->call_stmt);
   1610       gcc_checking_assert (TREE_CODE (fnaddr) == ADDR_EXPR
   1611 			   && TREE_OPERAND (fnaddr, 0) == node->decl);
   1612       if (strub_call_fntype_override_p (e->call_stmt))
   1613 	continue;
   1614       if (!new_ptr_type)
   1615 	new_ptr_type = build_pointer_type (new_type);
   1616       TREE_TYPE (fnaddr) = new_ptr_type;
   1617       gimple_call_set_fntype (e->call_stmt, new_type);
   1618     }
   1619 
   1620   TREE_TYPE (node->decl) = new_type;
   1621 }
   1622 
   1623 /* Return TRUE iff TYPE and any variants have the same strub mode.  */
   1624 
   1625 static bool
   1626 same_strub_mode_in_variants_p (tree type)
   1627 {
   1628   enum strub_mode mode = get_strub_mode_from_type (type);
   1629 
   1630   for (tree other = TYPE_MAIN_VARIANT (type);
   1631        other != NULL_TREE; other = TYPE_NEXT_VARIANT (other))
   1632     if (type != other && mode != get_strub_mode_from_type (other))
   1633       return false;
   1634 
   1635   /* Check that the canonical type, if set, either is in the same
   1636      variant chain, or has the same strub mode as type.  Also check
   1637      the variants of the canonical type.  */
   1638   if (TYPE_CANONICAL (type)
   1639       && (TYPE_MAIN_VARIANT (TYPE_CANONICAL (type))
   1640 	  != TYPE_MAIN_VARIANT (type)))
   1641     {
   1642       if (mode != get_strub_mode_from_type (TYPE_CANONICAL (type)))
   1643 	return false;
   1644       else
   1645 	return same_strub_mode_in_variants_p (TYPE_CANONICAL (type));
   1646     }
   1647 
   1648   return true;
   1649 }
   1650 
   1651 /* Check that strub functions don't call non-strub functions, and that
   1652    always_inline strub functions are only called by strub
   1653    functions.  */
   1654 
   1655 static void
   1656 verify_strub ()
   1657 {
   1658   cgraph_node *node;
   1659 
   1660   /* It's expected that check strub-wise pointer type compatibility of variables
   1661      and of functions is already taken care of by front-ends, on account of the
   1662      attribute's being marked as affecting type identity and of the creation of
   1663      distinct types.  */
   1664 
   1665   /* Check that call targets in strub contexts have strub-callable types.  */
   1666 
   1667   FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
   1668   {
   1669     enum strub_mode caller_mode = get_strub_mode (node);
   1670 
   1671     for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
   1672       {
   1673 	gcc_checking_assert (e->indirect_unknown_callee);
   1674 
   1675 	if (!e->call_stmt)
   1676 	  continue;
   1677 
   1678 	enum strub_mode callee_mode
   1679 	  = effective_strub_mode_for_call (e->call_stmt, NULL);
   1680 
   1681 	if (!strub_callable_from_p (caller_mode, callee_mode))
   1682 	  error_at (gimple_location (e->call_stmt),
   1683 		    "indirect non-%<strub%> call in %<strub%> context %qD",
   1684 		    node->decl);
   1685       }
   1686 
   1687     for (cgraph_edge *e = node->callees; e; e = e->next_callee)
   1688       {
   1689 	gcc_checking_assert (!e->indirect_unknown_callee);
   1690 
   1691 	if (!e->call_stmt)
   1692 	  continue;
   1693 
   1694 	tree callee_fntype;
   1695 	enum strub_mode callee_mode
   1696 	  = effective_strub_mode_for_call (e->call_stmt, &callee_fntype);
   1697 
   1698 	if (!strub_callable_from_p (caller_mode, callee_mode))
   1699 	  {
   1700 	    if (callee_mode == STRUB_INLINABLE)
   1701 	      error_at (gimple_location (e->call_stmt),
   1702 			"calling %<always_inline%> %<strub%> %qD"
   1703 			" in non-%<strub%> context %qD",
   1704 			e->callee->decl, node->decl);
   1705 	    else if (fndecl_built_in_p (e->callee->decl, BUILT_IN_APPLY_ARGS)
   1706 		     && caller_mode == STRUB_INTERNAL)
   1707 	      /* This is ok, it will be kept in the STRUB_WRAPPER, and removed
   1708 		 from the STRUB_WRAPPED's strub context.  */
   1709 	      continue;
   1710 	    else if (!strub_call_fntype_override_p (e->call_stmt))
   1711 	      error_at (gimple_location (e->call_stmt),
   1712 			"calling non-%<strub%> %qD in %<strub%> context %qD",
   1713 			e->callee->decl, node->decl);
   1714 	    else
   1715 	      error_at (gimple_location (e->call_stmt),
   1716 			"calling %qD using non-%<strub%> type %qT"
   1717 			" in %<strub%> context %qD",
   1718 			e->callee->decl, callee_fntype, node->decl);
   1719 	  }
   1720       }
   1721   }
   1722 }
   1723 
   1724 namespace {
   1725 
   1726 /* Define a pass to compute strub modes.  */
   1727 const pass_data pass_data_ipa_strub_mode = {
   1728   SIMPLE_IPA_PASS,
   1729   "strubm",
   1730   OPTGROUP_NONE,
   1731   TV_NONE,
   1732   PROP_cfg, // properties_required
   1733   0,	    // properties_provided
   1734   0,	    // properties_destroyed
   1735   0,	    // properties_start
   1736   0,	    // properties_finish
   1737 };
   1738 
   1739 class pass_ipa_strub_mode : public simple_ipa_opt_pass
   1740 {
   1741 public:
   1742   pass_ipa_strub_mode (gcc::context *ctxt)
   1743     : simple_ipa_opt_pass (pass_data_ipa_strub_mode, ctxt)
   1744   {}
   1745   opt_pass *clone () { return new pass_ipa_strub_mode (m_ctxt); }
   1746   virtual bool gate (function *) {
   1747     /* In relaxed (-3) and strict (-4) settings, that only enable strub at a
   1748        function or variable attribute's request, the attribute handler changes
   1749        flag_strub to -1 or -2, respectively, if any strub-enabling occurence of
   1750        the attribute is found.  Therefore, if it remains at -3 or -4, nothing
   1751        that would enable strub was found, so we can disable it and avoid the
   1752        overhead.  */
   1753     if (flag_strub < -2)
   1754       flag_strub = 0;
   1755     return flag_strub;
   1756   }
   1757   virtual unsigned int execute (function *);
   1758 };
   1759 
   1760 /* Define a pass to introduce strub transformations.  */
   1761 const pass_data pass_data_ipa_strub = {
   1762   SIMPLE_IPA_PASS,
   1763   "strub",
   1764   OPTGROUP_NONE,
   1765   TV_NONE,
   1766   PROP_cfg | PROP_ssa, // properties_required
   1767   0,	    // properties_provided
   1768   0,	    // properties_destroyed
   1769   0,	    // properties_start
   1770   TODO_update_ssa
   1771   | TODO_cleanup_cfg
   1772   | TODO_rebuild_cgraph_edges
   1773   | TODO_verify_il, // properties_finish
   1774 };
   1775 
   1776 class pass_ipa_strub : public simple_ipa_opt_pass
   1777 {
   1778 public:
   1779   pass_ipa_strub (gcc::context *ctxt)
   1780     : simple_ipa_opt_pass (pass_data_ipa_strub, ctxt)
   1781   {}
   1782   opt_pass *clone () { return new pass_ipa_strub (m_ctxt); }
   1783   virtual bool gate (function *) { return flag_strub && !seen_error (); }
   1784   virtual unsigned int execute (function *);
   1785 
   1786   /* Define on demand and cache some types we use often.  */
   1787 #define DEF_TYPE(IDX, NAME, INIT)		\
   1788   static inline tree get_ ## NAME () {		\
   1789     int idx = STRUB_TYPE_BASE + IDX;		\
   1790     static tree type = strub_cache[idx];	\
   1791     if (!type)					\
   1792       strub_cache[idx] = type = (INIT);		\
   1793     return type;				\
   1794   }
   1795 
   1796   /* Use a distinct ptr_type_node to denote the watermark, so that we can
   1797      recognize it in arg lists and avoid modifying types twice.  */
   1798   DEF_TYPE (0, wmt, build_variant_type_copy (ptr_type_node))
   1799 
   1800   DEF_TYPE (1, pwmt, build_reference_type (get_wmt ()))
   1801 
   1802   DEF_TYPE (2, qpwmt,
   1803 	    build_qualified_type (get_pwmt (),
   1804 				  TYPE_QUAL_RESTRICT
   1805 				  /* | TYPE_QUAL_CONST */))
   1806 
   1807   DEF_TYPE (3, qptr,
   1808 	    build_qualified_type (ptr_type_node,
   1809 				  TYPE_QUAL_RESTRICT
   1810 				  | TYPE_QUAL_CONST))
   1811 
   1812   DEF_TYPE (4, qpvalst,
   1813 	    build_qualified_type (build_reference_type
   1814 				  (va_list_type_node),
   1815 				  TYPE_QUAL_RESTRICT
   1816 				  /* | TYPE_QUAL_CONST */))
   1817 
   1818 #undef DEF_TYPE
   1819 
   1820   /* Define non-strub builtins on demand.  */
   1821 #define DEF_NM_BUILTIN(NAME, CODE, FNTYPELIST)			\
   1822   static tree get_ ## NAME () {					\
   1823     tree decl = builtin_decl_explicit (CODE);			\
   1824     if (!decl)							\
   1825       {								\
   1826 	tree type = build_function_type_list FNTYPELIST;	\
   1827 	decl = add_builtin_function				\
   1828 	  ("__builtin_" #NAME,					\
   1829 	   type, CODE, BUILT_IN_NORMAL,				\
   1830 	   NULL, NULL);						\
   1831 	TREE_NOTHROW (decl) = true;				\
   1832 	set_builtin_decl ((CODE), decl, true);			\
   1833       }								\
   1834     return decl;						\
   1835   }
   1836 
   1837   DEF_NM_BUILTIN (stack_address,
   1838 		  BUILT_IN_STACK_ADDRESS,
   1839 		  (ptr_type_node, NULL))
   1840 
   1841 #undef DEF_NM_BUILTIN
   1842 
   1843   /* Define strub builtins on demand.  */
   1844 #define DEF_SS_BUILTIN(NAME, FNSPEC, CODE, FNTYPELIST)		\
   1845   static tree get_ ## NAME () {					\
   1846     tree decl = builtin_decl_explicit (CODE);			\
   1847     if (!decl)							\
   1848       {								\
   1849 	tree type = build_function_type_list FNTYPELIST;	\
   1850 	tree attrs = NULL;					\
   1851 	if (FNSPEC)						\
   1852 	  attrs = tree_cons (get_identifier ("fn spec"),	\
   1853 			     build_tree_list			\
   1854 			     (NULL_TREE,			\
   1855 			      build_string (strlen (FNSPEC),	\
   1856 					    (FNSPEC))),		\
   1857 			     attrs);				\
   1858 	decl = add_builtin_function_ext_scope			\
   1859 	  ("__builtin___strub_" #NAME,				\
   1860 	   type, CODE, BUILT_IN_NORMAL,				\
   1861 	   "__strub_" #NAME, attrs);				\
   1862 	TREE_NOTHROW (decl) = true;				\
   1863 	set_builtin_decl ((CODE), decl, true);			\
   1864       }								\
   1865     return decl;						\
   1866   }
   1867 
   1868   DEF_SS_BUILTIN (enter, ". Ot",
   1869 		  BUILT_IN___STRUB_ENTER,
   1870 		  (void_type_node, get_qpwmt (), NULL))
   1871   DEF_SS_BUILTIN (update, ". Wt",
   1872 		  BUILT_IN___STRUB_UPDATE,
   1873 		  (void_type_node, get_qpwmt (), NULL))
   1874   DEF_SS_BUILTIN (leave, ". w ",
   1875 		  BUILT_IN___STRUB_LEAVE,
   1876 		  (void_type_node, get_qpwmt (), NULL))
   1877 
   1878 #undef DEF_SS_BUILTIN
   1879 
   1880     /* Define strub identifiers on demand.  */
   1881 #define DEF_IDENT(IDX, NAME)						\
   1882   static inline tree get_ ## NAME () {					\
   1883     int idx = STRUB_IDENT_BASE + IDX;					\
   1884     tree identifier = strub_cache[idx];					\
   1885     if (!identifier)							\
   1886       strub_cache[idx] = identifier = get_identifier (".strub." #NAME);	\
   1887     return identifier;							\
   1888   }
   1889 
   1890   DEF_IDENT (0, watermark_ptr)
   1891   DEF_IDENT (1, va_list_ptr)
   1892   DEF_IDENT (2, apply_args)
   1893 
   1894 #undef DEF_IDENT
   1895 
   1896   static inline int adjust_at_calls_type (tree);
   1897   static inline void adjust_at_calls_call (cgraph_edge *, int, tree);
   1898   static inline void adjust_at_calls_calls (cgraph_node *);
   1899 
   1900   /* Add to SEQ a call to the strub watermark update builtin, taking NODE's
   1901      location if given.  Optionally add the corresponding edge from NODE, with
   1902      execution frequency COUNT.  Return the modified SEQ.  */
   1903 
   1904   static inline gimple_seq
   1905   call_update_watermark (tree wmptr, cgraph_node *node, profile_count count,
   1906 			 gimple_seq seq = NULL)
   1907     {
   1908       tree uwm = get_update ();
   1909       gcall *update = gimple_build_call (uwm, 1, wmptr);
   1910       if (node)
   1911 	gimple_set_location (update, DECL_SOURCE_LOCATION (node->decl));
   1912       gimple_seq_add_stmt (&seq, update);
   1913       if (node)
   1914 	node->create_edge (cgraph_node::get_create (uwm), update, count, false);
   1915       return seq;
   1916     }
   1917 
   1918 };
   1919 
   1920 } // anon namespace
   1921 
   1922 /* Gather with this type a collection of parameters that we're turning into
   1923    explicit references.  */
   1924 
   1925 typedef hash_set<tree> indirect_parms_t;
   1926 
   1927 /* Dereference OP's incoming turned-into-reference parm if it's an
   1928    INDIRECT_PARMS or an ADDR_EXPR thereof.  Set *REC and return according to
   1929    gimple-walking expectations.  */
   1930 
   1931 static tree
   1932 maybe_make_indirect (indirect_parms_t &indirect_parms, tree op, int *rec)
   1933 {
   1934   if (DECL_P (op))
   1935     {
   1936       *rec = 0;
   1937       if (indirect_parms.contains (op))
   1938 	{
   1939 	  tree ret = gimple_fold_indirect_ref (op);
   1940 	  if (!ret)
   1941 	    ret = build2 (MEM_REF,
   1942 			  TREE_TYPE (TREE_TYPE (op)),
   1943 			  op,
   1944 			  build_int_cst (TREE_TYPE (op), 0));
   1945 	  if (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (op)))
   1946 	      && !TREE_THIS_VOLATILE (ret))
   1947 	    TREE_SIDE_EFFECTS (ret) = TREE_THIS_VOLATILE (ret) = 1;
   1948 	  return ret;
   1949 	}
   1950     }
   1951   else if (TREE_CODE (op) == ADDR_EXPR
   1952 	   && DECL_P (TREE_OPERAND (op, 0)))
   1953     {
   1954       *rec = 0;
   1955       if (indirect_parms.contains (TREE_OPERAND (op, 0)))
   1956 	{
   1957 	  op = TREE_OPERAND (op, 0);
   1958 	  return op;
   1959 	}
   1960     }
   1961 
   1962   return NULL_TREE;
   1963 }
   1964 
   1965 /* A gimple-walking function that adds dereferencing to indirect parms.  */
   1966 
   1967 static tree
   1968 walk_make_indirect (tree *op, int *rec, void *arg)
   1969 {
   1970   walk_stmt_info *wi = (walk_stmt_info *)arg;
   1971   indirect_parms_t &indirect_parms = *(indirect_parms_t *)wi->info;
   1972 
   1973   if (!*op || TYPE_P (*op))
   1974     {
   1975       *rec = 0;
   1976       return NULL_TREE;
   1977     }
   1978 
   1979   if (tree repl = maybe_make_indirect (indirect_parms, *op, rec))
   1980     {
   1981       *op = repl;
   1982       wi->changed = true;
   1983     }
   1984 
   1985   return NULL_TREE;
   1986 }
   1987 
   1988 /* A gimple-walking function that turns any non-gimple-val ADDR_EXPRs into a
   1989    separate SSA.  Though addresses of e.g. parameters, and of members thereof,
   1990    are gimple vals, turning parameters into references, with an extra layer of
   1991    indirection and thus explicit dereferencing, need to be regimplified.  */
   1992 
   1993 static tree
   1994 walk_regimplify_addr_expr (tree *op, int *rec, void *arg)
   1995 {
   1996   walk_stmt_info *wi = (walk_stmt_info *)arg;
   1997   gimple_stmt_iterator &gsi = *(gimple_stmt_iterator *)wi->info;
   1998 
   1999   *rec = 0;
   2000 
   2001   if (!*op || TREE_CODE (*op) != ADDR_EXPR)
   2002     return NULL_TREE;
   2003 
   2004   if (!is_gimple_val (*op))
   2005     {
   2006       tree ret = force_gimple_operand_gsi (&gsi, *op, true,
   2007 					   NULL_TREE, true, GSI_SAME_STMT);
   2008       gcc_assert (ret != *op);
   2009       *op = ret;
   2010       wi->changed = true;
   2011     }
   2012 
   2013   return NULL_TREE;
   2014 }
   2015 
   2016 /* Turn STMT's PHI arg defs into separate SSA defs if they've become
   2017    non-gimple_val.  Return TRUE if any edge insertions need to be committed.  */
   2018 
   2019 static bool
   2020 walk_regimplify_phi (gphi *stmt)
   2021 {
   2022   bool needs_commit = false;
   2023 
   2024   for (unsigned i = 0, n = gimple_phi_num_args (stmt); i < n; i++)
   2025     {
   2026       tree op = gimple_phi_arg_def (stmt, i);
   2027       if ((TREE_CODE (op) == ADDR_EXPR
   2028 	   && !is_gimple_val (op))
   2029 	  /* ??? A PARM_DECL that was addressable in the original function and
   2030 	     had its address in PHI nodes, but that became a reference in the
   2031 	     wrapped clone would NOT be updated by update_ssa in PHI nodes.
   2032 	     Alas, if we were to create a default def for it now, update_ssa
   2033 	     would complain that the symbol that needed rewriting already has
   2034 	     SSA names associated with it.  OTOH, leaving the PARM_DECL alone,
   2035 	     it eventually causes errors because it remains unchanged in PHI
   2036 	     nodes, but it gets rewritten as expected if it appears in other
   2037 	     stmts.  So we cheat a little here, and force the PARM_DECL out of
   2038 	     the PHI node and into an assignment.  It's a little expensive,
   2039 	     because we insert it at the edge, which introduces a basic block
   2040 	     that's entirely unnecessary, but it works, and the block will be
   2041 	     removed as the default def gets propagated back into the PHI node,
   2042 	     so the final optimized code looks just as expected.  */
   2043 	  || (TREE_CODE (op) == PARM_DECL
   2044 	      && !TREE_ADDRESSABLE (op)))
   2045 	{
   2046 	  tree temp = make_ssa_name (TREE_TYPE (op), stmt);
   2047 	  if (TREE_CODE (op) == PARM_DECL)
   2048 	    SET_SSA_NAME_VAR_OR_IDENTIFIER (temp, DECL_NAME (op));
   2049 	  SET_PHI_ARG_DEF (stmt, i, temp);
   2050 
   2051 	  gimple *assign = gimple_build_assign (temp, op);
   2052 	  if (gimple_phi_arg_has_location (stmt, i))
   2053 	    gimple_set_location (assign, gimple_phi_arg_location (stmt, i));
   2054 	  gsi_insert_on_edge (gimple_phi_arg_edge (stmt, i), assign);
   2055 	  needs_commit = true;
   2056 	}
   2057     }
   2058 
   2059   return needs_commit;
   2060 }
   2061 
   2062 /* Create a reference type to use for PARM when turning it into a
   2063    reference.  */
   2064 
   2065 static tree
   2066 build_ref_type_for (tree parm)
   2067 {
   2068   gcc_checking_assert (TREE_CODE (parm) == PARM_DECL);
   2069 
   2070   tree ref_type = build_reference_type (TREE_TYPE (parm));
   2071 
   2072   return ref_type;
   2073 }
   2074 
   2075 /* Add cgraph edges from current_function_decl to callees in SEQ with frequency
   2076    COUNT, assuming all calls in SEQ are direct.  */
   2077 
   2078 static void
   2079 add_call_edges_for_seq (gimple_seq seq, profile_count count)
   2080 {
   2081   cgraph_node *node = cgraph_node::get_create (current_function_decl);
   2082 
   2083   for (gimple_stmt_iterator gsi = gsi_start (seq);
   2084        !gsi_end_p (gsi); gsi_next (&gsi))
   2085     {
   2086       gimple *stmt = gsi_stmt (gsi);
   2087 
   2088       gcall *call = dyn_cast <gcall *> (stmt);
   2089       if (!call)
   2090 	continue;
   2091 
   2092       tree callee = gimple_call_fndecl (call);
   2093       gcc_checking_assert (callee);
   2094       node->create_edge (cgraph_node::get_create (callee), call, count, false);
   2095     }
   2096 }
   2097 
   2098 /* Insert SEQ after the call at GSI, as if the call was in a try block with SEQ
   2099    as finally, i.e., SEQ will run after the call whether it returns or
   2100    propagates an exception.  This handles block splitting, EH edge and block
   2101    creation, noreturn and nothrow optimizations, and even throwing calls without
   2102    preexisting local handlers.  */
   2103 
   2104 static void
   2105 gsi_insert_finally_seq_after_call (gimple_stmt_iterator gsi, gimple_seq seq)
   2106 {
   2107   if (!seq)
   2108     return;
   2109 
   2110   gimple *stmt = gsi_stmt (gsi);
   2111 
   2112   if (gimple_has_location (stmt))
   2113     annotate_all_with_location (seq, gimple_location (stmt));
   2114 
   2115   gcall *call = dyn_cast <gcall *> (stmt);
   2116   bool noreturn_p = call && gimple_call_noreturn_p (call);
   2117   int eh_lp = lookup_stmt_eh_lp (stmt);
   2118   bool must_not_throw_p = eh_lp < 0;
   2119   bool nothrow_p = (must_not_throw_p
   2120 		    || (call && gimple_call_nothrow_p (call))
   2121 		    || (eh_lp <= 0
   2122 			&& (TREE_NOTHROW (cfun->decl)
   2123 			    || !opt_for_fn (cfun->decl, flag_exceptions))));
   2124 
   2125   if (noreturn_p && nothrow_p)
   2126     return;
   2127 
   2128   /* Don't expect an EH edge if we're not to throw, or if we're not in an EH
   2129      region yet.  */
   2130   bool no_eh_edge_p = (nothrow_p || !eh_lp);
   2131   bool must_end_bb = stmt_ends_bb_p (stmt);
   2132 
   2133   edge eft = NULL, eeh = NULL;
   2134   if (must_end_bb && !(noreturn_p && no_eh_edge_p))
   2135     {
   2136       gcc_checking_assert (gsi_one_before_end_p (gsi));
   2137 
   2138       edge e;
   2139       edge_iterator ei;
   2140       FOR_EACH_EDGE (e, ei, gsi_bb (gsi)->succs)
   2141 	{
   2142 	  if ((e->flags & EDGE_EH))
   2143 	    {
   2144 	      gcc_checking_assert (!eeh);
   2145 	      eeh = e;
   2146 #if !CHECKING_P
   2147 	      if (eft || noreturn_p)
   2148 		break;
   2149 #endif
   2150 	    }
   2151 	  if ((e->flags & EDGE_FALLTHRU))
   2152 	    {
   2153 	      gcc_checking_assert (!eft);
   2154 	      eft = e;
   2155 #if !CHECKING_P
   2156 	      if (eeh || no_eh_edge_p)
   2157 		break;
   2158 #endif
   2159 	    }
   2160 	}
   2161 
   2162       gcc_checking_assert (!(eft && (eft->flags & EDGE_FALLTHRU))
   2163 			   == noreturn_p);
   2164       gcc_checking_assert (!(eeh && (eeh->flags & EDGE_EH))
   2165 			   == no_eh_edge_p);
   2166       gcc_checking_assert (eft != eeh);
   2167     }
   2168 
   2169   if (!noreturn_p)
   2170     {
   2171       gimple_seq nseq = nothrow_p ? seq : gimple_seq_copy (seq);
   2172 
   2173       if (must_end_bb)
   2174 	{
   2175 	  gcc_checking_assert (gsi_one_before_end_p (gsi));
   2176 	  add_call_edges_for_seq (nseq, eft->count ());
   2177 	  gsi_insert_seq_on_edge_immediate (eft, nseq);
   2178 	}
   2179       else
   2180 	{
   2181 	  add_call_edges_for_seq (nseq, gsi_bb (gsi)->count);
   2182 	  gsi_insert_seq_after (&gsi, nseq, GSI_SAME_STMT);
   2183 	}
   2184     }
   2185 
   2186   if (nothrow_p)
   2187     return;
   2188 
   2189   if (eh_lp)
   2190     {
   2191       add_call_edges_for_seq (seq, eeh->count ());
   2192       gsi_insert_seq_on_edge_immediate (eeh, seq);
   2193       return;
   2194     }
   2195 
   2196   /* A throwing call may appear within a basic block in a function that doesn't
   2197      have any EH regions.  We're going to add a cleanup if so, therefore the
   2198      block will have to be split.  */
   2199   basic_block bb = gsi_bb (gsi);
   2200   if (!gsi_one_before_end_p (gsi))
   2201     split_block (bb, stmt);
   2202 
   2203   /* Create a new block for the EH cleanup.  */
   2204   basic_block bb_eh_cleanup = create_empty_bb (bb);
   2205   if (dom_info_available_p (CDI_DOMINATORS))
   2206     set_immediate_dominator (CDI_DOMINATORS, bb_eh_cleanup, bb);
   2207   if (current_loops)
   2208     add_bb_to_loop (bb_eh_cleanup, current_loops->tree_root);
   2209 
   2210   /* Make the new block an EH cleanup for the call.  */
   2211   eh_region new_r = gen_eh_region_cleanup (NULL);
   2212   eh_landing_pad lp = gen_eh_landing_pad (new_r);
   2213   tree label = gimple_block_label (bb_eh_cleanup);
   2214   lp->post_landing_pad = label;
   2215   EH_LANDING_PAD_NR (label) = lp->index;
   2216   add_stmt_to_eh_lp (stmt, lp->index);
   2217 
   2218   /* Add the cleanup code to the EH cleanup block.  */
   2219   gsi = gsi_after_labels (bb_eh_cleanup);
   2220   gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
   2221 
   2222   /* And then propagate the exception further.  */
   2223   gresx *resx = gimple_build_resx (new_r->index);
   2224   if (gimple_has_location (stmt))
   2225     gimple_set_location (resx, gimple_location (stmt));
   2226   gsi_insert_before (&gsi, resx, GSI_SAME_STMT);
   2227 
   2228   /* Finally, wire the EH cleanup block into the CFG.  */
   2229   edge neeh = make_eh_edge (stmt);
   2230   neeh->probability = profile_probability::never ();
   2231   gcc_checking_assert (neeh->dest == bb_eh_cleanup);
   2232   gcc_checking_assert (!neeh->dest->count.initialized_p ());
   2233   neeh->dest->count = neeh->count ();
   2234   add_call_edges_for_seq (seq, neeh->dest->count);
   2235 }
   2236 
   2237 /* Copy the attribute list at *ATTRS, minus any NAME attributes, leaving
   2238    shareable trailing nodes alone.  */
   2239 
   2240 static inline void
   2241 remove_named_attribute_unsharing (const char *name, tree *attrs)
   2242 {
   2243   while (tree found = lookup_attribute (name, *attrs))
   2244     {
   2245       /* Copy nodes up to the next NAME attribute.  */
   2246       while (*attrs != found)
   2247 	{
   2248 	  *attrs = tree_cons (TREE_PURPOSE (*attrs),
   2249 			      TREE_VALUE (*attrs),
   2250 			      TREE_CHAIN (*attrs));
   2251 	  attrs = &TREE_CHAIN (*attrs);
   2252 	}
   2253       /* Then drop it.  */
   2254       gcc_checking_assert (*attrs == found);
   2255       *attrs = TREE_CHAIN (*attrs);
   2256     }
   2257 }
   2258 
   2259 /* Record the order of the last cgraph entry whose mode we've already set, so
   2260    that we can perform mode setting incrementally without duplication.  */
   2261 static int last_cgraph_order;
   2262 
   2263 /* Set strub modes for functions introduced since the last call.  */
   2264 
   2265 static void
   2266 ipa_strub_set_mode_for_new_functions ()
   2267 {
   2268   if (symtab->order == last_cgraph_order)
   2269     return;
   2270 
   2271   cgraph_node *node;
   2272 
   2273   /* Go through the functions twice, once over non-aliases, and then over
   2274      aliases, so that aliases can reuse the mode computation of their ultimate
   2275      targets.  */
   2276   for (int aliases = 0; aliases <= 1; aliases++)
   2277     FOR_EACH_FUNCTION (node)
   2278     {
   2279       if (!node->alias != !aliases)
   2280 	continue;
   2281 
   2282       /*  Already done.  */
   2283       if (node->order < last_cgraph_order)
   2284 	continue;
   2285 
   2286       set_strub_mode (node);
   2287     }
   2288 
   2289   last_cgraph_order = symtab->order;
   2290 }
   2291 
   2292 /* Return FALSE if NODE is a strub context, and TRUE otherwise.  */
   2293 
   2294 bool
   2295 strub_splittable_p (cgraph_node *node)
   2296 {
   2297   switch (get_strub_mode (node))
   2298     {
   2299     case STRUB_WRAPPED:
   2300     case STRUB_AT_CALLS:
   2301     case STRUB_AT_CALLS_OPT:
   2302     case STRUB_INLINABLE:
   2303     case STRUB_INTERNAL:
   2304     case STRUB_WRAPPER:
   2305       return false;
   2306 
   2307     case STRUB_CALLABLE:
   2308     case STRUB_DISABLED:
   2309       break;
   2310 
   2311     default:
   2312       gcc_unreachable ();
   2313     }
   2314 
   2315   return true;
   2316 }
   2317 
   2318 /* Return the PARM_DECL of the incoming watermark pointer, if there is one.  */
   2319 
   2320 tree
   2321 strub_watermark_parm (tree fndecl)
   2322 {
   2323   switch (get_strub_mode_from_fndecl (fndecl))
   2324     {
   2325     case STRUB_WRAPPED:
   2326     case STRUB_AT_CALLS:
   2327     case STRUB_AT_CALLS_OPT:
   2328       break;
   2329 
   2330     case STRUB_INTERNAL:
   2331     case STRUB_WRAPPER:
   2332     case STRUB_CALLABLE:
   2333     case STRUB_DISABLED:
   2334     case STRUB_INLINABLE:
   2335       return NULL_TREE;
   2336 
   2337     default:
   2338       gcc_unreachable ();
   2339     }
   2340 
   2341   for (tree parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
   2342     /* The type (variant) compare finds the parameter even in a just-created
   2343        clone, before we set its name, but the type-based compare doesn't work
   2344        during builtin expansion within the lto compiler, because we'll have
   2345        created a separate variant in that run.  */
   2346     if (TREE_TYPE (parm) == pass_ipa_strub::get_qpwmt ()
   2347 	|| DECL_NAME (parm) == pass_ipa_strub::get_watermark_ptr ())
   2348       return parm;
   2349 
   2350   gcc_unreachable ();
   2351 }
   2352 
   2353 /* Adjust a STRUB_AT_CALLS function TYPE, adding a watermark pointer if it
   2354    hasn't been added yet.  Return the named argument count.  */
   2355 
   2356 int
   2357 pass_ipa_strub::adjust_at_calls_type (tree type)
   2358 {
   2359   int named_args = 0;
   2360 
   2361   gcc_checking_assert (same_strub_mode_in_variants_p (type));
   2362 
   2363   if (!TYPE_ARG_TYPES (type))
   2364     return named_args;
   2365 
   2366   tree *tlist = &TYPE_ARG_TYPES (type);
   2367   tree qpwmptrt = get_qpwmt ();
   2368   while (*tlist && TREE_VALUE (*tlist) != void_type_node)
   2369     {
   2370       /* The type has already been adjusted.  */
   2371       if (TREE_VALUE (*tlist) == qpwmptrt)
   2372 	return named_args;
   2373       named_args++;
   2374       *tlist = tree_cons (TREE_PURPOSE (*tlist),
   2375 			  TREE_VALUE (*tlist),
   2376 			  TREE_CHAIN (*tlist));
   2377       tlist = &TREE_CHAIN (*tlist);
   2378     }
   2379 
   2380   /* Add the new argument after all named arguments, so as to not mess with
   2381      attributes that reference parameters.  */
   2382   *tlist = tree_cons (NULL_TREE, get_qpwmt (), *tlist);
   2383 
   2384 #if ATTR_FNSPEC_DECONST_WATERMARK
   2385   if (!type_already_adjusted)
   2386     {
   2387       int flags = flags_from_decl_or_type (type);
   2388       tree fnspec = lookup_attribute ("fn spec", type);
   2389 
   2390       if ((flags & (ECF_CONST | ECF_PURE | ECF_NOVOPS)) || fnspec)
   2391 	{
   2392 	  size_t xargs = 1;
   2393 	  size_t curlen = 0, tgtlen = 2 + 2 * (named_args + xargs);
   2394 	  auto_vec<char> nspecv (tgtlen);
   2395 	  char *nspec = &nspecv[0]; /* It will *not* be NUL-terminated!  */
   2396 	  if (fnspec)
   2397 	    {
   2398 	      tree fnspecstr = TREE_VALUE (TREE_VALUE (fnspec));
   2399 	      curlen = TREE_STRING_LENGTH (fnspecstr);
   2400 	      memcpy (nspec, TREE_STRING_POINTER (fnspecstr), curlen);
   2401 	    }
   2402 	  if (!curlen)
   2403 	    {
   2404 	      nspec[curlen++] = '.';
   2405 	      nspec[curlen++] = ((flags & ECF_CONST)
   2406 				 ? 'c'
   2407 				 : (flags & ECF_PURE)
   2408 				 ? 'p'
   2409 				 : ' ');
   2410 	    }
   2411 	  while (curlen < tgtlen - 2 * xargs)
   2412 	    {
   2413 	      nspec[curlen++] = '.';
   2414 	      nspec[curlen++] = ' ';
   2415 	    }
   2416 	  nspec[curlen++] = 'W';
   2417 	  nspec[curlen++] = 't';
   2418 
   2419 	  /* The type has already been copied, if needed, before adding
   2420 	     parameters.  */
   2421 	  TYPE_ATTRIBUTES (type)
   2422 	    = tree_cons (get_identifier ("fn spec"),
   2423 			 build_tree_list (NULL_TREE,
   2424 					  build_string (tgtlen, nspec)),
   2425 			 TYPE_ATTRIBUTES (type));
   2426 	}
   2427     }
   2428 #endif
   2429 
   2430   return named_args;
   2431 }
   2432 
   2433 /* Adjust a call to an at-calls call target.  Create a watermark local variable
   2434    if needed, initialize it before, pass it to the callee according to the
   2435    modified at-calls interface, and release the callee's stack space after the
   2436    call, if not deferred.  If the call is const or pure, arrange for the
   2437    watermark to not be assumed unused or unchanged.  */
   2438 
   2439 void
   2440 pass_ipa_strub::adjust_at_calls_call (cgraph_edge *e, int named_args,
   2441 				      tree callee_fntype)
   2442 {
   2443   gcc_checking_assert (e->call_stmt);
   2444   gcall *ocall = e->call_stmt;
   2445   gimple_stmt_iterator gsi = gsi_for_stmt (ocall);
   2446 
   2447   /* Make sure we haven't modified this call yet.  */
   2448   gcc_checking_assert (!(int (gimple_call_num_args (ocall)) > named_args
   2449 			 && (TREE_TYPE (gimple_call_arg (ocall, named_args))
   2450 			     == get_pwmt ())));
   2451 
   2452   tree tsup;
   2453   if (!(tsup = gimple_call_fndecl (ocall)))
   2454     tsup = TREE_TYPE (TREE_TYPE (gimple_call_fn (ocall)));
   2455   if (!strub_target_support_p (tsup, true, gimple_location (ocall)))
   2456     return;
   2457 
   2458   /* If we're already within a strub context, pass on the incoming watermark
   2459      pointer, and omit the enter and leave calls around the modified call, as an
   2460      optimization, or as a means to satisfy a tail-call requirement.  */
   2461   tree swmp = ((opt_for_fn (e->caller->decl, optimize_size)
   2462 		|| opt_for_fn (e->caller->decl, optimize) > 2
   2463 		|| gimple_call_must_tail_p (ocall)
   2464 		|| (opt_for_fn (e->caller->decl, optimize) == 2
   2465 		    && gimple_call_tail_p (ocall)))
   2466 	       ? strub_watermark_parm (e->caller->decl)
   2467 	       : NULL_TREE);
   2468   bool omit_own_watermark = swmp;
   2469   tree swm = NULL_TREE;
   2470   if (!omit_own_watermark)
   2471     {
   2472       swm = create_tmp_var (get_wmt (), ".strub.watermark");
   2473       TREE_ADDRESSABLE (swm) = true;
   2474       swmp = build1 (ADDR_EXPR, get_pwmt (), swm);
   2475 
   2476       /* Initialize the watermark before the call.  */
   2477       tree enter = get_enter ();
   2478       gcall *stptr = gimple_build_call (enter, 1,
   2479 					unshare_expr (swmp));
   2480       if (gimple_has_location (ocall))
   2481 	gimple_set_location (stptr, gimple_location (ocall));
   2482       gsi_insert_before (&gsi, stptr, GSI_SAME_STMT);
   2483       e->caller->create_edge (cgraph_node::get_create (enter),
   2484 			      stptr, gsi_bb (gsi)->count, false);
   2485     }
   2486 
   2487 
   2488   /* Replace the call with one that passes the swmp argument first.  */
   2489   gcall *wrcall;
   2490   { gcall *stmt = ocall;
   2491     // Mostly copied from gimple_call_copy_skip_args.
   2492     int i = 0;
   2493     int nargs = gimple_call_num_args (stmt);
   2494     auto_vec<tree> vargs (MAX (nargs, named_args) + 1);
   2495     gcall *new_stmt;
   2496 
   2497     /* pr71109.c calls a prototypeless function, then defines it with
   2498        additional arguments.  It's ill-formed, but after it's inlined,
   2499        it somehow works out.  */
   2500     for (; i < named_args && i < nargs; i++)
   2501       vargs.quick_push (gimple_call_arg (stmt, i));
   2502     for (; i < named_args; i++)
   2503       vargs.quick_push (null_pointer_node);
   2504 
   2505     vargs.quick_push (unshare_expr (swmp));
   2506 
   2507     for (; i < nargs; i++)
   2508       vargs.quick_push (gimple_call_arg (stmt, i));
   2509 
   2510     if (gimple_call_internal_p (stmt))
   2511       gcc_unreachable ();
   2512     else
   2513       new_stmt = gimple_build_call_vec (gimple_call_fn (stmt), vargs);
   2514     gimple_call_set_fntype (new_stmt, callee_fntype);
   2515 
   2516     if (gimple_call_lhs (stmt))
   2517       gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
   2518 
   2519     gimple_move_vops (new_stmt, stmt);
   2520 
   2521     if (gimple_has_location (stmt))
   2522       gimple_set_location (new_stmt, gimple_location (stmt));
   2523     gimple_call_copy_flags (new_stmt, stmt);
   2524     gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));
   2525 
   2526     gimple_set_modified (new_stmt, true);
   2527 
   2528     wrcall = new_stmt;
   2529   }
   2530 
   2531   update_stmt (wrcall);
   2532   gsi_replace (&gsi, wrcall, true);
   2533   cgraph_edge::set_call_stmt (e, wrcall, false);
   2534 
   2535   /* Insert the strub code after the call.  */
   2536   gimple_seq seq = NULL;
   2537 
   2538 #if !ATTR_FNSPEC_DECONST_WATERMARK
   2539   /* If the call will be assumed to not modify or even read the
   2540      watermark, make it read and modified ourselves.  */
   2541   if ((gimple_call_flags (wrcall)
   2542        & (ECF_CONST | ECF_PURE | ECF_NOVOPS)))
   2543     {
   2544       if (!swm)
   2545 	swm = build2 (MEM_REF,
   2546 		      TREE_TYPE (TREE_TYPE (swmp)),
   2547 		      swmp,
   2548 		      build_int_cst (TREE_TYPE (swmp), 0));
   2549 
   2550       vec<tree, va_gc> *inputs = NULL;
   2551       vec<tree, va_gc> *outputs = NULL;
   2552       vec_safe_push (outputs,
   2553 		     build_tree_list
   2554 		     (build_tree_list
   2555 		      (NULL_TREE, build_string (2, "=m")),
   2556 		      unshare_expr (swm)));
   2557       vec_safe_push (inputs,
   2558 		     build_tree_list
   2559 		     (build_tree_list
   2560 		      (NULL_TREE, build_string (1, "m")),
   2561 		      unshare_expr (swm)));
   2562       gasm *forcemod = gimple_build_asm_vec ("", inputs, outputs,
   2563 					     NULL, NULL);
   2564       gimple_seq_add_stmt (&seq, forcemod);
   2565 
   2566       /* If the call will be assumed to not even read the watermark,
   2567 	 make sure it is already in memory before the call.  */
   2568       if ((gimple_call_flags (wrcall) & ECF_CONST))
   2569 	{
   2570 	  vec<tree, va_gc> *inputs = NULL;
   2571 	  vec_safe_push (inputs,
   2572 			 build_tree_list
   2573 			 (build_tree_list
   2574 			  (NULL_TREE, build_string (1, "m")),
   2575 			  unshare_expr (swm)));
   2576 	  gasm *force_store = gimple_build_asm_vec ("", inputs, NULL,
   2577 						    NULL, NULL);
   2578 	  if (gimple_has_location (wrcall))
   2579 	    gimple_set_location (force_store, gimple_location (wrcall));
   2580 	  gsi_insert_before (&gsi, force_store, GSI_SAME_STMT);
   2581 	}
   2582     }
   2583 #endif
   2584 
   2585   if (!omit_own_watermark)
   2586     {
   2587       gcall *sleave = gimple_build_call (get_leave (), 1,
   2588 					 unshare_expr (swmp));
   2589       gimple_seq_add_stmt (&seq, sleave);
   2590 
   2591       gassign *clobber = gimple_build_assign (swm,
   2592 					      build_clobber
   2593 					      (TREE_TYPE (swm)));
   2594       gimple_seq_add_stmt (&seq, clobber);
   2595     }
   2596 
   2597   gsi_insert_finally_seq_after_call (gsi, seq);
   2598 }
   2599 
   2600 /* Adjust all at-calls calls in NODE. */
   2601 
   2602 void
   2603 pass_ipa_strub::adjust_at_calls_calls (cgraph_node *node)
   2604 {
   2605   /* Adjust unknown-callee indirect calls with STRUB_AT_CALLS types within
   2606      onode.  */
   2607   if (node->indirect_calls)
   2608     {
   2609       push_cfun (DECL_STRUCT_FUNCTION (node->decl));
   2610       for (cgraph_edge *e = node->indirect_calls; e; e = e->next_callee)
   2611 	{
   2612 	  gcc_checking_assert (e->indirect_unknown_callee);
   2613 
   2614 	  if (!e->call_stmt)
   2615 	    continue;
   2616 
   2617 	  tree callee_fntype;
   2618 	  enum strub_mode callee_mode
   2619 	    = effective_strub_mode_for_call (e->call_stmt, &callee_fntype);
   2620 
   2621 	  if (callee_mode != STRUB_AT_CALLS
   2622 	      && callee_mode != STRUB_AT_CALLS_OPT)
   2623 	    continue;
   2624 
   2625 	  int named_args = adjust_at_calls_type (callee_fntype);
   2626 
   2627 	  adjust_at_calls_call (e, named_args, callee_fntype);
   2628 	}
   2629       pop_cfun ();
   2630     }
   2631 
   2632   if (node->callees)
   2633     {
   2634       push_cfun (DECL_STRUCT_FUNCTION (node->decl));
   2635       for (cgraph_edge *e = node->callees; e; e = e->next_callee)
   2636 	{
   2637 	  gcc_checking_assert (!e->indirect_unknown_callee);
   2638 
   2639 	  if (!e->call_stmt)
   2640 	    continue;
   2641 
   2642 	  tree callee_fntype;
   2643 	  enum strub_mode callee_mode
   2644 	    = effective_strub_mode_for_call (e->call_stmt, &callee_fntype);
   2645 
   2646 	  if (callee_mode != STRUB_AT_CALLS
   2647 	      && callee_mode != STRUB_AT_CALLS_OPT)
   2648 	    continue;
   2649 
   2650 	  int named_args = adjust_at_calls_type (callee_fntype);
   2651 
   2652 	  adjust_at_calls_call (e, named_args, callee_fntype);
   2653 	}
   2654       pop_cfun ();
   2655     }
   2656 }
   2657 
   2658 /* The strubm (strub mode) pass computes a strub mode for each function in the
   2659    call graph, and checks, before any inlining, that strub callability
   2660    requirements in effect are satisfied.  */
   2661 
   2662 unsigned int
   2663 pass_ipa_strub_mode::execute (function *)
   2664 {
   2665   last_cgraph_order = 0;
   2666   ipa_strub_set_mode_for_new_functions ();
   2667 
   2668   /* Verify before any inlining or other transformations.  */
   2669   verify_strub ();
   2670 
   2671   return 0;
   2672 }
   2673 
   2674 /* Create a strub mode pass.  */
   2675 
   2676 simple_ipa_opt_pass *
   2677 make_pass_ipa_strub_mode (gcc::context *ctxt)
   2678 {
   2679   return new pass_ipa_strub_mode (ctxt);
   2680 }
   2681 
   2682 /* The strub pass proper adjusts types, signatures, and at-calls calls, and
   2683    splits internal-strub functions.  */
   2684 
   2685 unsigned int
   2686 pass_ipa_strub::execute (function *)
   2687 {
   2688   cgraph_node *onode;
   2689 
   2690   ipa_strub_set_mode_for_new_functions ();
   2691 
   2692   /* First, adjust the signature of at-calls functions.  We adjust types of
   2693      at-calls functions first, so that we don't modify types in place unless
   2694      strub is explicitly requested.  */
   2695   FOR_EACH_FUNCTION (onode)
   2696   {
   2697     enum strub_mode mode = get_strub_mode (onode);
   2698 
   2699     if (mode == STRUB_AT_CALLS
   2700 	|| mode == STRUB_AT_CALLS_OPT)
   2701       {
   2702 	/* Create a type variant if strubbing was not explicitly requested in
   2703 	   the function type.  */
   2704 	if (get_strub_mode_from_type (TREE_TYPE (onode->decl)) != mode)
   2705 	  distinctify_node_type (onode);
   2706 
   2707 	int named_args = adjust_at_calls_type (TREE_TYPE (onode->decl));
   2708 
   2709 	/* An external function explicitly declared with strub won't have a
   2710 	   body.  Even with implicit at-calls strub, a function may have had its
   2711 	   body removed after we selected the mode, and then we have nothing
   2712 	   further to do.  */
   2713 	if (!onode->has_gimple_body_p ())
   2714 	  continue;
   2715 
   2716 	tree *pargs = &DECL_ARGUMENTS (onode->decl);
   2717 
   2718 	/* A noninterposable_alias reuses the same parm decl chain, don't add
   2719 	   the parm twice.  */
   2720 	bool aliased_parms = (onode->alias && *pargs
   2721 			      && DECL_CONTEXT (*pargs) != onode->decl);
   2722 
   2723 	if (aliased_parms)
   2724 	  continue;
   2725 
   2726 	for (int i = 0; i < named_args; i++)
   2727 	  pargs = &DECL_CHAIN (*pargs);
   2728 
   2729 	tree wmptr = build_decl (DECL_SOURCE_LOCATION (onode->decl),
   2730 				 PARM_DECL,
   2731 				 get_watermark_ptr (),
   2732 				 get_qpwmt ());
   2733 	DECL_ARTIFICIAL (wmptr) = 1;
   2734 	DECL_ARG_TYPE (wmptr) = get_qpwmt ();
   2735 	DECL_CONTEXT (wmptr) = onode->decl;
   2736 	TREE_USED (wmptr) = 1;
   2737 	DECL_CHAIN (wmptr) = *pargs;
   2738 	*pargs = wmptr;
   2739 
   2740 	if (onode->alias)
   2741 	  continue;
   2742 
   2743 	cgraph_node *nnode = onode;
   2744 	push_cfun (DECL_STRUCT_FUNCTION (nnode->decl));
   2745 
   2746 	{
   2747 	  edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun));
   2748 	  gimple_seq seq = call_update_watermark (wmptr, nnode, e->src->count);
   2749 	  gsi_insert_seq_on_edge_immediate (e, seq);
   2750 	}
   2751 
   2752 	if (DECL_STRUCT_FUNCTION (nnode->decl)->calls_alloca)
   2753 	  {
   2754 	    basic_block bb;
   2755 	    FOR_EACH_BB_FN (bb, cfun)
   2756 	      for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
   2757 		   !gsi_end_p (gsi); gsi_next (&gsi))
   2758 		{
   2759 		  gimple *stmt = gsi_stmt (gsi);
   2760 
   2761 		  gcall *call = dyn_cast <gcall *> (stmt);
   2762 
   2763 		  if (!call)
   2764 		    continue;
   2765 
   2766 		  if (gimple_alloca_call_p (call))
   2767 		    {
   2768 		      /* Capture stack growth.  */
   2769 		      gimple_seq seq = call_update_watermark (wmptr, NULL,
   2770 							      gsi_bb (gsi)
   2771 							      ->count);
   2772 		      gsi_insert_finally_seq_after_call (gsi, seq);
   2773 		    }
   2774 		}
   2775 	  }
   2776 
   2777 	pop_cfun ();
   2778       }
   2779   }
   2780 
   2781   FOR_EACH_FUNCTION (onode)
   2782   {
   2783     if (!onode->has_gimple_body_p ())
   2784       continue;
   2785 
   2786     enum strub_mode mode = get_strub_mode (onode);
   2787 
   2788     if (mode != STRUB_INTERNAL)
   2789       {
   2790 	adjust_at_calls_calls (onode);
   2791 	continue;
   2792       }
   2793 
   2794     bool is_stdarg = calls_builtin_va_start_p (onode);;
   2795     bool apply_args = calls_builtin_apply_args_p (onode);
   2796 
   2797     vec<ipa_adjusted_param, va_gc> *nparms = NULL;
   2798     unsigned j = 0;
   2799     {
   2800       // The following loop copied from ipa-split.c:split_function.
   2801       for (tree parm = DECL_ARGUMENTS (onode->decl);
   2802 	   parm; parm = DECL_CHAIN (parm), j++)
   2803 	{
   2804 	  ipa_adjusted_param adj = {};
   2805 	  adj.op = IPA_PARAM_OP_COPY;
   2806 	  adj.base_index = j;
   2807 	  adj.prev_clone_index = j;
   2808 	  vec_safe_push (nparms, adj);
   2809 	}
   2810 
   2811       if (apply_args)
   2812 	{
   2813 	  ipa_adjusted_param aaadj = {};
   2814 	  aaadj.op = IPA_PARAM_OP_NEW;
   2815 	  aaadj.type = get_qptr ();
   2816 	  vec_safe_push (nparms, aaadj);
   2817 	}
   2818 
   2819       if (is_stdarg)
   2820 	{
   2821 	  ipa_adjusted_param vladj = {};
   2822 	  vladj.op = IPA_PARAM_OP_NEW;
   2823 	  vladj.type = get_qpvalst ();
   2824 	  vec_safe_push (nparms, vladj);
   2825 	}
   2826 
   2827       ipa_adjusted_param wmadj = {};
   2828       wmadj.op = IPA_PARAM_OP_NEW;
   2829       wmadj.type = get_qpwmt ();
   2830       vec_safe_push (nparms, wmadj);
   2831     }
   2832     ipa_param_adjustments adj (nparms, -1, false);
   2833 
   2834     cgraph_node *nnode = onode->create_version_clone_with_body
   2835       (auto_vec<cgraph_edge *> (0),
   2836        NULL, &adj, NULL, NULL, "strub", NULL);
   2837 
   2838     if (!nnode)
   2839       {
   2840 	error_at (DECL_SOURCE_LOCATION (onode->decl),
   2841 		  "failed to split %qD for %<strub%>",
   2842 		  onode->decl);
   2843 	continue;
   2844       }
   2845 
   2846     onode->split_part = true;
   2847     if (onode->calls_comdat_local)
   2848       nnode->add_to_same_comdat_group (onode);
   2849 
   2850     set_strub_mode_to (onode, STRUB_WRAPPER);
   2851     set_strub_mode_to (nnode, STRUB_WRAPPED);
   2852 
   2853     adjust_at_calls_calls (nnode);
   2854 
   2855     /* Decide which of the wrapped function's parms we want to turn into
   2856        references to the argument passed to the wrapper.  In general, we want to
   2857        copy small arguments, and avoid copying large ones.  Variable-sized array
   2858        lengths given by other arguments, as in 20020210-1.c, would lead to
   2859        problems if passed by value, after resetting the original function and
   2860        dropping the length computation; passing them by reference works.
   2861        DECL_BY_REFERENCE is *not* a substitute for this: it involves copying
   2862        anyway, but performed at the caller.  */
   2863     indirect_parms_t indirect_nparms (3, false);
   2864     unsigned adjust_ftype = 0;
   2865     unsigned named_args = 0;
   2866     for (tree parm = DECL_ARGUMENTS (onode->decl),
   2867 	   nparm = DECL_ARGUMENTS (nnode->decl),
   2868 	   nparmt = TYPE_ARG_TYPES (TREE_TYPE (nnode->decl));
   2869 	 parm;
   2870 	 named_args++,
   2871 	   parm = DECL_CHAIN (parm),
   2872 	   nparm = DECL_CHAIN (nparm),
   2873 	   nparmt = nparmt ? TREE_CHAIN (nparmt) : NULL_TREE)
   2874       if (TREE_THIS_VOLATILE (parm)
   2875 	  || !(0 /* DECL_BY_REFERENCE (narg) */
   2876 	       || is_gimple_reg_type (TREE_TYPE (nparm))
   2877 	       || VECTOR_TYPE_P (TREE_TYPE (nparm))
   2878 	       || TREE_CODE (TREE_TYPE (nparm)) == COMPLEX_TYPE
   2879 	       || (tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (nparm)))
   2880 		   && (tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (nparm)))
   2881 		       <= 4 * UNITS_PER_WORD))))
   2882 	{
   2883 	  /* No point in indirecting pointer types.  Presumably they
   2884 	     won't ever pass the size-based test above, but check the
   2885 	     assumption here, because getting this wrong would mess
   2886 	     with attribute access and possibly others.  We deal with
   2887 	     fn spec below.  */
   2888 	  gcc_checking_assert (!POINTER_TYPE_P (TREE_TYPE (nparm)));
   2889 
   2890 	  indirect_nparms.add (nparm);
   2891 
   2892 	  /* ??? Is there any case in which it is not safe to suggest the parms
   2893 	     turned indirect don't alias anything else?  They are distinct,
   2894 	     unaliased memory in the wrapper, and the wrapped can't possibly
   2895 	     take pointers into them because none of the pointers passed to the
   2896 	     wrapper can alias other incoming parameters passed by value, even
   2897 	     if with transparent reference, and the wrapper doesn't take any
   2898 	     extra parms that could point into wrapper's parms.  So we can
   2899 	     probably drop the TREE_ADDRESSABLE and keep the TRUE.  */
   2900 	  tree ref_type = build_ref_type_for (nparm);
   2901 
   2902 	  if (TREE_THIS_VOLATILE (nparm)
   2903 	      && TYPE_VOLATILE (TREE_TYPE (nparm))
   2904 	      && !TYPE_VOLATILE (ref_type))
   2905 	    TREE_SIDE_EFFECTS (nparm) = TREE_THIS_VOLATILE (nparm) = 0;
   2906 	  DECL_ARG_TYPE (nparm) = TREE_TYPE (nparm) = ref_type;
   2907 	  relayout_decl (nparm);
   2908 	  TREE_ADDRESSABLE (nparm) = 0;
   2909 	  DECL_BY_REFERENCE (nparm) = 0;
   2910 	  DECL_NOT_GIMPLE_REG_P (nparm) = 0;
   2911 	  /* ??? This avoids mismatches in debug info bind stmts in
   2912 	     e.g. a-chahan .  */
   2913 	  DECL_ABSTRACT_ORIGIN (nparm) = NULL;
   2914 
   2915 	  if (nparmt)
   2916 	    adjust_ftype++;
   2917 	}
   2918 
   2919     /* Also adjust the wrapped function type, if needed.  */
   2920     if (adjust_ftype)
   2921       {
   2922 	tree nftype = TREE_TYPE (nnode->decl);
   2923 
   2924 	/* We always add at least one argument at the end of the signature, when
   2925 	   cloning the function, so we don't expect to need to duplicate the
   2926 	   type here.  */
   2927 	gcc_checking_assert (TYPE_ARG_TYPES (nftype)
   2928 			     != TYPE_ARG_TYPES (TREE_TYPE (onode->decl)));
   2929 
   2930 	/* Check that fnspec still works for the modified function signature,
   2931 	   and drop it otherwise.  */
   2932 	bool drop_fnspec = false;
   2933 	tree fnspec = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (nftype));
   2934 	attr_fnspec spec = fnspec ? attr_fnspec (fnspec) : attr_fnspec ("");
   2935 
   2936 	unsigned retcopy;
   2937 	if (!(fnspec && spec.returns_arg (&retcopy)))
   2938 	  retcopy = (unsigned) -1;
   2939 
   2940 	unsigned i = 0;
   2941 	for (tree nparm = DECL_ARGUMENTS (nnode->decl),
   2942 	       nparmt = TYPE_ARG_TYPES (nftype);
   2943 	     adjust_ftype > 0;
   2944 	     i++, nparm = DECL_CHAIN (nparm), nparmt = TREE_CHAIN (nparmt))
   2945 	  if (indirect_nparms.contains (nparm))
   2946 	    {
   2947 	      TREE_VALUE (nparmt) = TREE_TYPE (nparm);
   2948 	      adjust_ftype--;
   2949 
   2950 	      if (fnspec && !drop_fnspec)
   2951 		{
   2952 		  if (i == retcopy)
   2953 		    drop_fnspec = true;
   2954 		  else if (spec.arg_specified_p (i))
   2955 		    {
   2956 		      /* Properties that apply to pointers only must not be
   2957 			 present, because we don't make pointers further
   2958 			 indirect.  */
   2959 		      gcc_checking_assert
   2960 			(!spec.arg_max_access_size_given_by_arg_p (i, NULL));
   2961 		      gcc_checking_assert (!spec.arg_copied_to_arg_p (i, NULL));
   2962 
   2963 		      /* Any claim of direct access only is invalidated by
   2964 			 adding an indirection level.  */
   2965 		      if (spec.arg_direct_p (i))
   2966 			drop_fnspec = true;
   2967 
   2968 		      /* If there's a claim the argument is not read from, the
   2969 			 added indirection invalidates it: if the argument is
   2970 			 used at all, then the pointer will necessarily be
   2971 			 read.  */
   2972 		      if (!spec.arg_maybe_read_p (i)
   2973 			  && spec.arg_used_p (i))
   2974 			drop_fnspec = true;
   2975 		    }
   2976 		}
   2977 	    }
   2978 
   2979 	/* ??? Maybe we could adjust it instead.  Note we don't need
   2980 	   to mess with attribute access: pointer-typed parameters are
   2981 	   not modified, so they can remain unchanged.  */
   2982 	if (drop_fnspec)
   2983 	  remove_named_attribute_unsharing ("fn spec",
   2984 					    &TYPE_ATTRIBUTES (nftype));
   2985 
   2986 	TREE_TYPE (nnode->decl) = nftype;
   2987       }
   2988 
   2989 #if ATTR_FNSPEC_DECONST_WATERMARK
   2990     {
   2991       int flags = flags_from_decl_or_type (nnode->decl);
   2992       tree fnspec = lookup_attribute ("fn spec", TREE_TYPE (nnode->decl));
   2993 
   2994       if ((flags & (ECF_CONST | ECF_PURE | ECF_NOVOPS)) || fnspec)
   2995 	{
   2996 	  size_t xargs = 1 + int (is_stdarg) + int (apply_args);
   2997 	  size_t curlen = 0, tgtlen = 2 + 2 * (named_args + xargs);
   2998 	  auto_vec<char> nspecv (tgtlen);
   2999 	  char *nspec = &nspecv[0]; /* It will *not* be NUL-terminated!  */
   3000 	  bool no_writes_p = true;
   3001 	  if (fnspec)
   3002 	    {
   3003 	      tree fnspecstr = TREE_VALUE (TREE_VALUE (fnspec));
   3004 	      curlen = TREE_STRING_LENGTH (fnspecstr);
   3005 	      memcpy (nspec, TREE_STRING_POINTER (fnspecstr), curlen);
   3006 	      if (!(flags & (ECF_CONST | ECF_PURE | ECF_NOVOPS))
   3007 		  && curlen >= 2
   3008 		  && nspec[1] != 'c' && nspec[1] != 'C'
   3009 		  && nspec[1] != 'p' && nspec[1] != 'P')
   3010 		no_writes_p = false;
   3011 	    }
   3012 	  if (!curlen)
   3013 	    {
   3014 	      nspec[curlen++] = '.';
   3015 	      nspec[curlen++] = ((flags & ECF_CONST)
   3016 				 ? 'c'
   3017 				 : (flags & ECF_PURE)
   3018 				 ? 'p'
   3019 				 : ' ');
   3020 	    }
   3021 	  while (curlen < tgtlen - 2 * xargs)
   3022 	    {
   3023 	      nspec[curlen++] = '.';
   3024 	      nspec[curlen++] = ' ';
   3025 	    }
   3026 
   3027 	  /* These extra args are unlikely to be present in const or pure
   3028 	     functions.  It's conceivable that a function that takes variable
   3029 	     arguments, or that passes its arguments on to another function,
   3030 	     could be const or pure, but it would not modify the arguments, and,
   3031 	     being pure or const, it couldn't possibly modify or even access
   3032 	     memory referenced by them.  But it can read from these internal
   3033 	     data structures created by the wrapper, and from any
   3034 	     argument-passing memory referenced by them, so we denote the
   3035 	     possibility of reading from multiple levels of indirection, but
   3036 	     only of reading because const/pure.  */
   3037 	  if (apply_args)
   3038 	    {
   3039 	      nspec[curlen++] = 'r';
   3040 	      nspec[curlen++] = ' ';
   3041 	    }
   3042 	  if (is_stdarg)
   3043 	    {
   3044 	      nspec[curlen++] = (no_writes_p ? 'r' : '.');
   3045 	      nspec[curlen++] = (no_writes_p ? 't' : ' ');
   3046 	    }
   3047 
   3048 	  nspec[curlen++] = 'W';
   3049 	  nspec[curlen++] = 't';
   3050 
   3051 	  /* The type has already been copied before adding parameters.  */
   3052 	  gcc_checking_assert (TYPE_ARG_TYPES (TREE_TYPE (nnode->decl))
   3053 			       != TYPE_ARG_TYPES (TREE_TYPE (onode->decl)));
   3054 	  TYPE_ATTRIBUTES (TREE_TYPE (nnode->decl))
   3055 	    = tree_cons (get_identifier ("fn spec"),
   3056 			 build_tree_list (NULL_TREE,
   3057 					  build_string (tgtlen, nspec)),
   3058 			 TYPE_ATTRIBUTES (TREE_TYPE (nnode->decl)));
   3059 	}
   3060     }
   3061 #endif
   3062 
   3063     {
   3064       tree decl = onode->decl;
   3065       cgraph_node *target = nnode;
   3066 
   3067       { // copied from create_wrapper
   3068 
   3069 	/* Preserve DECL_RESULT so we get right by reference flag.  */
   3070 	tree decl_result = DECL_RESULT (decl);
   3071 
   3072 	/* Remove the function's body but keep arguments to be reused
   3073 	   for thunk.  */
   3074 	onode->release_body (true);
   3075 	onode->reset (/* unlike create_wrapper: preserve_comdat_group = */true);
   3076 
   3077 	DECL_UNINLINABLE (decl) = false;
   3078 	DECL_RESULT (decl) = decl_result;
   3079 	DECL_INITIAL (decl) = NULL;
   3080 	allocate_struct_function (decl, false);
   3081 	set_cfun (NULL);
   3082 
   3083 	/* Turn alias into thunk and expand it into GIMPLE representation.  */
   3084 	onode->definition = true;
   3085 
   3086 	thunk_info::get_create (onode);
   3087 	onode->thunk = true;
   3088 	onode->create_edge (target, NULL, onode->count);
   3089 	onode->callees->can_throw_external = !TREE_NOTHROW (target->decl);
   3090 
   3091 	tree arguments = DECL_ARGUMENTS (decl);
   3092 
   3093 	while (arguments)
   3094 	  {
   3095 	    TREE_ADDRESSABLE (arguments) = false;
   3096 	    arguments = TREE_CHAIN (arguments);
   3097 	  }
   3098 
   3099 	{
   3100 	  tree alias = onode->callees->callee->decl;
   3101 	  tree thunk_fndecl = decl;
   3102 	  tree a;
   3103 
   3104 	  int nxargs = 1 + is_stdarg + apply_args;
   3105 
   3106 	  { // Simplified from expand_thunk.
   3107 	    tree restype;
   3108 	    basic_block bb, then_bb, else_bb, return_bb;
   3109 	    gimple_stmt_iterator bsi;
   3110 	    int nargs = 0;
   3111 	    tree arg;
   3112 	    int i;
   3113 	    tree resdecl;
   3114 	    tree restmp = NULL;
   3115 
   3116 	    gcall *call;
   3117 	    greturn *ret;
   3118 	    bool alias_is_noreturn = TREE_THIS_VOLATILE (alias);
   3119 
   3120 	    a = DECL_ARGUMENTS (thunk_fndecl);
   3121 
   3122 	    current_function_decl = thunk_fndecl;
   3123 
   3124 	    /* Ensure thunks are emitted in their correct sections.  */
   3125 	    resolve_unique_section (thunk_fndecl, 0,
   3126 				    flag_function_sections);
   3127 
   3128 	    bitmap_obstack_initialize (NULL);
   3129 
   3130 	    /* Build the return declaration for the function.  */
   3131 	    restype = TREE_TYPE (TREE_TYPE (thunk_fndecl));
   3132 	    if (DECL_RESULT (thunk_fndecl) == NULL_TREE)
   3133 	      {
   3134 		resdecl = build_decl (input_location, RESULT_DECL, 0, restype);
   3135 		DECL_ARTIFICIAL (resdecl) = 1;
   3136 		DECL_IGNORED_P (resdecl) = 1;
   3137 		DECL_CONTEXT (resdecl) = thunk_fndecl;
   3138 		DECL_RESULT (thunk_fndecl) = resdecl;
   3139 	      }
   3140 	    else
   3141 	      resdecl = DECL_RESULT (thunk_fndecl);
   3142 
   3143 	    profile_count cfg_count = onode->count;
   3144 	    if (!cfg_count.initialized_p ())
   3145 	      cfg_count = profile_count::from_gcov_type (BB_FREQ_MAX).guessed_local ();
   3146 
   3147 	    bb = then_bb = else_bb = return_bb
   3148 	      = init_lowered_empty_function (thunk_fndecl, true, cfg_count);
   3149 
   3150 	    bsi = gsi_start_bb (bb);
   3151 
   3152 	    /* Build call to the function being thunked.  */
   3153 	    if (!VOID_TYPE_P (restype)
   3154 		&& (!alias_is_noreturn
   3155 		    || TREE_ADDRESSABLE (restype)
   3156 		    || TREE_CODE (TYPE_SIZE_UNIT (restype)) != INTEGER_CST))
   3157 	      {
   3158 		if (DECL_BY_REFERENCE (resdecl))
   3159 		  {
   3160 		    restmp = gimple_fold_indirect_ref (resdecl);
   3161 		    if (!restmp)
   3162 		      restmp = build2 (MEM_REF,
   3163 				       TREE_TYPE (TREE_TYPE (resdecl)),
   3164 				       resdecl,
   3165 				       build_int_cst (TREE_TYPE (resdecl), 0));
   3166 		  }
   3167 		else if (aggregate_value_p (resdecl, TREE_TYPE (thunk_fndecl)))
   3168 		  {
   3169 		    restmp = resdecl;
   3170 
   3171 		    if (VAR_P (restmp))
   3172 		      {
   3173 			add_local_decl (cfun, restmp);
   3174 			BLOCK_VARS (DECL_INITIAL (current_function_decl))
   3175 			  = restmp;
   3176 		      }
   3177 		  }
   3178 		else
   3179 		  restmp = create_tmp_reg (restype, "retval");
   3180 	      }
   3181 
   3182 	    for (arg = a; arg; arg = DECL_CHAIN (arg))
   3183 	      nargs++;
   3184 	    auto_vec<tree> vargs (nargs + nxargs);
   3185 	    i = 0;
   3186 	    arg = a;
   3187 
   3188 	    if (nargs)
   3189 	      for (tree nparm = DECL_ARGUMENTS (nnode->decl);
   3190 		   i < nargs;
   3191 		   i++, arg = DECL_CHAIN (arg), nparm = DECL_CHAIN (nparm))
   3192 		{
   3193 		  tree save_arg = arg;
   3194 
   3195 		  /* Arrange to pass indirectly the parms, if we decided to do
   3196 		     so, and revert its type in the wrapper.  */
   3197 		  if (indirect_nparms.contains (nparm))
   3198 		    {
   3199 		      tree ref_type = TREE_TYPE (nparm);
   3200 		      TREE_ADDRESSABLE (arg) = true;
   3201 		      arg = build1 (ADDR_EXPR, ref_type, arg);
   3202 		    }
   3203 		  else if (!TREE_THIS_VOLATILE (arg))
   3204 		    DECL_NOT_GIMPLE_REG_P (arg) = 0;
   3205 
   3206 		  /* Convert the argument back to the type used by the calling
   3207 		     conventions, e.g. a non-prototyped float type is passed as
   3208 		     double, as in 930603-1.c, and needs to be converted back to
   3209 		     double to be passed on unchanged to the wrapped
   3210 		     function.  */
   3211 		  if (TREE_TYPE (nparm) != DECL_ARG_TYPE (nparm))
   3212 		    {
   3213 		      tree tmp = arg;
   3214 		      /* If ARG is e.g. volatile, we must copy and
   3215 			 convert in separate statements.  */
   3216 		      if (!is_gimple_val (arg))
   3217 			{
   3218 			  tmp = create_tmp_reg (TYPE_MAIN_VARIANT
   3219 						(TREE_TYPE (arg)), "arg");
   3220 			  gimple *stmt = gimple_build_assign (tmp, arg);
   3221 			  gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
   3222 			}
   3223 		      arg = fold_convert (DECL_ARG_TYPE (nparm), tmp);
   3224 		    }
   3225 
   3226 		  if (!is_gimple_val (arg))
   3227 		    {
   3228 		      tree tmp = create_tmp_reg (TYPE_MAIN_VARIANT
   3229 						 (TREE_TYPE (arg)), "arg");
   3230 		      gimple *stmt = gimple_build_assign (tmp, arg);
   3231 		      gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
   3232 		      arg = tmp;
   3233 		    }
   3234 		  vargs.quick_push (arg);
   3235 		  arg = save_arg;
   3236 		}
   3237 	    /* These strub arguments are adjusted later.  */
   3238 	    if (apply_args)
   3239 	      vargs.quick_push (null_pointer_node);
   3240 	    if (is_stdarg)
   3241 	      vargs.quick_push (null_pointer_node);
   3242 	    vargs.quick_push (null_pointer_node);
   3243 	    call = gimple_build_call_vec (build_fold_addr_expr_loc (0, alias),
   3244 					  vargs);
   3245 	    onode->callees->call_stmt = call;
   3246 	    // gimple_call_set_from_thunk (call, true);
   3247 	    if (DECL_STATIC_CHAIN (alias))
   3248 	      {
   3249 		tree p = DECL_STRUCT_FUNCTION (alias)->static_chain_decl;
   3250 		tree type = TREE_TYPE (p);
   3251 		tree decl = build_decl (DECL_SOURCE_LOCATION (thunk_fndecl),
   3252 					PARM_DECL, create_tmp_var_name ("CHAIN"),
   3253 					type);
   3254 		DECL_ARTIFICIAL (decl) = 1;
   3255 		DECL_IGNORED_P (decl) = 1;
   3256 		TREE_USED (decl) = 1;
   3257 		DECL_CONTEXT (decl) = thunk_fndecl;
   3258 		DECL_ARG_TYPE (decl) = type;
   3259 		TREE_READONLY (decl) = 1;
   3260 
   3261 		struct function *sf = DECL_STRUCT_FUNCTION (thunk_fndecl);
   3262 		sf->static_chain_decl = decl;
   3263 
   3264 		gimple_call_set_chain (call, decl);
   3265 	      }
   3266 
   3267 	    /* Return slot optimization is always possible and in fact required to
   3268 	       return values with DECL_BY_REFERENCE.  */
   3269 	    if (aggregate_value_p (resdecl, TREE_TYPE (thunk_fndecl))
   3270 		&& (!is_gimple_reg_type (TREE_TYPE (resdecl))
   3271 		    || DECL_BY_REFERENCE (resdecl)))
   3272 	      gimple_call_set_return_slot_opt (call, true);
   3273 
   3274 	    if (restmp)
   3275 	      {
   3276 		gimple_call_set_lhs (call, restmp);
   3277 		gcc_assert (useless_type_conversion_p (TREE_TYPE (restmp),
   3278 						       TREE_TYPE (TREE_TYPE (alias))));
   3279 	      }
   3280 	    gsi_insert_after (&bsi, call, GSI_NEW_STMT);
   3281 	    if (!alias_is_noreturn)
   3282 	      {
   3283 		/* Build return value.  */
   3284 		if (!DECL_BY_REFERENCE (resdecl))
   3285 		  ret = gimple_build_return (restmp);
   3286 		else
   3287 		  ret = gimple_build_return (resdecl);
   3288 
   3289 		gsi_insert_after (&bsi, ret, GSI_NEW_STMT);
   3290 	      }
   3291 	    else
   3292 	      {
   3293 		remove_edge (single_succ_edge (bb));
   3294 	      }
   3295 
   3296 	    cfun->gimple_df->in_ssa_p = true;
   3297 	    update_max_bb_count ();
   3298 	    profile_status_for_fn (cfun)
   3299 	      = cfg_count.initialized_p () && cfg_count.ipa_p ()
   3300 	      ? PROFILE_READ : PROFILE_GUESSED;
   3301 	    /* FIXME: C++ FE should stop setting TREE_ASM_WRITTEN on thunks.  */
   3302 	    // TREE_ASM_WRITTEN (thunk_fndecl) = false;
   3303 	    delete_unreachable_blocks ();
   3304 	    update_ssa (TODO_update_ssa);
   3305 	    checking_verify_flow_info ();
   3306 	    free_dominance_info (CDI_DOMINATORS);
   3307 
   3308 	    /* Since we want to emit the thunk, we explicitly mark its name as
   3309 	       referenced.  */
   3310 	    onode->thunk = false;
   3311 	    onode->lowered = true;
   3312 	    bitmap_obstack_release (NULL);
   3313 	  }
   3314 	  current_function_decl = NULL;
   3315 	  set_cfun (NULL);
   3316 	}
   3317 
   3318 	thunk_info::remove (onode);
   3319 
   3320 	// some more of create_wrapper at the end of the next block.
   3321       }
   3322     }
   3323 
   3324     {
   3325       tree aaval = NULL_TREE;
   3326       tree vaptr = NULL_TREE;
   3327       tree wmptr = NULL_TREE;
   3328       for (tree arg = DECL_ARGUMENTS (nnode->decl); arg; arg = DECL_CHAIN (arg))
   3329 	{
   3330 	  aaval = vaptr;
   3331 	  vaptr = wmptr;
   3332 	  wmptr = arg;
   3333 	}
   3334 
   3335       if (!apply_args)
   3336 	aaval = NULL_TREE;
   3337       /* The trailing args are [apply_args], [va_list_ptr], and
   3338 	 watermark.  If we don't have a va_list_ptr, the penultimate
   3339 	 argument is apply_args.
   3340        */
   3341       else if (!is_stdarg)
   3342 	aaval = vaptr;
   3343 
   3344       if (!is_stdarg)
   3345 	vaptr = NULL_TREE;
   3346 
   3347       DECL_NAME (wmptr) = get_watermark_ptr ();
   3348       DECL_ARTIFICIAL (wmptr) = 1;
   3349       DECL_IGNORED_P (wmptr) = 1;
   3350       TREE_USED (wmptr) = 1;
   3351 
   3352       if (is_stdarg)
   3353 	{
   3354 	  DECL_NAME (vaptr) = get_va_list_ptr ();
   3355 	  DECL_ARTIFICIAL (vaptr) = 1;
   3356 	  DECL_IGNORED_P (vaptr) = 1;
   3357 	  TREE_USED (vaptr) = 1;
   3358 	}
   3359 
   3360       if (apply_args)
   3361 	{
   3362 	  DECL_NAME (aaval) = get_apply_args ();
   3363 	  DECL_ARTIFICIAL (aaval) = 1;
   3364 	  DECL_IGNORED_P (aaval) = 1;
   3365 	  TREE_USED (aaval) = 1;
   3366 	}
   3367 
   3368       push_cfun (DECL_STRUCT_FUNCTION (nnode->decl));
   3369 
   3370       {
   3371 	edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun));
   3372 	gimple_seq seq = call_update_watermark (wmptr, nnode, e->src->count);
   3373 	gsi_insert_seq_on_edge_immediate (e, seq);
   3374       }
   3375 
   3376       bool any_indirect = !indirect_nparms.is_empty ();
   3377 
   3378       if (any_indirect)
   3379 	{
   3380 	  basic_block bb;
   3381 	  bool needs_commit = false;
   3382 	  FOR_EACH_BB_FN (bb, cfun)
   3383 	    {
   3384 	      for (gphi_iterator gsi = gsi_start_nonvirtual_phis (bb);
   3385 		   !gsi_end_p (gsi);
   3386 		   gsi_next_nonvirtual_phi (&gsi))
   3387 		{
   3388 		  gphi *stmt = gsi.phi ();
   3389 
   3390 		  walk_stmt_info wi = {};
   3391 		  wi.info = &indirect_nparms;
   3392 		  walk_gimple_op (stmt, walk_make_indirect, &wi);
   3393 		  if (wi.changed && !is_gimple_debug (gsi_stmt (gsi)))
   3394 		    if (walk_regimplify_phi (stmt))
   3395 		      needs_commit = true;
   3396 		}
   3397 
   3398 	      for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
   3399 		   !gsi_end_p (gsi); gsi_next (&gsi))
   3400 		{
   3401 		  gimple *stmt = gsi_stmt (gsi);
   3402 
   3403 		  walk_stmt_info wi = {};
   3404 		  wi.info = &indirect_nparms;
   3405 		  walk_gimple_op (stmt, walk_make_indirect, &wi);
   3406 		  if (wi.changed)
   3407 		    {
   3408 		      if (!is_gimple_debug (stmt))
   3409 			{
   3410 			  wi.info = &gsi;
   3411 			  walk_gimple_op (stmt, walk_regimplify_addr_expr,
   3412 					  &wi);
   3413 			}
   3414 		      update_stmt (stmt);
   3415 		    }
   3416 		}
   3417 	    }
   3418 	  if (needs_commit)
   3419 	    gsi_commit_edge_inserts ();
   3420 	}
   3421 
   3422       if (DECL_STRUCT_FUNCTION (nnode->decl)->calls_alloca
   3423 	  || is_stdarg || apply_args)
   3424 	for (cgraph_edge *e = nnode->callees, *enext; e; e = enext)
   3425 	  {
   3426 	    if (!e->call_stmt)
   3427 	      continue;
   3428 
   3429 	    gcall *call = e->call_stmt;
   3430 	    gimple_stmt_iterator gsi = gsi_for_stmt (call);
   3431 	    tree fndecl = e->callee->decl;
   3432 
   3433 	    enext = e->next_callee;
   3434 
   3435 	    if (gimple_alloca_call_p (call))
   3436 	      {
   3437 		gimple_seq seq = call_update_watermark (wmptr, NULL,
   3438 							gsi_bb (gsi)->count);
   3439 		gsi_insert_finally_seq_after_call (gsi, seq);
   3440 	      }
   3441 	    else if (fndecl && is_stdarg
   3442 		     && fndecl_built_in_p (fndecl, BUILT_IN_VA_START))
   3443 	      {
   3444 		/* Using a non-default stdarg ABI makes the function ineligible
   3445 		   for internal strub.  */
   3446 		gcc_checking_assert (builtin_decl_explicit (BUILT_IN_VA_START)
   3447 				     == fndecl);
   3448 		tree bvacopy = builtin_decl_explicit (BUILT_IN_VA_COPY);
   3449 		gimple_call_set_fndecl (call, bvacopy);
   3450 		tree arg = vaptr;
   3451 		/* The va_copy source must be dereferenced, unless it's an array
   3452 		   type, that would have decayed to a pointer.  */
   3453 		if (TREE_CODE (TREE_TYPE (TREE_TYPE (vaptr))) != ARRAY_TYPE)
   3454 		  {
   3455 		    arg = gimple_fold_indirect_ref (vaptr);
   3456 		    if (!arg)
   3457 		      arg = build2 (MEM_REF,
   3458 				    TREE_TYPE (TREE_TYPE (vaptr)),
   3459 				    vaptr,
   3460 				    build_int_cst (TREE_TYPE (vaptr), 0));
   3461 		    if (!is_gimple_val (arg))
   3462 		      arg = force_gimple_operand_gsi (&gsi, arg, true,
   3463 						      NULL_TREE, true, GSI_SAME_STMT);
   3464 		  }
   3465 		gimple_call_set_arg (call, 1, arg);
   3466 		update_stmt (call);
   3467 		e->redirect_callee (cgraph_node::get_create (bvacopy));
   3468 	      }
   3469 	    else if (fndecl && apply_args
   3470 		     && fndecl_built_in_p (fndecl, BUILT_IN_APPLY_ARGS))
   3471 	      {
   3472 		tree lhs = gimple_call_lhs (call);
   3473 		gimple *assign = (lhs
   3474 				  ? gimple_build_assign (lhs, aaval)
   3475 				  : gimple_build_nop ());
   3476 		gsi_replace (&gsi, assign, true);
   3477 		cgraph_edge::remove (e);
   3478 	      }
   3479 	  }
   3480 
   3481       { // a little more copied from create_wrapper
   3482 
   3483 	/* Inline summary set-up.  */
   3484 	nnode->analyze ();
   3485 	// inline_analyze_function (nnode);
   3486       }
   3487 
   3488       pop_cfun ();
   3489     }
   3490 
   3491     {
   3492       push_cfun (DECL_STRUCT_FUNCTION (onode->decl));
   3493       gimple_stmt_iterator gsi
   3494 	= gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
   3495 
   3496       gcall *wrcall;
   3497       while (!(wrcall = dyn_cast <gcall *> (gsi_stmt (gsi))))
   3498 	gsi_next (&gsi);
   3499 
   3500       tree swm = create_tmp_var (get_wmt (), ".strub.watermark");
   3501       TREE_ADDRESSABLE (swm) = true;
   3502       tree swmp = build1 (ADDR_EXPR, get_pwmt (), swm);
   3503 
   3504       tree enter = get_enter ();
   3505       gcall *stptr = gimple_build_call (enter, 1, unshare_expr (swmp));
   3506       gimple_set_location (stptr, gimple_location (wrcall));
   3507       gsi_insert_before (&gsi, stptr, GSI_SAME_STMT);
   3508       onode->create_edge (cgraph_node::get_create (enter),
   3509 			  stptr, gsi_bb (gsi)->count, false);
   3510 
   3511       int nargs = gimple_call_num_args (wrcall);
   3512 
   3513       gimple_seq seq = NULL;
   3514 
   3515       if (apply_args)
   3516 	{
   3517 	  tree aalst = create_tmp_var (ptr_type_node, ".strub.apply_args");
   3518 	  tree bappargs = builtin_decl_explicit (BUILT_IN_APPLY_ARGS);
   3519 	  gcall *appargs = gimple_build_call (bappargs, 0);
   3520 	  gimple_call_set_lhs (appargs, aalst);
   3521 	  gimple_set_location (appargs, gimple_location (wrcall));
   3522 	  gsi_insert_before (&gsi, appargs, GSI_SAME_STMT);
   3523 	  gimple_call_set_arg (wrcall, nargs - 2 - is_stdarg, aalst);
   3524 	  onode->create_edge (cgraph_node::get_create (bappargs),
   3525 			      appargs, gsi_bb (gsi)->count, false);
   3526 	}
   3527 
   3528       if (is_stdarg)
   3529 	{
   3530 	  tree valst = create_tmp_var (va_list_type_node, ".strub.va_list");
   3531 	  TREE_ADDRESSABLE (valst) = true;
   3532 	  tree vaptr = build1 (ADDR_EXPR,
   3533 			       build_pointer_type (va_list_type_node),
   3534 			       valst);
   3535 	  gimple_call_set_arg (wrcall, nargs - 2, unshare_expr (vaptr));
   3536 
   3537 	  tree bvastart = builtin_decl_explicit (BUILT_IN_VA_START);
   3538 	  gcall *vastart = gimple_build_call (bvastart, 2,
   3539 					      unshare_expr (vaptr),
   3540 					      integer_zero_node);
   3541 	  gimple_set_location (vastart, gimple_location (wrcall));
   3542 	  gsi_insert_before (&gsi, vastart, GSI_SAME_STMT);
   3543 	  onode->create_edge (cgraph_node::get_create (bvastart),
   3544 			      vastart, gsi_bb (gsi)->count, false);
   3545 
   3546 	  tree bvaend = builtin_decl_explicit (BUILT_IN_VA_END);
   3547 	  gcall *vaend = gimple_build_call (bvaend, 1, unshare_expr (vaptr));
   3548 	  gimple_set_location (vaend, gimple_location (wrcall));
   3549 	  gimple_seq_add_stmt (&seq, vaend);
   3550 	}
   3551 
   3552       gimple_call_set_arg (wrcall, nargs - 1, unshare_expr (swmp));
   3553       // gimple_call_set_tail (wrcall, false);
   3554       update_stmt (wrcall);
   3555 
   3556       {
   3557 #if !ATTR_FNSPEC_DECONST_WATERMARK
   3558 	/* If the call will be assumed to not modify or even read the
   3559 	   watermark, make it read and modified ourselves.  */
   3560 	if ((gimple_call_flags (wrcall)
   3561 	     & (ECF_CONST | ECF_PURE | ECF_NOVOPS)))
   3562 	  {
   3563 	    vec<tree, va_gc> *inputs = NULL;
   3564 	    vec<tree, va_gc> *outputs = NULL;
   3565 	    vec_safe_push (outputs,
   3566 			   build_tree_list
   3567 			   (build_tree_list
   3568 			    (NULL_TREE, build_string (2, "=m")),
   3569 			    swm));
   3570 	    vec_safe_push (inputs,
   3571 			   build_tree_list
   3572 			   (build_tree_list
   3573 			    (NULL_TREE, build_string (1, "m")),
   3574 			    swm));
   3575 	    gasm *forcemod = gimple_build_asm_vec ("", inputs, outputs,
   3576 						   NULL, NULL);
   3577 	    gimple_seq_add_stmt (&seq, forcemod);
   3578 
   3579 	    /* If the call will be assumed to not even read the watermark,
   3580 	       make sure it is already in memory before the call.  */
   3581 	    if ((gimple_call_flags (wrcall) & ECF_CONST))
   3582 	      {
   3583 		vec<tree, va_gc> *inputs = NULL;
   3584 		vec_safe_push (inputs,
   3585 			       build_tree_list
   3586 			       (build_tree_list
   3587 				(NULL_TREE, build_string (1, "m")),
   3588 				swm));
   3589 		gasm *force_store = gimple_build_asm_vec ("", inputs, NULL,
   3590 							  NULL, NULL);
   3591 		gimple_set_location (force_store, gimple_location (wrcall));
   3592 		gsi_insert_before (&gsi, force_store, GSI_SAME_STMT);
   3593 	      }
   3594 	  }
   3595 #endif
   3596 
   3597 	gcall *sleave = gimple_build_call (get_leave (), 1,
   3598 					   unshare_expr (swmp));
   3599 	gimple_seq_add_stmt (&seq, sleave);
   3600 
   3601 	gassign *clobber = gimple_build_assign (swm,
   3602 						build_clobber
   3603 						(TREE_TYPE (swm)));
   3604 	gimple_seq_add_stmt (&seq, clobber);
   3605       }
   3606 
   3607       gsi_insert_finally_seq_after_call (gsi, seq);
   3608 
   3609       /* For nnode, we don't rebuild edges because we wish to retain
   3610 	 any redirections copied to it from earlier passes, so we add
   3611 	 call graph edges explicitly there, but for onode, we create a
   3612 	 fresh function, so we may as well just issue the calls and
   3613 	 then rebuild all cgraph edges.  */
   3614       // cgraph_edge::rebuild_edges ();
   3615       onode->analyze ();
   3616       // inline_analyze_function (onode);
   3617 
   3618       pop_cfun ();
   3619     }
   3620   }
   3621 
   3622   return 0;
   3623 }
   3624 
   3625 simple_ipa_opt_pass *
   3626 make_pass_ipa_strub (gcc::context *ctxt)
   3627 {
   3628   return new pass_ipa_strub (ctxt);
   3629 }
   3630 
   3631 #include "gt-ipa-strub.h"
   3632