public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/arsenic/heads/polymorphic_call)] custom edge info for dynamic calls
@ 2021-07-27  9:03 Ankur saini
  0 siblings, 0 replies; only message in thread
From: Ankur saini @ 2021-07-27  9:03 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:94a679ef7b661b48a3a9a38e5d2f0129e8b1d149

commit 94a679ef7b661b48a3a9a38e5d2f0129e8b1d149
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-state.h       | 18 +++++-----
 gcc/analyzer/region-model.cc       | 66 ++++++++++++------------------------
 gcc/analyzer/region-model.h        |  1 +
 gcc/analyzer/supergraph.cc         |  5 ++-
 10 files changed, 151 insertions(+), 90 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 ef3df324365..87f396e7682 100644
--- a/gcc/analyzer/diagnostic-manager.cc
+++ b/gcc/analyzer/diagnostic-manager.cc
@@ -2093,18 +2093,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 ())
@@ -2126,15 +2125,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-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 ca6b04fb24c..fc97408f448 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -3147,28 +3147,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)
 {
@@ -3191,30 +3169,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)
@@ -3235,6 +3190,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 5c74b4fa85b..b4e8a8db8f2 100644
--- a/gcc/analyzer/region-model.h
+++ b/gcc/analyzer/region-model.h
@@ -597,6 +597,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 b1f6176e44b..a679ee3cacd 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:03 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:03 [gcc(refs/users/arsenic/heads/polymorphic_call)] 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).