From 2ca8118b22c2b98230a3d62e25c6b38f36297f63 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 7 Mar 2019 11:30:46 -0500
Subject: [PATCH 078/161] FIXME: break out engine::expand_call_summary from
 engine::expand_path

---
 gcc/analyzer/engine.cc | 165 +++++++++++++++++++++++++++++++++++--------------
 1 file changed, 120 insertions(+), 45 deletions(-)

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 3632552..63cbc27 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -494,18 +494,27 @@ public:
 class call_summary : public checker_event
 {
 public:
-  call_summary (location_t loc, tree fndecl, int depth,
-	      const char *desc)
-  : checker_event (EK_CALL_SUMMARY, loc, fndecl, depth, desc)
+  call_summary (const supernode *caller_node,
+		cgraph_edge *edge, int depth,
+		const char *desc)
+  : checker_event (EK_CALL_SUMMARY,
+		   edge->call_stmt->location,
+		   caller_node->m_fun->decl,
+		   depth, desc),
+    m_caller_node (caller_node),
+    m_edge (edge)
   {
   }
 
   checker_event *clone () const FINAL OVERRIDE
   {
-    return new call_summary (m_loc, m_fndecl, m_depth, m_desc);
+    return new call_summary (m_caller_node, m_edge, m_depth, m_desc);
   }
 
   // FIXME
+
+  const supernode *m_caller_node;
+  cgraph_edge *m_edge;
 };
 
 /* FIXME: a repeat of the warning message at the end of the path.  */
@@ -764,7 +773,11 @@ public:
 		     const backtrace &b, const path_state &ps);
 
   void emit_candidate_diagnostics ();
-  void expand_path (checker_path *path, tree var, state_machine::state_t state);
+
+  checker_path *expand_call_summary (const call_summary *summary_event,
+				     tree var, state_machine::state_t state);
+  checker_path *expand_path (const checker_path &path,
+			     tree var, state_machine::state_t state);
   void prune_path (checker_path *path, tree var, state_machine::state_t state);
   void maybe_emit (const candidate_diagnostic &cd);
 
