GCC Middle and Back End API Reference
tree-object-size.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "tree.h"
#include "gimple.h"
#include "tree-pass.h"
#include "ssa.h"
#include "gimple-pretty-print.h"
#include "fold-const.h"
#include "tree-object-size.h"
#include "gimple-iterator.h"
#include "gimple-fold.h"
#include "tree-cfg.h"
#include "tree-dfa.h"
#include "stringpool.h"
#include "attribs.h"
#include "builtins.h"
#include "gimplify-me.h"
Include dependency graph for tree-object-size.cc:

Data Structures

struct  object_size_info
 
struct  object_size
 

Functions

static tree compute_object_offset (tree, const_tree)
 
static bool addr_object_size (struct object_size_info *, const_tree, int, tree *, tree *t=NULL)
 
static tree alloc_object_size (const gcall *, int)
 
static tree pass_through_call (const gcall *)
 
static void collect_object_sizes_for (struct object_size_info *, tree)
 
static void expr_object_size (struct object_size_info *, tree, tree)
 
static bool merge_object_sizes (struct object_size_info *, tree, tree)
 
static bool plus_stmt_object_size (struct object_size_info *, tree, gimple *)
 
static bool cond_expr_object_size (struct object_size_info *, tree, gimple *)
 
static void init_offset_limit (void)
 
static void check_for_plus_in_loops (struct object_size_info *, tree)
 
static void check_for_plus_in_loops_1 (struct object_size_info *, tree, unsigned int)
 
static bool size_initval_p (tree val, int object_size_type)
 
static bool size_unknown_p (tree val, int object_size_type)
 
static bool size_valid_p (tree val, int object_size_type)
 
static bool size_usable_p (tree val)
 
static tree size_initval (int object_size_type)
 
static tree size_unknown (int object_size_type)
 
static void object_sizes_grow (int object_size_type)
 
static void object_sizes_release (int object_size_type)
 
static bool object_sizes_unknown_p (int object_size_type, unsigned varno)
 
static object_size object_sizes_get_raw (struct object_size_info *osi, unsigned varno)
 
static tree object_sizes_get (struct object_size_info *osi, unsigned varno, bool whole=false)
 
static void object_sizes_initialize (struct object_size_info *osi, unsigned varno, tree val, tree wholeval)
 
static tree bundle_sizes (tree name, tree expr)
 
static bool object_sizes_set (struct object_size_info *osi, unsigned varno, tree val, tree wholeval)
 
static void object_sizes_set_temp (struct object_size_info *osi, unsigned varno)
 
static tree size_for_offset (tree sz, tree offset, tree wholesize=NULL_TREE)
 
tree decl_init_size (tree decl, bool min)
 
static tree strdup_object_size (const gcall *call, int object_size_type, bool is_strndup)
 
static void emit_phi_nodes (gimple *stmt, tree size, tree wholesize)
 
static tree propagate_unknowns (object_size_info *osi, tree expr, bitmap unknowns)
 
static void gimplify_size_expressions (object_size_info *osi)
 
bool compute_builtin_object_size (tree ptr, int object_size_type, tree *psize)
 
static void call_object_size (struct object_size_info *osi, tree ptr, gcall *call)
 
static void unknown_object_size (struct object_size_info *osi, tree ptr)
 
static void dynamic_object_size (struct object_size_info *osi, tree var, tree *size, tree *wholesize)
 
static void parm_object_size (struct object_size_info *osi, tree var)
 
static void phi_dynamic_object_size (struct object_size_info *osi, tree var)
 
void init_object_sizes (void)
 
void fini_object_sizes (void)
 
static tree do_valueize (tree t)
 
static void early_object_sizes_execute_one (gimple_stmt_iterator *i, gimple *call)
 
static bool dynamic_object_sizes_execute_one (gimple_stmt_iterator *i, gimple *call)
 
static unsigned int object_sizes_execute (function *fun, bool early)
 
gimple_opt_passmake_pass_object_sizes (gcc::context *ctxt)
 
gimple_opt_passmake_pass_early_object_sizes (gcc::context *ctxt)
 

Variables

static vec< object_sizeobject_sizes [OST_END]
 
static bitmap computed [OST_END]
 
static unsigned HOST_WIDE_INT offset_limit
 
static unsigned todo
 

Function Documentation

◆ addr_object_size()

◆ alloc_object_size()

static tree alloc_object_size ( const gcall * call,
int object_size_type )
static
Compute __builtin_object_size for CALL, which is a GIMPLE_CALL.
Handles calls to functions declared with attribute alloc_size.
OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
If unknown, return size_unknown (object_size_type).   

