GCC Middle and Back End API Reference
ipa-strub.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "tree.h"
#include "gimple.h"
#include "gimplify.h"
#include "tree-pass.h"
#include "ssa.h"
#include "gimple-iterator.h"
#include "gimplify-me.h"
#include "tree-into-ssa.h"
#include "tree-ssa.h"
#include "tree-cfg.h"
#include "cfghooks.h"
#include "cfgloop.h"
#include "cfgcleanup.h"
#include "tree-eh.h"
#include "except.h"
#include "builtins.h"
#include "attribs.h"
#include "tree-inline.h"
#include "cgraph.h"
#include "alloc-pool.h"
#include "symbol-summary.h"
#include "sreal.h"
#include "ipa-cp.h"
#include "ipa-prop.h"
#include "ipa-fnsummary.h"
#include "gimple-fold.h"
#include "fold-const.h"
#include "gimple-walk.h"
#include "tree-dfa.h"
#include "langhooks.h"
#include "calls.h"
#include "vec.h"
#include "stor-layout.h"
#include "varasm.h"
#include "alias.h"
#include "diagnostic.h"
#include "intl.h"
#include "ipa-strub.h"
#include "symtab-thunks.h"
#include "attr-fnspec.h"
#include "target.h"
#include "gcc-urlifier.h"
#include "gt-ipa-strub.h"
Include dependency graph for ipa-strub.cc:

Macros

#define ATTR_FNSPEC_DECONST_WATERMARK   0
 
#define STRUB_ID_COUNT   8
 
#define STRUB_IDENT_COUNT   3
 
#define STRUB_TYPE_COUNT   5
 
#define STRUB_ID_BASE   0
 
#define STRUB_IDENT_BASE   (STRUB_ID_BASE + STRUB_ID_COUNT)
 
#define STRUB_TYPE_BASE   (STRUB_IDENT_BASE + STRUB_IDENT_COUNT)
 
#define STRUB_CACHE_SIZE   (STRUB_TYPE_BASE + STRUB_TYPE_COUNT)
 
#define DEF_STRUB_IDS(IDX, NAME, ID)
 
#define DEF_STRUB_ID(IDX, NAME)
 
#define STRUB_INTERNAL_MAX_EXTRA_ARGS   3
 
#define DEF_TYPE(IDX, NAME, INIT)
 
#define DEF_NM_BUILTIN(NAME, CODE, FNTYPELIST)
 
#define DEF_SS_BUILTIN(NAME, FNSPEC, CODE, FNTYPELIST)
 
#define DEF_IDENT(IDX, NAME)
 

Typedefs

typedef hash_set< treeindirect_parms_t
 

Enumerations

enum  strub_mode {
  STRUB_DISABLED = 0 , STRUB_AT_CALLS = 1 , STRUB_INTERNAL = 2 , STRUB_CALLABLE = 3 ,
  STRUB_WRAPPED = -1 , STRUB_WRAPPER = -2 , STRUB_INLINABLE = -3 , STRUB_AT_CALLS_OPT = -4
}
 

Functions

static tree get_strub_attr_from_type (tree type)
 
static tree get_strub_attr_from_decl (tree decl)
 
static tree get_strub_mode_attr_parm (enum strub_mode mode)
 
static tree get_strub_mode_attr_value (enum strub_mode mode)
 
int strub_validate_fn_attr_parm (tree id)
 
static enum strub_mode get_strub_mode_from_attr (tree strub_attr, bool var_p=false)
 
static enum strub_mode get_strub_mode_from_fndecl (tree fndecl)
 
static enum strub_mode get_strub_mode (cgraph_node *node)
 
static enum strub_mode get_strub_mode_from_type (tree type)
 
static bool calls_builtin_va_start_p (cgraph_node *node)
 
static bool calls_builtin_apply_args_p (cgraph_node *node, bool report=false)
 
static bool strub_always_inline_p (cgraph_node *node)
 
static bool strub_target_support_p (tree t, bool report=false, location_t loc=UNKNOWN_LOCATION)
 
static bool can_strub_p (cgraph_node *node, bool report=false)
 
static bool can_strub_at_calls_p (cgraph_node *node, bool report=false)
 
static bool strub_call_fntype_override_p (const gcall *gs)
 
static bool called_directly_with_type_override_p (cgraph_node *node, void *)
 
static bool called_with_type_override_p (cgraph_node *node)
 
static bool can_strub_internally_p (cgraph_node *node, bool report=false)
 
static bool strub_from_body_p (cgraph_node *node)
 
static bool strub_callable_builtin_p (cgraph_node *node)
 
static enum strub_mode compute_strub_mode (cgraph_node *node, tree strub_attr)
 
