#include "aop-type.h"
#include "aop-dynval.h"
-/* Returns true if func_decl matches the arguments described in
- param_list by type. */
+ /**
+ * \defgroup call_pc Function Call Pointcut Functions
+ * \{
+ */
+
+/* Given a GIMPLE_CALL statement, return the name of the called
+ function, or NULL if the function is not named. */
+static const char *
+get_function_name (gimple call_stmt)
+{
+ tree func;
+
+ aop_assert (gimple_code (call_stmt) == GIMPLE_CALL);
+
+ func = gimple_call_fn (call_stmt);
+
+ if (TREE_CODE (func) == ADDR_EXPR)
+ {
+ tree func_decl;
+ const char *func_name;
+
+ func_decl = TREE_OPERAND (func, 0);
+ func_name = IDENTIFIER_POINTER (DECL_NAME (func_decl));
+
+ return func_name;
+ }
+ else
+ {
+ /* This is a call to a function pointer, so it has no name. */
+ return NULL;
+ }
+}
+
+/* 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_param_type (gimple call_stmt, int n)
+{
+ aop_assert (gimple_code (call_stmt) == GIMPLE_CALL);
+
+ 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
+ name, return type, and argument types. */
static bool
-param_desc_matches (struct aop_param_desc *param_list, gimple func_stmt)
+call_matches (struct aop_pointcut *pc, gimple call_stmt)
{
- int num_args = gimple_call_num_args (func_stmt);
+ tree return_type;
+ struct aop_param_desc *param;
- while (param_list != NULL)
+ aop_assert (pc->kind == ATP_CALL);
+ aop_assert (gimple_code (call_stmt) == GIMPLE_CALL);
+
+ /* Check function name only if the user filtered by name. */
+ if (pc->pc_call.function_name != NULL)
{
- /* The param_list wants to match an argument that isn't
- there. */
- if (param_list->param_id >= num_args)
+ const char *func_name;
+
+ /* Note that get_function_name returns NULL if the call is to a
+ function pointer. We consider function pointer calls to
+ never match a name. */
+ if ((func_name = get_function_name (call_stmt)) == NULL
+ || strcmp (pc->pc_call.function_name, func_name) != 0)
return false;
+ }
+
+ /* Check parameter types. */
+ for (param = pc->pc_call.param_list_head ; param != NULL ; param = param->next)
+ {
+ tree param_type;
- param_list = param_list->next;
+ 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 = 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;
+
+ /* All checks were OK. */
return true;
}
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 parameter 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 = 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 parameter 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 = aop_t_all_unsigned ();
+ 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;
}
+
+ /* Close Doxygen defgroup block. */
+ /**
+ * /}
+ */