Added idea of pre_stmts.
authorJustin Seyster <jseyster@cs.sunysb.edu>
Wed, 27 Oct 2010 23:17:49 +0000 (19:17 -0400)
committerJustin Seyster <jseyster@cs.sunysb.edu>
Thu, 28 Oct 2010 00:28:12 +0000 (20:28 -0400)
The pre_stmts vector lets build_dynval construct a list of statements
it wants to insert rather than directly inserting those statements on
its own.

src/aop-weave.c

index 2b9415625e3e4ee284711378849eea1c82c5937b..711e75382edd1be05e5d178a616e188085f13d75 100644 (file)
@@ -157,7 +157,7 @@ build_string_ptr (const char *string)
    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;
@@ -167,7 +167,7 @@ insert_cast (tree val, tree cast_type, struct aop_joinpoint *jp)
   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;
 }
@@ -175,7 +175,7 @@ insert_cast (tree val, tree cast_type, struct aop_joinpoint *jp)
 /* 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;
@@ -191,7 +191,7 @@ cast_to_all_integer (tree val, struct aop_joinpoint *jp)
       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
     {
@@ -202,7 +202,7 @@ cast_to_all_integer (tree val, struct aop_joinpoint *jp)
 
 /* 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;
@@ -215,7 +215,7 @@ cast_to_all_fp (tree val, struct aop_joinpoint *jp)
 
   if (size != 8)
     {
-      return insert_cast (val, double_type_node, jp);
+      return insert_cast (val, double_type_node, pre_stmts);
     }
   else
     {
@@ -224,17 +224,20 @@ cast_to_all_fp (tree val, struct aop_joinpoint *jp)
     }
 }
 
+/* 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;
 }
@@ -244,10 +247,12 @@ build_dynval (struct aop_dynval *dv)
    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;
@@ -307,7 +312,7 @@ build_gcc_call (const char *func_name, tree return_type,
          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:
@@ -393,6 +398,7 @@ aop_insert_advice (struct aop_joinpoint *jp, const char *func_name,
   va_list argp;
   gimple func_call;
   struct aop_pointcut *pc;
+  VEC(gimple, heap) *pre_stmts;
 
   pc = jp->pc;
 
@@ -403,19 +409,59 @@ aop_insert_advice (struct aop_joinpoint *jp, const char *func_name,
       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);
 }
 
 /**
@@ -451,6 +497,7 @@ aop_duplicate (struct aop_joinpoint *jp, const char *func_name, ...)
   va_list argp;
   gimple func_call;
   struct aop_pointcut *pc;
+  VEC(gimple, heap) *pre_stmts;
 
   pc = jp->pc;
 
@@ -463,9 +510,11 @@ aop_duplicate (struct aop_joinpoint *jp, const char *func_name, ...)
   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);
@@ -473,4 +522,10 @@ aop_duplicate (struct aop_joinpoint *jp, const char *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);
 }