static void strub_set_fndt_mode_to (tree fndt, enum strub_mode mode, bool override)
 
void strub_make_callable (tree fndt)
 
static void set_strub_mode_to (cgraph_node *node, enum strub_mode mode)
 
static void set_strub_mode (cgraph_node *node)
 
static bool strub_callable_from_p (strub_mode caller_mode, strub_mode callee_mode)
 
bool strub_inlinable_to_p (cgraph_node *callee, cgraph_node *caller)
 
int strub_comptypes (tree t1, tree t2)
 
static enum strub_mode effective_strub_mode_for_call (gcall *call, tree *typep)
 
static void distinctify_node_type (cgraph_node *node)
 
static bool same_strub_mode_in_variants_p (tree type)
 
static void verify_strub ()
 
static tree maybe_make_indirect (indirect_parms_t &indirect_parms, tree op, int *rec)
 
static tree walk_make_indirect (tree *op, int *rec, void *arg)
 
static tree walk_regimplify_addr_expr (tree *op, int *rec, void *arg)
 
static bool walk_regimplify_phi (gphi *stmt)
 
static tree build_ref_type_for (tree parm)
 
static void add_call_edges_for_seq (gimple_seq seq, profile_count count)
 
static void gsi_insert_finally_seq_after_call (gimple_stmt_iterator gsi, gimple_seq seq)
 
static void remove_named_attribute_unsharing (const char *name, tree *attrs)
 
static void ipa_strub_set_mode_for_new_functions ()
 
bool strub_splittable_p (cgraph_node *node)
 
tree strub_watermark_parm (tree fndecl)
 
simple_ipa_opt_passmake_pass_ipa_strub_mode (gcc::context *ctxt)
 
simple_ipa_opt_passmake_pass_ipa_strub (gcc::context *ctxt)
 

Variables

static tree strub_cache [STRUB_CACHE_SIZE]
 
static int last_cgraph_uid
 

Macro Definition Documentation

◆ ATTR_FNSPEC_DECONST_WATERMARK

