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 "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)    DEF_STRUB_IDS (IDX, NAME, #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_order
 

Macro Definition Documentation

◆ ATTR_FNSPEC_DECONST_WATERMARK

#define ATTR_FNSPEC_DECONST_WATERMARK   0
strub (stack scrubbing) support.
   Copyright (C) 2021-2024 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; \
strub_cache[idx] = identifier = get_identifier (".strub." #NAME); \
return identifier; \
}
union tree_node * tree
Definition coretypes.h:97
T * ggc_alloc(ALONE_CXX_MEM_STAT_INFO)
Definition ggc.h:184
#define STRUB_IDENT_BASE
Definition ipa-strub.cc:300
static tree strub_cache[STRUB_CACHE_SIZE]
Definition ipa-strub.cc:305
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; \
}
static type_p type(options_p *optsp, bool nested)
Definition gengtype-parse.cc:883
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:725
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:7591
tree builtin_decl_explicit(enum built_in_function fncode)
Definition tree.h:5992

◆ DEF_SS_BUILTIN

#define DEF_SS_BUILTIN ( NAME,
FNSPEC,
CODE,
FNTYPELIST )
Value:
static tree get_ ## NAME () { \
if (!decl) \
{ \
attrs = tree_cons (get_identifier ("fn spec"), \
(FNSPEC))), \
attrs); \
("__builtin___strub_" #NAME, \
"__strub_" #NAME, attrs); \
TREE_NOTHROW (decl) = true; \
set_builtin_decl ((CODE), decl, true); \
} \
return decl; \
}
static class attr_desc * attrs[MAX_ATTRS_INDEX]
Definition genattrtab.cc:210
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:745
Definition var-tracking.cc:242
tree tree_cons(tree purpose, tree value, tree chain MEM_STAT_DECL)
Definition tree.cc:3546
tree build_tree_list(tree parm, tree value MEM_STAT_DECL)
Definition tree.cc:3516
tree build_string(unsigned len, const char *str)
Definition tree.cc:2468
#define NULL_TREE
Definition tree.h:317

◆ DEF_STRUB_ID

#define DEF_STRUB_ID ( IDX,
NAME )    DEF_STRUB_IDS (IDX, NAME, #NAME)
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; \
return identifier; \
}
@ ID
Definition gengtype.h:483
#define STRUB_ID_BASE
Definition ipa-strub.cc:299
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:301

◆ 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

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, gcc_checking_assert, cgraph_node::get_create(), ggc_alloc(), 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, ggc_alloc(), 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, 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(), ggc_alloc(), gimple_location(), 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 ggc_alloc().

◆ 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(), can_strub_p(), and ggc_alloc().

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, fndecl_built_in_p(), FOR_EACH_BB_FN, FORCED_LABEL, gcc_checking_assert, ggc_alloc(), 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(), 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, ggc_alloc(), 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, ggc_alloc(), gimple_call_fn(), gimple_call_set_fntype(), 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(), ggc_alloc(), gimple_call_fn(), gimple_call_fndecl(), gimple_call_fntype(), strub_call_fntype_override_p(), TREE_TYPE, and 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(), ggc_alloc(), 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, ggc_alloc(), 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()

◆ 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, last_cgraph_order, symtab_node::order, symbol_table::order, set_strub_mode(), and symtab.

◆ make_pass_ipa_strub()

simple_ipa_opt_pass * make_pass_ipa_strub ( gcc::context * ctxt)

References ggc_alloc().

◆ make_pass_ipa_strub_mode()

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

References ggc_alloc().

◆ 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(), DECL_P, ggc_alloc(), 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()

◆ 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 get_strub_mode_from_type(), ggc_alloc(), gimple_call_fn(), gimple_call_fndecl(), gimple_call_internal_p(), TREE_TYPE, 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(), gcc_unreachable, and ggc_alloc().

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, ggc_alloc(), 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(), ggc_alloc(), 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(), ggc_alloc(), 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 ggc_alloc(), 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(), ggc_alloc(), 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, ggc_alloc(), sorry_at(), and targetm.

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(), ggc_alloc(), 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()

◆ 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 ggc_alloc(), 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, ggc_alloc(), 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_order

int last_cgraph_order
static
Record the order 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.