Finshed function call parameter interface.
authorJustin Seyster <jseyster@cs.sunysb.edu>
Fri, 2 Jul 2010 23:24:44 +0000 (19:24 -0400)
committerJustin Seyster <jseyster@cs.sunysb.edu>
Fri, 2 Jul 2010 23:24:44 +0000 (19:24 -0400)
Added aop_filter_call_pc_by_param function to replace a handful of
temporary API functions.

Added aop_capture_param_by_type for capturing without filtering.

Replaced unnecessary get_return_value function with an equivalent
function already provided by GCC.

src/aop-dynval.h
src/aop-pc-fun-call.c
src/aop-pointcut.h
src/aop.h

index d1a0fd3c45a2d34c3fd3a8418e903b6c47fa210e..3c32266121f70fd565d7a8cd06e0406658844eb3 100644 (file)
@@ -29,7 +29,7 @@ enum aop_dvkind {
 };
 
 struct aop_dynval_fun_call {
-  int param_id;
+  int param_index;
 };
 
 /* An aop-dynval represents a dynamic value in the target program that
index f0bb6831452060b6421e4077cd9a863f5d83963d..f0e4a983fff105384efbf92edb3c2696829ad273 100644 (file)
 #include "aop-type.h"
 #include "aop-dynval.h"
 
-/* Given a GIMPLE_CALL statement, return the FUNCTION_TYPE tree node
-   that represents the function prototype. */
+/* Given a GIMPLE_CALL statement, return the type of the nth parameter
+   passed if there is an nth parameter or NULL if there is no nth
+   parameter. */
 static tree