#define ATTR_FNSPEC_DECONST_WATERMARK   0
strub (stack scrubbing) support. Copyright (C) 2021-2025 Free Software Foundation, Inc. Contributed by Alexandre Oliva <oliva@adacore.com>. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>.
This file introduces two passes that, together, implement machine-independent stack scrubbing, strub for short. It arranges for stack frames that have strub enabled to be zeroed-out after relinquishing control to a caller, whether by returning or by propagating an exception. This admittedly unusual design decision was driven by exception support (one needs a stack frame to be active to propagate exceptions out of it), and it enabled an implementation that is entirely machine-independent (no custom epilogue code is required). Strub modes can be selected for stack frames by attaching attribute strub to functions or to variables (to their types, actually). Different strub modes, with different implementation details, are available, and they can be selected by an argument to the strub attribute. When enabled by strub-enabled variables, whether by accessing (as in reading from) statically-allocated ones, or by introducing (as in declaring) automatically-allocated ones, a suitable mode is selected automatically. At-calls mode modifies the interface of a function, adding a stack watermark argument, that callers use to clean up the stack frame of the called function. Because of the interface change, it can only be used when explicitly selected, or when a function is internal to a translation unit. Strub-at-calls function types are distinct from their original types (they're not modified in-place), and they are not interchangeable with other function types. Internal mode, in turn, does not modify the type or the interface of a function. It is currently implemented by turning the function into a wrapper, moving the function body to a separate wrapped function, and scrubbing the wrapped body's stack in the wrapper. Internal-strub function types are mostly interface-compatible with other strub modes, namely callable (from strub functions, though not strub-enabled) and disabled (not callable from strub functions). Always_inline functions can be strub functions, but they can only be called from other strub functions, because strub functions must never be inlined into non-strub functions. Internal and at-calls modes are indistinguishable when it comes to always_inline functions: they will necessarily be inlined into another strub function, and will thus be integrated into the caller's stack frame, whatever the mode. (Contrast with non-always_inline strub functions: an at-calls function can be called from other strub functions, ensuring no discontinuity in stack erasing, whereas an internal-strub function can only be called from other strub functions if it happens to be inlined, or if -fstrub=relaxed mode is in effect (that's the default). In -fstrub=strict mode, internal-strub functions are not callable from strub functions, because the wrapper itself is not strubbed. The implementation involves two simple-IPA passes. The earliest one, strub-mode, assigns strub modes to functions. It needs to run before any inlining, so that we can prevent inlining of strub functions into non-strub functions. It notes explicit strub mode requests, enables strub in response to strub variables and testing options, and flags unsatisfiable requests. Three possibilities of unsatisfiable requests come to mind: (a) when a strub mode is explicitly selected, but the function uses features that make it ineligible for that mode (e.g. at-calls rules out calling __builtin_apply_args, because of the interface changes, and internal mode rules out noclone or otherwise non-versionable functions, non-default varargs, non-local or forced labels, and functions with far too many arguments); (b) when some strub mode must be enabled because of a strub variable, but the function is not eligible or not viable for any mode; and (c) when -fstrub=strict is enabled, and calls are found in strub functions to functions that are not callable from strub contexts. compute_strub_mode implements (a) and (b), and verify_strub implements (c). The second IPA pass modifies interfaces of at-calls-strub functions and types, introduces strub calls in and around them. and splits internal-strub functions. It is placed after early inlining, so that even internal-strub functions get a chance of being inlined into other strub functions, but before non-early inlining, so that internal-strub wrapper functions still get a chance of inlining after splitting. Wrappers avoid duplicating the copying of large arguments again by passing them by reference to the wrapped bodies. This involves occasional SSA rewriting of address computations, because of the additional indirection. Besides these changes, and the introduction of the stack watermark parameter, wrappers and wrapped functions cooperate to handle variable argument lists (performing va_start in the wrapper, passing the list as an argument, and replacing va_start calls in the wrapped body with va_copy), and __builtin_apply_args (also called in the wrapper and passed to the wrapped body as an argument). Strub bodies (both internal-mode wrapped bodies, and at-calls functions) always start by adjusting the watermark parameter, by calling __builtin___strub_update. The compiler inserts them in the main strub pass. Allocations of additional stack space for the frame (__builtin_alloca) are also followed by watermark updates. Stack space temporarily allocated to pass arguments to other functions, released right after the call, is not regarded as part of the frame. Around calls to them, i.e., in internal-mode wrappers and at-calls callers (even calls through pointers), calls to __builtin___strub_enter and __builtin___strub_leave are inserted, the latter as a __finally block, so that it runs at regular and exceptional exit paths. strub_enter only initializes the stack watermark, and strub_leave is where the scrubbing takes place, overwriting with zeros the stack space from the top of the stack to the watermark. These calls can be optimized in various cases. In pass_ipa_strub::adjust_at_calls_call, for example, we enable tail-calling and other optimized calls from one strub body to another by passing on the watermark parameter. The builtins themselves may undergo inline substitution during expansion, dependign on optimization levels. This involves dealing with stack red zones (when the builtins are called out-of-line, the red zone cannot be used) and other ugly details related with inlining strub bodies into other strub bodies (see expand_builtin_strub_update). expand_builtin_strub_leave may even perform partial inline substitution.
Const and pure functions that gain a watermark parameter for strub purposes are still regarded as such, which may cause the inline expansions of the __strub builtins to malfunction. Ideally, attribute "fn spec" would enable us to inform the backend about requirements and side effects of the call, but call_fusage building in calls.c:expand_call does not even look at attr_fnspec, so we resort to asm loads and updates to attain an equivalent effect. Once expand_call gains the ability to issue extra memory uses and clobbers based on pure/const function's fnspec, we can define this to 1.

◆ DEF_IDENT

#define DEF_IDENT ( IDX,
NAME )
Value:
static inline tree get_ ## NAME () { \
int idx = STRUB_IDENT_BASE + IDX; \
tree identifier = strub_cache[idx]; \
if (!identifier) \
strub_cache[idx] = identifier = get_identifier (".strub." #NAME); \
return identifier; \
}
union tree_node * tree
Definition coretypes.h:97
#define STRUB_IDENT_BASE
Definition ipa-strub.cc:301
static tree strub_cache[STRUB_CACHE_SIZE]
Definition ipa-strub.cc:306
tree get_identifier(const char *text)
Definition stringpool.cc:105
@ NAME
Definition tree-ssa-pre.cc:242

◆ DEF_NM_BUILTIN

#define DEF_NM_BUILTIN ( NAME,
CODE,
FNTYPELIST )
Value:
static tree get_ ## NAME () { \
if (!decl) \
{ \
("__builtin_" #NAME, \
NULL, NULL); \
TREE_NOTHROW (decl) = true; \
set_builtin_decl ((CODE), decl, true); \
} \
return decl; \
}
tree add_builtin_function(const char *name, tree type, int function_code, enum built_in_class cl, const char *library_name, tree attrs)
Definition langhooks.cc:752
Definition genautomata.cc:499
Definition gengtype.h:252
#define NULL
Definition system.h:50
@ BUILT_IN_NORMAL
Definition tree-core.h:169
tree build_function_type_list(tree return_type,...)
Definition tree.cc:7708
tree builtin_decl_explicit(enum built_in_function fncode)
Definition tree.h:6093

◆ DEF_SS_BUILTIN