References ALLOCA_FUNCTION_CODE_P, BUILT_IN_NORMAL, DECL_FUNCTION_CODE(), fold_convert, gcc_assert, ggc_alloc(), gimple_call_arg(), gimple_call_builtin_p(), gimple_call_fndecl(), gimple_call_fntype(), gimple_call_num_args(), INTEGRAL_TYPE_P, is_gimple_call(), lookup_attribute(), NULL_TREE, size_binop, size_unknown(), sizetype, TREE_CHAIN, TREE_INT_CST_LOW, TREE_TYPE, TREE_VALUE, TYPE_ATTRIBUTES, and TYPE_PRECISION.

Referenced by call_object_size().

◆ bundle_sizes()

static tree bundle_sizes ( tree name,
tree expr )
static
Return a MODIFY_EXPR for cases where SSA and EXPR have the same type.  The
TREE_VEC is returned only in case of PHI nodes.   

References build2(), expr, gcc_checking_assert, ggc_alloc(), sizetype, TREE_CODE, TREE_TYPE, TREE_VEC_ELT, TREE_VEC_LENGTH, and types_compatible_p().

Referenced by object_sizes_set().

◆ call_object_size()

◆ check_for_plus_in_loops()

static void check_for_plus_in_loops ( struct object_size_info * osi,
tree var )
static
Check if some pointer we are computing object size of is being increased
within a loop.  If yes, assume all the SSA variables participating in
that loop have minimum object sizes 0.   

References check_for_plus_in_loops_1(), compare_tree_int(), gcc_assert, ggc_alloc(), gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), integer_zerop(), is_gimple_assign(), offset_limit, SSA_NAME_DEF_STMT, SSA_NAME_VERSION, and TREE_CODE.

Referenced by compute_builtin_object_size().

◆ check_for_plus_in_loops_1()

◆ collect_object_sizes_for()

static void collect_object_sizes_for ( struct object_size_info * osi,
tree var )
static
Compute object sizes for VAR.
For ADDR_EXPR an object size is the number of remaining bytes
to the end of the object (where what is considered an object depends on
OSI->object_size_type).
For allocation GIMPLE_CALL like malloc or calloc object size is the size
of the allocation.
For POINTER_PLUS_EXPR where second operand is a constant integer,
object size is object size of the first operand minus the constant.
If the constant is bigger than the number of remaining bytes until the
end of the object, object size is 0, but if it is instead a pointer
subtraction, object size is size_unknown (object_size_type).
To differentiate addition from subtraction, ADDR_EXPR returns
size_unknown (object_size_type) for all objects bigger than half of the
address space, and constants less than half of the address space are
considered addition, while bigger constants subtraction.
For a memcpy like GIMPLE_CALL that always returns one of its arguments, the
object size is object size of that argument.
Otherwise, object size is the maximum of object sizes of variables
that it might be set to.   

References bitmap_bit_p, bitmap_clear_bit(), bitmap_set_bit, call_object_size(), computed, cond_expr_object_size(), dump_file, dump_flags, expr_object_size(), gcc_unreachable, ggc_alloc(), gimple_assign_rhs1(), gimple_assign_rhs_code(), gimple_assign_single_p(), gimple_assign_unary_nop_p(), gimple_phi_arg(), gimple_phi_num_args(), i, merge_object_sizes(), object_size_info::object_size_type, object_sizes_initialize(), object_sizes_set_temp(), object_sizes_unknown_p(), OST_DYNAMIC, parm_object_size(), pass_through_call(), phi_dynamic_object_size(), plus_stmt_object_size(), POINTER_TYPE_P, print_generic_expr(), object_size_info::reexamine, size_initval(), SSA_NAME_DEF_STMT, SSA_NAME_VAR, SSA_NAME_VERSION, TDF_DETAILS, TREE_CODE, TREE_OPERAND, TREE_TYPE, and unknown_object_size().

Referenced by addr_object_size(), compute_builtin_object_size(), dynamic_object_size(), merge_object_sizes(), and plus_stmt_object_size().

◆ compute_builtin_object_size()

◆ compute_object_offset()

◆ cond_expr_object_size()

◆ decl_init_size()

tree decl_init_size ( tree decl,
bool min )
Returns the size of the object designated by DECL considering its
initializer if it either has one or if it would not affect its size,
otherwise the size of the object without the initializer when MIN
is true, else null.  An object's initializer affects the object's
size if it's a struct type with a flexible array member.   

