variable with a cast. Insert the assignment before the join point
and return the temporary value. */
static tree
-insert_cast (tree val, tree cast_type, struct aop_joinpoint *jp)
+insert_cast (tree val, tree cast_type, VEC(gimple, heap) *pre_stmts)
{
tree tmp;
tree cast;
cast = build1 (CONVERT_EXPR, cast_type, val);
cast_assign = gimple_build_assign (tmp, cast);
- jp->pc->insert_before (jp, cast_assign);
+ VEC_safe_push (gimple, heap, pre_stmts, cast_assign);
return tmp;
}
/* Whenver InterAspect matches an "all signed" or "all unsigned"
value, it needs to cast it up to a long long before passing it. */
static tree
-cast_to_all_integer (tree val, struct aop_joinpoint *jp)
+cast_to_all_integer (tree val, VEC(gimple, heap) *pre_stmts)
{
tree gcc_type;
HOST_WIDE_INT size;
tree cast_type = TYPE_UNSIGNED (gcc_type) ? long_long_unsigned_type_node
: long_long_integer_type_node;
- return insert_cast (val, cast_type, jp);
+ return insert_cast (val, cast_type, pre_stmts);
}
else
{
/* Similar to cast_to_all_integer, above. */
static tree
-cast_to_all_fp (tree val, struct aop_joinpoint *jp)
+cast_to_all_fp (tree val, VEC(gimple, heap) *pre_stmts)
{
tree gcc_type;
HOST_WIDE_INT size;
if (size != 8)
{
- return insert_cast (val, double_type_node, jp);
+ return insert_cast (val, double_type_node, pre_stmts);
}
else
{
}
}
+/* Building a dynval creates a tree node but may also generate GIMPLE
+ statements that are necessary setup for the tree node. Those
+ statements are output to the pre_stmts list. */
static tree
-build_dynval (struct aop_dynval *dv)
+build_dynval (struct aop_dynval *dv, VEC(gimple, heap) *pre_stmts)
{
tree val;
val = dv->get_dynval (dv);
if (is_all_integer_type (dv->type))
- val = cast_to_all_integer (val, dv->jp);
+ val = cast_to_all_integer (val, pre_stmts);
else if (is_all_fp_type (dv->type))
- val = cast_to_all_fp (val, dv->jp);
+ val = cast_to_all_fp (val, pre_stmts);
return val;
}
iterates through those arguments and creates GIMPLE tree nodes for
each of them.
- The new nodes get stored in arglist. */
+ The new nodes get stored in arglist. GIMPLE statements that must
+ be inserted before the call are put in the pre_stmts list. */
static gimple
build_gcc_call (const char *func_name, tree return_type,
- enum aop_insert_location location, va_list argp)
+ enum aop_insert_location location, VEC(gimple, heap) *pre_stmts,
+ va_list argp)
{
enum aop_argkind kind;
VEC(tree, heap) *arg_list;
if (location == AOP_INSERT_BEFORE)
verify_legal_in_before_advice (dv);
- new_arg = build_dynval (dv);
+ new_arg = build_dynval (dv, pre_stmts);
VEC_safe_push (tree, heap, arg_list, new_arg);
break;
default:
va_list argp;
gimple func_call;
struct aop_pointcut *pc;
+ VEC(gimple, heap) *pre_stmts;
pc = jp->pc;
jp->is_prepared = true;
}
+ pre_stmts = VEC_alloc (gimple, heap, 2);
+
va_start (argp, location);
- func_call = build_gcc_call (func_name, void_type_node, location, argp);
+ func_call = build_gcc_call (func_name, void_type_node, location, pre_stmts,
+ argp);
va_end (argp);
va_start (argp, location);
insert_prototype (false /* void return type */, func_name,
gimple_call_num_args (func_call), argp);
va_end (argp);
-
+
if(location == AOP_INSERT_BEFORE)
- pc->insert_before(jp, func_call);
+ {
+ int i;
+ gimple stmt;
+
+ for (i = 0; VEC_iterate (gimple, pre_stmts, i, stmt); i++)
+ pc->insert_before (jp, stmt);
+ pc->insert_before (jp, func_call);
+ }
else if(location == AOP_INSERT_AFTER)
- pc->insert_after(jp, func_call);
+ {
+ /* insert_after() adds statements backwards, so we have to work
+ in reverse. */
+ pc->insert_after (jp, func_call);
+ while (!VEC_empty (gimple, pre_stmts))
+ {
+ gimple stmt;
+ stmt = VEC_pop (gimple, pre_stmts);
+ aop_assert (stmt != NULL);
+
+ pc->insert_after (jp, stmt);
+ }
+ }
+
+ VEC_free(gimple, heap, pre_stmts);
+}
+
+/* Take a list of statements and insert them at the current function's
+ main entry point. */
+static void
+insert_stmts_at_entry (VEC(gimple, heap) *stmt_list)
+{
+ int i;
+ edge in_edge;
+ gimple stmt;
+
+ /* Get the edge for the main entry point. */
+ in_edge = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FUNCTION (cfun));
+
+ for (i = 0; VEC_iterate (gimple, stmt_list, i, stmt); i++)
+ gsi_insert_on_edge_immediate (in_edge, stmt);
}
/**
va_list argp;
gimple func_call;
struct aop_pointcut *pc;
+ VEC(gimple, heap) *pre_stmts;
pc = jp->pc;
else if (is_current_func_duplicated())
fatal_error ("(InterAspect) Cannot duplicate a function more than once.");
+ pre_stmts = VEC_alloc (gimple, heap, 2);
+
va_start (argp, func_name);
func_call = build_gcc_call (func_name, integer_type_node, AOP_INSERT_BEFORE,
- argp);
+ pre_stmts, argp);
va_end (argp);
va_start (argp, func_name);
gimple_call_num_args (func_call), argp);
duplicate_function_body ("ia_body_index", func_call);
+
+ /* Insert all of the pre_stmts at the function entry so they will be
+ before func_call. */
+ insert_stmts_at_entry (pre_stmts);
+
+ VEC_free(gimple, heap, pre_stmts);
}