Merge branch 'master' into autoheaders
authorJustin Seyster <jseyster@cs.sunysb.edu>
Thu, 2 Sep 2010 22:54:05 +0000 (18:54 -0400)
committerJustin Seyster <jseyster@cs.sunysb.edu>
Thu, 2 Sep 2010 22:54:05 +0000 (18:54 -0400)
Conflicts:
src/Makefile.am
src/aop-main.c
src/aop-type.h
src/aop.h

1  2 
src/Makefile.am
src/aop-main.c
src/aop-type.c
src/aop-type.h
src/aop-weave.c
src/aop.h

diff --cc src/Makefile.am
index de2564c0d8cc4088ed69b3433e7cfb6af7d3270c,0c6c3d2ef9957d0fa175a168b30ab5835bef6a4c..b596c80f750f85b40d1d521b7e871e781c829e6c
@@@ -1,6 -1,7 +1,7 @@@
  lib_LTLIBRARIES = libinteraspect.la
  libinteraspect_la_SOURCES = aop-pc-assign.c aop-main.c aop-type.c aop-weave.c \
-       aop-pc-entry.c aop-pc-exit.c aop-pc-fun-call.c aop-header.c
 -      aop-pc-entry.c aop-pc-exit.c aop-pc-fun-call.c aop-pointcut.c \
 -      aop-duplicate.c
++      aop-pc-entry.c aop-pc-exit.c aop-pc-fun-call.c aop-header.c \
++      aop-pointcut.c aop-duplicate.c
  libinteraspect_la_CFLAGS = -Wall -Werror -fvisibility=hidden -prefer-pic
  libinteraspect_la_LDFLAGS = -static -prefer-pic -version-info 1:0:0
  libinteraspect_la_CPPFLAGS = -DHAVE_CONFIG_H -DIN_GCC -I$(gcc_includes)
diff --cc src/aop-main.c
index 83c76f53f3d05ecfc688b869e90b7a1fffca8f2c,1a06f31f80205d017a0d1797380cd108b8881f0c..f25ba94fe10e7bcf2ce0cd8e4eca3e821c09b95b
  #include <c-common.h>
  
  #include "aop.h"
+ #include "aop-duplicate.h"
 +#include "aop-header.h"
  #include "aop-pointcut.h"
+ #include "aop-type.h"
  
  //#define PAUSE_ON_START
  