-get_function_prototype (gimple call_stmt)
-{
-  tree func;
-  tree func_type_pointer;
-  tree func_type;
-
-  aop_assert (gimple_code (call_stmt) == GIMPLE_CALL);
-
-  func = gimple_call_fn (call_stmt);
-
-  /* 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);
-
-  return func_type;
-}
-
-/* Given a GIMPLE_CALL statement, return the type node for the
-   function's return type. */
-static tree
-get_return_type (gimple call_stmt)
+get_param_type (gimple call_stmt, int n)
 {
   aop_assert (gimple_code (call_stmt) == GIMPLE_CALL);
 
-  return TREE_TYPE (get_function_prototype (call_stmt));
-}
-
-/* Returns true if func_decl matches the arguments described in
-   param_list by type. */
-static bool
-param_desc_matches (struct aop_param_desc *param_list, gimple func_stmt)
-{
-  int num_args = gimple_call_num_args (func_stmt);
-
-  while (param_list != NULL)
-    {
-      /* The param_list wants to match an argument that isn't
-        there. */
-      if (param_list->param_id >= num_args)
-       return false;
-
-      param_list = param_list->next;
-    }
-
-  return true;
+  if (n < gimple_call_num_args (call_stmt))
+    return TREE_TYPE (gimple_call_arg (call_stmt, n));
+  else
+    return NULL;
 }
 
 /* Return true if a call statement matches the pointcut's criteria for
@@ -99,6 +60,7 @@ call_matches (struct aop_pointcut *pc, gimple call_stmt)
 {
   tree func;
   tree return_type;
+  struct aop_param_desc *param;
 
   aop_assert (pc->kind == ATP_CALL);
   aop_assert (gimple_code (call_stmt) == GIMPLE_CALL);
@@ -129,8 +91,18 @@ call_matches (struct aop_pointcut *pc, gimple call_stmt)
        }
     }
 
+  /* Check parameter types. */
+  for (param = pc->pc_call.param_list_head ; param != NULL ; param = param->next)
+    {
+      tree param_type;
+
+      if ((param_type = get_param_type (call_stmt, param->param_index)) == NULL
+         || !does_type_match (param_type, param->type))
+       return false;
+    }
+
   /* Check return type (if the user filtered by return type). */
-  return_type = get_return_type (call_stmt);
+  return_type = gimple_call_return_type (call_stmt);
   if (pc->pc_call.return_type != NULL
       && !does_type_match (return_type, pc->pc_call.return_type))
     return false;
@@ -161,8 +133,7 @@ op_join_on_function_call (struct aop_pointcut *pc, join_callback cb,
 
          if (gimple_code (stmt) == GIMPLE_CALL)
            {
-             if (call_matches (pc, stmt)
-                 && param_desc_matches (pc->pc_call.param_list_head, stmt))
+             if (call_matches (pc, stmt))
                {                       
                  struct aop_joinpoint jp;
                  jp.pc = pc;
@@ -215,31 +186,52 @@ aop_filter_call_pc_by_name (struct aop_pointcut *pc_function_call,
   pc_function_call->pc_call.function_name = name;
 }
 
+/**
+ * Filter a function call pointcut to only include calls with a
+ * parameter that matches a specified type.  This filter removes join
+ * points when parameter n does not match type or when there is no
+ * parameter n.
+ *
+ * Filters on the same parameter do not stack on top of each other.
+ * If multiple parameter filters with the same n are applied a
+ * pointcut, only the last one will have any effect.
+ *
+ * Note that you must filter a parameter by its type in order to
+ * capture it with aop_capture_param().
+ * \param pc The function call pointcut to filter.  Function call
+ * pointcuts are created with aop_match_function_call().
+ * \param n The index of the parameter to filter on.  Parameters are
+ * indexed from zero.
+ * \param The parameter type to filter by.
+ */
 void
-aop_add_param_descriptor (struct aop_pointcut *pc, int param_id)
+aop_filter_call_pc_by_param (struct aop_pointcut *pc, int n,
+                            const struct aop_type *type)
 {
-   struct aop_param_desc *iter = NULL; 
-   struct aop_param_desc *desc = ggc_alloc (sizeof (struct aop_param_desc)); 
-   desc->param_id = param_id;
-   desc->next = NULL;
-   if(pc->pc_call.param_list_head == NULL ) {
-               
-     pc->pc_call.param_list_head = desc;
-   }
-   else {
-     iter =  pc->pc_call.param_list_head;
-     while( iter->next != NULL ) {
-       iter = iter->next;      
-     }
-     iter->next = desc;        
-   }   
-}
+  struct aop_param_desc *param = NULL;
+  struct aop_param_desc *iter;
 
-void
-aop_filter_function_call_pointcut_by_param_index(struct aop_pointcut *pc,
-                                                int param_id)
-{
-  aop_add_param_descriptor (pc, param_id);
+  /* Is there already a filter for this parameter? */
+  for (iter = pc->pc_call.param_list_head ; iter != NULL ; iter = iter->next)
+    {
+      if (iter->param_index == n)
+       {
+         param = iter;
+         break;
+       }
+    }
+
+  /* No? Then create one and add it to the list. */
+  if (param == NULL)
+    {
+      param = ggc_alloc (sizeof (struct aop_param_desc));
+
+      param->next = pc->pc_call.param_list_head;
+      pc->pc_call.param_list_head = param;
+    }
+
+  param->param_index = n;
+  param->type = type;
 }
 
 static tree
@@ -341,7 +333,7 @@ aop_capture_return_value_by_type (struct aop_joinpoint *jp,
                 " unsupported join point.");
 
   /* Does this join point match the specified type? */
-  return_type = get_return_type (jp->stmt);
+  return_type = gimple_call_return_type (jp->stmt);
   if (!does_type_match (return_type, type))
     return NULL;
 
@@ -359,23 +351,102 @@ op_get_param (struct aop_dynval *dv)
   gimple stmt;
   tree param;
   struct aop_joinpoint *jp = dv->jp;
+
   aop_assert (dv->kind == ADV_FUN_PARAM);
   aop_assert (jp->pc->kind == ATP_CALL);
-  stmt = gsi_stmt (*(jp->gsi));
 
-  param = stabilize_reference (gimple_call_arg (stmt, dv->dynval_call.param_id));
+  stmt = jp->stmt;
+  aop_assert (gimple_code (stmt) == GIMPLE_CALL);
+
+  param = gimple_call_arg (stmt, dv->dynval_call.param_index);
+  param = stabilize_reference (param);
   return param;
 }
 
+/**
+ * Get a dynval representing parameter n passed to a function call.
+ * Note that you must use aop_filter_call_pc_by_param() to filter a
+ * pointcut by parameter type for any parameter you wish to capture
+ * with this function.
+ * \param jp A function call join point.  Function call join points
+ * are obtained by joining on an aop_match_function_call() pointcut.
+ * \param n The index of the parameter to capture.  Parameters are
+ * indexed from zero.
+ * \return A dynval with its type determined by
+ * aop_filter_call_pc_by_param().
+ */
 struct aop_dynval *
-aop_capture_param (struct aop_joinpoint *jp, int param_index)
+aop_capture_param (struct aop_joinpoint *jp, int n)
 {
+  struct aop_pointcut *pc;
   struct aop_dynval *dv;
+  struct aop_param_desc *param;
+
+  pc = jp->pc;
+  if (pc->kind != ATP_CALL)
+    fatal_error ("(InterAspect) Attempt to capture return value from an"
+                " unsupported join point.");
+
+  /* Search for an aop_param_desc for this parameter, so that we know
+     its type. */
+  for (param = pc->pc_call.param_list_head; param != NULL; param = param->next)
+    if (param->param_index == n)
+      break;  /* Found it. */
+
+  /* If we don't find the appropriate aop_param_desc, param will be NULL. */
+  if (param == NULL)
+    fatal_error ("(InterAspect) Attempt to capture parameter without specifying"
+                " type.");
+
   dv = ggc_alloc (sizeof (struct aop_dynval));
   dv->kind = ADV_FUN_PARAM;
-  dv->type = aop_t_all_unsigned ();
+  dv->type = param->type;
+  dv->jp = jp;
+  dv->get_dynval = op_get_param;
+  dv->dynval_call.param_index = n;
+  return dv;
+}
+
+/**
+ * Get a dynval representing parameter n passed to a function call if
+ * there is a parameter n and it matches the specified type.  This
+ * function makes it possible to capture a parameter even if yuo have
+ * not filtered on its type with aop_filter_call_pc_by_param().
+ * However, it returns NULL if there is no parameter n or if parameter
+ * n does not match the specified type.
+ * \param jp A function call join point.  Function call join points
+ * are obtained by joining on an aop_match_function_call() pointcut.
+ * \param n The index of the parameter to capture.  Parameters are
+ * indexed from zero.
+ * \type This function verifies that the captured parameter matches
+ * the specified type.
+ * \return A dynval with its type determined by the specified type or
+ * NULL if there is no matching parameter n.
+ */
+struct aop_dynval *
+aop_capture_param_by_type (struct aop_joinpoint *jp, int n,
+                          const struct aop_type *type)
+{
+  struct aop_pointcut *pc;
+  struct aop_dynval *dv;
+  tree param_type;
+
+  pc = jp->pc;
+  if (pc->kind != ATP_CALL)
+    fatal_error ("(InterAspect) Attempt to capture return value from an"
+                " unsupported join point.");
+
+  /* Check that there is a nth parameter and that it matches the
+     type. */
+  if ((param_type = get_param_type (jp->stmt, n)) == NULL
+      || !does_type_match (param_type, type))
+    return NULL;
+
+  dv = ggc_alloc (sizeof (struct aop_dynval));
+  dv->kind = ADV_FUN_PARAM;
+  dv->type = type;
   dv->jp = jp;
   dv->get_dynval = op_get_param;
-  dv->dynval_call.param_id = param_index;
+  dv->dynval_call.param_index = n;
   return dv;
 }
index 4bb941ea4c714bb4ff25bef770255a9815f91441..015c9102ae73b3fbb3a562c83de52ac06f35640f 100644 (file)
@@ -33,7 +33,9 @@ enum aop_pckind {
 /* An aop_param_desc describes a single function parameter, including
    its type. */
 struct aop_param_desc {
-  int param_id;
+  int param_index;
+  const struct aop_type *type;
+
   struct aop_param_desc *next;
 };
 
index 5560ea278d24475eb2301c360a50f54231c880dc..fb1b31dedec4ee30dd4727ce1b4bef89a187fc99 100644 (file)
--- a/src/aop.h
+++ b/src/aop.h
@@ -103,6 +103,8 @@ extern struct aop_pointcut *aop_match_function_call ();
 
 extern void aop_filter_call_pc_by_name (struct aop_pointcut *pc_function_call,
                                        const char *advice_function_call);
+extern void aop_filter_call_pc_by_param (struct aop_pointcut *pc, int n,
+                                        const struct aop_type *type);
 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 (
@@ -113,6 +115,8 @@ extern struct aop_dynval *aop_capture_return_value_by_type (
   struct aop_joinpoint *jp, const struct aop_type *type);
 extern struct aop_dynval *aop_capture_param (struct aop_joinpoint *jp,
                                             int param_index);
+extern struct aop_dynval *aop_capture_param_by_type (
+  struct aop_joinpoint *jp, int n, const struct aop_type *type);
 
 extern struct aop_pointcut *aop_match_assignment_by_type (
   const struct aop_type *type);