@@ -1840,8 +1853,7 @@ engine::follow_call (sm_instance sm_inst, backtrace b, path_state ps,
 
     backtrace new_b (b);
     checker_event *event
-      = new call_summary (edge->call_stmt->location,
-			  caller_node->m_fun->decl,
+      = new call_summary (caller_node, edge,
 			  0,/*int depth,*/
 			  "FIXME: call summary (using cache)");
     new_b.m_path.add_event (event);
@@ -2048,49 +2060,89 @@ engine::emit_candidate_diagnostics ()
     maybe_emit (*cd);
 }
 
+checker_path *
+engine::expand_call_summary (const call_summary *summary_event,
+			     tree var, state_machine::state_t state)
+{
+  JIT_LOG_FUNC (get_logger ());
+  if (get_logger ())
+    {
+      log ("var: %s", expr_to_string (var).c_str ());
+      log ("state: %s", m_sm.get_state_name (state));
+    }
+
+  const supernode *callee_node
+    = m_sg.get_node_for_function_entry (summary_event->m_edge->callee->get_fun ());
+  const supernode *caller_node
+    = summary_event->m_caller_node;
+
+  checker_path *result = new checker_path ();
+
+  // TODO:
+  result->add_event (new debug_event (summary_event->m_loc,
+				      summary_event->m_fndecl,
+				      summary_event->m_depth,
+				      print ("calling %qE from %qE",
+					     callee_node->m_fun->decl,
+					     caller_node->m_fun->decl)));
+
+  // TODO: body of function
+
+  result->add_event (new debug_event (callee_node->get_start_location (),
+				      callee_node->m_fun->decl,
+				      summary_event->m_depth + 1,
+				      print ("within %qE",
+					     callee_node->m_fun->decl)));
+
+
+  result->add_event (new debug_event (summary_event->m_loc, // FIXME
+				      callee_node->m_fun->decl,
+				      summary_event->m_depth + 1,
+				      print ("returning to %qE from %qE",
+					     caller_node->m_fun->decl,
+					     callee_node->m_fun->decl)));
+  return result;
+}
+
 /* FIXME.  */
+// Clone IN_PATH
 
-void
-engine::expand_path (checker_path *path, tree var, state_machine::state_t state)
+checker_path *
+engine::expand_path (const checker_path &in_path,
+		     tree var, state_machine::state_t state)
 {
+  checker_path *result = new checker_path ();
+
   // FIXME:
   // expand call summaries (recursively?)
-  int idx = 0;
-  while (idx < path->m_events.length ())
+  for (unsigned idx = 0; idx < in_path.m_events.length (); idx++)
     {
-      checker_event *base_event = path->m_events[idx];
-      if (base_event->m_kind == EK_CALL_SUMMARY)
+      const checker_event *base_event = in_path.m_events[idx];
+      if (base_event->m_kind != EK_CALL_SUMMARY)
 	{
-	  call_summary *summary_event = (call_summary *)base_event;
-
-	  /* TODO: are we interested in a state change within this function?
-	     If not, we can simply eliminate it.
-	     If we are interested, we want to find a path (ideally feasible)
-	     within it that makes the state change happen.  We can probably
-	     figure that out from the suffix summaries.  */
-
-	  /* Build path representing the inside of the function.  */
-	  checker_path child_path;
-	  child_path.add_event (new debug_event (summary_event->m_loc,
-						 summary_event->m_fndecl,
-						 summary_event->m_depth,
-						 "calling"));
-	  child_path.add_event (new debug_event (summary_event->m_loc,
-						 summary_event->m_fndecl,
-						 summary_event->m_depth,
-						 "returning"));
-
-	  /* Replace the summary with a clone of the events on the child_path.  */
-	  path->delete_event (idx);
-#if 1
-	  for (int j = 0; j < child_path.m_events.length (); j++)
-	    path->add_event_at (child_path.m_events[j]->clone (), idx + j);
-	  idx += child_path.m_events.length ();
-#endif
+	  result->add_event (base_event->clone ());
+	  continue;
 	}
-      else
-	idx++;
+
+      const call_summary *summary_event = (call_summary *)base_event;
+
+      /* TODO: are we interested in a state change within this function?
+	 If not, we can simply eliminate it.
+	 If we are interested, we want to find a path (ideally feasible)
+	 within it that makes the state change happen.  We can probably
+	 figure that out from the suffix summaries.  */
+
+      /* Build path representing the inside of the function.  */
+      checker_path *child_path
+	= expand_call_summary (summary_event, var, state);
+      for (unsigned j = 0; j < child_path->m_events.length (); j++)
+	result->add_event (child_path->m_events[j]->clone ());
+      delete child_path;
+      // FIXME: lots of copying/allocation here;
+      // get it working first before optimizing
     }
+
+  return result;
 }
 
 /* FIXME.  */
@@ -2098,6 +2150,16 @@ engine::expand_path (checker_path *path, tree var, state_machine::state_t state)
 void
 engine::prune_path (checker_path *path, tree var, state_machine::state_t state)
 {
+  JIT_LOG_FUNC (get_logger ());
+  if (get_logger ())
+    {
+      log ("path: %s", path->to_str ().c_str ());
+      for (int i = 0; i < path->m_events.length (); i++)
+	{
+	  log ("path[%i]: %s", i, path->m_events[i]->to_str ().c_str ());
+	}
+    }
+
   // TODO
   /* TODO: go backwards, skipping state change events that aren't var
      but update the pertinent var when state-copying occurs.  */
@@ -2206,8 +2268,8 @@ engine::maybe_emit (const candidate_diagnostic &cd)
   checker_path path (cd.m_path);
 #endif
 
-  expand_path (&path, cd.m_var, cd.m_state);
-  prune_path (&path, cd.m_var, cd.m_state);
+  checker_path *expanded_path = expand_path (path, cd.m_var, cd.m_state);
+  prune_path (expanded_path, cd.m_var, cd.m_state);
 
   char *msg = print ("here (%qE is in state %qs)", cd.m_var,
 		     m_sm.get_state_name (cd.m_state));
@@ -2216,16 +2278,29 @@ engine::maybe_emit (const candidate_diagnostic &cd)
    = new warning_event (cd.m_stmt->location,
 			cd.m_node->m_fun->decl, path.m_stack_depth,
 			msg);
-  path.add_event (end_of_path);
+  expanded_path->add_event (end_of_path);
   // FIXME: ideally would show the full message here, too?
 
-  rich_loc.set_path (&path);
+
+  if (get_logger ())
+    {
+      log ("path for emission: %s", expanded_path->to_str ().c_str ());
+      for (int i = 0; i < expanded_path->m_events.length (); i++)
+	{
+	  log ("path[%i]: %s", i,
+	       expanded_path->m_events[i]->to_str ().c_str ());
+	}
+    }
+
+  rich_loc.set_path (expanded_path);
 
   /* Push/pop cfun to ensure we get "In function " announcements
      from the diagnostics subsystem.  */
   push_cfun (cd.m_node->m_fun);
   cd.m_pd->emit (&rich_loc);
   pop_cfun ();
+
+  delete expanded_path;
 }
 
 /* FIXME.  */
-- 
1.8.5.3

