public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/arsenic/heads/vtable_region)] custom edge info for dynamic calls
@ 2021-07-27 9:47 Ankur saini
0 siblings, 0 replies; only message in thread
From: Ankur saini @ 2021-07-27 9:47 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:78395c1208b688c8dde7b443f66b52133b626118
commit 78395c1208b688c8dde7b443f66b52133b626118
Author: Ankur Saini <arsenic@sourceware.org>
Date: Thu Jul 22 11:23:47 2021 +0530
custom edge info for dynamic calls
Diff:
---
gcc/analyzer/analysis-plan.cc | 2 +-
gcc/analyzer/checker-path.cc | 28 ++++++++++------
gcc/analyzer/checker-path.h | 6 ++++
gcc/analyzer/diagnostic-manager.cc | 19 ++++-------
gcc/analyzer/engine.cc | 68 ++++++++++++++++++++++++++++++++------
gcc/analyzer/exploded-graph.h | 28 ++++++++++++++++
gcc/analyzer/program-point.cc | 4 +--
gcc/analyzer/program-state.h | 18 +++++-----
gcc/analyzer/region-model.cc | 66 ++++++++++++------------------------
gcc/analyzer/region-model.h | 1 +
gcc/analyzer/supergraph.cc | 5 ++-
11 files changed, 153 insertions(+), 92 deletions(-)
diff --git a/gcc/analyzer/analysis-plan.cc b/gcc/analyzer/analysis-plan.cc
index 1c7e4d2cc84..57a6dcb1f6e 100644
--- a/gcc/analyzer/analysis-plan.cc
+++ b/gcc/analyzer/analysis-plan.cc
@@ -110,7 +110,7 @@ analysis_plan::use_summary_p (const cgraph_edge *edge) const
return false;
/* Don't use call summaries if there is no callgraph edge */
- if(!edge || !edge->callee)
+ if (!edge || !edge->callee)
return false;
/* TODO: don't count callsites each time. */
diff --git a/gcc/analyzer/checker-path.cc b/gcc/analyzer/checker-path.cc
index e10c8e2bb7c..b7304e234cc 100644
--- a/gcc/analyzer/checker-path.cc
+++ b/gcc/analyzer/checker-path.cc
@@ -614,7 +614,11 @@ call_event::call_event (const exploded_edge &eedge,
location_t loc, tree fndecl, int depth)
: superedge_event (EK_CALL_EDGE, eedge, loc, fndecl, depth)
{
- gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_CALL);
+ if (eedge.m_sedge)
+ gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_CALL);
+
+ m_src_snode = eedge.m_src->get_supernode ();
+ m_dest_snode = eedge.m_dest->get_supernode ();
}
/* Implementation of diagnostic_event::get_desc vfunc for
@@ -638,8 +642,8 @@ call_event::get_desc (bool can_colorize) const
label_text custom_desc
= m_pending_diagnostic->describe_call_with_state
(evdesc::call_with_state (can_colorize,
- m_sedge->m_src->m_fun->decl,
- m_sedge->m_dest->m_fun->decl,
+ m_src_snode->m_fun->decl,
+ m_dest_snode->m_fun->decl,
var,
m_critical_state));
if (custom_desc.m_buffer)
@@ -648,8 +652,8 @@ call_event::get_desc (bool can_colorize) const
return make_label_text (can_colorize,
"calling %qE from %qE",
- m_sedge->m_dest->m_fun->decl,
- m_sedge->m_src->m_fun->decl);
+ m_dest_snode->m_fun->decl,
+ m_src_snode->m_fun->decl);
}
/* Override of checker_event::is_call_p for calls. */
@@ -668,7 +672,11 @@ return_event::return_event (const exploded_edge &eedge,
location_t loc, tree fndecl, int depth)
: superedge_event (EK_RETURN_EDGE, eedge, loc, fndecl, depth)
{
- gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_RETURN);
+ if (eedge.m_sedge)
+ gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_RETURN);
+
+ m_src_snode = eedge.m_src->get_supernode ();
+ m_dest_snode = eedge.m_dest->get_supernode ();
}
/* Implementation of diagnostic_event::get_desc vfunc for
@@ -694,16 +702,16 @@ return_event::get_desc (bool can_colorize) const
label_text custom_desc
= m_pending_diagnostic->describe_return_of_state
(evdesc::return_of_state (can_colorize,
- m_sedge->m_dest->m_fun->decl,
- m_sedge->m_src->m_fun->decl,
+ m_dest_snode->m_fun->decl,
+ m_src_snode->m_fun->decl,
m_critical_state));
if (custom_desc.m_buffer)
return custom_desc;
}
return make_label_text (can_colorize,
"returning to %qE from %qE",
- m_sedge->m_dest->m_fun->decl,
- m_sedge->m_src->m_fun->decl);
+ m_dest_snode->m_fun->decl,
+ m_src_snode->m_fun->decl);
}
/* Override of checker_event::is_return_p for returns. */
diff --git a/gcc/analyzer/checker-path.h b/gcc/analyzer/checker-path.h
index 1843c4bc7b4..27634c20864 100644
--- a/gcc/analyzer/checker-path.h
+++ b/gcc/analyzer/checker-path.h
@@ -338,6 +338,9 @@ public:
label_text get_desc (bool can_colorize) const FINAL OVERRIDE;
bool is_call_p () const FINAL OVERRIDE;
+
+ const supernode *m_src_snode;
+ const supernode *m_dest_snode;
};
/* A concrete event subclass for an interprocedural return. */
@@ -351,6 +354,9 @@ public:
label_text get_desc (bool can_colorize) const FINAL OVERRIDE;
bool is_return_p () const FINAL OVERRIDE;
+
+ const supernode *m_src_snode;
+ const supernode *m_dest_snode;
};
/* A concrete event subclass for the start of a consolidated run of CFG
diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc
index 631fef6ad78..d7d9fa4c3d8 100644
--- a/gcc/analyzer/diagnostic-manager.cc
+++ b/gcc/analyzer/diagnostic-manager.cc
@@ -2060,18 +2060,17 @@ diagnostic_manager::prune_for_sm_diagnostic (checker_path *path,
case EK_CALL_EDGE:
{
call_event *event = (call_event *)base_event;
- const callgraph_superedge& cg_superedge
- = event->get_callgraph_superedge ();
const region_model *callee_model
= event->m_eedge.m_dest->get_state ().m_region_model;
+ const region_model *caller_model
+ = event->m_eedge.m_src->get_state ().m_region_model;
tree callee_var = callee_model->get_representative_tree (sval);
/* We could just use caller_model->get_representative_tree (sval);
to get the caller_var, but for now use
map_expr_from_callee_to_caller so as to only record critical
state for parms and the like. */
callsite_expr expr;
- tree caller_var
- = cg_superedge.map_expr_from_callee_to_caller (callee_var, &expr);
+ tree caller_var = caller_model->get_representative_tree (sval);
if (caller_var)
{
if (get_logger ())
@@ -2093,15 +2092,11 @@ diagnostic_manager::prune_for_sm_diagnostic (checker_path *path,
if (sval)
{
return_event *event = (return_event *)base_event;
- const callgraph_superedge& cg_superedge
- = event->get_callgraph_superedge ();
- const region_model *caller_model
- = event->m_eedge.m_dest->get_state ().m_region_model;
- tree caller_var = caller_model->get_representative_tree (sval);
callsite_expr expr;
- tree callee_var
- = cg_superedge.map_expr_from_caller_to_callee (caller_var,
- &expr);
+
+ const region_model *callee_model
+ = event->m_eedge.m_src->get_state ().m_region_model;
+ tree callee_var = callee_model->get_representative_tree (sval);
if (callee_var)
{
if (get_logger ())
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index c0d55bbcaba..d6de8094dde 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -1627,6 +1627,50 @@ exploded_node::dump_succs_and_preds (FILE *outf) const
}
}
+/* class dynamic_call_info_t : public exploded_edge::custom_info_t. */
+
+/* Implementation of exploded_edge::custom_info_t::update_model vfunc
+ for dynamic_call_info_t.
+
+ Update state for the dynamically discorverd calls */
+
+void
+dynamic_call_info_t::update_model (region_model *model,
+ const exploded_edge &eedge)
+{
+ const program_state &dest_state = eedge.m_dest->get_state ();
+ *model = *dest_state.m_region_model;
+}
+
+/* Implementation of exploded_edge::custom_info_t::add_events_to_path vfunc
+ for dynamic_call_info_t. */
+
+void
+dynamic_call_info_t::add_events_to_path (checker_path *emission_path,
+ const exploded_edge &eedge)
+{
+ const exploded_node *src_node = eedge.m_src;
+ const program_point &src_point = src_node->get_point ();
+ const int src_stack_depth = src_point.get_stack_depth ();
+ const exploded_node *dest_node = eedge.m_dest;
+ const program_point &dest_point = dest_node->get_point ();
+ const int dest_stack_depth = dest_point.get_stack_depth ();
+
+ if (m_is_returning_call)
+ emission_path->add_event (new return_event (eedge, (m_dynamic_call
+ ? m_dynamic_call->location
+ : UNKNOWN_LOCATION),
+ dest_point.get_fndecl (),
+ dest_stack_depth));
+ else
+ emission_path->add_event (new call_event (eedge, (m_dynamic_call
+ ? m_dynamic_call->location
+ : UNKNOWN_LOCATION),
+ src_point.get_fndecl (),
+ src_stack_depth));
+
+}
+
/* class rewind_info_t : public exploded_edge::custom_info_t. */
/* Implementation of exploded_edge::custom_info_t::update_model vfunc
@@ -3221,8 +3265,8 @@ exploded_graph::process_node (exploded_node *node)
/* Check if now the analyzer know about the call via
function pointer or not. */
- if (succ->m_kind == SUPEREDGE_INTRAPROCEDURAL_CALL &&
- !(succ->get_any_callgraph_edge()))
+ if (succ->m_kind == SUPEREDGE_INTRAPROCEDURAL_CALL
+ && !(succ->get_any_callgraph_edge ()))
{
const program_point *this_point = &node->get_point();
const program_state *this_state = &node->get_state ();
@@ -3241,9 +3285,9 @@ exploded_graph::process_node (exploded_node *node)
function *fun = DECL_STRUCT_FUNCTION(fn_decl);
if(fun)
{
- const supergraph *sg = &(this->get_supergraph());
- supernode * sn_entry = sg->get_node_for_function_entry (fun);
- supernode * sn_exit = sg->get_node_for_function_exit (fun);
+ const supergraph &sg = this->get_supergraph();
+ supernode * sn_entry = sg.get_node_for_function_entry (fun);
+ supernode * sn_exit = sg.get_node_for_function_exit (fun);
program_point new_point
= program_point::before_supernode (sn_entry,
@@ -3255,13 +3299,15 @@ exploded_graph::process_node (exploded_node *node)
next_state.push_call(*this, node, call, &uncertainty);
+ // TODO: add some logging here regarding dynamic call
+
if (next_state.m_valid)
{
exploded_node *enode = get_or_create_node (new_point,
next_state,
node);
if (enode)
- add_edge (node,enode, NULL);
+ add_edge (node,enode, NULL, new dynamic_call_info_t (call));
}
}
}
@@ -3284,10 +3330,10 @@ exploded_graph::process_node (exploded_node *node)
/* Return from the calls which doesn't have a return superedge.
Such case occurs when GCC's middle end didn't knew which function to
call but analyzer did */
- if((is_an_exit_block && !found_a_superedge) &&
- (!point.get_call_string().empty_p()))
+ if((is_an_exit_block && !found_a_superedge)
+ && (!point.get_call_string ().empty_p ()))
{
- const call_string cs = point.get_call_string();
+ const call_string cs = point.get_call_string ();
program_point next_point
= program_point::before_supernode (cs.get_caller_node (),
NULL,
@@ -3304,12 +3350,12 @@ exploded_graph::process_node (exploded_node *node)
if (next_state.m_valid)
{
- next_point.pop_from_call_stack();
+ next_point.pop_from_call_stack ();
exploded_node *enode = get_or_create_node (next_point,
next_state,
node);
if (enode)
- add_edge (node,enode, NULL);
+ add_edge (node, enode, NULL, new dynamic_call_info_t (call, true));
}
}
}
diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h
index 8f48d8a286c..cf4a6bfea1e 100644
--- a/gcc/analyzer/exploded-graph.h
+++ b/gcc/analyzer/exploded-graph.h
@@ -362,6 +362,34 @@ private:
DISABLE_COPY_AND_ASSIGN (exploded_edge);
};
+/* Extra data for an exploded_edge that represents a dynamic call info ( calls
+ that doesn't have a superedge representing the call ). */
+
+class dynamic_call_info_t : public exploded_edge::custom_info_t
+{
+public:
+ dynamic_call_info_t (const gcall *dynamic_call,
+ const bool is_returning_call = false)
+ : m_dynamic_call (dynamic_call),
+ m_is_returning_call (is_returning_call)
+ {}
+
+ void print (pretty_printer *pp) FINAL OVERRIDE
+ {
+ pp_string (pp, "dynamic_call");
+ }
+
+ void update_model (region_model *model,
+ const exploded_edge &eedge) FINAL OVERRIDE;
+
+ void add_events_to_path (checker_path *emission_path,
+ const exploded_edge &eedge) FINAL OVERRIDE;
+private:
+ const gcall *m_dynamic_call;
+ const bool m_is_returning_call;
+};
+
+
/* Extra data for an exploded_edge that represents a rewind from a
longjmp to a setjmp (or from a siglongjmp to a sigsetjmp). */
diff --git a/gcc/analyzer/program-point.cc b/gcc/analyzer/program-point.cc
index f3b332774a2..ad9bc17313b 100644
--- a/gcc/analyzer/program-point.cc
+++ b/gcc/analyzer/program-point.cc
@@ -449,8 +449,8 @@ program_point::on_edge (exploded_graph &eg,
return false;
}
const call_string::element_t top_of_stack = m_call_string.pop ();
- call_string::element_t current_call_string_element (succ->m_src,
- succ->m_dest);
+ call_string::element_t current_call_string_element (succ->m_dest,
+ succ->m_src);
if (top_of_stack != current_call_string_element)
{
if (logger)
diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h
index e91381a6d7d..658dbb69075 100644
--- a/gcc/analyzer/program-state.h
+++ b/gcc/analyzer/program-state.h
@@ -217,14 +217,16 @@ public:
void push_frame (const extrinsic_state &ext_state, function *fun);
function * get_current_function () const;
- void push_call(exploded_graph &eg,
- exploded_node *enode,
- const gcall *call_stmt,
- uncertainty_t *uncertainty);
- void returning_call(exploded_graph &eg,
- exploded_node *enode,
- const gcall *call_stmt,
- uncertainty_t *uncertainty);
+
+ void push_call (exploded_graph &eg,
+ exploded_node *enode,
+ const gcall *call_stmt,
+ uncertainty_t *uncertainty);
+
+ void returning_call (exploded_graph &eg,
+ exploded_node *enode,
+ const gcall *call_stmt,
+ uncertainty_t *uncertainty);
bool on_edge (exploded_graph &eg,
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 1a6f4e1abc4..5dfe7a0f487 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -3139,28 +3139,6 @@ region_model::maybe_update_for_edge (const superedge &edge,
caller's frame. */
void
-region_model::update_for_call_superedge (const call_superedge &call_edge,
- region_model_context *ctxt)
-{
- /* Build a vec of argument svalues, using the current top
- frame for resolving tree expressions. */
- const gcall *call_stmt = call_edge.get_call_stmt ();
- auto_vec<const svalue *> arg_svals (gimple_call_num_args (call_stmt));
-
- for (unsigned i = 0; i < gimple_call_num_args (call_stmt); i++)
- {
- tree arg = gimple_call_arg (call_stmt, i);
- arg_svals.quick_push (get_rvalue (arg, ctxt));
- }
-
- push_frame (call_edge.get_callee_function (), &arg_svals, ctxt);
-}
-
-/* Push a new frame_region on to the stack region.
- works in similar manner of that of region_model::update_for_call_superedge()
- but it get the call info from CALL_STMT instead from a suerpedge and
- is availabe publicically */
-void
region_model::update_for_gcall (const gcall *call_stmt,
region_model_context *ctxt)
{
@@ -3183,30 +3161,7 @@ region_model::update_for_gcall (const gcall *call_stmt,
/* Pop the top-most frame_region from the stack, and copy the return
region's values (if any) into the region for the lvalue of the LHS of
the call (if any). */
-void
-region_model::update_for_return_superedge (const return_superedge &return_edge,
- region_model_context *ctxt)
-{
- /* Get the region for the result of the call, within the caller frame. */
- const region *result_dst_reg = NULL;
- const gcall *call_stmt = return_edge.get_call_stmt ();
- tree lhs = gimple_call_lhs (call_stmt);
- if (lhs)
- {
- /* Normally we access the top-level frame, which is:
- path_var (expr, get_stack_depth () - 1)
- whereas here we need the caller frame, hence "- 2" here. */
- gcc_assert (get_stack_depth () >= 2);
- result_dst_reg = get_lvalue (path_var (lhs, get_stack_depth () - 2),
- ctxt);
- }
- pop_frame (result_dst_reg, NULL, ctxt);
-}
-
-/* do exatly what region_model::update_for_return_superedge() do
- but get the call info from CALL_STMT instead from a suerpedge and
- is availabe publicically */
void
region_model::update_for_return_gcall (const gcall *call_stmt,
region_model_context *ctxt)
@@ -3227,6 +3182,27 @@ region_model::update_for_return_gcall (const gcall *call_stmt,
pop_frame (result_dst_reg, NULL, ctxt);
}
+/* Extract calling infromation from the superedge and update the model for the
+ call */
+
+void
+region_model::update_for_call_superedge (const call_superedge &call_edge,
+ region_model_context *ctxt)
+{
+ const gcall *call_stmt = call_edge.get_call_stmt ();
+ update_for_gcall (call_stmt,ctxt);
+}
+
+/* Extract calling infromation from the return superedge and update the model
+ for the returning call */
+
+void
+region_model::update_for_return_superedge (const return_superedge &return_edge,
+ region_model_context *ctxt)
+{
+ const gcall *call_stmt = return_edge.get_call_stmt ();
+ update_for_return_gcall (call_stmt, ctxt);
+}
/* Update this region_model with a summary of the effect of calling
and returning from CG_SEDGE.
diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h
index 05acb8240b1..a15bc9e2f6d 100644
--- a/gcc/analyzer/region-model.h
+++ b/gcc/analyzer/region-model.h
@@ -591,6 +591,7 @@ class region_model
void update_for_gcall (const gcall *call_stmt,
region_model_context *ctxt);
+
void update_for_return_gcall (const gcall *call_stmt,
region_model_context *ctxt);
diff --git a/gcc/analyzer/supergraph.cc b/gcc/analyzer/supergraph.cc
index ace9e7b128a..598965dd7fc 100644
--- a/gcc/analyzer/supergraph.cc
+++ b/gcc/analyzer/supergraph.cc
@@ -189,11 +189,10 @@ supergraph::supergraph (logger *logger)
NULL);
m_cgraph_edge_to_caller_next_node.put (edge, node_for_stmts);
}
- else
+ else
{
// maybe call is via a function pointer
- gcall *call = dyn_cast<gcall *> (stmt);
- if (call)
+ if (gcall *call = dyn_cast<gcall *> (stmt))
{
cgraph_edge *edge
= cgraph_node::get (fun->decl)->get_edge (stmt);
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-07-27 9:47 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-27 9:47 [gcc(refs/users/arsenic/heads/vtable_region)] custom edge info for dynamic calls Ankur saini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).