public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/arsenic/heads/polymorphic_call)] analyzer: detect and analyzer vfunc calls
@ 2021-08-01  9:21 Ankur saini
  0 siblings, 0 replies; only message in thread
From: Ankur saini @ 2021-08-01  9:21 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:450989a9458e3d0087b01a2bb04b7667fb60afb5

commit 450989a9458e3d0087b01a2bb04b7667fb60afb5
Author: Ankur Saini <arsenic@sourceware.org>
Date:   Thu Jul 29 17:20:10 2021 +0530

    analyzer: detect and analyzer vfunc calls

Diff:
---
 gcc/analyzer/engine.cc        | 61 ++++++++++++++++++++++++++++++++++++++-----
 gcc/analyzer/program-state.cc |  5 ++--
 gcc/analyzer/program-state.h  |  3 ++-
 gcc/analyzer/region-model.cc  | 11 +++++---
 gcc/analyzer/region-model.h   |  3 ++-
 5 files changed, 69 insertions(+), 14 deletions(-)

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 29209030b5b..f4cf0864008 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -65,6 +65,7 @@ along with GCC; see the file COPYING3.  If not see
 #include <zlib.h>
 #include "plugin.h"
 #include "target.h"
+#include "ipa-utils.h"
 
 /* For an overview, see gcc/doc/analyzer.texi.  */
 
@@ -1242,6 +1243,17 @@ exploded_node::on_stmt (exploded_graph &eg,
 	unknown_side_effects = false;
     }
 
+  /* If the statmement is a polymorphic call then assume 
+     there are no side effects.  */
+  gimple *call_stmt = const_cast<gimple *>(stmt);
+  if (gcall *call = dyn_cast<gcall *> (call_stmt))
+  {
+    function *fun = this->get_function();
+    cgraph_edge *e = cgraph_node::get (fun->decl)->get_edge (call);
+    if ((e && e->indirect_info) && (e->indirect_info->polymorphic))
+        unknown_side_effects = false;
+  }
+
   on_stmt_post (stmt, state, unknown_side_effects, &ctxt);
 
   return on_stmt_flags ();
