Added proper support for filtering calls by return type.
authorJustin Seyster <jseyster@cs.sunysb.edu>
Wed, 30 Jun 2010 23:22:56 +0000 (19:22 -0400)
committerJustin Seyster <jseyster@cs.sunysb.edu>
Wed, 30 Jun 2010 23:25:48 +0000 (19:25 -0400)
src/aop-pc-fun-call.c
src/aop-pointcut.h
src/aop.h

index 36cae9f72ab7bd99497eb73238013c2b832658e0..922f3a9e4c176ef2faa682dbf06cf6b413c1db95 100644 (file)
@@ -30,6 +30,7 @@
 #include <ggc.h>
 #include <basic-block.h>
 #include <gimple.h>
+#include <toplev.h>
 #include <diagnostic.h>
 #include <string.h>
 
@@ -58,14 +59,66 @@ param_desc_matches (struct aop_param_desc *param_list, gimple func_stmt)
   return true;
 }
 
+/* Return true if a call statement matches the pointcut's criteria for
+   name, return type, and argument types. */
+static bool
+call_matches (struct aop_pointcut *pc, gimple call_stmt)
+{
+  tree func;
+  tree func_type_pointer;
+  tree func_type;
+
+  aop_assert (pc->kind == ATP_CALL);
+  aop_assert (gimple_code (call_stmt) == GIMPLE_CALL);
+
+  func = gimple_call_fn (call_stmt);
+
+  /* Check function name only if the user filtered by name. */
+  if (pc->pc_call.function_name != NULL)
+    {
+      if (TREE_CODE (func) == ADDR_EXPR)
+       {
+         /* Get the function's name and compare it to the filter-by
+            name. */
+         tree func_decl;
+         const char *func_name;
+
+         func_decl = TREE_OPERAND (func, 0);
+         func_name = IDENTIFIER_POINTER (DECL_NAME (func_decl));
+
+         if (strcmp (pc->pc_call.function_name, func_name) != 0)
+           return false;
+       }
+      else
+       {
+         /* This is a call to a function pointer, so it can't match a
+            name. */
+         return false;
+       }
+    }
+
+  /* Get the function type.  The func tree should have a pointer type,
+     pointing to the actual function type. */
+  func_type_pointer = TREE_TYPE (func);
+  aop_assert (TREE_CODE (func_type_pointer) == POINTER_TYPE);
+  func_type = TREE_TYPE (func_type_pointer);
+  aop_assert (TREE_CODE (func_type) == FUNCTION_TYPE);
+
+  /* Check return type (if the user filtered by return type). */
+  if (pc->pc_call.return_type != NULL
+      && !does_type_match (TREE_TYPE (func_type), pc->pc_call.return_type))
+    return false;
+
+  /* All checks were OK. */
+  return true;
+}
+
 static void
 op_join_on_function_call (struct aop_pointcut *pc, join_callback cb,
                          void *callback_param)
 {
   basic_block my_basic_block;
   gimple_stmt_iterator gsi;
-  tree func_decl;
-  tree func;
 
   aop_assert (pc->kind == ATP_CALL);
 
@@ -82,25 +135,9 @@ op_join_on_function_call (struct aop_pointcut *pc, join_callback cb,
 
          if (gimple_code (stmt) == GIMPLE_CALL)
            {
-             const char *func_name;
-
-             func = gimple_call_fn (stmt);
-           
-             if (TREE_CODE (func) != ADDR_EXPR)
-               {
-                 /* This is a call to a function pointer.  Don't
-                    worry about it. */
-                 continue;
-               }
-           
-             func_decl = TREE_OPERAND (func, 0);
-             func_name = IDENTIFIER_POINTER (DECL_NAME (func_decl));
-   
-             if (strcmp (pc->pc_call.function_name, func_name) == 0) 
-               {
-                 if (!param_desc_matches (pc->pc_call.param_list_head, stmt))
-                   continue;
-                                       
+             if (call_matches (pc, stmt)
+                 && param_desc_matches (pc->pc_call.param_list_head, stmt))
+               {                       
                  struct aop_joinpoint jp;
                  jp.pc = pc;
                  jp.gsi = &gsi;
@@ -109,7 +146,7 @@ op_join_on_function_call (struct aop_pointcut *pc, join_callback cb,
                }
            }
        }
-    } 
+    }
 }
 
 struct aop_pointcut *
@@ -124,18 +161,21 @@ aop_match_function_call ()
   pc->insert_before = op_default_insert_before;
   pc->prepare_for_weave = op_default_prepare_for_weave;
 