#define DEF_SS_BUILTIN ( NAME,
FNSPEC,
CODE,
FNTYPELIST )
Value:
static tree get_ ## NAME () { \
if (!decl) \
{ \
if (FNSPEC) \
attrs = tree_cons (get_identifier ("fn spec"), \
build_string (strlen (FNSPEC), \
(FNSPEC))), \
attrs); \
("__builtin___strub_" #NAME, \
"__strub_" #NAME, attrs); \
TREE_NOTHROW (decl) = true; \
set_builtin_decl ((CODE), decl, true); \
} \
return decl; \
}
tree add_builtin_function_ext_scope(const char *name, tree type, int function_code, enum built_in_class cl, const char *library_name, tree attrs)
Definition langhooks.cc:772
Definition var-tracking.cc:242
tree tree_cons(tree purpose, tree value, tree chain MEM_STAT_DECL)
Definition tree.cc:3631
tree build_tree_list(tree parm, tree value MEM_STAT_DECL)
Definition tree.cc:3601
tree build_string(unsigned len, const char *str)
Definition tree.cc:2553
#define NULL_TREE
Definition tree.h:317

◆ DEF_STRUB_ID

#define DEF_STRUB_ID ( IDX,
NAME )
Value:
#define DEF_STRUB_IDS(IDX, NAME, ID)
Definition ipa-strub.cc:310
Same as DEF_STRUB_IDS, but use the string expansion of NAME as ID.

◆ DEF_STRUB_IDS

#define DEF_STRUB_IDS ( IDX,
NAME,
ID )
Value:
static inline tree get_strub_mode_id_ ## NAME () { \
int idx = STRUB_ID_BASE + IDX; \
tree identifier = strub_cache[idx]; \
if (!identifier) \
strub_cache[idx] = identifier = get_identifier (ID); \
return identifier; \
}
@ ID
Definition gengtype.h:483
#define STRUB_ID_BASE
Definition ipa-strub.cc:300
Define a function to cache identifier ID, to be used as a strub attribute parameter for a strub mode named after NAME.

◆ DEF_TYPE

#define DEF_TYPE ( IDX,
NAME,
INIT )
Value:
static inline tree get_ ## NAME () { \
int idx = STRUB_TYPE_BASE + IDX; \
static tree type = strub_cache[idx]; \
if (!type) \
strub_cache[idx] = type = (INIT); \
return type; \
}
#define STRUB_TYPE_BASE
Definition ipa-strub.cc:302

◆ STRUB_CACHE_SIZE

#define STRUB_CACHE_SIZE   (STRUB_TYPE_BASE + STRUB_TYPE_COUNT)

◆ STRUB_ID_BASE

#define STRUB_ID_BASE   0

◆ STRUB_ID_COUNT

#define STRUB_ID_COUNT   8

◆ STRUB_IDENT_BASE

#define STRUB_IDENT_BASE   (STRUB_ID_BASE + STRUB_ID_COUNT)

◆ STRUB_IDENT_COUNT

#define STRUB_IDENT_COUNT   3

◆ STRUB_INTERNAL_MAX_EXTRA_ARGS

#define STRUB_INTERNAL_MAX_EXTRA_ARGS   3
Symbolic macro for the max number of arguments that internal strub may add to a function.

Referenced by can_strub_internally_p().

◆ STRUB_TYPE_BASE

#define STRUB_TYPE_BASE   (STRUB_IDENT_BASE + STRUB_IDENT_COUNT)

◆ STRUB_TYPE_COUNT

#define STRUB_TYPE_COUNT   5

Typedef Documentation

◆ indirect_parms_t

Gather with this type a collection of parameters that we're turning into explicit references.

Enumeration Type Documentation

◆ strub_mode

enum strub_mode
Enumerator
STRUB_DISABLED 
STRUB_AT_CALLS 
STRUB_INTERNAL 
STRUB_CALLABLE 
STRUB_WRAPPED 
STRUB_WRAPPER 
STRUB_INLINABLE 
STRUB_AT_CALLS_OPT 

Function Documentation

◆ add_call_edges_for_seq()

static void add_call_edges_for_seq ( gimple_seq seq,
profile_count count )
static
Add cgraph edges from current_function_decl to callees in SEQ with frequency COUNT, assuming all calls in SEQ are direct.

References count, cgraph_node::create_edge(), current_function_decl, dyn_cast(), gcc_checking_assert, cgraph_node::get_create(), gimple_call_fndecl(), gsi_end_p(), gsi_next(), gsi_start(), and gsi_stmt().

Referenced by gsi_insert_finally_seq_after_call().

◆ build_ref_type_for()

static tree build_ref_type_for ( tree parm)
static
Create a reference type to use for PARM when turning it into a reference.

