#include <string.h>
#include "aop.h"
+#include "aop-duplicate.h"
#include "aop-pointcut.h"
#include "aop-type.h"
* \{
*/
-static void
-op_join_on_function_entry (struct aop_pointcut *pc, join_callback cb,
- void *callback_param)
+/* Function have only one entry. Return true if that entry matches
+ the pointcut's filtering criteria. */
+static bool
+is_function_entry_matching (struct aop_pointcut *pc)
{
- 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)
+ /* Filter by name. */
+ if(pc->pc_entry.function_name == NULL)
+ {
+ /* No name filter in place. */
+ return true;
+ }
+ else
{
const char *func_name =
IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
- if (strcmp (func_name, pc->pc_entry.function_name) != 0)
- return;
- }
+ return (strcmp (func_name, pc->pc_entry.function_name) == 0);
+ }
+}
+
+/* We represent the function's entry as a control-flow graph edge.
+ That edge is the only thing necessary to join on the pointcut's one
+ join point. */
+static void
+join_on_entry_edge (struct aop_pointcut *pc, edge in_edge, join_callback cb,
+ void *callback_param)
+{
+ struct aop_joinpoint jp;
+ 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
memset (&gsi, 0xfa, sizeof (gimple_stmt_iterator));
init_joinpoint (&jp, &gsi, pc, NULL);
+ jp.in_edge = in_edge;
cb (&jp, callback_param);
}
+static void
+op_join_on_function_entry (struct aop_pointcut *pc, join_callback cb,
+ void *callback_param)
+{
+ edge in_edge;
+
+ aop_assert (pc->kind == ATP_ENTRY);
+
+ if (!is_function_entry_matching (pc))
+ return;
+
+ /* Get the function's actual entry point: the edge coming out of the
+ entry block. */
+ in_edge = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FUNCTION (cfun));
+ join_on_entry_edge (pc, in_edge, cb, callback_param);
+}
+
static void
op_join_on_copy_function_entry (struct aop_pointcut *pc, int copy,
join_callback cb, void *callback_param)
{
- /* Not yet supported. */
- aop_assert(0);
+ int last_copy;
+ edge in_edge;
+
+ aop_assert (pc->kind == ATP_ENTRY);
+ aop_assert (is_current_func_duplicated ());
+
+ if (!is_function_entry_matching (pc))
+ return;
+
+ /* We wish to join on the entry to the duplicated function body.
+ This will be one of the edges coming out of the distributor
+ block. */
+ last_copy = EDGE_COUNT (distributor_bb->succs) - 1;
+ copy = (copy <= last_copy) ? copy : last_copy;
+ in_edge = EDGE_SUCC (distributor_bb, copy);
+
+ join_on_entry_edge (pc, in_edge, cb, callback_param);
}
/* There is no GIMPLE statement that is suitable as an anchor point
{
gimple nop;
basic_block bb;
- edge in_edge;
aop_assert (jp->pc->kind = ATP_ENTRY);
+ aop_assert (jp->in_edge != NULL);
nop = gimple_build_nop ();
-
- in_edge = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FUNCTION(cfun));
- gsi_insert_on_edge_immediate (in_edge, nop);
+ gsi_insert_on_edge_immediate (jp->in_edge, nop);
/* Find an iterator pointing to the nop. */
FOR_EACH_BB (bb)
}
}
- /* We failed to found the statement we just inserted! */
+ /* We failed to find the statement we just inserted! */
aop_assert (0);
}