@@ -3035,12 +3047,11 @@ void
 exploded_graph::create_dynamic_call (const gcall *call,
                                      tree fn_decl,
                                      exploded_node *node,
-                                     program_state &next_state,
+                                     program_state next_state,
                                      program_point &next_point,
                                      uncertainty_t *uncertainty)
 {
   const program_point *this_point = &node->get_point ();
-  // assert for fn_decl ?
   function *fun = DECL_STRUCT_FUNCTION (fn_decl);
   if (fun)
     {
@@ -3055,7 +3066,7 @@ exploded_graph::create_dynamic_call (const gcall *call,
 
       new_point.push_to_call_stack (sn_exit,
   				    next_point.get_supernode());
-      next_state.push_call (*this, node, call, uncertainty);
+      next_state.push_call (*this, node, call, uncertainty, fn_decl);
 
       // TODO: add some logging here regarding dynamic call
       
@@ -3327,9 +3338,47 @@ exploded_graph::process_node (exploded_node *node)
                 region_model *model = state.m_region_model;
 
                 /* Call is possibly happening via a function pointer.  */
-                if (tree fn_decl = model->get_fndecl_for_call(call,&ctxt))
-                  create_dynamic_call (call, fn_decl, node, next_state,
-                                       next_point, &uncertainty);
+                if (tree fn_decl = model->get_fndecl_for_call (call,&ctxt))
+                  create_dynamic_call (call,
+                  		       fn_decl,
+                  		       node,
+                  		       next_state,
+                                       next_point,
+                                       &uncertainty);
+                else
+                  {
+                    /* Call is possibly a polymorphic call.
+
+                       In such case, use devirtisation tools to find 
+                       possible callees of this function call and let the 
+                       analyzer specluate them all.  */
+		    function *fun = node->get_function ();
+                    gcall *stmt  = const_cast<gcall *>(call);
+                    cgraph_edge *e
+                      = cgraph_node::get (fun->decl)->get_edge (stmt);
+                    if (e->indirect_info->polymorphic)
+                      {
+			void *cache_token;
+			bool final;
+			vec <cgraph_node *> targets
+			  = possible_polymorphic_call_targets (e,
+							       &final,
+							       &cache_token,
+							       true);
+	       		for (cgraph_node *x : targets)
+	       		  {
+	       		    if (logger)
+	          		logger->log ("found call to : %s\n",
+		               		     x->dump_name());
+	       		    create_dynamic_call (stmt,
+						 x->decl,
+						 node,
+						 next_state,
+						 next_point,
+						 &uncertainty);
+	       		  }
+                      }
+                  }
               }
 
 	    if (!node->on_edge (*this, succ, &next_point, &next_state,
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index eb05994f0ef..b1c1d67bb8b 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -1042,7 +1042,8 @@ void
 program_state::push_call (exploded_graph &eg,
       			  exploded_node *enode,
       			  const gcall *call_stmt,
-      			  uncertainty_t *uncertainty)
+      			  uncertainty_t *uncertainty,
+      			  tree fn_decl)
 {
   /* Update state.  */
   const program_point &point = enode->get_point ();
@@ -1053,7 +1054,7 @@ program_state::push_call (exploded_graph &eg,
           			  this,
           			  uncertainty,
           			  last_stmt);
-  m_region_model->update_for_gcall (call_stmt, &ctxt);
+  m_region_model->update_for_gcall(call_stmt, &ctxt, fn_decl);
 }
 
 /* Update this program_state to reflect a return from function
diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h
index 658dbb69075..f4bd4cbcf49 100644
--- a/gcc/analyzer/program-state.h
+++ b/gcc/analyzer/program-state.h
@@ -221,7 +221,8 @@ public:
   void push_call (exploded_graph &eg,
       		  exploded_node *enode,
       		  const gcall *call_stmt,
-      		  uncertainty_t *uncertainty);
+      		  uncertainty_t *uncertainty,
+      		  tree fn_decl = NULL);
 
   void returning_call (exploded_graph &eg,
       		       exploded_node *enode,
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 1e86d1f3bf8..935a8c6431a 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -3140,7 +3140,8 @@ region_model::maybe_update_for_edge (const superedge &edge,
 
 void
 region_model::update_for_gcall (const gcall *call_stmt,
-				region_model_context *ctxt)
+				region_model_context *ctxt,
+				tree fn_decl)
 {
   /* Build a vec of argument svalues, using the current top
      frame for resolving tree expressions.  */
@@ -3151,9 +3152,11 @@ region_model::update_for_gcall (const gcall *call_stmt,
       tree arg = gimple_call_arg (call_stmt, i);
       arg_svals.quick_push (get_rvalue (arg, ctxt));
     }
-
-  /* Get the function * from the call.  */
-  tree fn_decl = get_fndecl_for_call (call_stmt,ctxt);
+  
+  /* Get the fn_decl from the call if not provided as argument.  */
+  if (!fn_decl)
+    fn_decl = get_fndecl_for_call (call_stmt,ctxt);
+ 
   function *fun = DECL_STRUCT_FUNCTION (fn_decl);
   push_frame (fun, &arg_svals, ctxt);
 }
diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h
index a15bc9e2f6d..f06788771dc 100644
--- a/gcc/analyzer/region-model.h
+++ b/gcc/analyzer/region-model.h
@@ -590,7 +590,8 @@ class region_model
 			      rejected_constraint **out);
 
   void update_for_gcall (const gcall *call_stmt,
-			 region_model_context *ctxt);
+			 region_model_context *ctxt,
+			 tree fn_decl = NULL);
   
   void update_for_return_gcall (const gcall *call_stmt,
 				region_model_context *ctxt);


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-08-01  9:21 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-01  9:21 [gcc(refs/users/arsenic/heads/polymorphic_call)] analyzer: detect and analyzer vfunc 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).