References build_reference_type(), gcc_checking_assert, TREE_CODE, and TREE_TYPE.

◆ called_directly_with_type_override_p()

static bool called_directly_with_type_override_p ( cgraph_node * node,
void *  )
static
Return TRUE iff NODE is called directly with a type override.

References cgraph_node::callers, cgraph_edge::next_caller, and strub_call_fntype_override_p().

Referenced by called_with_type_override_p().

◆ called_with_type_override_p()

static bool called_with_type_override_p ( cgraph_node * node)
static
Return TRUE iff NODE or any other nodes aliased to it are called with type overrides. We can't safely change the type of such functions.

References cgraph_node::call_for_symbol_thunks_and_aliases(), called_directly_with_type_override_p(), and NULL.

Referenced by compute_strub_mode().

◆ calls_builtin_apply_args_p()

static bool calls_builtin_apply_args_p ( cgraph_node * node,
bool report = false )
static
Return TRUE iff NODE calls builtin apply_args, and optionally REPORT it.

References cgraph_node::callees, symtab_node::decl, DECL_SOURCE_LOCATION, fndecl_built_in_p(), gimple_location(), cgraph_edge::next_callee, and sorry_at().

Referenced by can_strub_at_calls_p().

◆ calls_builtin_va_start_p()

static bool calls_builtin_va_start_p ( cgraph_node * node)
static
Return TRUE iff NODE calls builtin va_start.

References cgraph_node::callees, fndecl_built_in_p(), and cgraph_edge::next_callee.

◆ can_strub_at_calls_p()

static bool can_strub_at_calls_p ( cgraph_node * node,
bool report = false )
static
Return TRUE iff NODE is eligible for at-calls strub, and optionally REPORT the reasons for ineligibility. Besides general non-eligibility for strub-enabled modes, at-calls rules out calling builtin apply_args.

References calls_builtin_apply_args_p(), and can_strub_p().

Referenced by compute_strub_mode(), and set_strub_mode_to().

◆ can_strub_internally_p()

static bool can_strub_internally_p ( cgraph_node * node,
bool report = false )
static
We can't perform internal strubbing if the function body involves certain features: - a non-default __builtin_va_start (e.g. x86's __builtin_ms_va_start) is currently unsupported because we can't discover the corresponding va_copy and va_end decls in the wrapper, and we don't convey the alternate variable arguments ABI to the modified wrapped function. The default __builtin_va_start is supported by calling va_start/va_end at the wrapper, that takes variable arguments, passing a pointer to the va_list object to the wrapped function, that runs va_copy from it where the original function ran va_start. __builtin_next_arg is currently unsupported because the wrapped function won't be a variable argument function. We could process it in the wrapper, that remains a variable argument function, and replace calls in the wrapped body, but we currently don't. __builtin_return_address is rejected because it's generally used when the actual caller matters, and introducing a wrapper breaks such uses as those in the unwinder.

References builtin_decl_explicit(), cgraph_node::callees, can_strub_p(), symtab_node::decl, DECL_ATTRIBUTES, DECL_SOURCE_LOCATION, DECL_STRUCT_FUNCTION, dyn_cast(), fndecl_built_in_p(), FOR_EACH_BB_FN, FORCED_LABEL, gcc_checking_assert, gimple_label_label(), gimple_location(), gsi_end_p(), gsi_next(), gsi_start_bb(), gsi_stmt(), function::has_forced_label_in_static, cgraph_node::has_gimple_body_p(), function::has_nonlocal_label, HOST_WIDE_INT_1, IPA_PARAM_MAX_INDEX_BITS, list_length(), lookup_attribute(), cgraph_edge::next_callee, sorry_at(), strub_always_inline_p(), STRUB_INTERNAL_MAX_EXTRA_ARGS, TREE_TYPE, tree_versionable_function_p(), and TYPE_ARG_TYPES.

Referenced by compute_strub_mode(), and set_strub_mode_to().

◆ can_strub_p()

static bool can_strub_p ( cgraph_node * node,
bool report = false )
inlinestatic
Return TRUE iff NODE is potentially eligible for any strub-enabled mode, and optionally REPORT the reasons for ineligibility.

References symtab_node::decl, DECL_ATTRIBUTES, DECL_SOURCE_LOCATION, lookup_attribute(), sorry_at(), strub_always_inline_p(), and strub_target_support_p().

Referenced by can_strub_at_calls_p(), can_strub_internally_p(), and compute_strub_mode().

◆ compute_strub_mode()

◆ distinctify_node_type()

static void distinctify_node_type ( cgraph_node * node)
static
Create a distinct copy of the type of NODE's function, and change the fntype of all calls to it with the same main type to the new type.

