enum aop_dvkind {
ADV_LHS_ADDR,
- ADV_FUN_RETVAL
+ ADV_FUN_PARAM,
++ ADV_FUN_RETVAL,
+ ADV_ASSIGN_VAL,
};
+struct aop_dynval_fun_call {
+ int param_id;
+};
+
/* An aop-dynval represents a dynamic value in the target program that
can be passed to an advice function. AOP weaving functions (such
as aop_insert_advice()) use a dynval to create instrumentation that
struct aop_dynval
{
enum aop_dvkind kind;
--
const struct aop_type *type;
struct aop_joinpoint *jp;
+
+ union {
+ struct aop_dynval_fun_call dynval_call;
+ };
/* Ops vector for aop_dynval. */
/* The get_dynval() op gets called when an advice call gets
void (*join_on) (struct aop_pointcut *, join_callback, void *);
insert_callback insert_before;
+ insert_callback insert_after;
+
+
+ /* prepare_for_weave() gets called once for each joinpoint before
+ any advice gets inserted at that joinpoint. */
+ void (*prepare_for_weave) (struct aop_joinpoint *);
+
union {
struct aop_pc_assign pc_assign;
+ struct aop_pc_entry pc_entry;
+ struct aop_pc_fun_call pc_call;
};
};
/* The GIMPLE statement being instrumented (where relevant). */
gimple stmt;
+
+ /* True if prepare_for_weave() has been called for this
+ joinpoint. */
+ bool is_prepared;
};
+ void op_default_prepare_for_weave (struct aop_joinpoint *jp);
void op_default_insert_before (struct aop_joinpoint *jp, gimple stmt);
+void op_default_insert_after (struct aop_joinpoint *jp, gimple stmt);
#endif
gsi_insert_before (jp->gsi, stmt, GSI_SAME_STMT);
}
+
+/* This is the default insert_after() operation for aop_pointcut
+ objects. It just inserts a gimple statement before the iterator in
+ the aop_joinpoint object. This function holds to the requirement
+ that inserting multiple gimple statements at the joinpoint will
+ result in those statements appearing in the order they were
+ added. */
+void
+op_default_insert_after (struct aop_joinpoint *jp, gimple stmt)
+{
+ gsi_insert_after (jp->gsi, stmt, GSI_SAME_STMT);
+}
+
+ /* This is the default prepare_for_weave() operation for aop_pointcut
+ objects. It does nothing. */
+ void
+ op_default_prepare_for_weave (struct aop_joinpoint *jp)
+ {
+ /* This space intentionally left blank. */
+ }
+
void
-aop_insert_advice (struct aop_joinpoint *jp, const char *func_name, ...)
+aop_insert_advice (struct aop_joinpoint *jp, const char *func_name,
+ enum aop_insert_location location, ...)
{
va_list argp;
gimple func_call;
struct aop_pointcut *pc;
+ va_start (argp, location);
+ func_call = build_gcc_call (func_name, void_type_node, argp);
+ va_end (argp);
+
pc = jp->pc;
- va_start (argp, func_name);
- func_call = build_gcc_call (func_name, void_type_node, argp);
- va_end (argp);
-
- pc->insert_before(jp, func_call);
+
+ /* Make sure this joinpoint is prepared for advice. */
+ if (!jp->is_prepared)
+ {
+ pc->prepare_for_weave (jp);
+ jp->is_prepared = true;
+ }
+
- {
+ if(location == AOP_INSERT_BEFORE)
- }
+ pc->insert_before(jp, func_call);
- {
+ else if(location == AOP_INSERT_AFTER)
- }
+ pc->insert_after(jp, func_call);
++ pc = jp->pc;
}
const char *aop_capture_function_name (struct aop_joinpoint *jp);
struct aop_dynval *aop_capture_lhs_addr (struct aop_joinpoint *jp);
+ struct aop_dynval *aop_capture_assigned_value (struct aop_joinpoint *jp);
struct aop_pointcut *aop_match_function_entry ();
struct aop_pointcut *aop_match_function_exit ();
+struct aop_pointcut *aop_match_function_call ();
+
+void aop_filter_function_entry_pointcut(struct aop_pointcut *pc_function_entry,
+ const char *advice_function_entry);
+
+void aop_filter_function_call_pointcut(struct aop_pointcut *pc_function_call,
+ const char *advice_function_call);
+
+void aop_filter_function_call_pointcut_by_param_index(struct aop_pointcut *pc,
+ int param_index);
+
+struct aop_dynval *
+aop_capture_return_value (struct aop_joinpoint *jp);
+
+struct aop_dynval *
+aop_capture_param (struct aop_joinpoint *jp, int param_index);
#endif