From: Justin Seyster Date: Thu, 21 Oct 2010 02:53:58 +0000 (-0400) Subject: Added filtering and capturing on return value for exit join points. X-Git-Tag: release-v1.0~25 X-Git-Url: https://git.fsl.cs.stonybrook.edu/?a=commitdiff_plain;h=129e07d9d718a3c97845703ac06b0397f7c8cb09;p=interaspect.git Added filtering and capturing on return value for exit join points. --- diff --git a/src/aop-dynval.h b/src/aop-dynval.h index 1a3008e..0504ae7 100644 --- a/src/aop-dynval.h +++ b/src/aop-dynval.h @@ -34,6 +34,7 @@ enum aop_dvkind { ADV_LHS_ADDR, ADV_FUN_PARAM, ADV_FUN_RETVAL, + ADV_EXIT_RETVAL, ADV_ASSIGN_VAL, }; diff --git a/src/aop-pc-exit.c b/src/aop-pc-exit.c index 434d62f..cc78f02 100644 --- a/src/aop-pc-exit.c +++ b/src/aop-pc-exit.c @@ -40,11 +40,13 @@ #include #include #include +#include #include #include #include "aop.h" #include "aop-duplicate.h" +#include "aop-dynval.h" #include "aop-pointcut.h" #include "aop-type.h" @@ -80,13 +82,35 @@ join_on_bb_function_exit (basic_block bb, struct aop_pointcut *pc, } } +/* Return true if the current function's return type matches the + specified type. */ +static bool +return_type_matches (const struct aop_type *type) +{ + tree cfun_type; + tree cfun_return_type; + + cfun_type = TREE_TYPE (current_function_decl); + + aop_assert (cfun_type != NULL && TREE_CODE (cfun_type) == FUNCTION_TYPE); + cfun_return_type = TREE_TYPE (cfun_type); + + return does_type_match (cfun_return_type, type); +} + static void op_join_on_function_exit (struct aop_pointcut *pc, join_callback cb, void *callback_param) { basic_block bb; + const struct aop_type *return_type_filter; aop_assert (pc->kind == ATP_EXIT); + + /* Filter by return type? */ + return_type_filter = pc->pc_exit.return_type; + if (return_type_filter != NULL && !return_type_matches(return_type_filter)) + return; /* Treat as an empty pointcut. */ FOR_EACH_BB(bb) { @@ -100,10 +124,16 @@ op_join_on_copy_function_exit (struct aop_pointcut *pc, int copy, { unsigned int pair_index; bb_pair *pair; + const struct aop_type *return_type_filter; aop_assert (pc->kind == ATP_EXIT); aop_assert (is_current_func_duplicated ()); + /* Filter by return type? */ + return_type_filter = pc->pc_exit.return_type; + if (return_type_filter != NULL && !return_type_matches(return_type_filter)) + return; /* Treat as an empty pointcut. */ + FOR_EACH_BB_PAIR (bb_pairs, pair_index, pair) { basic_block bb = (copy == 0) ? pair->old : pair->new; @@ -150,9 +180,87 @@ aop_match_function_exit () pc->join_on_copy = op_join_on_copy_function_exit; pc->prepare_for_weave = op_prepare_exit; + pc->pc_exit.return_type = NULL; + return pc; } +/** + * Filter a function exit pointcut by the function's return type. + * This is an all-or-nothing filter: because all the function's return + * statements will have the same type, either all of the exit join + * points will be filtered out or none will. + * + * Note that you must filter a pointcut by return type in order to + * call aop_capture_exit_return_value() on any of its join points. + * + * \param pc The function exit pointcut to filter. Function exit + * pointcuts are created with aop_match_function_exit(). + * \param type The return type to filter by. + */ +void +aop_filter_exit_by_return_type (struct aop_pointcut *pc, + const struct aop_type *type) +{ + if (pc->kind != ATP_EXIT) + fatal_error ("(InterAspect) Attempt to filter by return type on" + " unsupported join point."); + + pc->pc_exit.return_type = type; +} + +static tree +op_get_exit_return_value (struct aop_dynval *dv) +{ + gimple stmt; + tree return_value; + + struct aop_joinpoint *jp = dv->jp; + stmt = jp->stmt; + + aop_assert (gimple_code (stmt) == GIMPLE_RETURN); + + if (gimple_return_retval (stmt) == NULL) + fatal_error ("(InterAspect) Attempt to capture return value from function" + " that does not always return a value."); + + return_value = stabilize_reference (gimple_return_retval (stmt)); + return return_value; +} + +/** + * Get a dynval representing the value returned at a function exit + * join point. Note that you must filter with + * aop_filter_exit_by_return_type() in order to capture the return + * value using aop_capture_exit_return_value(). + * \param jp A function exit join point. Function exit join points + * are obtained by joining on an aop_match_function_exit() pointcut. + * \param A dynval with its type determined by + * aop_filter_exit_by_return_type(). + */ +struct aop_dynval * +aop_capture_exit_return_value (struct aop_joinpoint *jp) +{ + struct aop_pointcut *pc; + struct aop_dynval *dv; + + pc = jp->pc; + if (pc->kind != ATP_EXIT) + fatal_error ("(InterAspect) Attempt to capture return value from an" + " unsupported join point."); + + if (pc->pc_exit.return_type == NULL) + fatal_error ("(InterAspect) Attempt to capture return value without" + " specifying type."); + + dv = ggc_alloc (sizeof (struct aop_dynval)); + dv->kind = ADV_EXIT_RETVAL; + dv->type = pc->pc_exit.return_type; + dv->jp = jp; + dv->get_dynval = op_get_exit_return_value; + return dv; +} + /* Close Doxygen defgroup block. */ /** * \} diff --git a/src/aop-pointcut.h b/src/aop-pointcut.h index 6f66b80..1449d5f 100644 --- a/src/aop-pointcut.h +++ b/src/aop-pointcut.h @@ -62,6 +62,10 @@ struct aop_pc_entry { const char *function_name; }; +struct aop_pc_exit { + const struct aop_type *return_type; +}; + struct aop_pc_fun_call { const char *function_name; const struct aop_type *return_type; @@ -91,6 +95,7 @@ struct aop_pointcut { union { struct aop_pc_assign pc_assign; struct aop_pc_entry pc_entry; + struct aop_pc_exit pc_exit; struct aop_pc_fun_call pc_call; }; diff --git a/src/aop.h b/src/aop.h index 8e20f7b..411e3c3 100644 --- a/src/aop.h +++ b/src/aop.h @@ -332,11 +332,15 @@ extern void aop_filter_by_in_param (struct aop_pointcut *pc, int n, extern struct aop_dynval *aop_capture_in_param (struct aop_joinpoint *jp, int param_index); -extern struct aop_pointcut *aop_match_function_exit (); - extern void aop_filter_entry_by_name(struct aop_pointcut *pc_function_entry, const char *advice_function_entry); +extern struct aop_pointcut *aop_match_function_exit (); +extern void aop_filter_exit_by_return_type (struct aop_pointcut *pc, + const struct aop_type *type); +struct aop_dynval *aop_capture_exit_return_value (struct aop_joinpoint *jp); + + extern struct aop_pointcut *aop_match_function_call (); extern void aop_filter_call_pc_by_name (struct aop_pointcut *pc_function_call,