References build3(), byte_position(), component_ref_size(), DECL_SIZE_UNIT, fold_build2, ggc_alloc(), last, last_field(), NULL_TREE, TREE_CODE, TREE_TYPE, TYPE_SIZE, and TYPE_SIZE_UNIT.

Referenced by addr_object_size(), and handle_decl().

◆ do_valueize()

static tree do_valueize ( tree t)
static
Dummy valueize function.   

Referenced by object_sizes_execute().

◆ dynamic_object_size()

static void dynamic_object_size ( struct object_size_info * osi,
tree var,
tree * size,
tree * wholesize )
static
Compute the dynamic object size for VAR.  Return the result in SIZE and
WHOLESIZE.   

References addr_object_size(), collect_object_sizes_for(), ggc_alloc(), object_size_info::object_size_type, object_sizes_get(), size_unknown(), SSA_NAME_VERSION, and TREE_CODE.

Referenced by cond_expr_object_size(), and phi_dynamic_object_size().

◆ dynamic_object_sizes_execute_one()

static bool dynamic_object_sizes_execute_one ( gimple_stmt_iterator * i,
gimple * call )
static
Attempt to fold one __builtin_dynamic_object_size call in CALL into an
expression and insert it at I.  Return true if it succeeds.   

References dump_file, dump_flags, EXPR_LOC_OR_LOC, fold_builtin_call_array(), gcc_assert, ggc_alloc(), gimple_call_arg(), gimple_call_fn(), gimple_call_num_args(), gimple_call_return_type(), gimplify_and_update_call_from_tree(), i, input_location, print_generic_expr(), print_gimple_stmt(), STRIP_NOPS, and TDF_DETAILS.

Referenced by object_sizes_execute().

◆ early_object_sizes_execute_one()

static void early_object_sizes_execute_one ( gimple_stmt_iterator * i,
gimple * call )
static
Process a __builtin_object_size or __builtin_dynamic_object_size call in
CALL early for subobjects before any object information is lost due to
optimization.  Insert a MIN or MAX expression of the result and
__builtin_object_size at I so that it may be processed in the second pass.
__builtin_dynamic_object_size is treated like __builtin_object_size here
since we're only looking for constant bounds.   

References compute_builtin_object_size(), fold_convert, g, gcc_assert, ggc_alloc(), gimple_build_assign(), gimple_call_arg(), gimple_call_lhs(), gimple_call_set_lhs(), gsi_insert_after(), GSI_NEW_STMT, i, int_fits_type_p(), make_ssa_name(), NULL_TREE, object_size_info::object_size_type, OST_MINIMUM, TREE_CODE, tree_fits_uhwi_p(), tree_to_uhwi(), TREE_TYPE, and update_stmt().

Referenced by object_sizes_execute().

◆ emit_phi_nodes()

◆ expr_object_size()

◆ fini_object_sizes()

void fini_object_sizes ( void )
Destroy data structures after the object size computation.   

References BITMAP_FREE, computed, object_size_info::object_size_type, object_sizes_release(), and OST_END.

Referenced by object_sizes_execute().

◆ gimplify_size_expressions()

◆ init_object_sizes()

void init_object_sizes ( void )
Initialize data structures for the object size computation.   

References BITMAP_ALLOC, computed, init_offset_limit(), NULL, object_size_info::object_size_type, object_sizes_grow(), and OST_END.

Referenced by object_sizes_execute().

◆ init_offset_limit()

static void init_offset_limit ( void )
static
Initialize OFFSET_LIMIT variable.   

References offset_limit, sizetype, tree_fits_uhwi_p(), tree_to_uhwi(), and TYPE_MAX_VALUE.

Referenced by compute_builtin_object_size(), and init_object_sizes().

◆ make_pass_early_object_sizes()

gimple_opt_pass * make_pass_early_object_sizes ( gcc::context * ctxt)

References ggc_alloc().

◆ make_pass_object_sizes()

gimple_opt_pass * make_pass_object_sizes ( gcc::context * ctxt)

References ggc_alloc().

◆ merge_object_sizes()

static bool merge_object_sizes ( struct object_size_info * osi,
tree dest,
tree orig )
static
Merge object sizes of ORIG + OFFSET into DEST.  Return true if
the object size might need reexamination later.   

References bitmap_bit_p, collect_object_sizes_for(), ggc_alloc(), object_size_info::object_size_type, object_sizes_get(), object_sizes_set(), object_sizes_unknown_p(), and SSA_NAME_VERSION.

Referenced by collect_object_sizes_for(), and cond_expr_object_size().

◆ object_sizes_execute()

◆ object_sizes_get()

