#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
{
tree func;
tree return_type;
+ struct aop_param_desc *param;
aop_assert (pc->kind == ATP_CALL);
aop_assert (gimple_code (call_stmt) == GIMPLE_CALL);
}
}
+ /* 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;
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;
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
" 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;
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;
}