From: Justin Seyster Date: Fri, 2 Jul 2010 23:24:44 +0000 (-0400) Subject: Finshed function call parameter interface. X-Git-Tag: release-v1.0~93 X-Git-Url: https://git.fsl.cs.stonybrook.edu/?a=commitdiff_plain;h=5653cd32da51c490a72629a016c68eee284da163;p=interaspect.git Finshed function call parameter interface. 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. --- diff --git a/src/aop-dynval.h b/src/aop-dynval.h index d1a0fd3..3c32266 100644 --- a/src/aop-dynval.h +++ b/src/aop-dynval.h @@ -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 diff --git a/src/aop-pc-fun-call.c b/src/aop-pc-fun-call.c index f0bb683..f0e4a98 100644 --- a/src/aop-pc-fun-call.c +++ b/src/aop-pc-fun-call.c @@ -39,57 +39,18 @@ #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; } diff --git a/src/aop-pointcut.h b/src/aop-pointcut.h index 4bb941e..015c910 100644 --- a/src/aop-pointcut.h +++ b/src/aop-pointcut.h @@ -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; }; diff --git a/src/aop.h b/src/aop.h index 5560ea2..fb1b31d 100644 --- 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);