static tree object_sizes_get ( struct object_size_info * osi,
unsigned varno,
bool whole = false )
inlinestatic
Return a size tree for VARNO corresponding to OSI.  If WHOLE is true, return
the whole object size.  Use this for building size expressions based on size
of VARNO.   

References gcc_checking_assert, ggc_alloc(), object_sizes, OST_DYNAMIC, size_usable_p(), TREE_CODE, TREE_OPERAND, TREE_VEC_ELT, and TREE_VEC_LENGTH.

Referenced by addr_object_size(), check_for_plus_in_loops_1(), compute_builtin_object_size(), dynamic_object_size(), gimplify_size_expressions(), merge_object_sizes(), object_sizes_set_temp(), and plus_stmt_object_size().

◆ object_sizes_get_raw()

static object_size object_sizes_get_raw ( struct object_size_info * osi,
unsigned varno )
inlinestatic
Return the raw size expression for VARNO corresponding to OSI.  This returns
the TREE_VEC as is and should only be used during gimplification.   

References gcc_assert, ggc_alloc(), and object_sizes.

Referenced by gimplify_size_expressions().

◆ object_sizes_grow()

static void object_sizes_grow ( int object_size_type)
inlinestatic
Grow object_sizes[OBJECT_SIZE_TYPE] to num_ssa_names.   

References num_ssa_names, and object_sizes.

Referenced by compute_builtin_object_size(), and init_object_sizes().

◆ object_sizes_initialize()

static void object_sizes_initialize ( struct object_size_info * osi,
unsigned varno,
tree val,
tree wholeval )
inlinestatic
Set size for VARNO corresponding to OSI to VAL.   

References ggc_alloc(), and object_sizes.

Referenced by collect_object_sizes_for(), and gimplify_size_expressions().

◆ object_sizes_release()

static void object_sizes_release ( int object_size_type)
inlinestatic
Release object_sizes[OBJECT_SIZE_TYPE].   

References object_sizes.

Referenced by fini_object_sizes().

◆ object_sizes_set()

static bool object_sizes_set ( struct object_size_info * osi,
unsigned varno,
tree val,
tree wholeval )
static
Set size for VARNO corresponding to OSI to VAL if it is the new minimum or
maximum.  For static sizes, each element of TREE_VEC is always INTEGER_CST
throughout the computation.  For dynamic sizes, each element may either be a
gimple variable, a MODIFY_EXPR or a TREE_VEC.  The MODIFY_EXPR is for
expressions that need to be gimplified.  TREE_VECs are special, they're
emitted only for GIMPLE_PHI and the PHI result variable is the last element
of the vector.   

References bitmap_bit_p, bitmap_set_bit, bundle_sizes(), changed, gcc_checking_assert, ggc_alloc(), make_ssa_name(), object_sizes, OST_DYNAMIC, OST_MINIMUM, size_binop, size_initval_p(), size_usable_p(), sizetype, SSA_NAME_DEF_STMT, TREE_CODE, and tree_int_cst_compare().

Referenced by call_object_size(), check_for_plus_in_loops_1(), cond_expr_object_size(), expr_object_size(), merge_object_sizes(), object_sizes_set_temp(), parm_object_size(), phi_dynamic_object_size(), plus_stmt_object_size(), and unknown_object_size().

◆ object_sizes_set_temp()

static void object_sizes_set_temp ( struct object_size_info * osi,
unsigned varno )
inlinestatic
Set temporary SSA names for object size and whole size to resolve dependency
loops in dynamic size computation.   

References ggc_alloc(), make_ssa_name(), object_sizes_get(), object_sizes_set(), size_initval_p(), and sizetype.

Referenced by collect_object_sizes_for().

◆ object_sizes_unknown_p()

static bool object_sizes_unknown_p ( int object_size_type,
unsigned varno )
inlinestatic

◆ parm_object_size()

◆ pass_through_call()

static tree pass_through_call ( const gcall * call)
static
If object size is propagated from one of function's arguments directly
to its return value, return that argument for GIMPLE_CALL statement CALL.
Otherwise return NULL.   

References ERF_RETURN_ARG_MASK, ERF_RETURNS_ARG, ggc_alloc(), gimple_call_arg(), gimple_call_builtin_p(), gimple_call_num_args(), gimple_call_return_flags(), and NULL_TREE.

Referenced by check_for_plus_in_loops_1(), and collect_object_sizes_for().

◆ phi_dynamic_object_size()

◆ plus_stmt_object_size()

◆ propagate_unknowns()