References build_distinct_type_copy(), build_pointer_type(), cgraph_node::callers, symtab_node::decl, gcc_checking_assert, gimple_call_fn(), gimple_call_set_fntype(), cgraph_edge::next_caller, NULL_TREE, strub_call_fntype_override_p(), TREE_CODE, TREE_OPERAND, and TREE_TYPE.

◆ effective_strub_mode_for_call()

static enum strub_mode effective_strub_mode_for_call ( gcall * call,
tree * typep )
static
Return the effective strub mode used for CALL, and set *TYPEP to the effective type used for the call. The effective type and mode are those of the callee, unless the call involves a typecast.

References get_strub_mode_from_fndecl(), get_strub_mode_from_type(), gimple_call_fn(), gimple_call_fndecl(), gimple_call_fntype(), strub_call_fntype_override_p(), and TREE_TYPE.

Referenced by verify_strub().

◆ get_strub_attr_from_decl()

static tree get_strub_attr_from_decl ( tree decl)
static
Look up a strub attribute in DECL or in its type, and return it.

References DECL_ATTRIBUTES, get_strub_attr_from_type(), lookup_attribute(), and TREE_TYPE.

Referenced by get_strub_mode_from_fndecl(), set_strub_mode(), set_strub_mode_to(), and strub_set_fndt_mode_to().

◆ get_strub_attr_from_type()

static tree get_strub_attr_from_type ( tree type)
static
Look up a strub attribute in TYPE, and return it.

References lookup_attribute(), and TYPE_ATTRIBUTES.

Referenced by get_strub_attr_from_decl(), get_strub_mode_from_type(), and strub_set_fndt_mode_to().

◆ get_strub_mode()

static enum strub_mode get_strub_mode ( cgraph_node * node)
static
Look up, decode and return the strub mode associated with NODE.

References symtab_node::decl, and get_strub_mode_from_fndecl().

Referenced by set_strub_mode(), strub_inlinable_to_p(), strub_splittable_p(), and verify_strub().

◆ get_strub_mode_attr_parm()

static tree get_strub_mode_attr_parm ( enum strub_mode mode)
static
Define functions for each of the strub mode identifiers. Expose dashes rather than underscores.
Release the temporary macro names.
Return the identifier corresponding to strub MODE.

References gcc_unreachable, STRUB_AT_CALLS, STRUB_AT_CALLS_OPT, STRUB_CALLABLE, STRUB_DISABLED, STRUB_INLINABLE, STRUB_INTERNAL, STRUB_WRAPPED, and STRUB_WRAPPER.

Referenced by get_strub_mode_attr_value(), get_strub_mode_from_attr(), set_strub_mode_to(), and strub_validate_fn_attr_parm().

◆ get_strub_mode_attr_value()

static tree get_strub_mode_attr_value ( enum strub_mode mode)
static
Return the parmeters (TREE_VALUE) for a strub attribute of MODE. We know we use a single parameter, so we bypass the creation of a tree list.

References get_strub_mode_attr_parm().

Referenced by strub_set_fndt_mode_to().

◆ get_strub_mode_from_attr()

static enum strub_mode get_strub_mode_from_attr ( tree strub_attr,
bool var_p = false )
static

◆ get_strub_mode_from_fndecl()

static enum strub_mode get_strub_mode_from_fndecl ( tree fndecl)
static
Look up, decode and return the strub mode associated with FNDECL.

References get_strub_attr_from_decl(), and get_strub_mode_from_attr().

Referenced by effective_strub_mode_for_call(), get_strub_mode(), and strub_watermark_parm().

◆ get_strub_mode_from_type()

static enum strub_mode get_strub_mode_from_type ( tree type)
static

◆ gsi_insert_finally_seq_after_call()

◆ ipa_strub_set_mode_for_new_functions()

static void ipa_strub_set_mode_for_new_functions ( )
static
Set strub modes for functions introduced since the last call.

References symtab_node::alias, FOR_EACH_FUNCTION, symtab_node::get_uid(), last_cgraph_uid, set_strub_mode(), and symtab.

◆ make_pass_ipa_strub()

simple_ipa_opt_pass * make_pass_ipa_strub ( gcc::context * ctxt)

◆ make_pass_ipa_strub_mode()

simple_ipa_opt_pass * make_pass_ipa_strub_mode ( gcc::context * ctxt)
Create a strub mode pass.

◆ maybe_make_indirect()

static tree maybe_make_indirect ( indirect_parms_t & indirect_parms,
tree op,
int * rec )
static
Dereference OP's incoming turned-into-reference parm if it's an INDIRECT_PARMS or an ADDR_EXPR thereof. Set *REC and return according to gimple-walking expectations.