-  /* Initialize the list to NULL */
+  pc->pc_call.function_name = NULL;
+  pc->pc_call.return_type = NULL;
   pc->pc_call.param_list_head = NULL;
   return pc;
 }
 
-void aop_filter_function_call_pointcut (struct aop_pointcut *pc_function_call,
-                                       const char *advice_function_call)
+void
+aop_filter_function_call_pointcut (struct aop_pointcut *pc_function_call,
+                                  const char *advice_function_call)
 {
   pc_function_call->pc_call.function_name = advice_function_call;
 }
 
-void aop_add_param_descriptor (struct aop_pointcut *pc,int param_id)
+void
+aop_add_param_descriptor (struct aop_pointcut *pc, int param_id)
 {
    struct aop_param_desc *iter = NULL; 
    struct aop_param_desc *desc = ggc_alloc (sizeof (struct aop_param_desc)); 
@@ -154,8 +194,9 @@ void aop_add_param_descriptor (struct aop_pointcut *pc,int param_id)
    }   
 }
 
-void aop_filter_function_call_pointcut_by_param_index(struct aop_pointcut *pc,
-                                                     int param_id)
+void
+aop_filter_function_call_pointcut_by_param_index(struct aop_pointcut *pc,
+                                                int param_id)
 {
   aop_add_param_descriptor (pc, param_id);
 }
@@ -166,9 +207,6 @@ op_get_return_value (struct aop_dynval *dv)
   gimple stmt;
   tree return_value;
 
-  /* If this function isn't on the right side of an assignment, we
-     need to _put it_ on the right hand side of an assignment so we
-     can grab its return value.  */
   struct aop_joinpoint *jp = dv->jp;
   stmt = gsi_stmt (*(jp->gsi));
   
@@ -187,13 +225,31 @@ op_get_return_value (struct aop_dynval *dv)
   return return_value;
 }
 
+void
+aop_filter_call_pc_by_return_type (struct aop_pointcut *pc,
+                                  const struct aop_type *type)
+{
+  pc->pc_call.return_type = type;
+}
+
 struct aop_dynval *
 aop_capture_return_value (struct aop_joinpoint *jp)
 {
+  struct aop_pointcut *pc;
   struct aop_dynval *dv;
+
+  pc = jp->pc;
+  if (pc->kind != ATP_CALL)
+    fatal_error ("(InterAspect) Attempt to capture return value from an"
+                " unsupported join point.");
+
+  if (pc->pc_call.return_type == NULL)
+    fatal_error ("(InterAspect) Attempt to capture return value without"
+                " specifying type.");
+
   dv = ggc_alloc (sizeof (struct aop_dynval));
   dv->kind = ADV_FUN_RETVAL;
-  dv->type = aop_t_all_unsigned ();
+  dv->type = pc->pc_call.return_type;
   dv->jp = jp;
   dv->get_dynval = op_get_return_value;
   return dv;  
@@ -225,4 +281,3 @@ aop_capture_param (struct aop_joinpoint *jp, int param_index)
   dv->dynval_call.param_id = param_index;
   return dv;
 }
-
index f5014efbf04550d12e6978ef5f47af80bb26d6ee..4bb941ea4c714bb4ff25bef770255a9815f91441 100644 (file)
@@ -52,6 +52,7 @@ struct aop_pc_entry {
 
 struct aop_pc_fun_call {
   const char *function_name;
+  const struct aop_type *return_type;
   struct aop_param_desc *param_list_head; 
 };
 
index 62692c12a6df3fb4f339a1830772f7b613dc3372..505ce542f8748c6275e35701a20c855762697771 100644 (file)
--- a/src/aop.h
+++ b/src/aop.h
@@ -101,9 +101,11 @@ extern void aop_filter_entry_by_name(struct aop_pointcut *pc_function_entry,
 
 extern struct aop_pointcut *aop_match_function_call ();
 
-extern void aop_filter_function_call_pointcut(
+extern void aop_filter_function_call_pointcut (
   struct aop_pointcut *pc_function_call, const char *advice_function_call);
-extern void aop_filter_function_call_pointcut_by_param_index(
+extern void aop_filter_call_pc_by_return_type (struct aop_pointcut *pc,
+                                              const struct aop_type *type);
+extern void aop_filter_function_call_pointcut_by_param_index (
   struct aop_pointcut *pc, int param_index);
 
 extern struct aop_dynval *aop_capture_return_value (struct aop_joinpoint *jp);