static tree propagate_unknowns ( object_size_info * osi,
tree expr,
bitmap unknowns )
static
Descend through EXPR and return size_unknown if it uses any SSA variable
object_size_set or object_size_set_temp generated, which turned out to be
size_unknown, as noted in UNKNOWNS.   

References bitmap_bit_p, expr, ggc_alloc(), i, propagate_unknowns(), size_unknown(), size_unknown_p(), SSA_NAME_VERSION, TREE_CODE, TREE_OPERAND, TREE_VEC_ELT, and TREE_VEC_LENGTH.

Referenced by gimplify_size_expressions(), and propagate_unknowns().

◆ size_for_offset()

static tree size_for_offset ( tree sz,
tree offset,
tree wholesize = NULL_TREE )
static
Bytes at end of the object with SZ from offset OFFSET.  If WHOLESIZE is not
NULL_TREE, use it to get the net offset of the pointer, which should always
be positive and hence, be within OFFSET_LIMIT for valid offsets.   

References compare_tree_int(), fold_build2, fold_convert, gcc_checking_assert, ggc_alloc(), integer_zerop(), offset, offset_limit, size_binop, size_zero_node, sizetype, TREE_CODE, tree_int_cst_compare(), TREE_TYPE, types_compatible_p(), and useless_type_conversion_p().

Referenced by addr_object_size(), compute_builtin_object_size(), and plus_stmt_object_size().

◆ size_initval()

static tree size_initval ( int object_size_type)
inlinestatic
Return a tree with initial value for OBJECT_SIZE_TYPE.   

References OST_MINIMUM, size_zero_node, sizetype, and TYPE_MAX_VALUE.

Referenced by collect_object_sizes_for().

◆ size_initval_p()

static bool size_initval_p ( tree val,
int object_size_type )
inlinestatic
Return true if VAL represents an initial size for OBJECT_SIZE_TYPE.   

References integer_all_onesp(), integer_zerop(), and OST_MINIMUM.

Referenced by object_sizes_set(), and object_sizes_set_temp().

◆ size_unknown()

◆ size_unknown_p()

static bool size_unknown_p ( tree val,
int object_size_type )
inlinestatic

◆ size_usable_p()

static bool size_usable_p ( tree val)
inlinestatic
Return true if VAL is usable as an object size in the object_sizes
vectors.   

References ggc_alloc(), and TREE_CODE.

Referenced by gimplify_size_expressions(), object_sizes_get(), and object_sizes_set().

◆ size_valid_p()

static bool size_valid_p ( tree val,
int object_size_type )
inlinestatic
Return true if VAL represents a valid size for OBJECT_SIZE_TYPE.   

References ggc_alloc(), OST_DYNAMIC, and TREE_CODE.

Referenced by addr_object_size(), call_object_size(), plus_stmt_object_size(), and strdup_object_size().

◆ strdup_object_size()

static tree strdup_object_size ( const gcall * call,
int object_size_type,
bool is_strndup )
static
Compute __builtin_object_size for CALL, which is a call to either
BUILT_IN_STRDUP or BUILT_IN_STRNDUP; IS_STRNDUP indicates which it is.
OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
If unknown, return size_unknown (object_size_type).   

References build_call_expr(), builtin_decl_implicit(), c_strlen(), compute_builtin_object_size(), fold_build2, get_base_address(), ggc_alloc(), gimple_call_arg(), NULL_TREE, OST_MINIMUM, size_one_node, size_unknown(), size_unknown_p(), size_valid_p(), sizetype, todo, TODO_update_ssa_only_virtuals, TREE_CODE, and TREE_OPERAND.

Referenced by call_object_size().

◆ unknown_object_size()

static void unknown_object_size ( struct object_size_info * osi,
tree ptr )
static

Variable Documentation

◆ computed

bitmap computed[OST_END]
static

◆ object_sizes

vec<object_size> object_sizes[OST_END]
static
object_sizes[0] is upper bound for the object size and number of bytes till
the end of the object.
object_sizes[1] is upper bound for the object size and number of bytes till
the end of the subobject (innermost array or field with address taken).
object_sizes[2] is lower bound for the object size and number of bytes till
the end of the object and object_sizes[3] lower bound for subobject.

For static object sizes, the object size and the bytes till the end of the
object are both INTEGER_CST.  In the dynamic case, they are finally either a
gimple variable or an INTEGER_CST.   

Referenced by object_sizes_get(), object_sizes_get_raw(), object_sizes_grow(), object_sizes_initialize(), object_sizes_release(), object_sizes_set(), and object_sizes_unknown_p().

◆ offset_limit

unsigned HOST_WIDE_INT offset_limit
static

◆ todo