Message ID | 20140416140313.GC41722@msticlxl57.ims.intel.com |
---|---|
State | New |
Headers | show |
Ping 2014-04-16 18:03 GMT+04:00 Ilya Enkovich <enkovich.gnu@gmail.com>: > Hi, > > This patch introduces changes in call graph for Pointer Bounds Checker. > > New fields instrumented_version, instrumentation_clone and orig_decl are added for cgraph_node: > - instrumentation_clone field is 1 for nodes created for instrumented version of functions > - instrumented_version points to instrumented/original node > - orig_decl holds original function declaration for instrumented nodes in case original node is removed > > IPA_REF_CHKP reference type is introduced for nodes to reference instrumented function versions from originals. It is used to have proper reachability analysis. > > When original function bodies are not needed anymore, functions are transformed into thunks having call edge to the instrumented function. Therefore new field appeared in cgraph_thunk_info to mark such thunks. > > Does it look OK? > > Bootstrapped and tested on linux-x86_64. > > Thanks, > Ilya > -- > gcc/ > > 2014-04-16 Ilya Enkovich <ilya.enkovich@intel.com> > > * cgraph.h (cgraph_thunk_info): Add add_pointer_bounds_args > field. > (cgraph_node): Add instrumented_version, orig_decl and > instrumentation_clone fields. > (symtab_alias_target): Allow IPA_REF_CHKP reference. > * cgraph.c (cgraph_remove_node): Fix instrumented_version > of the referenced node if any. > (dump_cgraph_node): Dump instrumentation_clone and > instrumented_version fields. > (verify_cgraph_node): Check correctness of IPA_REF_CHKP > references and instrumentation thunks. > * cgraphbuild.c (rebuild_cgraph_edges): Rebuild IPA_REF_CHKP > reference. > (cgraph_rebuild_references): Likewise. > * cgraphunit.c (assemble_thunks_and_aliases): Skip thunks > calling instrumneted function version. > * ipa-ref.h (ipa_ref_use): Add IPA_REF_CHKP. > (ipa_ref): increase size of use field. > * ipa-ref.c (ipa_ref_use_name): Add element for IPA_REF_CHKP. > * lto-cgraph.c (lto_output_node): Output instrumentation_clone, > thunk.add_pointer_bounds_args and orig_decl field. > (lto_output_ref): Adjust to new ipa_ref::use field size. > (input_overwrite_node): Read instrumentation_clone field. > (input_node): Read thunk.add_pointer_bounds_args and orig_decl > fields. > (input_ref): Adjust to new ipa_ref::use field size. > (input_cgraph_1): Compute instrumented_version fields and restore > IDENTIFIER_TRANSPARENT_ALIAS chains. > * lto-streamer.h (LTO_minor_version): Change minor version from > 0 to 1. > * ipa.c (symtab_remove_unreachable_nodes): Consider instrumented > clone as address taken if the original one is address taken. > (cgraph_externally_visible_p): Mark instrumented 'main' as > externally visible. > (function_and_variable_visibility): Filter instrumentation > thunks. > > > diff --git a/gcc/cgraph.c b/gcc/cgraph.c > index be3661a..6210c68 100644 > --- a/gcc/cgraph.c > +++ b/gcc/cgraph.c > @@ -1828,6 +1828,12 @@ cgraph_remove_node (struct cgraph_node *node) > } > cgraph_n_nodes--; > > + if (node->instrumented_version) > + { > + node->instrumented_version->instrumented_version = NULL; > + node->instrumented_version = NULL; > + } > + > /* Clear out the node to NULL all pointers and add the node to the free > list. */ > memset (node, 0, sizeof (*node)); > @@ -2070,6 +2076,11 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) > if (indirect_calls_count) > fprintf (f, " Has %i outgoing edges for indirect calls.\n", > indirect_calls_count); > + > + if (node->instrumentation_clone) > + fprintf (f, " Is instrumented version.\n"); > + else if (node->instrumented_version) > + fprintf (f, " Has instrumented version.\n"); > } > > > @@ -2850,7 +2861,9 @@ verify_cgraph_node (struct cgraph_node *node) > } > for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, > i, ref); i++) > - if (ref->use != IPA_REF_ALIAS) > + if (ref->use == IPA_REF_CHKP) > + ; > + else if (ref->use != IPA_REF_ALIAS) > { > error ("Alias has non-alias reference"); > error_found = true; > @@ -2868,6 +2881,35 @@ verify_cgraph_node (struct cgraph_node *node) > error_found = true; > } > } > + > + /* Check all nodes reference their instrumented versions. */ > + if (node->analyzed > + && node->instrumented_version > + && !node->instrumentation_clone) > + { > + bool ref_found = false; > + int i; > + struct ipa_ref *ref; > + > + for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, > + i, ref); i++) > + if (ref->use == IPA_REF_CHKP) > + { > + if (ref_found) > + { > + error ("Node has more than one chkp reference"); > + error_found = true; > + } > + ref_found = true; > + } > + > + if (!ref_found) > + { > + error ("Analyzed node has no reference to instrumented version"); > + error_found = true; > + } > + } > + > if (node->analyzed && node->thunk.thunk_p) > { > if (!node->callees) > @@ -2885,6 +2927,12 @@ verify_cgraph_node (struct cgraph_node *node) > error ("Thunk is not supposed to have body"); > error_found = true; > } > + if (node->thunk.add_pointer_bounds_args > + && node->callees->callee != node->instrumented_version) > + { > + error ("Instrumentation thunk has wrong edge callee"); > + error_found = true; > + } > } > else if (node->analyzed && gimple_has_body_p (node->decl) > && !TREE_ASM_WRITTEN (node->decl) > diff --git a/gcc/cgraph.h b/gcc/cgraph.h > index a6a51cf..5e702a7 100644 > --- a/gcc/cgraph.h > +++ b/gcc/cgraph.h > @@ -191,6 +191,7 @@ struct GTY(()) cgraph_thunk_info { > tree alias; > bool this_adjusting; > bool virtual_offset_p; > + bool add_pointer_bounds_args; > /* Set to true when alias node is thunk. */ > bool thunk_p; > }; > @@ -373,6 +374,13 @@ public: > struct cgraph_node *prev_sibling_clone; > struct cgraph_node *clones; > struct cgraph_node *clone_of; > + /* If instrumentation_clone is 1 then instrumented_version points > + to the original function used to make instrumented version. > + Otherwise points to instrumented version of the function. */ > + struct cgraph_node *instrumented_version; > + /* If instrumentation_clone is 1 then orig_decl is the original > + function declaration. */ > + tree orig_decl; > /* For functions with many calls sites it holds map from call expression > to the edge to speed up cgraph_edge function. */ > htab_t GTY((param_is (struct cgraph_edge))) call_site_hash; > @@ -433,6 +441,9 @@ public: > /* True if this decl calls a COMDAT-local function. This is set up in > compute_inline_parameters and inline_call. */ > unsigned calls_comdat_local : 1; > + /* True when function is clone created for Pointer Bounds Checker > + instrumentation. */ > + unsigned instrumentation_clone : 1; > }; > > > @@ -1412,6 +1423,8 @@ symtab_alias_target (symtab_node *n) > { > struct ipa_ref *ref; > ipa_ref_list_reference_iterate (&n->ref_list, 0, ref); > + if (ref->use == IPA_REF_CHKP) > + ipa_ref_list_reference_iterate (&n->ref_list, 1, ref); > gcc_checking_assert (ref->use == IPA_REF_ALIAS); > return ref->referred; > } > diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c > index 19961e2..a2b2106 100644 > --- a/gcc/cgraphbuild.c > +++ b/gcc/cgraphbuild.c > @@ -481,6 +481,10 @@ rebuild_cgraph_edges (void) > record_eh_tables (node, cfun); > gcc_assert (!node->global.inlined_to); > > + if (node->instrumented_version > + && !node->instrumentation_clone) > + ipa_record_reference (node, node->instrumented_version, IPA_REF_CHKP, NULL); > + > return 0; > } > > @@ -513,6 +517,11 @@ cgraph_rebuild_references (void) > ipa_record_stmt_references (node, gsi_stmt (gsi)); > } > record_eh_tables (node, cfun); > + > + > + if (node->instrumented_version > + && !node->instrumentation_clone) > + ipa_record_reference (node, node->instrumented_version, IPA_REF_CHKP, NULL); > } > > namespace { > diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c > index 06283fc..ceb4060 100644 > --- a/gcc/cgraphunit.c > +++ b/gcc/cgraphunit.c > @@ -1702,7 +1702,8 @@ assemble_thunks_and_aliases (struct cgraph_node *node) > struct ipa_ref *ref; > > for (e = node->callers; e;) > - if (e->caller->thunk.thunk_p) > + if (e->caller->thunk.thunk_p > + && !e->caller->thunk.add_pointer_bounds_args) > { > struct cgraph_node *thunk = e->caller; > > diff --git a/gcc/ipa-ref.c b/gcc/ipa-ref.c > index 6aa41e6..3a055d9 100644 > --- a/gcc/ipa-ref.c > +++ b/gcc/ipa-ref.c > @@ -27,7 +27,7 @@ along with GCC; see the file COPYING3. If not see > #include "cgraph.h" > #include "ipa-utils.h" > > -static const char *ipa_ref_use_name[] = {"read","write","addr","alias"}; > +static const char *ipa_ref_use_name[] = {"read","write","addr","alias","chkp"}; > > /* Return ipa reference from REFERING_NODE or REFERING_VARPOOL_NODE > to REFERED_NODE or REFERED_VARPOOL_NODE. USE_TYPE specify type > diff --git a/gcc/ipa-ref.h b/gcc/ipa-ref.h > index 4ce5f8d..d0df0bf 100644 > --- a/gcc/ipa-ref.h > +++ b/gcc/ipa-ref.h > @@ -29,7 +29,8 @@ enum GTY(()) ipa_ref_use > IPA_REF_LOAD, > IPA_REF_STORE, > IPA_REF_ADDR, > - IPA_REF_ALIAS > + IPA_REF_ALIAS, > + IPA_REF_CHKP > }; > > /* Record of reference in callgraph or varpool. */ > @@ -40,7 +41,7 @@ struct GTY(()) ipa_ref > gimple stmt; > unsigned int lto_stmt_uid; > unsigned int referred_index; > - ENUM_BITFIELD (ipa_ref_use) use:2; > + ENUM_BITFIELD (ipa_ref_use) use:3; > unsigned int speculative:1; > }; > > diff --git a/gcc/ipa.c b/gcc/ipa.c > index 5ab3aed..1d7fa35 100644 > --- a/gcc/ipa.c > +++ b/gcc/ipa.c > @@ -508,6 +508,12 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) > cgraph_node_remove_callees (node); > ipa_remove_all_references (&node->ref_list); > changed = true; > + if (node->thunk.thunk_p > + && node->thunk.add_pointer_bounds_args) > + { > + node->thunk.thunk_p = false; > + node->thunk.add_pointer_bounds_args = false; > + } > } > } > else > @@ -583,7 +589,10 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) > if (node->address_taken > && !node->used_from_other_partition) > { > - if (!cgraph_for_node_and_aliases (node, has_addr_references_p, NULL, true)) > + if (!cgraph_for_node_and_aliases (node, has_addr_references_p, NULL, true) > + && (!node->instrumentation_clone > + || !node->instrumented_version > + || !node->instrumented_version->address_taken)) > { > if (file) > fprintf (file, " %s", node->name ()); > @@ -814,6 +823,10 @@ cgraph_externally_visible_p (struct cgraph_node *node, > if (MAIN_NAME_P (DECL_NAME (node->decl))) > return true; > > + if (node->instrumentation_clone > + && MAIN_NAME_P (DECL_NAME (node->orig_decl))) > + return true; > + > return false; > } > > @@ -1016,6 +1029,7 @@ function_and_variable_visibility (bool whole_program) > } > > if (node->thunk.thunk_p > + && !node->thunk.add_pointer_bounds_args > && TREE_PUBLIC (node->decl)) > { > struct cgraph_node *decl_node = node; > diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c > index 999ce3d..58105f0 100644 > --- a/gcc/lto-cgraph.c > +++ b/gcc/lto-cgraph.c > @@ -526,6 +526,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, > bp_pack_value (&bp, node->thunk.thunk_p && !boundary_p, 1); > bp_pack_enum (&bp, ld_plugin_symbol_resolution, > LDPR_NUM_KNOWN, node->resolution); > + bp_pack_value (&bp, node->instrumentation_clone, 1); > streamer_write_bitpack (&bp); > > if (node->thunk.thunk_p && !boundary_p) > @@ -533,11 +534,15 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, > streamer_write_uhwi_stream > (ob->main_stream, > 1 + (node->thunk.this_adjusting != 0) * 2 > - + (node->thunk.virtual_offset_p != 0) * 4); > + + (node->thunk.virtual_offset_p != 0) * 4 > + + (node->thunk.add_pointer_bounds_args != 0) * 8); > streamer_write_uhwi_stream (ob->main_stream, node->thunk.fixed_offset); > streamer_write_uhwi_stream (ob->main_stream, node->thunk.virtual_value); > } > streamer_write_hwi_stream (ob->main_stream, node->profile_id); > + > + if (node->instrumentation_clone) > + lto_output_fn_decl_index (ob->decl_state, ob->main_stream, node->orig_decl); > } > > /* Output the varpool NODE to OB. > @@ -613,7 +618,7 @@ lto_output_ref (struct lto_simple_output_block *ob, struct ipa_ref *ref, > struct cgraph_node *node; > > bp = bitpack_create (ob->main_stream); > - bp_pack_value (&bp, ref->use, 2); > + bp_pack_value (&bp, ref->use, 3); > bp_pack_value (&bp, ref->speculative, 1); > streamer_write_bitpack (&bp); > nref = lto_symtab_encoder_lookup (encoder, ref->referred); > @@ -1002,6 +1007,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data, > node->thunk.thunk_p = bp_unpack_value (bp, 1); > node->resolution = bp_unpack_enum (bp, ld_plugin_symbol_resolution, > LDPR_NUM_KNOWN); > + node->instrumentation_clone = bp_unpack_value (bp, 1); > gcc_assert (flag_ltrans > || (!node->in_other_partition > && !node->used_from_other_partition)); > @@ -1112,10 +1118,19 @@ input_node (struct lto_file_decl_data *file_data, > node->thunk.this_adjusting = (type & 2); > node->thunk.virtual_value = virtual_value; > node->thunk.virtual_offset_p = (type & 4); > + node->thunk.add_pointer_bounds_args = (type & 8); > } > if (node->alias && !node->analyzed && node->weakref) > node->alias_target = get_alias_symbol (node->decl); > node->profile_id = streamer_read_hwi (ib); > + > + if (node->instrumentation_clone) > + { > + decl_index = streamer_read_uhwi (ib); > + fn_decl = lto_file_decl_data_get_fn_decl (file_data, decl_index); > + node->orig_decl = fn_decl; > + } > + > return node; > } > > @@ -1196,7 +1211,7 @@ input_ref (struct lto_input_block *ib, > struct ipa_ref *ref; > > bp = streamer_read_bitpack (ib); > - use = (enum ipa_ref_use) bp_unpack_value (&bp, 2); > + use = (enum ipa_ref_use) bp_unpack_value (&bp, 3); > speculative = (enum ipa_ref_use) bp_unpack_value (&bp, 1); > node = nodes[streamer_read_hwi (ib)]; > ref = ipa_record_reference (referring_node, node, use, NULL); > @@ -1337,6 +1352,22 @@ input_cgraph_1 (struct lto_file_decl_data *file_data, > cgraph (node)->global.inlined_to = cgraph (nodes[ref]); > else > cnode->global.inlined_to = NULL; > + > + /* Compute instrumented_version. */ > + if (cnode->instrumentation_clone) > + { > + gcc_assert (cnode->orig_decl); > + > + cnode->instrumented_version = cgraph_get_node (cnode->orig_decl); > + if (cnode->instrumented_version) > + cnode->instrumented_version->instrumented_version = cnode; > + > + /* Restore decl names reference. */ > + if (IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (cnode->decl)) > + && !TREE_CHAIN (DECL_ASSEMBLER_NAME (cnode->decl))) > + TREE_CHAIN (DECL_ASSEMBLER_NAME (cnode->decl)) > + = DECL_ASSEMBLER_NAME (cnode->orig_decl); > + } > } > > ref = (int) (intptr_t) node->same_comdat_group; > diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h > index 51b1903..62a5fe0 100644 > --- a/gcc/lto-streamer.h > +++ b/gcc/lto-streamer.h > @@ -141,7 +141,7 @@ along with GCC; see the file COPYING3. If not see > #define LTO_SECTION_NAME_PREFIX ".gnu.lto_" > > #define LTO_major_version 3 > -#define LTO_minor_version 0 > +#define LTO_minor_version 1 > > typedef unsigned char lto_decl_flags_t; >
Ping 2014-05-06 16:13 GMT+04:00 Ilya Enkovich <enkovich.gnu@gmail.com>: > Ping > > 2014-04-16 18:03 GMT+04:00 Ilya Enkovich <enkovich.gnu@gmail.com>: >> Hi, >> >> This patch introduces changes in call graph for Pointer Bounds Checker. >> >> New fields instrumented_version, instrumentation_clone and orig_decl are added for cgraph_node: >> - instrumentation_clone field is 1 for nodes created for instrumented version of functions >> - instrumented_version points to instrumented/original node >> - orig_decl holds original function declaration for instrumented nodes in case original node is removed >> >> IPA_REF_CHKP reference type is introduced for nodes to reference instrumented function versions from originals. It is used to have proper reachability analysis. >> >> When original function bodies are not needed anymore, functions are transformed into thunks having call edge to the instrumented function. Therefore new field appeared in cgraph_thunk_info to mark such thunks. >> >> Does it look OK? >> >> Bootstrapped and tested on linux-x86_64. >> >> Thanks, >> Ilya >> -- >> gcc/ >> >> 2014-04-16 Ilya Enkovich <ilya.enkovich@intel.com> >> >> * cgraph.h (cgraph_thunk_info): Add add_pointer_bounds_args >> field. >> (cgraph_node): Add instrumented_version, orig_decl and >> instrumentation_clone fields. >> (symtab_alias_target): Allow IPA_REF_CHKP reference. >> * cgraph.c (cgraph_remove_node): Fix instrumented_version >> of the referenced node if any. >> (dump_cgraph_node): Dump instrumentation_clone and >> instrumented_version fields. >> (verify_cgraph_node): Check correctness of IPA_REF_CHKP >> references and instrumentation thunks. >> * cgraphbuild.c (rebuild_cgraph_edges): Rebuild IPA_REF_CHKP >> reference. >> (cgraph_rebuild_references): Likewise. >> * cgraphunit.c (assemble_thunks_and_aliases): Skip thunks >> calling instrumneted function version. >> * ipa-ref.h (ipa_ref_use): Add IPA_REF_CHKP. >> (ipa_ref): increase size of use field. >> * ipa-ref.c (ipa_ref_use_name): Add element for IPA_REF_CHKP. >> * lto-cgraph.c (lto_output_node): Output instrumentation_clone, >> thunk.add_pointer_bounds_args and orig_decl field. >> (lto_output_ref): Adjust to new ipa_ref::use field size. >> (input_overwrite_node): Read instrumentation_clone field. >> (input_node): Read thunk.add_pointer_bounds_args and orig_decl >> fields. >> (input_ref): Adjust to new ipa_ref::use field size. >> (input_cgraph_1): Compute instrumented_version fields and restore >> IDENTIFIER_TRANSPARENT_ALIAS chains. >> * lto-streamer.h (LTO_minor_version): Change minor version from >> 0 to 1. >> * ipa.c (symtab_remove_unreachable_nodes): Consider instrumented >> clone as address taken if the original one is address taken. >> (cgraph_externally_visible_p): Mark instrumented 'main' as >> externally visible. >> (function_and_variable_visibility): Filter instrumentation >> thunks. >> >> >> diff --git a/gcc/cgraph.c b/gcc/cgraph.c >> index be3661a..6210c68 100644 >> --- a/gcc/cgraph.c >> +++ b/gcc/cgraph.c >> @@ -1828,6 +1828,12 @@ cgraph_remove_node (struct cgraph_node *node) >> } >> cgraph_n_nodes--; >> >> + if (node->instrumented_version) >> + { >> + node->instrumented_version->instrumented_version = NULL; >> + node->instrumented_version = NULL; >> + } >> + >> /* Clear out the node to NULL all pointers and add the node to the free >> list. */ >> memset (node, 0, sizeof (*node)); >> @@ -2070,6 +2076,11 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) >> if (indirect_calls_count) >> fprintf (f, " Has %i outgoing edges for indirect calls.\n", >> indirect_calls_count); >> + >> + if (node->instrumentation_clone) >> + fprintf (f, " Is instrumented version.\n"); >> + else if (node->instrumented_version) >> + fprintf (f, " Has instrumented version.\n"); >> } >> >> >> @@ -2850,7 +2861,9 @@ verify_cgraph_node (struct cgraph_node *node) >> } >> for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, >> i, ref); i++) >> - if (ref->use != IPA_REF_ALIAS) >> + if (ref->use == IPA_REF_CHKP) >> + ; >> + else if (ref->use != IPA_REF_ALIAS) >> { >> error ("Alias has non-alias reference"); >> error_found = true; >> @@ -2868,6 +2881,35 @@ verify_cgraph_node (struct cgraph_node *node) >> error_found = true; >> } >> } >> + >> + /* Check all nodes reference their instrumented versions. */ >> + if (node->analyzed >> + && node->instrumented_version >> + && !node->instrumentation_clone) >> + { >> + bool ref_found = false; >> + int i; >> + struct ipa_ref *ref; >> + >> + for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, >> + i, ref); i++) >> + if (ref->use == IPA_REF_CHKP) >> + { >> + if (ref_found) >> + { >> + error ("Node has more than one chkp reference"); >> + error_found = true; >> + } >> + ref_found = true; >> + } >> + >> + if (!ref_found) >> + { >> + error ("Analyzed node has no reference to instrumented version"); >> + error_found = true; >> + } >> + } >> + >> if (node->analyzed && node->thunk.thunk_p) >> { >> if (!node->callees) >> @@ -2885,6 +2927,12 @@ verify_cgraph_node (struct cgraph_node *node) >> error ("Thunk is not supposed to have body"); >> error_found = true; >> } >> + if (node->thunk.add_pointer_bounds_args >> + && node->callees->callee != node->instrumented_version) >> + { >> + error ("Instrumentation thunk has wrong edge callee"); >> + error_found = true; >> + } >> } >> else if (node->analyzed && gimple_has_body_p (node->decl) >> && !TREE_ASM_WRITTEN (node->decl) >> diff --git a/gcc/cgraph.h b/gcc/cgraph.h >> index a6a51cf..5e702a7 100644 >> --- a/gcc/cgraph.h >> +++ b/gcc/cgraph.h >> @@ -191,6 +191,7 @@ struct GTY(()) cgraph_thunk_info { >> tree alias; >> bool this_adjusting; >> bool virtual_offset_p; >> + bool add_pointer_bounds_args; >> /* Set to true when alias node is thunk. */ >> bool thunk_p; >> }; >> @@ -373,6 +374,13 @@ public: >> struct cgraph_node *prev_sibling_clone; >> struct cgraph_node *clones; >> struct cgraph_node *clone_of; >> + /* If instrumentation_clone is 1 then instrumented_version points >> + to the original function used to make instrumented version. >> + Otherwise points to instrumented version of the function. */ >> + struct cgraph_node *instrumented_version; >> + /* If instrumentation_clone is 1 then orig_decl is the original >> + function declaration. */ >> + tree orig_decl; >> /* For functions with many calls sites it holds map from call expression >> to the edge to speed up cgraph_edge function. */ >> htab_t GTY((param_is (struct cgraph_edge))) call_site_hash; >> @@ -433,6 +441,9 @@ public: >> /* True if this decl calls a COMDAT-local function. This is set up in >> compute_inline_parameters and inline_call. */ >> unsigned calls_comdat_local : 1; >> + /* True when function is clone created for Pointer Bounds Checker >> + instrumentation. */ >> + unsigned instrumentation_clone : 1; >> }; >> >> >> @@ -1412,6 +1423,8 @@ symtab_alias_target (symtab_node *n) >> { >> struct ipa_ref *ref; >> ipa_ref_list_reference_iterate (&n->ref_list, 0, ref); >> + if (ref->use == IPA_REF_CHKP) >> + ipa_ref_list_reference_iterate (&n->ref_list, 1, ref); >> gcc_checking_assert (ref->use == IPA_REF_ALIAS); >> return ref->referred; >> } >> diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c >> index 19961e2..a2b2106 100644 >> --- a/gcc/cgraphbuild.c >> +++ b/gcc/cgraphbuild.c >> @@ -481,6 +481,10 @@ rebuild_cgraph_edges (void) >> record_eh_tables (node, cfun); >> gcc_assert (!node->global.inlined_to); >> >> + if (node->instrumented_version >> + && !node->instrumentation_clone) >> + ipa_record_reference (node, node->instrumented_version, IPA_REF_CHKP, NULL); >> + >> return 0; >> } >> >> @@ -513,6 +517,11 @@ cgraph_rebuild_references (void) >> ipa_record_stmt_references (node, gsi_stmt (gsi)); >> } >> record_eh_tables (node, cfun); >> + >> + >> + if (node->instrumented_version >> + && !node->instrumentation_clone) >> + ipa_record_reference (node, node->instrumented_version, IPA_REF_CHKP, NULL); >> } >> >> namespace { >> diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c >> index 06283fc..ceb4060 100644 >> --- a/gcc/cgraphunit.c >> +++ b/gcc/cgraphunit.c >> @@ -1702,7 +1702,8 @@ assemble_thunks_and_aliases (struct cgraph_node *node) >> struct ipa_ref *ref; >> >> for (e = node->callers; e;) >> - if (e->caller->thunk.thunk_p) >> + if (e->caller->thunk.thunk_p >> + && !e->caller->thunk.add_pointer_bounds_args) >> { >> struct cgraph_node *thunk = e->caller; >> >> diff --git a/gcc/ipa-ref.c b/gcc/ipa-ref.c >> index 6aa41e6..3a055d9 100644 >> --- a/gcc/ipa-ref.c >> +++ b/gcc/ipa-ref.c >> @@ -27,7 +27,7 @@ along with GCC; see the file COPYING3. If not see >> #include "cgraph.h" >> #include "ipa-utils.h" >> >> -static const char *ipa_ref_use_name[] = {"read","write","addr","alias"}; >> +static const char *ipa_ref_use_name[] = {"read","write","addr","alias","chkp"}; >> >> /* Return ipa reference from REFERING_NODE or REFERING_VARPOOL_NODE >> to REFERED_NODE or REFERED_VARPOOL_NODE. USE_TYPE specify type >> diff --git a/gcc/ipa-ref.h b/gcc/ipa-ref.h >> index 4ce5f8d..d0df0bf 100644 >> --- a/gcc/ipa-ref.h >> +++ b/gcc/ipa-ref.h >> @@ -29,7 +29,8 @@ enum GTY(()) ipa_ref_use >> IPA_REF_LOAD, >> IPA_REF_STORE, >> IPA_REF_ADDR, >> - IPA_REF_ALIAS >> + IPA_REF_ALIAS, >> + IPA_REF_CHKP >> }; >> >> /* Record of reference in callgraph or varpool. */ >> @@ -40,7 +41,7 @@ struct GTY(()) ipa_ref >> gimple stmt; >> unsigned int lto_stmt_uid; >> unsigned int referred_index; >> - ENUM_BITFIELD (ipa_ref_use) use:2; >> + ENUM_BITFIELD (ipa_ref_use) use:3; >> unsigned int speculative:1; >> }; >> >> diff --git a/gcc/ipa.c b/gcc/ipa.c >> index 5ab3aed..1d7fa35 100644 >> --- a/gcc/ipa.c >> +++ b/gcc/ipa.c >> @@ -508,6 +508,12 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) >> cgraph_node_remove_callees (node); >> ipa_remove_all_references (&node->ref_list); >> changed = true; >> + if (node->thunk.thunk_p >> + && node->thunk.add_pointer_bounds_args) >> + { >> + node->thunk.thunk_p = false; >> + node->thunk.add_pointer_bounds_args = false; >> + } >> } >> } >> else >> @@ -583,7 +589,10 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) >> if (node->address_taken >> && !node->used_from_other_partition) >> { >> - if (!cgraph_for_node_and_aliases (node, has_addr_references_p, NULL, true)) >> + if (!cgraph_for_node_and_aliases (node, has_addr_references_p, NULL, true) >> + && (!node->instrumentation_clone >> + || !node->instrumented_version >> + || !node->instrumented_version->address_taken)) >> { >> if (file) >> fprintf (file, " %s", node->name ()); >> @@ -814,6 +823,10 @@ cgraph_externally_visible_p (struct cgraph_node *node, >> if (MAIN_NAME_P (DECL_NAME (node->decl))) >> return true; >> >> + if (node->instrumentation_clone >> + && MAIN_NAME_P (DECL_NAME (node->orig_decl))) >> + return true; >> + >> return false; >> } >> >> @@ -1016,6 +1029,7 @@ function_and_variable_visibility (bool whole_program) >> } >> >> if (node->thunk.thunk_p >> + && !node->thunk.add_pointer_bounds_args >> && TREE_PUBLIC (node->decl)) >> { >> struct cgraph_node *decl_node = node; >> diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c >> index 999ce3d..58105f0 100644 >> --- a/gcc/lto-cgraph.c >> +++ b/gcc/lto-cgraph.c >> @@ -526,6 +526,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, >> bp_pack_value (&bp, node->thunk.thunk_p && !boundary_p, 1); >> bp_pack_enum (&bp, ld_plugin_symbol_resolution, >> LDPR_NUM_KNOWN, node->resolution); >> + bp_pack_value (&bp, node->instrumentation_clone, 1); >> streamer_write_bitpack (&bp); >> >> if (node->thunk.thunk_p && !boundary_p) >> @@ -533,11 +534,15 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, >> streamer_write_uhwi_stream >> (ob->main_stream, >> 1 + (node->thunk.this_adjusting != 0) * 2 >> - + (node->thunk.virtual_offset_p != 0) * 4); >> + + (node->thunk.virtual_offset_p != 0) * 4 >> + + (node->thunk.add_pointer_bounds_args != 0) * 8); >> streamer_write_uhwi_stream (ob->main_stream, node->thunk.fixed_offset); >> streamer_write_uhwi_stream (ob->main_stream, node->thunk.virtual_value); >> } >> streamer_write_hwi_stream (ob->main_stream, node->profile_id); >> + >> + if (node->instrumentation_clone) >> + lto_output_fn_decl_index (ob->decl_state, ob->main_stream, node->orig_decl); >> } >> >> /* Output the varpool NODE to OB. >> @@ -613,7 +618,7 @@ lto_output_ref (struct lto_simple_output_block *ob, struct ipa_ref *ref, >> struct cgraph_node *node; >> >> bp = bitpack_create (ob->main_stream); >> - bp_pack_value (&bp, ref->use, 2); >> + bp_pack_value (&bp, ref->use, 3); >> bp_pack_value (&bp, ref->speculative, 1); >> streamer_write_bitpack (&bp); >> nref = lto_symtab_encoder_lookup (encoder, ref->referred); >> @@ -1002,6 +1007,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data, >> node->thunk.thunk_p = bp_unpack_value (bp, 1); >> node->resolution = bp_unpack_enum (bp, ld_plugin_symbol_resolution, >> LDPR_NUM_KNOWN); >> + node->instrumentation_clone = bp_unpack_value (bp, 1); >> gcc_assert (flag_ltrans >> || (!node->in_other_partition >> && !node->used_from_other_partition)); >> @@ -1112,10 +1118,19 @@ input_node (struct lto_file_decl_data *file_data, >> node->thunk.this_adjusting = (type & 2); >> node->thunk.virtual_value = virtual_value; >> node->thunk.virtual_offset_p = (type & 4); >> + node->thunk.add_pointer_bounds_args = (type & 8); >> } >> if (node->alias && !node->analyzed && node->weakref) >> node->alias_target = get_alias_symbol (node->decl); >> node->profile_id = streamer_read_hwi (ib); >> + >> + if (node->instrumentation_clone) >> + { >> + decl_index = streamer_read_uhwi (ib); >> + fn_decl = lto_file_decl_data_get_fn_decl (file_data, decl_index); >> + node->orig_decl = fn_decl; >> + } >> + >> return node; >> } >> >> @@ -1196,7 +1211,7 @@ input_ref (struct lto_input_block *ib, >> struct ipa_ref *ref; >> >> bp = streamer_read_bitpack (ib); >> - use = (enum ipa_ref_use) bp_unpack_value (&bp, 2); >> + use = (enum ipa_ref_use) bp_unpack_value (&bp, 3); >> speculative = (enum ipa_ref_use) bp_unpack_value (&bp, 1); >> node = nodes[streamer_read_hwi (ib)]; >> ref = ipa_record_reference (referring_node, node, use, NULL); >> @@ -1337,6 +1352,22 @@ input_cgraph_1 (struct lto_file_decl_data *file_data, >> cgraph (node)->global.inlined_to = cgraph (nodes[ref]); >> else >> cnode->global.inlined_to = NULL; >> + >> + /* Compute instrumented_version. */ >> + if (cnode->instrumentation_clone) >> + { >> + gcc_assert (cnode->orig_decl); >> + >> + cnode->instrumented_version = cgraph_get_node (cnode->orig_decl); >> + if (cnode->instrumented_version) >> + cnode->instrumented_version->instrumented_version = cnode; >> + >> + /* Restore decl names reference. */ >> + if (IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (cnode->decl)) >> + && !TREE_CHAIN (DECL_ASSEMBLER_NAME (cnode->decl))) >> + TREE_CHAIN (DECL_ASSEMBLER_NAME (cnode->decl)) >> + = DECL_ASSEMBLER_NAME (cnode->orig_decl); >> + } >> } >> >> ref = (int) (intptr_t) node->same_comdat_group; >> diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h >> index 51b1903..62a5fe0 100644 >> --- a/gcc/lto-streamer.h >> +++ b/gcc/lto-streamer.h >> @@ -141,7 +141,7 @@ along with GCC; see the file COPYING3. If not see >> #define LTO_SECTION_NAME_PREFIX ".gnu.lto_" >> >> #define LTO_major_version 3 >> -#define LTO_minor_version 0 >> +#define LTO_minor_version 1 >> >> typedef unsigned char lto_decl_flags_t; >>
On 04/16/14 08:03, Ilya Enkovich wrote: > Hi, > > This patch introduces changes in call graph for Pointer Bounds Checker. > > New fields instrumented_version, instrumentation_clone and orig_decl are added for cgraph_node: > - instrumentation_clone field is 1 for nodes created for instrumented version of functions > - instrumented_version points to instrumented/original node > - orig_decl holds original function declaration for instrumented nodes in case original node is removed > > IPA_REF_CHKP reference type is introduced for nodes to reference instrumented function versions from originals. It is used to have proper reachability analysis. > > When original function bodies are not needed anymore, functions are transformed into thunks having call edge to the instrumented function. Therefore new field appeared in cgraph_thunk_info to mark such thunks. > > Does it look OK? > > Bootstrapped and tested on linux-x86_64. > > Thanks, > Ilya > -- > gcc/ > > 2014-04-16 Ilya Enkovich <ilya.enkovich@intel.com> > > * cgraph.h (cgraph_thunk_info): Add add_pointer_bounds_args > field. > (cgraph_node): Add instrumented_version, orig_decl and > instrumentation_clone fields. > (symtab_alias_target): Allow IPA_REF_CHKP reference. > * cgraph.c (cgraph_remove_node): Fix instrumented_version > of the referenced node if any. > (dump_cgraph_node): Dump instrumentation_clone and > instrumented_version fields. > (verify_cgraph_node): Check correctness of IPA_REF_CHKP > references and instrumentation thunks. > * cgraphbuild.c (rebuild_cgraph_edges): Rebuild IPA_REF_CHKP > reference. > (cgraph_rebuild_references): Likewise. > * cgraphunit.c (assemble_thunks_and_aliases): Skip thunks > calling instrumneted function version. > * ipa-ref.h (ipa_ref_use): Add IPA_REF_CHKP. > (ipa_ref): increase size of use field. > * ipa-ref.c (ipa_ref_use_name): Add element for IPA_REF_CHKP. > * lto-cgraph.c (lto_output_node): Output instrumentation_clone, > thunk.add_pointer_bounds_args and orig_decl field. > (lto_output_ref): Adjust to new ipa_ref::use field size. > (input_overwrite_node): Read instrumentation_clone field. > (input_node): Read thunk.add_pointer_bounds_args and orig_decl > fields. > (input_ref): Adjust to new ipa_ref::use field size. > (input_cgraph_1): Compute instrumented_version fields and restore > IDENTIFIER_TRANSPARENT_ALIAS chains. > * lto-streamer.h (LTO_minor_version): Change minor version from > 0 to 1. > * ipa.c (symtab_remove_unreachable_nodes): Consider instrumented > clone as address taken if the original one is address taken. > (cgraph_externally_visible_p): Mark instrumented 'main' as > externally visible. > (function_and_variable_visibility): Filter instrumentation > thunks. > > > diff --git a/gcc/cgraph.c b/gcc/cgraph.c > index be3661a..6210c68 100644 > --- a/gcc/cgraph.c > +++ b/gcc/cgraph.c > @@ -2850,7 +2861,9 @@ verify_cgraph_node (struct cgraph_node *node) > } > for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, > i, ref); i++) > - if (ref->use != IPA_REF_ALIAS) > + if (ref->use == IPA_REF_CHKP) > + ; > + else if (ref->use != IPA_REF_ALIAS) > { > error ("Alias has non-alias reference"); > error_found = true; Is there any checking you can/should be doing here? And I'm asking because I'm pretty sure there's something you ought to be checking here :-) There's a general desire for key datastructures to sanity check them as much as possible. > + /* If instrumentation_clone is 1 then instrumented_version points > + to the original function used to make instrumented version. > + Otherwise points to instrumented version of the function. */ > + struct cgraph_node *instrumented_version; > + /* If instrumentation_clone is 1 then orig_decl is the original > + function declaration. */ > + tree orig_decl; So I don't see anything which checks these two invariants. Mostly it looks good. I do want to look at it again once the verification stuff is beefed up. Jeff
diff --git a/gcc/cgraph.c b/gcc/cgraph.c index be3661a..6210c68 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -1828,6 +1828,12 @@ cgraph_remove_node (struct cgraph_node *node) } cgraph_n_nodes--; + if (node->instrumented_version) + { + node->instrumented_version->instrumented_version = NULL; + node->instrumented_version = NULL; + } + /* Clear out the node to NULL all pointers and add the node to the free list. */ memset (node, 0, sizeof (*node)); @@ -2070,6 +2076,11 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) if (indirect_calls_count) fprintf (f, " Has %i outgoing edges for indirect calls.\n", indirect_calls_count); + + if (node->instrumentation_clone) + fprintf (f, " Is instrumented version.\n"); + else if (node->instrumented_version) + fprintf (f, " Has instrumented version.\n"); } @@ -2850,7 +2861,9 @@ verify_cgraph_node (struct cgraph_node *node) } for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) - if (ref->use != IPA_REF_ALIAS) + if (ref->use == IPA_REF_CHKP) + ; + else if (ref->use != IPA_REF_ALIAS) { error ("Alias has non-alias reference"); error_found = true; @@ -2868,6 +2881,35 @@ verify_cgraph_node (struct cgraph_node *node) error_found = true; } } + + /* Check all nodes reference their instrumented versions. */ + if (node->analyzed + && node->instrumented_version + && !node->instrumentation_clone) + { + bool ref_found = false; + int i; + struct ipa_ref *ref; + + for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, + i, ref); i++) + if (ref->use == IPA_REF_CHKP) + { + if (ref_found) + { + error ("Node has more than one chkp reference"); + error_found = true; + } + ref_found = true; + } + + if (!ref_found) + { + error ("Analyzed node has no reference to instrumented version"); + error_found = true; + } + } + if (node->analyzed && node->thunk.thunk_p) { if (!node->callees) @@ -2885,6 +2927,12 @@ verify_cgraph_node (struct cgraph_node *node) error ("Thunk is not supposed to have body"); error_found = true; } + if (node->thunk.add_pointer_bounds_args + && node->callees->callee != node->instrumented_version) + { + error ("Instrumentation thunk has wrong edge callee"); + error_found = true; + } } else if (node->analyzed && gimple_has_body_p (node->decl) && !TREE_ASM_WRITTEN (node->decl) diff --git a/gcc/cgraph.h b/gcc/cgraph.h index a6a51cf..5e702a7 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -191,6 +191,7 @@ struct GTY(()) cgraph_thunk_info { tree alias; bool this_adjusting; bool virtual_offset_p; + bool add_pointer_bounds_args; /* Set to true when alias node is thunk. */ bool thunk_p; }; @@ -373,6 +374,13 @@ public: struct cgraph_node *prev_sibling_clone; struct cgraph_node *clones; struct cgraph_node *clone_of; + /* If instrumentation_clone is 1 then instrumented_version points + to the original function used to make instrumented version. + Otherwise points to instrumented version of the function. */ + struct cgraph_node *instrumented_version; + /* If instrumentation_clone is 1 then orig_decl is the original + function declaration. */ + tree orig_decl; /* For functions with many calls sites it holds map from call expression to the edge to speed up cgraph_edge function. */ htab_t GTY((param_is (struct cgraph_edge))) call_site_hash; @@ -433,6 +441,9 @@ public: /* True if this decl calls a COMDAT-local function. This is set up in compute_inline_parameters and inline_call. */ unsigned calls_comdat_local : 1; + /* True when function is clone created for Pointer Bounds Checker + instrumentation. */ + unsigned instrumentation_clone : 1; }; @@ -1412,6 +1423,8 @@ symtab_alias_target (symtab_node *n) { struct ipa_ref *ref; ipa_ref_list_reference_iterate (&n->ref_list, 0, ref); + if (ref->use == IPA_REF_CHKP) + ipa_ref_list_reference_iterate (&n->ref_list, 1, ref); gcc_checking_assert (ref->use == IPA_REF_ALIAS); return ref->referred; } diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c index 19961e2..a2b2106 100644 --- a/gcc/cgraphbuild.c +++ b/gcc/cgraphbuild.c @@ -481,6 +481,10 @@ rebuild_cgraph_edges (void) record_eh_tables (node, cfun); gcc_assert (!node->global.inlined_to); + if (node->instrumented_version + && !node->instrumentation_clone) + ipa_record_reference (node, node->instrumented_version, IPA_REF_CHKP, NULL); + return 0; } @@ -513,6 +517,11 @@ cgraph_rebuild_references (void) ipa_record_stmt_references (node, gsi_stmt (gsi)); } record_eh_tables (node, cfun); + + + if (node->instrumented_version + && !node->instrumentation_clone) + ipa_record_reference (node, node->instrumented_version, IPA_REF_CHKP, NULL); } namespace { diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 06283fc..ceb4060 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -1702,7 +1702,8 @@ assemble_thunks_and_aliases (struct cgraph_node *node) struct ipa_ref *ref; for (e = node->callers; e;) - if (e->caller->thunk.thunk_p) + if (e->caller->thunk.thunk_p + && !e->caller->thunk.add_pointer_bounds_args) { struct cgraph_node *thunk = e->caller; diff --git a/gcc/ipa-ref.c b/gcc/ipa-ref.c index 6aa41e6..3a055d9 100644 --- a/gcc/ipa-ref.c +++ b/gcc/ipa-ref.c @@ -27,7 +27,7 @@ along with GCC; see the file COPYING3. If not see #include "cgraph.h" #include "ipa-utils.h" -static const char *ipa_ref_use_name[] = {"read","write","addr","alias"}; +static const char *ipa_ref_use_name[] = {"read","write","addr","alias","chkp"}; /* Return ipa reference from REFERING_NODE or REFERING_VARPOOL_NODE to REFERED_NODE or REFERED_VARPOOL_NODE. USE_TYPE specify type diff --git a/gcc/ipa-ref.h b/gcc/ipa-ref.h index 4ce5f8d..d0df0bf 100644 --- a/gcc/ipa-ref.h +++ b/gcc/ipa-ref.h @@ -29,7 +29,8 @@ enum GTY(()) ipa_ref_use IPA_REF_LOAD, IPA_REF_STORE, IPA_REF_ADDR, - IPA_REF_ALIAS + IPA_REF_ALIAS, + IPA_REF_CHKP }; /* Record of reference in callgraph or varpool. */ @@ -40,7 +41,7 @@ struct GTY(()) ipa_ref gimple stmt; unsigned int lto_stmt_uid; unsigned int referred_index; - ENUM_BITFIELD (ipa_ref_use) use:2; + ENUM_BITFIELD (ipa_ref_use) use:3; unsigned int speculative:1; }; diff --git a/gcc/ipa.c b/gcc/ipa.c index 5ab3aed..1d7fa35 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -508,6 +508,12 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) cgraph_node_remove_callees (node); ipa_remove_all_references (&node->ref_list); changed = true; + if (node->thunk.thunk_p + && node->thunk.add_pointer_bounds_args) + { + node->thunk.thunk_p = false; + node->thunk.add_pointer_bounds_args = false; + } } } else @@ -583,7 +589,10 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) if (node->address_taken && !node->used_from_other_partition) { - if (!cgraph_for_node_and_aliases (node, has_addr_references_p, NULL, true)) + if (!cgraph_for_node_and_aliases (node, has_addr_references_p, NULL, true) + && (!node->instrumentation_clone + || !node->instrumented_version + || !node->instrumented_version->address_taken)) { if (file) fprintf (file, " %s", node->name ()); @@ -814,6 +823,10 @@ cgraph_externally_visible_p (struct cgraph_node *node, if (MAIN_NAME_P (DECL_NAME (node->decl))) return true; + if (node->instrumentation_clone + && MAIN_NAME_P (DECL_NAME (node->orig_decl))) + return true; + return false; } @@ -1016,6 +1029,7 @@ function_and_variable_visibility (bool whole_program) } if (node->thunk.thunk_p + && !node->thunk.add_pointer_bounds_args && TREE_PUBLIC (node->decl)) { struct cgraph_node *decl_node = node; diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index 999ce3d..58105f0 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -526,6 +526,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, bp_pack_value (&bp, node->thunk.thunk_p && !boundary_p, 1); bp_pack_enum (&bp, ld_plugin_symbol_resolution, LDPR_NUM_KNOWN, node->resolution); + bp_pack_value (&bp, node->instrumentation_clone, 1); streamer_write_bitpack (&bp); if (node->thunk.thunk_p && !boundary_p) @@ -533,11 +534,15 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, streamer_write_uhwi_stream (ob->main_stream, 1 + (node->thunk.this_adjusting != 0) * 2 - + (node->thunk.virtual_offset_p != 0) * 4); + + (node->thunk.virtual_offset_p != 0) * 4 + + (node->thunk.add_pointer_bounds_args != 0) * 8); streamer_write_uhwi_stream (ob->main_stream, node->thunk.fixed_offset); streamer_write_uhwi_stream (ob->main_stream, node->thunk.virtual_value); } streamer_write_hwi_stream (ob->main_stream, node->profile_id); + + if (node->instrumentation_clone) + lto_output_fn_decl_index (ob->decl_state, ob->main_stream, node->orig_decl); } /* Output the varpool NODE to OB. @@ -613,7 +618,7 @@ lto_output_ref (struct lto_simple_output_block *ob, struct ipa_ref *ref, struct cgraph_node *node; bp = bitpack_create (ob->main_stream); - bp_pack_value (&bp, ref->use, 2); + bp_pack_value (&bp, ref->use, 3); bp_pack_value (&bp, ref->speculative, 1); streamer_write_bitpack (&bp); nref = lto_symtab_encoder_lookup (encoder, ref->referred); @@ -1002,6 +1007,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data, node->thunk.thunk_p = bp_unpack_value (bp, 1); node->resolution = bp_unpack_enum (bp, ld_plugin_symbol_resolution, LDPR_NUM_KNOWN); + node->instrumentation_clone = bp_unpack_value (bp, 1); gcc_assert (flag_ltrans || (!node->in_other_partition && !node->used_from_other_partition)); @@ -1112,10 +1118,19 @@ input_node (struct lto_file_decl_data *file_data, node->thunk.this_adjusting = (type & 2); node->thunk.virtual_value = virtual_value; node->thunk.virtual_offset_p = (type & 4); + node->thunk.add_pointer_bounds_args = (type & 8); } if (node->alias && !node->analyzed && node->weakref) node->alias_target = get_alias_symbol (node->decl); node->profile_id = streamer_read_hwi (ib); + + if (node->instrumentation_clone) + { + decl_index = streamer_read_uhwi (ib); + fn_decl = lto_file_decl_data_get_fn_decl (file_data, decl_index); + node->orig_decl = fn_decl; + } + return node; } @@ -1196,7 +1211,7 @@ input_ref (struct lto_input_block *ib, struct ipa_ref *ref; bp = streamer_read_bitpack (ib); - use = (enum ipa_ref_use) bp_unpack_value (&bp, 2); + use = (enum ipa_ref_use) bp_unpack_value (&bp, 3); speculative = (enum ipa_ref_use) bp_unpack_value (&bp, 1); node = nodes[streamer_read_hwi (ib)]; ref = ipa_record_reference (referring_node, node, use, NULL); @@ -1337,6 +1352,22 @@ input_cgraph_1 (struct lto_file_decl_data *file_data, cgraph (node)->global.inlined_to = cgraph (nodes[ref]); else cnode->global.inlined_to = NULL; + + /* Compute instrumented_version. */ + if (cnode->instrumentation_clone) + { + gcc_assert (cnode->orig_decl); + + cnode->instrumented_version = cgraph_get_node (cnode->orig_decl); + if (cnode->instrumented_version) + cnode->instrumented_version->instrumented_version = cnode; + + /* Restore decl names reference. */ + if (IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (cnode->decl)) + && !TREE_CHAIN (DECL_ASSEMBLER_NAME (cnode->decl))) + TREE_CHAIN (DECL_ASSEMBLER_NAME (cnode->decl)) + = DECL_ASSEMBLER_NAME (cnode->orig_decl); + } } ref = (int) (intptr_t) node->same_comdat_group; diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index 51b1903..62a5fe0 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -141,7 +141,7 @@ along with GCC; see the file COPYING3. If not see #define LTO_SECTION_NAME_PREFIX ".gnu.lto_" #define LTO_major_version 3 -#define LTO_minor_version 0 +#define LTO_minor_version 1 typedef unsigned char lto_decl_flags_t;