References build2(), build_int_cst(), hash_set< KeyId, Lazy, Traits >::contains(), DECL_P, gimple_fold_indirect_ref(), NULL_TREE, TREE_CODE, TREE_OPERAND, TREE_SIDE_EFFECTS, TREE_THIS_VOLATILE, TREE_TYPE, and TYPE_VOLATILE.

Referenced by walk_make_indirect().

◆ remove_named_attribute_unsharing()

static void remove_named_attribute_unsharing ( const char * name,
tree * attrs )
inlinestatic
Copy the attribute list at *ATTRS, minus any NAME attributes, leaving shareable trailing nodes alone.

References gcc_checking_assert, lookup_attribute(), TREE_CHAIN, tree_cons(), TREE_PURPOSE, and TREE_VALUE.

◆ same_strub_mode_in_variants_p()

static bool same_strub_mode_in_variants_p ( tree type)
static
Return TRUE iff TYPE and any variants have the same strub mode.

References get_strub_mode_from_type(), NULL_TREE, same_strub_mode_in_variants_p(), TYPE_CANONICAL, TYPE_MAIN_VARIANT, and TYPE_NEXT_VARIANT.

Referenced by same_strub_mode_in_variants_p().

◆ set_strub_mode()

◆ set_strub_mode_to()

static void set_strub_mode_to ( cgraph_node * node,
enum strub_mode mode )
static

◆ strub_always_inline_p()

static bool strub_always_inline_p ( cgraph_node * node)
inlinestatic
Return TRUE iff NODE carries the always_inline attribute.

References symtab_node::decl, DECL_ATTRIBUTES, and lookup_attribute().

Referenced by can_strub_internally_p(), can_strub_p(), and compute_strub_mode().

◆ strub_call_fntype_override_p()

static bool strub_call_fntype_override_p ( const gcall * gs)
inlinestatic
Return TRUE iff the called function (pointer or, if available, decl) undergoes a significant type conversion for the call. Strub mode changes between function types, and other non-useless type conversions, are regarded as significant. When the function type is overridden, the effective strub mode for the call is that of the call fntype, rather than that of the pointer or of the decl. Functions called with type overrides cannot undergo type changes; it's as if their address was taken, so they're considered non-viable for implicit at-calls strub mode.

References gcall::fntype, get_strub_mode_from_type(), gimple_call_fn(), gimple_call_fndecl(), gimple_call_internal_p(), TREE_TYPE, gcall::u, and useless_type_conversion_p().

Referenced by called_directly_with_type_override_p(), distinctify_node_type(), effective_strub_mode_for_call(), and verify_strub().

◆ strub_callable_builtin_p()

static bool strub_callable_builtin_p ( cgraph_node * node)
inlinestatic
Return TRUE iff node is associated with a builtin that should be callable from strub contexts.

References BUILT_IN_NORMAL, symtab_node::decl, DECL_BUILT_IN_CLASS, DECL_FUNCTION_CODE(), and gcc_unreachable.

Referenced by compute_strub_mode().

◆ strub_callable_from_p()

static bool strub_callable_from_p ( strub_mode caller_mode,
strub_mode callee_mode )
static
Non-strub functions shouldn't be called from within strub contexts, except through callable ones. Always inline strub functions can only be called from strub functions.

References gcc_unreachable, STRUB_AT_CALLS, STRUB_AT_CALLS_OPT, STRUB_CALLABLE, STRUB_DISABLED, STRUB_INLINABLE, STRUB_INTERNAL, STRUB_WRAPPED, and STRUB_WRAPPER.

Referenced by verify_strub().

◆ strub_comptypes()

int strub_comptypes ( tree t1,
tree t2 )
Check that types T1 and T2 are strub-compatible. Return 1 if the strub modes are the same, 2 if they are interchangeable, and 0 otherwise.

References FUNC_OR_METHOD_TYPE_P, get_strub_mode_from_type(), STRUB_AT_CALLS, STRUB_INTERNAL, and TREE_CODE.

Referenced by comp_type_attributes().

◆ strub_from_body_p()

static bool strub_from_body_p ( cgraph_node * node)
static
Return TRUE iff NODE has any strub-requiring local variable, or accesses (as in reading) any variable through a strub-requiring type.

References symtab_node::decl, DECL_STRUCT_FUNCTION, FOR_EACH_BB_FN, FOR_EACH_LOCAL_DECL, get_strub_mode_from_type(), gimple_assign_load_p(), gimple_assign_rhs1(), gsi_end_p(), gsi_next(), gsi_start_bb(), gsi_stmt(), cgraph_node::has_gimple_body_p(), i, STRUB_DISABLED, and TREE_TYPE.

Referenced by compute_strub_mode().

◆ strub_inlinable_to_p()