@@@ -160,7 -219,7 +220,8 @@@ cleanup_passes (
  static void
  aop_cleanup (void *event_date, void *data)
  {
+   free_type_table ();
 +  free_prototype_table ();
    cleanup_passes ();
  }
  
@@@ -188,7 -247,8 +249,9 @@@ plugin_init (struct plugin_name_args *p
  
    aop_plugin_name = plugin_info->base_name;
  
 -  /* Initialization for aop-type.c. */
++  /* Initialization for aop-type.c and aop-header.c. */
+   init_type_table ();
 +  init_prototype_table ();
  
    /* Register our cleanup function. */
    register_callback (aop_plugin_name, PLUGIN_FINISH, aop_cleanup, NULL);
diff --cc src/aop-type.c
index 605bf7835ee702d46d065166f29ed705be49d06d,8702ac03e445eeeb89195ce5ebca1ee294006111..acf30aa10cd80139d7f0ee283899ea57f19f7c6f
@@@ -85,87 -752,35 +752,90 @@@ does_custom_type_match (tree gcc_type, 
  bool
  does_type_match (tree gcc_type, const struct aop_type *aop_type)
  {
+   int pointer_levels;
    aop_assert (gcc_type != NULL && aop_type != NULL);
  
-   if (aop_type->kind == ATK_ALL_POINTER)
+   pointer_levels = aop_type->pointer_levels;
+   while (pointer_levels > 0)
      {
-       return (TREE_CODE (gcc_type) == POINTER_TYPE);
+       if (TREE_CODE (gcc_type) != POINTER_TYPE)
+       return false;
+       /* What type does it point to? */
+       gcc_type = TREE_TYPE (gcc_type);
+       pointer_levels--;
      }
-   else if (aop_type->pointer_levels == 0)
+   switch (aop_type->kind)
      {
-       switch (aop_type->kind)
-       {
-       case ATK_ALL_SIGNED:
-         return (TREE_CODE (gcc_type) == INTEGER_TYPE
-                 && !TYPE_UNSIGNED (gcc_type));
-       case ATK_ALL_UNSIGNED:
-         return (TREE_CODE (gcc_type) == INTEGER_TYPE
-                 && TYPE_UNSIGNED (gcc_type));
-       case ATK_ALL_FP:
-         return (TREE_CODE (gcc_type) == REAL_TYPE);
-       default:
-         break;
-       }
+     case ATK_ALL_POINTER:
+       return (TREE_CODE (gcc_type) == POINTER_TYPE);
+     case ATK_SIGNED_INT:
+     case ATK_UNSIGNED_INT:
+       return does_int_type_match (gcc_type, aop_type->kind, aop_type->size);
+     case ATK_FP:
+       return does_fp_type_match (gcc_type, aop_type->size);
+     case ATK_STRUCT:
+     case ATK_UNION:
+     case ATK_ENUM:
+       return does_custom_type_match (gcc_type, aop_type->kind, aop_type->tag);
+     default:
+       aop_assert (0);
      }
-   aop_assert (0);
  }
-       goto terminate;
 +
 +/* Return true if two aop_type objects are equal. */
 +bool
 +are_types_equal (const struct aop_type *a, const struct aop_type *b)
 +{
 +  return (a == b);
 +}
 +
 +/* C names for special aop_type objects. */
 +static const char *all_signed_name = "ALL_SIGNED_T";
 +static const char *all_unsigned_name = "ALL_UNSIGNED_T";
 +static const char *all_fp_name = "ALL_FP_T";
 +static const char *all_pointer_name = "ALL_POINTER_T";
 +
 +/* Format an aop_type as a C/C++ typename.  The result is stored in
 +   the output buffer (n is the size of the buffer).  Returns the
 +   number characters written (but without regard to truncation because
 +   of a too small output buffer, as with snprintf()). */
 +int
 +format_c_type (const struct aop_type *type, int n, char *output)
 +{
 +  int size;
 +
 +  if (type->kind == ATK_ALL_POINTER)
 +    {
 +      size = snprintf (output, n, "%s", all_pointer_name);
-   else if (type->pointer_levels == 0)
 +    }
-       switch (type->kind)
-       {
-       case ATK_ALL_SIGNED:
-         size = snprintf (output, n, "%s", all_signed_name);
-         goto terminate;
-       case ATK_ALL_UNSIGNED:
-         size = snprintf (output, n, "%s", all_unsigned_name);
-         goto terminate;
-       case ATK_ALL_FP:
-         size = snprintf (output, n, "%s", all_fp_name);
-         goto terminate;
-       default:
-         break;
-       }
++  else if (is_all_integer_type (type))
 +    {
-   aop_assert (0);
-  terminate:
++      if (type->kind == ATK_SIGNED_INT)
++      size = snprintf (output, n, "%s", all_signed_name);
++      else if (type->kind == ATK_UNSIGNED_INT)
++      size = snprintf (output, n, "%s", all_unsigned_name);
++      else
++      aop_assert (0); /* Should never happen. */
++    }
++  else if (is_all_fp_type (type))
++    {
++      size = snprintf (output, n, "%s", all_fp_name);
++    }
++  else
++    {
++      aop_assert (0);  /* Not yet supported. */
 +    }
 +
 +  /* Before returning, make absolutely sure that the result is
 +     NULL-terminated.  Note that snprintf will not terminate a string
 +     that it has to truncate because of too small buffer. */
 +  if (size < n)
 +    output[size] = '\0';
 +  else
 +    output[n - 1] = '\0';
 +
 +  return size;
 +}
diff --cc src/aop-type.h
index 4eff58c411f36fa002626b30408c9c663e8d5b7f,5bb167e16242e666da7e82f8e4e567fcdb40b8c5..d024aeb61035b2b8abee2a18be26ac38dde023e4
@@@ -33,11 -37,15 +37,19 @@@ struct aop_type 
  
    int pointer_levels;
    const char *tag;
+   int size;
  };
  
- bool does_type_match (tree gcc_type, const struct aop_type *aop_type);
- bool are_types_equal (const struct aop_type *a, const struct aop_type *b);
+ extern void init_type_table ();
+ extern void free_type_table ();
+ extern bool is_all_integer_type (const struct aop_type *type);
+ extern bool is_all_fp_type (const struct aop_type *type);
+ extern bool does_type_match (tree gcc_type, const struct aop_type *aop_type);
  
- int format_c_type (const struct aop_type *type, int n, char *output);
++extern bool are_types_equal (const struct aop_type *a,
++                           const struct aop_type *b);
++extern int format_c_type (const struct aop_type *type, int n, char *output);
 +
  #endif
diff --cc src/aop-weave.c
index c8edaa8d9eb12289942faf200b2989d8a38b258d,6c4f292fbb861702025a7f709df95886ed97999f..b3f26a73ed6aac974a7de6df515204d4cc45e39b
  #undef GENERATOR_FILE
  
  #include "aop.h"
+ #include "aop-duplicate.h"
  #include "aop-dynval.h"
 +#include "aop-header.h"
  #include "aop-pointcut.h"
+ #include "aop-type.h"
  
  /* Throw a fatal error if a dynval is not allowed in a before-advice
     call. */
@@@ -266,4 -323,57 +329,56 @@@ aop_insert_advice (struct aop_joinpoin
      pc->insert_before(jp, func_call);
    else if(location == AOP_INSERT_AFTER)
      pc->insert_after(jp, func_call);
 -
  }
+ /**
+  * Duplicate the current function's body so that there are two copies
+  * available for instrumentation.  A function entry join point is
+  * required because the duplication process inserts an advice call at
+  * function entry which serves as a <i>distributor</i>.
+  *
+  * The distributor advice decides which copy to execute.  A
+  * distributor advice function returns an int (unlike regular advice,
+  * which has void return type): a zero value will execute the original
+  * copy and a non-zero value will execute the new copy.
+  *
+  * Any arguments following func_name are arguments to be passed to the
+  * distributor advice function.  (See the documentation for
+  * aop_insert_advice() for an explanation of passing arguments to
+  * advice.)  #AOP_TERM_ARG must be the last argument to
+  * aop_duplicate(), even when not specifying any arguments for the
+  * advice function.
+  *
+  * \param jp The function entry join point for the current join point.
+  * The distributor advice will be inserted here.  Function entry join
+  * points are obtained by joining on an aop_match_function_entry()
+  * pointcut.
+  * \param func_name The name of the distributor advice function.
+  * \param ... A list of arguments to pass to the advice function,
+  * terminated by #AOP_TERM_ARG.
+  */
+ void
+ aop_duplicate (struct aop_joinpoint *jp, const char *func_name, ...)
+ {
+   va_list argp;
+   gimple func_call;
+   struct aop_pointcut *pc;
+   pc = jp->pc;
+   if (pc->kind != ATP_ENTRY)
+     fatal_error ("(InterAspect) Function duplication must be done on a"
+                " function entry join point.");
+   else if (jp->is_prepared)
+     fatal_error ("(InterAspect) Illegal to duplicate using a join point that"
+                " has already been used to insert advice.");
+   else if (is_current_func_duplicated())
+     fatal_error ("(InterAspect) Cannot duplicate a function more than once.");
+   va_start (argp, func_name);
+   func_call = build_gcc_call (func_name, integer_type_node, AOP_INSERT_BEFORE,
+                             argp);
+   va_end (argp);
+   duplicate_function_body ("ia_body_index", func_call);
+ }
diff --cc src/aop.h
index d2d40bafa59ce53e4d637f961533c48d373dcbeb,3bc065a8a032cc90b5016191955ef6a4cf7e45d8..050f7b5755937abff5f93e867ee8df7ce5f13468
+++ b/src/aop.h
@@@ -263,7 -286,44 +286,49 @@@ extern struct aop_dynval *aop_capture_l
  extern const char *aop_capture_lhs_name (struct aop_joinpoint *jp);
  extern struct aop_dynval *aop_capture_assigned_value (struct aop_joinpoint *jp);
  
 +extern int aop_write_c_header (const char *filename, const char *guard,
 +                             const char *license, const char *preamble);
 +
++
+ /**
+  * \defgroup scope_val aop_capture_lhs_var_scope() Return Values
+  *
+  * The aop_capture_lhs_var_scope() returns one of these values when
+  * the variable assigned to does not have function local scope (or
+  * when the assignment does not assign directly to a variable).
+  * \{
+  */
+ /**
+  * The variable is accessible by name from anywhere in the program.
+  */
+ #define AOP_GLOBAL_SCOPE -1
+ /**
+  * The variable is only accessible by name from the current file.
+  */
+ #define AOP_FILE_SCOPE -2
+ /**
+  * Used for an assignment that does not assign to a variable.  For
+  * example, the assignment may be to a field in a struct or a
+  * dereferenced pointer.
+  */
+ #define AOP_MEMORY_SCOPE -3
+ /**
+  * Use this macro to check if a variable has function-local scope.
+  */
+ #define AOP_LOCAL_SCOPE(SCOPE) (SCOPE >= 0)
+ /* Close Doxygen defgroup block. */
+ /**
+  * \}
+  */
+ extern int aop_capture_lhs_var_scope (struct aop_joinpoint *jp);
+ extern int aop_capture_lineno (struct aop_joinpoint *jp);
+ extern const char *aop_capture_file_name (struct aop_joinpoint *jp);
++
  #endif