#include <ggc.h>
#include <basic-block.h>
#include <gimple.h>
+#include <toplev.h>
#include <diagnostic.h>
#include <string.h>
return true;
}
+/* Return true if a call statement matches the pointcut's criteria for
+ name, return type, and argument types. */
+static bool
+call_matches (struct aop_pointcut *pc, gimple call_stmt)
+{
+ tree func;
+ tree func_type_pointer;
+ tree func_type;
+
+ aop_assert (pc->kind == ATP_CALL);
+ aop_assert (gimple_code (call_stmt) == GIMPLE_CALL);
+
+ func = gimple_call_fn (call_stmt);
+
+ /* Check function name only if the user filtered by name. */
+ if (pc->pc_call.function_name != NULL)
+ {
+ if (TREE_CODE (func) == ADDR_EXPR)
+ {
+ /* Get the function's name and compare it to the filter-by
+ name. */
+ tree func_decl;
+ const char *func_name;
+
+ func_decl = TREE_OPERAND (func, 0);
+ func_name = IDENTIFIER_POINTER (DECL_NAME (func_decl));
+
+ if (strcmp (pc->pc_call.function_name, func_name) != 0)
+ return false;
+ }
+ else
+ {
+ /* This is a call to a function pointer, so it can't match a
+ name. */
+ return false;
+ }
+ }
+
+ /* Get the function type. The func tree should have a pointer type,
+ pointing to the actual function type. */
+ func_type_pointer = TREE_TYPE (func);
+ aop_assert (TREE_CODE (func_type_pointer) == POINTER_TYPE);
+ func_type = TREE_TYPE (func_type_pointer);
+ aop_assert (TREE_CODE (func_type) == FUNCTION_TYPE);
+
+ /* Check return type (if the user filtered by return type). */
+ if (pc->pc_call.return_type != NULL
+ && !does_type_match (TREE_TYPE (func_type), pc->pc_call.return_type))
+ return false;
+
+ /* All checks were OK. */
+ return true;
+}
+
static void
op_join_on_function_call (struct aop_pointcut *pc, join_callback cb,
void *callback_param)
{
basic_block my_basic_block;
gimple_stmt_iterator gsi;
- tree func_decl;
- tree func;
aop_assert (pc->kind == ATP_CALL);
if (gimple_code (stmt) == GIMPLE_CALL)
{
- const char *func_name;
-
- func = gimple_call_fn (stmt);
-
- if (TREE_CODE (func) != ADDR_EXPR)
- {
- /* This is a call to a function pointer. Don't
- worry about it. */
- continue;
- }
-
- func_decl = TREE_OPERAND (func, 0);
- func_name = IDENTIFIER_POINTER (DECL_NAME (func_decl));
-
- if (strcmp (pc->pc_call.function_name, func_name) == 0)
- {
- if (!param_desc_matches (pc->pc_call.param_list_head, stmt))
- continue;
-
+ if (call_matches (pc, stmt)
+ && param_desc_matches (pc->pc_call.param_list_head, stmt))
+ {
struct aop_joinpoint jp;
jp.pc = pc;
jp.gsi = &gsi;
}
}
}
- }
+ }
}
struct aop_pointcut *
pc->insert_before = op_default_insert_before;
pc->prepare_for_weave = op_default_prepare_for_weave;
- /* Initialize the list to NULL */
+ pc->pc_call.function_name = NULL;
+ pc->pc_call.return_type = NULL;
pc->pc_call.param_list_head = NULL;
return pc;
}
-void aop_filter_function_call_pointcut (struct aop_pointcut *pc_function_call,
- const char *advice_function_call)
+void
+aop_filter_function_call_pointcut (struct aop_pointcut *pc_function_call,
+ const char *advice_function_call)
{
pc_function_call->pc_call.function_name = advice_function_call;
}
-void aop_add_param_descriptor (struct aop_pointcut *pc,int param_id)
+void
+aop_add_param_descriptor (struct aop_pointcut *pc, int param_id)
{
struct aop_param_desc *iter = NULL;
struct aop_param_desc *desc = ggc_alloc (sizeof (struct aop_param_desc));
}
}
-void aop_filter_function_call_pointcut_by_param_index(struct aop_pointcut *pc,
- int param_id)
+void
+aop_filter_function_call_pointcut_by_param_index(struct aop_pointcut *pc,
+ int param_id)
{
aop_add_param_descriptor (pc, param_id);
}
gimple stmt;
tree return_value;
- /* If this function isn't on the right side of an assignment, we
- need to _put it_ on the right hand side of an assignment so we
- can grab its return value. */
struct aop_joinpoint *jp = dv->jp;
stmt = gsi_stmt (*(jp->gsi));
return return_value;
}
+void
+aop_filter_call_pc_by_return_type (struct aop_pointcut *pc,
+ const struct aop_type *type)
+{
+ pc->pc_call.return_type = type;
+}
+
struct aop_dynval *
aop_capture_return_value (struct aop_joinpoint *jp)
{
+ struct aop_pointcut *pc;
struct aop_dynval *dv;
+
+ pc = jp->pc;
+ if (pc->kind != ATP_CALL)
+ fatal_error ("(InterAspect) Attempt to capture return value from an"
+ " unsupported join point.");
+
+ if (pc->pc_call.return_type == NULL)
+ fatal_error ("(InterAspect) Attempt to capture return value without"
+ " specifying type.");
+
dv = ggc_alloc (sizeof (struct aop_dynval));
dv->kind = ADV_FUN_RETVAL;
- dv->type = aop_t_all_unsigned ();
+ dv->type = pc->pc_call.return_type;
dv->jp = jp;
dv->get_dynval = op_get_return_value;
return dv;
dv->dynval_call.param_id = param_index;
return dv;
}
-