bool strub_inlinable_to_p ( cgraph_node * callee,
cgraph_node * caller )
Return TRUE iff CALLEE can be inlined into CALLER. We wish to avoid inlining WRAPPED functions back into their WRAPPERs. More generally, we wish to avoid inlining strubbed functions into non-strubbed ones. CALLER doesn't have to be an immediate caller of CALLEE: the immediate caller may have already been cloned for inlining, and then CALLER may be further up the original call chain. ??? It would be nice if our own caller would retry inlining callee if caller gets inlined.

References gcc_unreachable, get_strub_mode(), STRUB_AT_CALLS, STRUB_AT_CALLS_OPT, STRUB_CALLABLE, STRUB_DISABLED, STRUB_INLINABLE, STRUB_INTERNAL, STRUB_WRAPPED, and STRUB_WRAPPER.

Referenced by can_inline_edge_p().

◆ strub_make_callable()

void strub_make_callable ( tree fndt)
Set FNDT's strub mode to callable. FNDT may be a function decl or a function type.

References STRUB_CALLABLE, and strub_set_fndt_mode_to().

◆ strub_set_fndt_mode_to()

static void strub_set_fndt_mode_to ( tree fndt,
enum strub_mode mode,
bool override )
static
Set FNDT's strub mode to MODE; FNDT may be a function decl or function type. If OVERRIDE, do not check whether a mode is already set.

References DECL_ATTRIBUTES, DECL_P, FUNC_OR_METHOD_TYPE_P, gcc_checking_assert, gcc_unreachable, get_identifier(), get_strub_attr_from_decl(), get_strub_attr_from_type(), get_strub_mode_attr_value(), NULL, NULL_TREE, TREE_CHAIN, tree_cons(), TREE_TYPE, and TYPE_ATTRIBUTES.

Referenced by set_strub_mode_to(), and strub_make_callable().

◆ strub_splittable_p()

bool strub_splittable_p ( cgraph_node * node)

◆ strub_target_support_p()

static bool strub_target_support_p ( tree t,
bool report = false,
location_t loc = UNKNOWN_LOCATION )
inlinestatic
Return TRUE iff the target has strub support for T, a function decl, or a type used in an indirect call, and optionally REPORT the reasons for ineligibility. If T is a type and error REPORTing is enabled, the LOCation (of the indirect call) should be provided.

References DECL_P, DECL_SOURCE_LOCATION, sorry_at(), targetm, and UNKNOWN_LOCATION.

Referenced by can_strub_p().

◆ strub_validate_fn_attr_parm()

int strub_validate_fn_attr_parm ( tree id)
Determine whether ID is a well-formed strub mode-specifying attribute parameter for a function (type). Only user-visible modes are accepted, and ID must be non-NULL. For unacceptable parms, return 0, otherwise a nonzero value as below. If the parm enables strub, return positive, otherwise negative. If the affected type must be a distinct, incompatible type,return an integer of absolute value 2, otherwise 1.

References get_strub_mode_attr_parm(), IDENTIFIER_LENGTH, IDENTIFIER_POINTER, NULL, STRUB_AT_CALLS, STRUB_CALLABLE, STRUB_DISABLED, STRUB_INTERNAL, TREE_CODE, TREE_STRING_LENGTH, and TREE_STRING_POINTER.

◆ strub_watermark_parm()

◆ verify_strub()

static void verify_strub ( )
static

◆ walk_make_indirect()

static tree walk_make_indirect ( tree * op,
int * rec,
void * arg )
static
A gimple-walking function that adds dereferencing to indirect parms.

References maybe_make_indirect(), NULL_TREE, and TYPE_P.

◆ walk_regimplify_addr_expr()

static tree walk_regimplify_addr_expr ( tree * op,
int * rec,
void * arg )
static
A gimple-walking function that turns any non-gimple-val ADDR_EXPRs into a separate SSA. Though addresses of e.g. parameters, and of members thereof, are gimple vals, turning parameters into references, with an extra layer of indirection and thus explicit dereferencing, need to be regimplified.

References force_gimple_operand_gsi(), gcc_assert, GSI_SAME_STMT, is_gimple_val(), NULL_TREE, and TREE_CODE.

◆ walk_regimplify_phi()

static bool walk_regimplify_phi ( gphi * stmt)
static

Variable Documentation

◆ last_cgraph_uid

int last_cgraph_uid
static
Record the uid of the last cgraph entry whose mode we've already set, so that we can perform mode setting incrementally without duplication.

Referenced by ipa_strub_set_mode_for_new_functions().

◆ strub_cache

tree strub_cache[STRUB_CACHE_SIZE]
static
Keep the strub mode and temp identifiers and types from being GC'd.