op_join_on_function_entry (struct aop_pointcut *pc, join_callback cb,
void *callback_param)
{
- basic_block bb;
+ struct aop_joinpoint jp;
+ gimple_stmt_iterator gsi;
+
aop_assert (pc->kind == ATP_ENTRY);
+ /* Filter this pointcut by function name if necessary. */
if(pc->pc_entry.function_name != NULL)
{
const char *func_name =
return;
}
- FOR_EACH_BB(bb)
- {
- gimple_stmt_iterator gsi;
+ /* Note that the gimple iterator gets initialized by
+ op_prepare_entry when it is time to insert advice. (We poison it
+ just to make sure that initialization is getting called.)*/
+ memset (&gsi, 0xfa, sizeof (gimple_stmt_iterator));
+
+ jp.pc = pc;
+ jp.gsi = &gsi;
+ jp.is_prepared = false;
+ cb (&jp, callback_param);
+}
- for (gsi = gsi_start_bb (bb) ; !gsi_end_p (gsi) ; gsi_next (&gsi))
+/* There is no GIMPLE statement that is suitable as an anchor point
+ for inserting advice at the beginning of a function.
+
+ The first GIMPLE statement in the function is no good because it
+ may be a label statement at the beginning of a basic block.
+ Inserting a statement before a label would cause a label in the
+ middle of a basic block, which is a no-no.
+
+ We use the gsi_insert_on_edge_immediate() function to add a NOP
+ statement that is definitely legal. It serves as an anchor point
+ for inserting before and after advice! */
+static void
+op_prepare_entry (struct aop_joinpoint *jp)
+{
+ gimple nop;
+ basic_block bb;
+ edge in_edge;
+
+ aop_assert (jp->pc->kind = ATP_ENTRY);
+
+ nop = gimple_build_nop ();
+
+ in_edge = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FUNCTION(cfun));
+ gsi_insert_on_edge_immediate (in_edge, nop);
+
+ /* Find an iterator pointing to the nop. */
+ FOR_EACH_BB (bb)
+ {
+ for (*jp->gsi = gsi_start_bb (bb);
+ !gsi_end_p (*jp->gsi);
+ gsi_next (jp->gsi))
{
- struct aop_joinpoint jp;
- jp.pc = pc;
- jp.gsi = &gsi;
- jp.is_prepared = false;
- cb (&jp, callback_param);
- return;
+ if (gsi_stmt (*jp->gsi) == nop)
+ return; /* Found! */
}
}
+
+ /* We failed to found the statement we just inserted! */
+ aop_assert (0);
}
struct aop_pointcut *
pc->kind = ATP_ENTRY;
pc->join_on = op_join_on_function_entry;
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_entry;
+
+ pc->pc_entry.function_name = NULL;
return pc;
}
-void aop_filter_function_entry_pointcut(struct aop_pointcut *pc_function_entry,
- const char *advice_function_entry)
+void aop_filter_entry_by_name(struct aop_pointcut *pc_function_entry,
+ const char *advice_function_entry)
{
pc_function_entry->pc_entry.function_name = advice_function_entry;
}