{
aop_assert (pc != NULL && pc->join_on != NULL);
+ /* Filtering on in_params is universal across a function. Either
+ every join point in the function match or none do.*/
+ if (!check_in_params (pc))
+ return;
+
pc->join_on (pc, callback, callback_param);
/* Call regimplification only if the pointcut needs it */
fatal_error ("(InterAspect) Attempt to use aop_join_on_copy() to join on a"
" function that was not duplicated.");
+ /* Filtering on in_params is universal across a function. Either
+ every join point in the function match or none do.*/
+ if (!check_in_params (pc))
+ return;
+
pc->join_on_copy (pc, copy, callback, callback_param);
/* Call regimplification only if the pointcut needs it */
IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
return (strcmp (func_name, pc->pc_entry.function_name) == 0);
}
- return check_in_params (pc);
}
/* We represent the function's entry as a control-flow graph edge.
pc_function_entry->pc_entry.function_name = advice_function_entry;
}
-/**
- * Filter a function entry pointcut to only include function entries
- * with a parameter that matches a specified type. This filter removes join
- * points when parameter n does not match type or when there is no
- * parameter n.
- *
- * Filters on the same parameter do not stack on top of each other.
- * If multiple parameter filters with the same n are applied a
- * pointcut, only the last one will have any effect.
- *
- * Note that you must filter a parameter by its type in order to
- * capture it with aop_capture_in_param().
- * \param pc The function call pointcut to filter. Function entry
- * pointcuts are created with aop_match_function_entry().
- * \param n The index of the parameter to filter on. Parameters are
- * indexed from zero.
- * \param The parameter type to filter by.
- */
-void
-aop_filter_entry_by_in_param (struct aop_pointcut *pc, int n,
- const struct aop_type *type)
-{
- struct aop_param_desc *param = NULL;
- struct aop_param_desc *iter;
-
- /* Is there already a filter for this parameter? */
- for (iter = pc->in_param_list_head ; iter != NULL ; iter = iter->next)
- {
- if (iter->param_index == n)
- {
- param = iter;
- break;
- }
- }
-
- /* No? Then create one and add it to the list. */
- if (param == NULL)
- {
- param = ggc_alloc (sizeof (struct aop_param_desc));
-
- param->next = pc->in_param_list_head;
- pc->in_param_list_head = param;
- }
-
- param->param_index = n;
- param->type = type;
-}
-
/* Close Doxygen defgroup block. */
/**
* \}
jp->file = file;
jp->in_edge = NULL;
jp->is_prepared = false;
-
}
int
return jp->file;
}
+/* Sometimes we want to capture a parameter some place that is not at
+ the beginning of the function. The parameter may change during the
+ function, so we save its value at function start to preserve it
+ until we need it.
+
+ Returns the temporary variable holding the preserved parameter
+ value. */
+static tree
+save_param(tree param)
+{
+ edge in_edge;
+ tree tmp_val;
+ gimple new_assign;
+
+ aop_assert (TREE_CODE (param) == PARM_DECL);
+
+ tmp_val = create_tmp_var (TREE_TYPE (param), "ia_preserved_param");
+ new_assign = gimple_build_assign (tmp_val, stabilize_reference (param));
+
+ /* Insert the assignment at the very beginning of the function. */
+ in_edge = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FUNCTION (cfun));
+ gsi_insert_on_edge_immediate (in_edge, new_assign);
+
+ return tmp_val;
+}
+
static tree
op_get_in_param (struct aop_dynval *dv)
{
int index = 0;
aop_assert (dv->kind == ADV_FUN_PARAM);
- aop_assert (jp->pc->kind == ATP_ENTRY);
stmt = jp->stmt;
{
if (index == dv->dynval_in_param.param_index)
{
- param = param_iter;
- param = stabilize_reference (param);
+ param = save_param (param_iter);
break;
}
index++;
struct aop_param_desc *param;
pc = jp->pc;
- if (pc->kind != ATP_ENTRY)
- fatal_error ("(InterAspect) Attempt to capture parameter from an"
- " unsupported join point.");
/* Search for an aop_param_desc for this parameter, so that we know
its type. */
return true;
}
+
+/**
+ * Filter a function entry pointcut to only include function entries
+ * with a parameter that matches a specified type. This filter removes join
+ * points when parameter n does not match type or when there is no
+ * parameter n.
+ *
+ * Filters on the same parameter do not stack on top of each other.
+ * If multiple parameter filters with the same n are applied a
+ * pointcut, only the last one will have any effect.
+ *
+ * Note that you must filter a parameter by its type in order to
+ * capture it with aop_capture_in_param().
+ * \param pc The function call pointcut to filter. Function entry
+ * pointcuts are created with aop_match_function_entry().
+ * \param n The index of the parameter to filter on. Parameters are
+ * indexed from zero.
+ * \param The parameter type to filter by.
+ */
+void
+aop_filter_by_in_param (struct aop_pointcut *pc, int n,
+ const struct aop_type *type)
+{
+ struct aop_param_desc *param = NULL;
+ struct aop_param_desc *iter;
+
+ /* Is there already a filter for this parameter? */
+ for (iter = pc->in_param_list_head ; iter != NULL ; iter = iter->next)
+ {
+ if (iter->param_index == n)
+ {
+ param = iter;
+ break;
+ }
+ }
+
+ /* No? Then create one and add it to the list. */
+ if (param == NULL)
+ {
+ param = ggc_alloc (sizeof (struct aop_param_desc));
+
+ param->next = pc->in_param_list_head;
+ pc->in_param_list_head = param;
+ }
+
+ param->param_index = n;
+ param->type = type;
+}
+
extern const char *aop_capture_function_name (struct aop_joinpoint *jp);
extern struct aop_pointcut *aop_match_function_entry ();
-extern void aop_filter_entry_by_in_param (struct aop_pointcut *pc, int n,
- const struct aop_type *type);
+extern void aop_filter_by_in_param (struct aop_pointcut *pc, int n,
+ const struct aop_type *type);
extern struct aop_dynval *aop_capture_in_param (struct aop_joinpoint *jp,
int param_index);
pc = aop_match_function_entry();
aop_filter_entry_by_name(pc, "foo");
- aop_filter_entry_by_in_param(pc, 0, aop_t_all_signed());
- aop_filter_entry_by_in_param(pc, 1, aop_t_all_fp());
+ aop_filter_by_in_param(pc, 0, aop_t_all_signed());
+ aop_filter_by_in_param(pc, 1, aop_t_all_fp());
aop_join_on(pc, plugin_join_on_call, "_advice_foo");
return 0;