From 78718f742585e5a20960b0437c3f3343771da1bc Mon Sep 17 00:00:00 2001 From: Justin Seyster Date: Fri, 18 Jun 2010 17:12:44 -0400 Subject: [PATCH] Cleaned up function exit pointcuts so that after advice works. Also documented the use of before and after advice in detail in the aop_insert_advice() documentation. --- src/aop-pc-exit.c | 37 ++++++++++++++++++++++++++++++++++--- src/aop-weave.c | 27 +++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/aop-pc-exit.c b/src/aop-pc-exit.c index 3dbe43b..c8b7fc7 100644 --- a/src/aop-pc-exit.c +++ b/src/aop-pc-exit.c @@ -48,22 +48,52 @@ op_join_on_function_exit (struct aop_pointcut *pc, join_callback cb, FOR_EACH_BB(bb) { gimple_stmt_iterator gsi; - for (gsi = gsi_start_bb(bb) ; !gsi_end_p(gsi) ; gsi_next(&gsi)) + for (gsi = gsi_start_bb (bb) ; !gsi_end_p (gsi) ; gsi_next (&gsi)) { stmt = gsi_stmt (gsi); - + if (gimple_code (stmt) == GIMPLE_RETURN) { struct aop_joinpoint jp; jp.pc = pc; jp.gsi = &gsi; + jp.stmt = stmt; jp.is_prepared = false; cb (&jp, callback_param); + + /* It's possible that gsi is no longer a valid iterator + if the callback inserted advice. Anyway, that's fine + because there shouldn't be any statements in the + basic block after the return! On to the next basic + block. */ + break; } } } } +/* Prepare for an insert at a function entry join point. + + Attempting to insert an advice call _after_ a return statement + doesn't make any sense and will fail. GIMPLE does not allow any + statements in a basic block after a return statement (sensibly). + + We create a NOP statement before the return statement that serves + as an anchor for inserting advice. Any advice calls inserted with + AOP_INSERT_AFTER will still execute before the return but will + execute after any calls inserted with AOP_INSERT_BEFORE (no matter + the order in which they were inserted). */ +static void +op_prepare_exit (struct aop_joinpoint *jp) +{ + gimple nop; + + aop_assert (jp->pc->kind == ATP_EXIT); + + nop = gimple_build_nop (); + gsi_insert_before (jp->gsi, nop, GSI_NEW_STMT); +} + struct aop_pointcut * aop_match_function_exit () { @@ -72,6 +102,7 @@ aop_match_function_exit () pc->kind = ATP_EXIT; pc->join_on = op_join_on_function_exit; pc->insert_before = op_default_insert_before; - pc->prepare_for_weave = op_default_prepare_for_weave; + pc->insert_after = op_default_insert_after; + pc->prepare_for_weave = op_prepare_exit; return pc; } diff --git a/src/aop-weave.c b/src/aop-weave.c index 769b83e..4016a06 100644 --- a/src/aop-weave.c +++ b/src/aop-weave.c @@ -166,6 +166,33 @@ op_default_prepare_for_weave (struct aop_joinpoint *jp) /* This space intentionally left blank. */ } +/** + * Insert a call to an advice function at a join point with any number + * of arguments. Any arguments following location are arguments to be + * passed to the advice function. Because C does not know the types + * of vararg arguments, a type macro (such as #AOP_STR_CST or + * #AOP_DYNVAL) is necessary for each advice argument. #AOP_TERM_ARG + * must be the last argument to aop_insert_advice(), even when not + * specifying any arguments for the advice function. + * + * Specifying AOP_INSERT_BEFORE or AOP_INSERT_AFTER will place the + * call before or after the join point (when possible) and will + * guarantee certain properties about ordering of advice calls. Using + * AOP_INSERT_BEFORE to insert multiple advice calls at the same join + * point will place advice calls in the order they are inserted. With + * AOP_INSERT_AFTER, however, advice calls will be placed in _reverse_ + * order. No matter what order calls are inserted in, all + * AOP_INSERT_BEFORE calls will be placed before all AOP_INSERT_AFTER + * calls. + * + * It is legal to use AOP_INSERT_BEFORE and AOP_INSERT_AFTER to + * enforce ordering among advice calls even when inserting before or + * after a join point does not make sense. For example, it does not + * make sense to insert an advice call before a function entry join + * point. Using AOP_INSERT_BEFORE will still insert the advice after + * function entry, but it will place the advice before any + * AOP_INSERT_AFTER advice. + */ void aop_insert_advice (struct aop_joinpoint *jp, const char *func_name, enum aop_insert_location location, ...) -- 2.43.0