Cleaned up function entry pointcut.
authorJustin Seyster <jseyster@cs.sunysb.edu>
Fri, 18 Jun 2010 02:10:49 +0000 (22:10 -0400)
committerJustin Seyster <jseyster@cs.sunysb.edu>
Fri, 18 Jun 2010 02:10:49 +0000 (22:10 -0400)
Fixed bug because of uninitialized function_name field in the
pointcut.

Added a prepare function that guards against the case of adding to a
function that begins with a label.

Renamed the filter by name function.

src/aop-pc-entry.c
src/aop.h

index b24bd02848f6e6a49d39e5812d9cd2b0100e7eed..6129435318fdff86f30053b5095eb2558dd2392a 100644 (file)
@@ -41,9 +41,12 @@ static void
 op_join_on_function_entry (struct aop_pointcut *pc, join_callback cb,
                           void *callback_param)
 {
-  basic_block bb;
+  struct aop_joinpoint jp;
+  gimple_stmt_iterator gsi;
+
   aop_assert (pc->kind == ATP_ENTRY);
 
+  /* Filter this pointcut by function name if necessary. */
   if(pc->pc_entry.function_name != NULL)
     {
       const char *func_name =
@@ -52,20 +55,56 @@ op_join_on_function_entry (struct aop_pointcut *pc, join_callback cb,
        return;
     }
 
-  FOR_EACH_BB(bb)
-    {
-      gimple_stmt_iterator gsi;
+  /* Note that the gimple iterator gets initialized by
+     op_prepare_entry when it is time to insert advice.  (We poison it
+     just to make sure that initialization is getting called.)*/
+  memset (&gsi, 0xfa, sizeof (gimple_stmt_iterator));
+
+  jp.pc = pc;
+  jp.gsi = &gsi;
+  jp.is_prepared = false;
+  cb (&jp, callback_param);
+}
 
-      for (gsi = gsi_start_bb (bb) ; !gsi_end_p (gsi) ; gsi_next (&gsi))
+/* There is no GIMPLE statement that is suitable as an anchor point
+   for inserting advice at the beginning of a function.
+
+   The first GIMPLE statement in the function is no good because it
+   may be a label statement at the beginning of a basic block.
+   Inserting a statement before a label would cause a label in the
+   middle of a basic block, which is a no-no.
+
+   We use the gsi_insert_on_edge_immediate() function to add a NOP
+   statement that is definitely legal.  It serves as an anchor point
+   for inserting before and after advice! */
+static void
+op_prepare_entry (struct aop_joinpoint *jp)
+{
+  gimple nop;
+  basic_block bb;
+  edge in_edge;
+
+  aop_assert (jp->pc->kind = ATP_ENTRY);
+
+  nop = gimple_build_nop ();
+
+  in_edge = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FUNCTION(cfun));
+  gsi_insert_on_edge_immediate (in_edge, nop);
+
+  /* Find an iterator pointing to the nop. */
+  FOR_EACH_BB (bb)
+    {
+      for (*jp->gsi = gsi_start_bb (bb);
+          !gsi_end_p (*jp->gsi);
+          gsi_next (jp->gsi))
        {
-         struct aop_joinpoint jp;
-         jp.pc = pc;
-         jp.gsi = &gsi;
-         jp.is_prepared = false;
-         cb (&jp, callback_param);
-         return;
+         if (gsi_stmt (*jp->gsi) == nop)
+           return;  /* Found! */
        }
     }
+
+  /* We failed to found the statement we just inserted! */
+  aop_assert (0);
 }
 
 struct aop_pointcut *
@@ -76,12 +115,15 @@ aop_match_function_entry ()
   pc->kind = ATP_ENTRY;
   pc->join_on = op_join_on_function_entry;
   pc->insert_before = op_default_insert_before;
-  pc->prepare_for_weave = op_default_prepare_for_weave;
+  pc->insert_after = op_default_insert_after;
+  pc->prepare_for_weave = op_prepare_entry;
+
+  pc->pc_entry.function_name = NULL;
   return pc;
 }
 
-void aop_filter_function_entry_pointcut(struct aop_pointcut *pc_function_entry,
-                                       const char *advice_function_entry)
+void aop_filter_entry_by_name(struct aop_pointcut *pc_function_entry,
+                             const char *advice_function_entry)
 {
   pc_function_entry->pc_entry.function_name = advice_function_entry;
 }
index 8bc0b09463f19992180cc494902e80a6cb8cf8d5..62692c12a6df3fb4f339a1830772f7b613dc3372 100644 (file)
--- a/src/aop.h
+++ b/src/aop.h
@@ -96,8 +96,8 @@ extern const char *aop_capture_function_name (struct aop_joinpoint *jp);
 extern struct aop_pointcut *aop_match_function_entry ();
 extern struct aop_pointcut *aop_match_function_exit ();
 
-extern void aop_filter_function_entry_pointcut(
-  struct aop_pointcut *pc_function_entry, const char *advice_function_entry);
+extern void aop_filter_entry_by_name(struct aop_pointcut *pc_function_entry,
+                                    const char *advice_function_entry);
 
 extern struct aop_pointcut *aop_match_function_call ();