From: Jan Hubicka Date: Thu, 25 Sep 2014 01:48:34 +0000 (+0200) Subject: cgraph.h (class ipa_polymorphic_call_context): Move here from ipa-utils.h; add stream... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ba3923391e896c0efdfcd49eb0334525ed8bd2c0;p=gcc.git cgraph.h (class ipa_polymorphic_call_context): Move here from ipa-utils.h; add stream_int and stream_out methods. * cgraph.h (class ipa_polymorphic_call_context): Move here from ipa-utils.h; add stream_int and stream_out methods. (cgraph_indirect_call_info): Remove SPECILATIVE_OFFSET, OUTER_TYPE, SPECULATIVE_OUTER_TYPE, MAYBE_IN_CONSTRUCTION MAYBE_DERIVED_TYPE and SPECULATIEVE_MAYBE_DERIVED_TYPE; add CONTEXT. (ipa_polymorphic_call_context::ipa_polymorphic_call_context, ipa_polymorphic_call_context::ipa_polymorphic_call_context, ipa_polymorphic_call_context::clear_speculation, ipa_polymorphic_call_context::clear_outer_type): Move here from ipa-utils.h * ipa-utils.h (class ipa_polymorphic_call_context): Move to cgraph.h (ipa_polymorphic_call_context::ipa_polymorphic_call_context, ipa_polymorphic_call_context::ipa_polymorphic_call_context, ipa_polymorphic_call_context::clear_speculation, ipa_polymorphic_call_context::clear_outer_type): Likewise. * ipa-devirt.c: Include data-streamer.h, lto-streamer.h and streamer-hooks.h (ipa_polymorphic_call_context::stream_out): New method. (ipa_polymorphic_call_context::stream_in): New method. (noncall_stmt_may_be_vtbl_ptr_store): Add forgotten static. * ipa-prop.c (ipa_analyze_indirect_call_uses): Do not care about OUTER_TYPE. (ipa_analyze_call_uses): Simplify. (update_indirect_edges_after_inlining): Do not care about outer_type. (ipa_write_indirect_edge_info): Update. (ipa_write_indirect_edge_info): Likewise. * cgraph.c (cgraph_node::create_indirect_edge): Simplify. (dump_edge_flags): Break out from ... (cgraph_node::dump): ... here; dump indirect edges. From-SVN: r215575 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 666f1a61cdc..220027e8a30 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,36 @@ +2014-09-24 Jan Hubicka + + * cgraph.h (class ipa_polymorphic_call_context): Move here from + ipa-utils.h; add stream_int and stream_out methods. + (cgraph_indirect_call_info): Remove SPECILATIVE_OFFSET, + OUTER_TYPE, SPECULATIVE_OUTER_TYPE, MAYBE_IN_CONSTRUCTION + MAYBE_DERIVED_TYPE and SPECULATIEVE_MAYBE_DERIVED_TYPE; + add CONTEXT. + (ipa_polymorphic_call_context::ipa_polymorphic_call_context, + ipa_polymorphic_call_context::ipa_polymorphic_call_context, + ipa_polymorphic_call_context::clear_speculation, + ipa_polymorphic_call_context::clear_outer_type): Move here from + ipa-utils.h + * ipa-utils.h (class ipa_polymorphic_call_context): Move to cgraph.h + (ipa_polymorphic_call_context::ipa_polymorphic_call_context, + ipa_polymorphic_call_context::ipa_polymorphic_call_context, + ipa_polymorphic_call_context::clear_speculation, + ipa_polymorphic_call_context::clear_outer_type): Likewise. + * ipa-devirt.c: Include data-streamer.h, lto-streamer.h and + streamer-hooks.h + (ipa_polymorphic_call_context::stream_out): New method. + (ipa_polymorphic_call_context::stream_in): New method. + (noncall_stmt_may_be_vtbl_ptr_store): Add forgotten static. + * ipa-prop.c (ipa_analyze_indirect_call_uses): Do not care about + OUTER_TYPE. + (ipa_analyze_call_uses): Simplify. + (update_indirect_edges_after_inlining): Do not care about outer_type. + (ipa_write_indirect_edge_info): Update. + (ipa_write_indirect_edge_info): Likewise. + * cgraph.c (cgraph_node::create_indirect_edge): Simplify. + (dump_edge_flags): Break out from ... + (cgraph_node::dump): ... here; dump indirect edges. + 2014-09-24 Jan Hubicka * ipa-utils.h (polymorphic_call_context): Add diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 8f04284863f..1cfc783f80a 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -893,16 +893,7 @@ cgraph_node::create_indirect_edge (gimple call_stmt, int ecf_flags, = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (target)); edge->indirect_info->otr_type = obj_type_ref_class (target); gcc_assert (TREE_CODE (edge->indirect_info->otr_type) == RECORD_TYPE); - edge->indirect_info->outer_type = context.outer_type; - edge->indirect_info->speculative_outer_type - = context.speculative_outer_type; - edge->indirect_info->offset = context.offset; - edge->indirect_info->speculative_offset = context.speculative_offset; - edge->indirect_info->maybe_in_construction - = context.maybe_in_construction; - edge->indirect_info->maybe_derived_type = context.maybe_derived_type; - edge->indirect_info->speculative_maybe_derived_type - = context.speculative_maybe_derived_type; + edge->indirect_info->context = context; } edge->next_callee = indirect_calls; @@ -1851,6 +1842,26 @@ cgraph_inline_failed_type (cgraph_inline_failed_t reason) const char * const cgraph_availability_names[] = {"unset", "not_available", "overwritable", "available", "local"}; +/* Output flags of edge E. */ + +static void +dump_edge_flags (FILE *f, struct cgraph_edge *edge) +{ + if (edge->speculative) + fprintf (f, "(speculative) "); + if (!edge->inline_failed) + fprintf (f, "(inlined) "); + if (edge->indirect_inlining_edge) + fprintf (f, "(indirect_inlining) "); + if (edge->count) + fprintf (f, "(%"PRId64"x) ", + (int64_t)edge->count); + if (edge->frequency) + fprintf (f, "(%.2f per call) ", + edge->frequency / (double)CGRAPH_FREQ_BASE); + if (edge->can_throw_external) + fprintf (f, "(can throw external) "); +} /* Dump call graph node to file F. */ @@ -1858,7 +1869,6 @@ void cgraph_node::dump (FILE *f) { cgraph_edge *edge; - int indirect_calls_count = 0; dump_base (f); @@ -1937,20 +1947,7 @@ cgraph_node::dump (FILE *f) { fprintf (f, "%s/%i ", edge->caller->asm_name (), edge->caller->order); - if (count) - fprintf (f, "(%"PRId64"x) ", - (int64_t)count); - if (frequency) - fprintf (f, "(%.2f per call) ", - frequency / (double)CGRAPH_FREQ_BASE); - if (edge->speculative) - fprintf (f, "(speculative) "); - if (!edge->inline_failed) - fprintf (f, "(inlined) "); - if (edge->indirect_inlining_edge) - fprintf (f, "(indirect_inlining) "); - if (edge->can_throw_external) - fprintf (f, "(can throw external) "); + dump_edge_flags (f, edge); } fprintf (f, "\n Calls: "); @@ -1958,28 +1955,34 @@ cgraph_node::dump (FILE *f) { fprintf (f, "%s/%i ", edge->callee->asm_name (), edge->callee->order); - if (edge->speculative) - fprintf (f, "(speculative) "); - if (!edge->inline_failed) - fprintf (f, "(inlined) "); - if (edge->indirect_inlining_edge) - fprintf (f, "(indirect_inlining) "); - if (edge->count) - fprintf (f, "(%"PRId64"x) ", - (int64_t)count); - if (edge->frequency) - fprintf (f, "(%.2f per call) ", - frequency / (double)CGRAPH_FREQ_BASE); - if (edge->can_throw_external) - fprintf (f, "(can throw external) "); + dump_edge_flags (f, edge); } fprintf (f, "\n"); for (edge = indirect_calls; edge; edge = edge->next_callee) - indirect_calls_count++; - if (indirect_calls_count) - fprintf (f, " Has %i outgoing edges for indirect calls.\n", - indirect_calls_count); + { + if (edge->indirect_info->polymorphic) + { + fprintf (f, " Polymorphic indirect call of type "); + print_generic_expr (f, edge->indirect_info->otr_type, TDF_SLIM); + fprintf (f, " token:%i", (int) edge->indirect_info->otr_token); + } + else + fprintf (f, " Indirect call"); + dump_edge_flags (f, edge); + if (edge->indirect_info->param_index != -1) + { + fprintf (f, " of param:%i", edge->indirect_info->param_index); + if (edge->indirect_info->agg_contents) + fprintf (f, " loaded from %s %s at offset %i", + edge->indirect_info->member_ptr ? "member ptr" : "aggregate", + edge->indirect_info->by_ref ? "passed by reference":"", + (int)edge->indirect_info->offset); + } + fprintf (f, "\n"); + if (edge->indirect_info->polymorphic) + edge->indirect_info->context.dump (f); + } } /* Dump call graph node NODE to stderr. */ diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 7e90bf07521..74819064fff 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -1267,19 +1267,83 @@ struct varpool_node_set_iterator unsigned index; }; +/* Context of polymorphic call. It represent information about the type of + instance that may reach the call. This is used by ipa-devirt walkers of the + type inheritance graph. */ + +class GTY(()) ipa_polymorphic_call_context { +public: + /* The called object appears in an object of type OUTER_TYPE + at offset OFFSET. When information is not 100% reliable, we + use SPECULATIVE_OUTER_TYPE and SPECULATIVE_OFFSET. */ + HOST_WIDE_INT offset; + HOST_WIDE_INT speculative_offset; + tree outer_type; + tree speculative_outer_type; + /* True if outer object may be in construction or destruction. */ + bool maybe_in_construction; + /* True if outer object may be of derived type. */ + bool maybe_derived_type; + /* True if speculative outer object may be of derived type. We always + speculate that construction does not happen. */ + bool speculative_maybe_derived_type; + /* True if the context is invalid and all calls should be redirected + to BUILTIN_UNREACHABLE. */ + bool invalid; + + /* Build empty "I know nothing" context. */ + ipa_polymorphic_call_context (); + /* Build polymorphic call context for indirect call E. */ + ipa_polymorphic_call_context (cgraph_edge *e); + /* Build polymorphic call context for IP invariant CST. + If specified, OTR_TYPE specify the type of polymorphic call + that takes CST+OFFSET as a prameter. */ + ipa_polymorphic_call_context (tree cst, tree otr_type = NULL, + HOST_WIDE_INT offset = 0); + /* Build context for pointer REF contained in FNDECL at statement STMT. + if INSTANCE is non-NULL, return pointer to the object described by + the context. */ + ipa_polymorphic_call_context (tree fndecl, tree ref, gimple stmt, + tree *instance = NULL); + + /* Look for vtable stores or constructor calls to work out dynamic type + of memory location. */ + bool get_dynamic_type (tree, tree, tree, gimple); + + /* Make context non-speculative. */ + void clear_speculation (); + + /* Walk container types and modify context to point to actual class + containing EXPECTED_TYPE as base class. */ + bool restrict_to_inner_class (tree expected_type); + + /* Dump human readable context to F. */ + void dump (FILE *f) const; + void DEBUG_FUNCTION debug () const; + + /* LTO streaming. */ + void stream_out (struct output_block *) const; + void stream_in (struct lto_input_block *, struct data_in *data_in); + +private: + void set_by_decl (tree, HOST_WIDE_INT); + bool set_by_invariant (tree, tree, HOST_WIDE_INT); + void clear_outer_type (tree otr_type = NULL); +}; + /* Structure containing additional information about an indirect call. */ struct GTY(()) cgraph_indirect_call_info { - /* When polymorphic is set, this field contains offset where the object which - was actually used in the polymorphic resides within a larger structure. - If agg_contents is set, the field contains the offset within the aggregate - from which the address to call was loaded. */ - HOST_WIDE_INT offset, speculative_offset; + /* When agg_content is set, an offset where the call pointer is located + within the aggregate. */ + HOST_WIDE_INT offset; + /* Context of the polymorphic call; use only when POLYMORPHIC flag is set. */ + ipa_polymorphic_call_context context; /* OBJ_TYPE_REF_TOKEN of a polymorphic call (if polymorphic is set). */ HOST_WIDE_INT otr_token; /* Type of the object from OBJ_TYPE_REF_OBJECT. */ - tree otr_type, outer_type, speculative_outer_type; + tree otr_type; /* Index of the parameter that is called. */ int param_index; /* ECF flags determined from the caller. */ @@ -1300,9 +1364,6 @@ struct GTY(()) cgraph_indirect_call_info /* When the previous bit is set, this one determines whether the destination is loaded from a parameter passed by reference. */ unsigned by_ref : 1; - unsigned int maybe_in_construction : 1; - unsigned int maybe_derived_type : 1; - unsigned int speculative_maybe_derived_type : 1; }; struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"))) cgraph_edge { @@ -2532,4 +2593,45 @@ inline symtab_node * symtab_node::get_create (tree node) return cgraph_node::get_create (node); } +/* Build polymorphic call context for indirect call E. */ + +inline +ipa_polymorphic_call_context::ipa_polymorphic_call_context (cgraph_edge *e) +{ + gcc_checking_assert (e->indirect_info->polymorphic); + *this = e->indirect_info->context; +} + +/* Build empty "I know nothing" context. */ + +inline +ipa_polymorphic_call_context::ipa_polymorphic_call_context () +{ + clear_speculation (); + clear_outer_type (); + invalid = false; +} + +/* Make context non-speculative. */ + +inline void +ipa_polymorphic_call_context::clear_speculation () +{ + speculative_outer_type = NULL; + speculative_offset = 0; + speculative_maybe_derived_type = false; +} + +/* Produce context specifying all derrived types of OTR_TYPE. + If OTR_TYPE is NULL or type of the OBJ_TYPE_REF, the context is set + to dummy "I know nothing" setting. */ + +inline void +ipa_polymorphic_call_context::clear_outer_type (tree otr_type) +{ + outer_type = otr_type ? TYPE_MAIN_VARIANT (otr_type) : NULL; + offset = 0; + maybe_derived_type = true; + maybe_in_construction = true; +} #endif /* GCC_CGRAPH_H */ diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index afa263f1e7f..954cd540987 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -135,6 +135,9 @@ along with GCC; see the file COPYING3. If not see #include "stor-layout.h" #include "intl.h" #include "hash-map.h" +#include "data-streamer.h" +#include "lto-streamer.h" +#include "streamer-hooks.h" /* Hash based set of pairs of types. */ typedef struct @@ -2570,6 +2573,71 @@ ipa_polymorphic_call_context::debug () const dump (stderr); } +/* Stream out the context to OB. */ + +void +ipa_polymorphic_call_context::stream_out (struct output_block *ob) const +{ + struct bitpack_d bp = bitpack_create (ob->main_stream); + + bp_pack_value (&bp, invalid, 1); + bp_pack_value (&bp, maybe_in_construction, 1); + bp_pack_value (&bp, maybe_derived_type, 1); + bp_pack_value (&bp, speculative_maybe_derived_type, 1); + bp_pack_value (&bp, outer_type != NULL, 1); + bp_pack_value (&bp, offset != 0, 1); + bp_pack_value (&bp, speculative_outer_type != NULL, 1); + streamer_write_bitpack (&bp); + + if (outer_type != NULL) + stream_write_tree (ob, outer_type, true); + if (offset) + streamer_write_hwi (ob, offset); + if (speculative_outer_type != NULL) + { + stream_write_tree (ob, speculative_outer_type, true); + streamer_write_hwi (ob, speculative_offset); + } + else + gcc_assert (!speculative_offset); +} + +/* Stream in the context from IB and DATA_IN. */ + +void +ipa_polymorphic_call_context::stream_in (struct lto_input_block *ib, + struct data_in *data_in) +{ + struct bitpack_d bp = streamer_read_bitpack (ib); + + invalid = bp_unpack_value (&bp, 1); + maybe_in_construction = bp_unpack_value (&bp, 1); + maybe_derived_type = bp_unpack_value (&bp, 1); + speculative_maybe_derived_type = bp_unpack_value (&bp, 1); + bool outer_type_p = bp_unpack_value (&bp, 1); + bool offset_p = bp_unpack_value (&bp, 1); + bool speculative_outer_type_p = bp_unpack_value (&bp, 1); + + if (outer_type_p) + outer_type = stream_read_tree (ib, data_in); + else + outer_type = NULL; + if (offset_p) + offset = (HOST_WIDE_INT) streamer_read_hwi (ib); + else + offset = 0; + if (speculative_outer_type_p) + { + speculative_outer_type = stream_read_tree (ib, data_in); + speculative_offset = (HOST_WIDE_INT) streamer_read_hwi (ib); + } + else + { + speculative_outer_type = NULL; + speculative_offset = 0; + } +} + /* Proudce polymorphic call context for call method of instance that is located within BASE (that is assumed to be a decl) at offset OFF. */ @@ -2894,7 +2962,7 @@ struct type_change_info We take advantage of fact that vtable stores must appear within constructor and destructor functions. */ -bool +static bool noncall_stmt_may_be_vtbl_ptr_store (gimple stmt) { if (is_gimple_assign (stmt)) diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index b65a1e21493..36949e32709 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -416,6 +416,8 @@ ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node) } else fprintf (f, "\n"); + if (ii->polymorphic) + ii->context.dump (f); ipa_print_node_jump_functions_for_edge (f, cs); } } @@ -2153,8 +2155,6 @@ ipa_analyze_indirect_call_uses (struct func_body_info *fbi, gimple call, NULL, &by_ref)) { struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call); - if (cs->indirect_info->offset != offset) - cs->indirect_info->outer_type = NULL; cs->indirect_info->offset = offset; cs->indirect_info->agg_contents = 1; cs->indirect_info->by_ref = by_ref; @@ -2255,8 +2255,6 @@ ipa_analyze_indirect_call_uses (struct func_body_info *fbi, gimple call, && parm_preserved_before_stmt_p (fbi, index, call, rec)) { struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call); - if (cs->indirect_info->offset != offset) - cs->indirect_info->outer_type = NULL; cs->indirect_info->offset = offset; cs->indirect_info->agg_contents = 1; cs->indirect_info->member_ptr = 1; @@ -2345,36 +2343,20 @@ ipa_analyze_call_uses (struct func_body_info *fbi, gimple call) if (cs->indirect_info->polymorphic) { - tree otr_type; - HOST_WIDE_INT otr_token; tree instance; tree target = gimple_call_fn (call); ipa_polymorphic_call_context context (current_function_decl, target, call, &instance); - otr_type = obj_type_ref_class (target); - otr_token = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (target)); + gcc_checking_assert (cs->indirect_info->otr_type + == obj_type_ref_class (target)); + gcc_checking_assert (cs->indirect_info->otr_token + == tree_to_shwi (OBJ_TYPE_REF_TOKEN (target))); if (context.get_dynamic_type (instance, OBJ_TYPE_REF_OBJECT (target), - otr_type, call) - && context.offset == cs->indirect_info->offset) - { - gcc_assert (TREE_CODE (otr_type) == RECORD_TYPE); - cs->indirect_info->polymorphic = true; - cs->indirect_info->param_index = -1; - cs->indirect_info->otr_token = otr_token; - cs->indirect_info->otr_type = otr_type; - cs->indirect_info->outer_type = context.outer_type; - cs->indirect_info->speculative_outer_type = context.speculative_outer_type; - cs->indirect_info->offset = context.offset; - cs->indirect_info->speculative_offset = context.speculative_offset; - cs->indirect_info->maybe_in_construction - = context.maybe_in_construction; - cs->indirect_info->maybe_derived_type = context.maybe_derived_type; - cs->indirect_info->speculative_maybe_derived_type - = context.speculative_maybe_derived_type; - } + obj_type_ref_class (target), call)) + cs->indirect_info->context = context; } if (TREE_CODE (target) == SSA_NAME) @@ -3253,8 +3235,6 @@ update_indirect_edges_after_inlining (struct cgraph_edge *cs, else { ici->param_index = ipa_get_jf_ancestor_formal_id (jfunc); - if (ipa_get_jf_ancestor_offset (jfunc)) - ici->outer_type = NULL; ici->offset += ipa_get_jf_ancestor_offset (jfunc); } } @@ -4735,25 +4715,22 @@ ipa_write_indirect_edge_info (struct output_block *ob, struct bitpack_d bp; streamer_write_hwi (ob, ii->param_index); - streamer_write_hwi (ob, ii->offset); bp = bitpack_create (ob->main_stream); bp_pack_value (&bp, ii->polymorphic, 1); bp_pack_value (&bp, ii->agg_contents, 1); bp_pack_value (&bp, ii->member_ptr, 1); bp_pack_value (&bp, ii->by_ref, 1); - bp_pack_value (&bp, ii->maybe_in_construction, 1); - bp_pack_value (&bp, ii->maybe_derived_type, 1); - bp_pack_value (&bp, ii->speculative_maybe_derived_type, 1); streamer_write_bitpack (&bp); + if (ii->agg_contents || ii->polymorphic) + streamer_write_hwi (ob, ii->offset); + else + gcc_assert (ii->offset == 0); if (ii->polymorphic) { streamer_write_hwi (ob, ii->otr_token); stream_write_tree (ob, ii->otr_type, true); - stream_write_tree (ob, ii->outer_type, true); - stream_write_tree (ob, ii->speculative_outer_type, true); - if (ii->speculative_outer_type) - streamer_write_hwi (ob, ii->speculative_offset); + ii->context.stream_out (ob); } } @@ -4762,30 +4739,27 @@ ipa_write_indirect_edge_info (struct output_block *ob, static void ipa_read_indirect_edge_info (struct lto_input_block *ib, - struct data_in *data_in ATTRIBUTE_UNUSED, + struct data_in *data_in, struct cgraph_edge *cs) { struct cgraph_indirect_call_info *ii = cs->indirect_info; struct bitpack_d bp; ii->param_index = (int) streamer_read_hwi (ib); - ii->offset = (HOST_WIDE_INT) streamer_read_hwi (ib); bp = streamer_read_bitpack (ib); ii->polymorphic = bp_unpack_value (&bp, 1); ii->agg_contents = bp_unpack_value (&bp, 1); ii->member_ptr = bp_unpack_value (&bp, 1); ii->by_ref = bp_unpack_value (&bp, 1); - ii->maybe_in_construction = bp_unpack_value (&bp, 1); - ii->maybe_derived_type = bp_unpack_value (&bp, 1); - ii->speculative_maybe_derived_type = bp_unpack_value (&bp, 1); + if (ii->agg_contents || ii->polymorphic) + ii->offset = (HOST_WIDE_INT) streamer_read_hwi (ib); + else + ii->offset = 0; if (ii->polymorphic) { ii->otr_token = (HOST_WIDE_INT) streamer_read_hwi (ib); ii->otr_type = stream_read_tree (ib, data_in); - ii->outer_type = stream_read_tree (ib, data_in); - ii->speculative_outer_type = stream_read_tree (ib, data_in); - if (ii->speculative_outer_type) - ii->speculative_offset = (HOST_WIDE_INT) streamer_read_hwi (ib); + ii->context.stream_in (ib, data_in); } } diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h index 409e4853858..7ff29f8c147 100644 --- a/gcc/ipa-utils.h +++ b/gcc/ipa-utils.h @@ -34,114 +34,6 @@ struct ipa_dfs_info { PTR aux; }; -/* Context of polymorphic call. This is used by ipa-devirt walkers of the - type inheritance graph. */ - -class ipa_polymorphic_call_context { -public: - /* The called object appears in an object of type OUTER_TYPE - at offset OFFSET. When information is not 100% reliable, we - use SPECULATIVE_OUTER_TYPE and SPECULATIVE_OFFSET. */ - HOST_WIDE_INT offset; - HOST_WIDE_INT speculative_offset; - tree outer_type; - tree speculative_outer_type; - /* True if outer object may be in construction or destruction. */ - bool maybe_in_construction; - /* True if outer object may be of derived type. */ - bool maybe_derived_type; - /* True if speculative outer object may be of derived type. We always - speculate that construction does not happen. */ - bool speculative_maybe_derived_type; - /* True if the context is invalid and all calls should be redirected - to BUILTIN_UNREACHABLE. */ - bool invalid; - - /* Build empty "I know nothing" context. */ - ipa_polymorphic_call_context (); - /* Build polymorphic call context for indirect call E. */ - ipa_polymorphic_call_context (cgraph_edge *e); - /* Build polymorphic call context for IP invariant CST. - If specified, OTR_TYPE specify the type of polymorphic call - that takes CST+OFFSET as a prameter. */ - ipa_polymorphic_call_context (tree cst, tree otr_type = NULL, - HOST_WIDE_INT offset = 0); - /* Build context for pointer REF contained in FNDECL at statement STMT. - if INSTANCE is non-NULL, return pointer to the object described by - the context. */ - ipa_polymorphic_call_context (tree fndecl, tree ref, gimple stmt, - tree *instance = NULL); - - /* Look for vtable stores or constructor calls to work out dynamic type - of memory location. */ - bool get_dynamic_type (tree, tree, tree, gimple); - - /* Make context non-speculative. */ - void clear_speculation (); - - /* Walk container types and modify context to point to actual class - containing EXPECTED_TYPE as base class. */ - bool restrict_to_inner_class (tree expected_type); - - /* Dump human readable context to F. */ - void dump (FILE *f) const; - void DEBUG_FUNCTION debug () const; - -private: - void set_by_decl (tree, HOST_WIDE_INT); - bool set_by_invariant (tree, tree, HOST_WIDE_INT); - void clear_outer_type (tree otr_type = NULL); -}; - -/* Build polymorphic call context for indirect call E. */ - -inline -ipa_polymorphic_call_context::ipa_polymorphic_call_context (cgraph_edge *e) -{ - gcc_checking_assert (e->indirect_info->polymorphic); - - offset = e->indirect_info->offset; - speculative_offset = e->indirect_info->speculative_offset; - outer_type = e->indirect_info->outer_type; - speculative_outer_type = e->indirect_info->speculative_outer_type; - maybe_in_construction = e->indirect_info->maybe_in_construction; - maybe_derived_type = e->indirect_info->maybe_derived_type; - speculative_maybe_derived_type = e->indirect_info->speculative_maybe_derived_type; - invalid = false; -} - -/* Build empty "I know nothing" context. */ - -inline -ipa_polymorphic_call_context::ipa_polymorphic_call_context () -{ - clear_speculation (); - clear_outer_type (); - invalid = false; -} - -/* Make context non-speculative. */ - -inline void -ipa_polymorphic_call_context::clear_speculation () -{ - speculative_outer_type = NULL; - speculative_offset = 0; - speculative_maybe_derived_type = false; -} - -/* Produce context specifying all derrived types of OTR_TYPE. - If OTR_TYPE is NULL or type of the OBJ_TYPE_REF, the context is set - to dummy "I know nothing" setting. */ - -inline void -ipa_polymorphic_call_context::clear_outer_type (tree otr_type) -{ - outer_type = otr_type ? TYPE_MAIN_VARIANT (otr_type) : NULL; - offset = 0; - maybe_derived_type = true; - maybe_in_construction = true; -} /* In ipa-utils.c */ void ipa_print_order (FILE*, const char *, struct cgraph_node**, int);