jp->file = file;
jp->in_edge = NULL;
jp->is_prepared = false;
- int
- aop_capture_lineno (struct aop_joinpoint *jp)
- {
- return jp->line;
- }
-
- const char *
- aop_capture_file_name (struct aop_joinpoint *jp)
- {
- 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)
+{
+ gimple stmt;
+ tree param = NULL;
+ tree param_iter;
+ struct aop_joinpoint *jp = dv->jp;
+ int index = 0;
+
+ aop_assert (dv->kind == ADV_FUN_PARAM);
+
+ stmt = jp->stmt;
+ for (param_iter = DECL_ARGUMENTS (current_function_decl);
+ param_iter; param_iter = TREE_CHAIN (param_iter))
+ {
+ if (index == dv->dynval_in_param.param_index)
+ {
+ param = save_param (param_iter);
+ break;
+ }
+ index++;
+ }
+
+ aop_assert (param != NULL);
+ return param;
}
/**
- * \defgroup univeral Universal Capture Functions
+ * Get a dynval representing the nth parameter passed to the current
+ * fuction. Be careful not to capture the <code>in_param</code> of
+ * the current function when you actually intend to capture the
+ * <code>call_param</code> being passed to a function call join point.
+ * (For the latter, use aop_capture_param() instead).
*
- * These capture functions work on any kind of join point.
- * \{
+ * Note that you must use aop_filter_by_in_param() to filter a
+ * pointcut by parameter type for any parameter you wish to capture
+ * with this function.
+ * \param jp Any kind of join point. Join points are obtained by
+ * joining on a pointcut.
+ * \param n The index of the parameter to capture. Parameters are
+ * indexed from zero.
+ * \return A dynval with its type determined by
+ * aop_filter_by_in_param().
*/
+struct aop_dynval *
+aop_capture_in_param (struct aop_joinpoint *jp, int n)
+{
+ struct aop_pointcut *pc;
+ struct aop_dynval *dv;
+ struct aop_param_desc *param;
+
+ pc = jp->pc;
+
+ /* Search for an aop_param_desc for this parameter, so that we know
+ its type. */
+ for (param = pc->in_param_list_head; param != NULL; param = param->next)
+ if (param->param_index == n)
+ break; /* Found it. */
+
+ /* If we don't find the appropriate aop_param_desc, param will be NULL. */
+ if (param == NULL)
+ fatal_error ("(InterAspect) Attempt to capture parameter without specifying"
+ " type.");
+
+ dv = ggc_alloc (sizeof (struct aop_dynval));
+ dv->kind = ADV_FUN_PARAM;
+ dv->type = param->type;
+ dv->jp = jp;
+ dv->get_dynval = op_get_in_param;
+ dv->dynval_in_param.param_index = n;
+ return dv;
+}
+
+bool
+check_in_param (struct aop_param_desc *param_desc)
+{
+ tree param_type;
+ tree param_decl;
+ int index = 0;
+ bool index_found = false;
+ for (param_decl = DECL_ARGUMENTS (current_function_decl);
+ param_decl; param_decl = TREE_CHAIN (param_decl))
+ {
+ if (index == param_desc->param_index)
+ {
+ /* Index found check the type */
+ if ((param_type = TREE_TYPE (param_decl)) == NULL
+ || !does_type_match (param_type, param_desc->type))
+ index_found = false;
+ else
+ index_found = true;
+
+ break;
+ }
+ index++;
+ }
+ return index_found;
+}
+
+bool
+check_in_params (struct aop_pointcut *pc)
+{
+ struct aop_param_desc *param_desc;
+
+ /* Check parameter types. */
+ for (param_desc = pc->in_param_list_head ; param_desc != NULL ;
+ param_desc = param_desc->next)
+ {
+ if(!check_in_param (param_desc))
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Filter a pointcut (of any type) to only include join points within
+ * functions that take an nth parameter matching the specified type.
+ * Be careful not to use this function when you actually intend to
+ * filter a function call pointcut by the parameters that the function
+ * call takes. (For the latter, use aop_filter_call_pc_by_param()).
+ *
+ * Because pointcuts are created per function, this kind of filtering
+ * is actually all-or-nothing. It will either empty the pointcut or
+ * leave it as is.
+ *
+ * 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 pointcut to filter.
+ * \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;
+}
+ /**
+ * Get the line number of join point. You usually want to call this
+ * with aop_capture_file_name() to fully identify the line of code the
+ * join point is from.
+ * \param jp Any join point.
+ */
+ int
+ aop_capture_lineno (struct aop_joinpoint *jp)
+ {
+ return jp->line;
+ }
+
+ /**
+ * Get the name of the file this join point is in. This function will
+ * usually return the name of the file that is currently being
+ * compiled, but compiler macros make it possible for their to be join
+ * points from other files.
+ * \param jp Any join point.
+ */
+ const char *
+ aop_capture_file_name (struct aop_joinpoint *jp)
+ {
+ return jp->file;
+ }
+
+ /**
+ * \}
+ */