From: Justin Seyster Date: Wed, 30 Jun 2010 23:22:56 +0000 (-0400) Subject: Added proper support for filtering calls by return type. X-Git-Tag: release-v1.0~96 X-Git-Url: https://git.fsl.cs.stonybrook.edu/?a=commitdiff_plain;h=5e40d80b0fab7fad4e6548db96dcc4eac9723ed7;p=interaspect.git Added proper support for filtering calls by return type. --- diff --git a/src/aop-pc-fun-call.c b/src/aop-pc-fun-call.c index 36cae9f..922f3a9 100644 --- a/src/aop-pc-fun-call.c +++ b/src/aop-pc-fun-call.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -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; } - diff --git a/src/aop-pointcut.h b/src/aop-pointcut.h index f5014ef..4bb941e 100644 --- a/src/aop-pointcut.h +++ b/src/aop-pointcut.h @@ -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; }; diff --git a/src/aop.h b/src/aop.h index 62692c1..505ce54 100644 --- 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);