GCC Middle and Back End API 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"
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< tree > | indirect_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 } |
Variables | |
static tree | strub_cache [STRUB_CACHE_SIZE] |
static int | last_cgraph_order |
#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.
#define DEF_IDENT | ( | IDX, | |
NAME ) |
#define DEF_NM_BUILTIN | ( | NAME, | |
CODE, | |||
FNTYPELIST ) |
#define DEF_SS_BUILTIN | ( | NAME, | |
FNSPEC, | |||
CODE, | |||
FNTYPELIST ) |
#define DEF_STRUB_ID | ( | IDX, | |
NAME ) |
Same as DEF_STRUB_IDS, but use the string expansion of NAME as ID.
Define a function to cache identifier ID, to be used as a strub attribute parameter for a strub mode named after NAME.
#define DEF_TYPE | ( | IDX, | |
NAME, | |||
INIT ) |
#define STRUB_CACHE_SIZE (STRUB_TYPE_BASE + STRUB_TYPE_COUNT) |
#define STRUB_ID_BASE 0 |
#define STRUB_ID_COUNT 8 |
#define STRUB_IDENT_BASE (STRUB_ID_BASE + STRUB_ID_COUNT) |
#define STRUB_IDENT_COUNT 3 |
#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().
#define STRUB_TYPE_BASE (STRUB_IDENT_BASE + STRUB_IDENT_COUNT) |
#define STRUB_TYPE_COUNT 5 |
typedef hash_set<tree> indirect_parms_t |
Gather with this type a collection of parameters that we're turning into explicit references.
enum strub_mode |
|
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().
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.
|
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().
|
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().
|
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().
|
static |
Return TRUE iff NODE calls builtin va_start.
References cgraph_node::callees, fndecl_built_in_p(), and cgraph_edge::next_callee.
|
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().
|
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().
|
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().
|
static |
Compute the strub mode to be used for NODE. STRUB_ATTR should be the strub attribute,found for NODE, if any.
References symtab_node::binds_to_current_def_p(), called_with_type_override_p(), cgraph_node::can_be_local_p(), can_strub_at_calls_p(), can_strub_internally_p(), can_strub_p(), symtab_node::decl, DECL_SOURCE_LOCATION, error_at(), symtab_node::externally_visible, gcc_checking_assert, gcc_unreachable, get_strub_mode_from_attr(), cgraph_node::has_gimple_body_p(), cgraph_node::only_called_directly_p(), strub_always_inline_p(), STRUB_AT_CALLS, STRUB_AT_CALLS_OPT, STRUB_CALLABLE, strub_callable_builtin_p(), STRUB_DISABLED, strub_from_body_p(), STRUB_INLINABLE, STRUB_INTERNAL, STRUB_WRAPPED, and STRUB_WRAPPER.
Referenced by set_strub_mode().
|
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.
|
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(), TREE_TYPE, and type().
Referenced by verify_strub().
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().
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().
|
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().
|
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().
|
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().
|
static |
Return the strub mode from STRUB_ATTR. VAR_P should be TRUE if the attribute is taken from a variable, rather than from a function, or a type thereof.
References gcc_checking_assert, gcc_unreachable, get_strub_mode_attr_parm(), IDENTIFIER_LENGTH, IDENTIFIER_POINTER, STRUB_AT_CALLS, STRUB_AT_CALLS_OPT, STRUB_CALLABLE, STRUB_DISABLED, STRUB_INLINABLE, STRUB_INTERNAL, STRUB_WRAPPED, STRUB_WRAPPER, TREE_CODE, TREE_STRING_LENGTH, TREE_STRING_POINTER, and TREE_VALUE.
Referenced by compute_strub_mode(), get_strub_mode_from_fndecl(), get_strub_mode_from_type(), set_strub_mode(), and set_strub_mode_to().
|
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().
|
static |
Look up, decode and return the strub mode associated with TYPE.
References FUNC_OR_METHOD_TYPE_P, get_strub_attr_from_type(), get_strub_mode_from_attr(), STRUB_CALLABLE, and STRUB_DISABLED.
Referenced by effective_strub_mode_for_call(), same_strub_mode_in_variants_p(), strub_call_fntype_override_p(), strub_comptypes(), and strub_from_body_p().
|
static |
Insert SEQ after the call at GSI, as if the call was in a try block with SEQ as finally, i.e., SEQ will run after the call whether it returns or propagates an exception. This handles block splitting, EH edge and block creation, noreturn and nothrow optimizations, and even throwing calls without preexisting local handlers.
References add_bb_to_loop(), add_call_edges_for_seq(), add_stmt_to_eh_lp(), annotate_all_with_location(), CDI_DOMINATORS, cfun, count, create_empty_bb(), current_loops, dom_info_available_p(), dyn_cast(), EH_LANDING_PAD_NR, FOR_EACH_EDGE, gcc_checking_assert, gen_eh_landing_pad(), gen_eh_region_cleanup(), gimple_block_label(), gimple_build_resx(), gimple_call_noreturn_p(), gimple_call_nothrow_p(), gimple_has_location(), gimple_location(), gimple_seq_copy(), gimple_set_location(), gsi_after_labels(), gsi_bb(), gsi_insert_before(), gsi_insert_seq_after(), gsi_insert_seq_before(), gsi_insert_seq_on_edge_immediate(), gsi_one_before_end_p(), GSI_SAME_STMT, gsi_stmt(), eh_landing_pad_d::index, eh_region_d::index, lookup_stmt_eh_lp(), make_eh_edge(), profile_probability::never(), NULL, opt_for_fn, eh_landing_pad_d::post_landing_pad, set_immediate_dominator(), split_block(), stmt_ends_bb_p(), and TREE_NOTHROW.
|
static |
Set strub modes for functions introduced since the last call.
References symtab_node::alias, FOR_EACH_FUNCTION, last_cgraph_order, symbol_table::order, symtab_node::order, set_strub_mode(), and symtab.
simple_ipa_opt_pass * make_pass_ipa_strub | ( | gcc::context * | ctxt | ) |
simple_ipa_opt_pass * make_pass_ipa_strub_mode | ( | gcc::context * | ctxt | ) |
Create a strub mode pass.
|
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().
|
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.
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().
|
static |
Compute and set NODE's strub mode.
References symtab_node::alias, compute_strub_mode(), symtab_node::decl, gcc_unreachable, get_strub_attr_from_decl(), get_strub_mode(), get_strub_mode_from_attr(), set_strub_mode_to(), STRUB_AT_CALLS, STRUB_AT_CALLS_OPT, STRUB_CALLABLE, STRUB_DISABLED, STRUB_INLINABLE, STRUB_INTERNAL, STRUB_WRAPPED, STRUB_WRAPPER, and cgraph_node::ultimate_alias_target().
Referenced by ipa_strub_set_mode_for_new_functions().
|
static |
Set NODE to strub MODE. Report incompatibilities between MODE and the mode requested through explicit attributes, and cases of non-eligibility.
References symtab_node::alias, can_strub_at_calls_p(), can_strub_internally_p(), symtab_node::decl, DECL_ATTRIBUTES, DECL_SOURCE_LOCATION, error_at(), get_strub_attr_from_decl(), get_strub_mode_attr_parm(), get_strub_mode_from_attr(), STRUB_AT_CALLS, STRUB_CALLABLE, STRUB_INLINABLE, STRUB_INTERNAL, strub_set_fndt_mode_to(), STRUB_WRAPPED, STRUB_WRAPPER, TREE_CHAIN, and cgraph_node::ultimate_alias_target().
Referenced by set_strub_mode().
|
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().
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().
|
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().
|
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().
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().
|
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().
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().
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().
|
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().
bool strub_splittable_p | ( | cgraph_node * | node | ) |
Return FALSE if NODE is a strub context, and TRUE otherwise.
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 execute_split_functions().
|
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(), and targetm.
Referenced by can_strub_p().
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.
Return the PARM_DECL of the incoming watermark pointer, if there is one.
References DECL_ARGUMENTS, DECL_CHAIN, DECL_NAME, gcc_unreachable, get_strub_mode_from_fndecl(), NULL_TREE, STRUB_AT_CALLS, STRUB_AT_CALLS_OPT, STRUB_CALLABLE, STRUB_DISABLED, STRUB_INLINABLE, STRUB_INTERNAL, STRUB_WRAPPED, STRUB_WRAPPER, and TREE_TYPE.
Referenced by expand_builtin_strub_leave(), and expand_builtin_strub_update().
|
static |
Check that strub functions don't call non-strub functions, and that always_inline strub functions are only called by strub functions.
References cgraph_node::callees, symtab_node::decl, effective_strub_mode_for_call(), error_at(), fndecl_built_in_p(), FOR_EACH_FUNCTION_WITH_GIMPLE_BODY, gcc_checking_assert, get_strub_mode(), gimple_location(), cgraph_node::indirect_calls, cgraph_edge::next_callee, NULL, strub_call_fntype_override_p(), strub_callable_from_p(), STRUB_INLINABLE, and STRUB_INTERNAL.
A gimple-walking function that adds dereferencing to indirect parms.
References maybe_make_indirect(), NULL_TREE, and TYPE_P.
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.
Turn STMT's PHI arg defs into separate SSA defs if they've become non-gimple_val. Return TRUE if any edge insertions need to be committed.
References DECL_NAME, gimple_build_assign(), gimple_phi_arg_def(), gimple_phi_arg_edge(), gimple_phi_arg_has_location(), gimple_phi_arg_location(), gimple_phi_num_args(), gimple_set_location(), gsi_insert_on_edge(), i, is_gimple_val(), make_ssa_name(), SET_PHI_ARG_DEF, SET_SSA_NAME_VAR_OR_IDENTIFIER, TREE_ADDRESSABLE, TREE_CODE, and TREE_TYPE.
|
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().
|
static |
Keep the strub mode and temp identifiers and types from being GC'd.