Added noinstrument attribute (with test case).
authorJustin Seyster <jseyster@cs.sunysb.edu>
Thu, 9 Sep 2010 00:18:56 +0000 (20:18 -0400)
committerJustin Seyster <jseyster@cs.sunysb.edu>
Thu, 9 Sep 2010 00:18:56 +0000 (20:18 -0400)
src/aop-main.c
test/Makefile.am
test/noinstrument-hooks.c [new file with mode: 0644]
test/noinstrument-target.c [new file with mode: 0644]
test/noinstrument.xml [new file with mode: 0644]
test/plugin-noinstrument.c [new file with mode: 0644]

index 95b21cede07132e5bbaf88cec473ad3d4a198a2d..89210f8fc8f4e7712839b4fc5f149fb7079337b9 100644 (file)
@@ -59,6 +59,8 @@
 
 //#define PAUSE_ON_START
 
+#define NOINSTR_ATTR "noinstrument"
+
 static const char *aop_plugin_name;
 
 static const struct plugin_argument *plugin_argv;
@@ -155,6 +157,51 @@ aop_join_on_copy (struct aop_pointcut *pc, int copy, join_callback callback,
   }
 }
 
+/* This is the "gate" function for all client plug-in passes that gets
+   to decide whether the pass will execute or not.*/
+static bool
+noinstrument_gate ()
+{
+  /* Execute the pass iff the current function is not annotated with
+     the noinstrument attribute. */
+  return (lookup_attribute (NOINSTR_ATTR, DECL_ATTRIBUTES (cfun->decl))
+         == NULL);
+}
+
+/* Register an attribute only if it has not yet been registered.  If
+   the user loads multiple InterAspect plug-ins, they will all try to
+   register the noinstrument attribute.  We have to make sure we don't
+   attempt to call GCC's register_attribute multiple times, or it will
+   throw an assertion failure! */
+static void
+register_attribute_once(const struct attribute_spec *attr)
+{
+  if (lookup_attribute_spec (get_identifier (attr->name)) == NULL)
+    register_attribute (attr);
+}
+
+static tree
+null_attrib_handler(tree *node, tree name, tree args, int flags, bool *no_add_attrs)
+{
+  return NULL_TREE;
+}
+
+static struct attribute_spec noinstr_attr = {
+  .name = NOINSTR_ATTR,
+  .min_length = 0,
+  .max_length = 0,
+  .decl_required = false,
+  .type_required = false,
+  .function_type_required = false,
+  .handler = null_attrib_handler,
+};
+
+static void
+register_plugin_attributes(void *event_data, void *data)
+{
+  register_attribute_once(&noinstr_attr);
+}
+
 /* This pass gets called before any passes that the client plug-in
    registers.  It's here for any administrative details that need to
    take place before the instrumentation passes can execute. */
@@ -288,6 +335,7 @@ aop_register_pass (const char *pass_name, pass_callback callback)
 
   pass_aop->name = xstrdup (pass_name);
   pass_aop->execute = callback;
+  pass_aop->gate = noinstrument_gate;
 
   pass_info.pass = pass_aop;
   pass_info.reference_pass_name = "veclower";
@@ -364,6 +412,9 @@ plugin_init (struct plugin_name_args *plugin_info,
   init_type_table ();
   init_prototype_table ();
 
+  /* Register attributes. */
+  register_callback(aop_plugin_name, PLUGIN_ATTRIBUTES, register_plugin_attributes, NULL);
+
   /* Register our cleanup function. */
   register_callback (aop_plugin_name, PLUGIN_FINISH, aop_cleanup, NULL);
 
index 11005db262c36d71da904e479991c1b5b0d37c30..8add3574591698f62484b24065f3705c766d073b 100644 (file)
@@ -3,5 +3,5 @@ TESTS_ENVIRONMENT = $(PYTHON) $(srcdir)/run-testcase.py --with-gcc=$(CC) \
        --with-ia-lib-dir=$(top_builddir)/src/.libs \
        --with-ia-src-dir=$(top_srcdir) --with-tests-dir=$(srcdir)
 TESTS = int-types.xml float-types.xml pointer-types.xml struct-types.xml \
-       reinst.xml
+       reinst.xml noinstrument.xml
 endif
diff --git a/test/noinstrument-hooks.c b/test/noinstrument-hooks.c
new file mode 100644 (file)
index 0000000..c7a0ea6
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+void _advice_foo()
+{
+  printf("In foo() advice.\n");
+}
diff --git a/test/noinstrument-target.c b/test/noinstrument-target.c
new file mode 100644 (file)
index 0000000..b7d0eef
--- /dev/null
@@ -0,0 +1,23 @@
+#include <stdio.h>
+
+void foo()
+{
+  printf("Call to foo().\n");
+}
+
+void instrumented()
+{
+  foo();
+}
+
+__attribute__((noinstrument)) void uninsrumented()
+{
+  foo();
+}
+
+int run_test()
+{
+  instrumented();
+  uninsrumented();
+  return 0;
+}
diff --git a/test/noinstrument.xml b/test/noinstrument.xml
new file mode 100644 (file)
index 0000000..85202a2
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE testcase SYSTEM "testcase.dtd">
+<testcase name="Noinstrument">
+  <plugin id="plugin-noinstrument" source="plugin-noinstrument.c" />
+  <run name="Noinstrument attribute" target="noinstrument-target.c" hooks="noinstrument-hooks.c">
+    <using plugin="plugin-noinstrument" />
+    <output>
+      In foo() advice.
+      Call to foo().
+      Call to foo().
+    </output>
+  </run>
+</testcase>
diff --git a/test/plugin-noinstrument.c b/test/plugin-noinstrument.c
new file mode 100644 (file)
index 0000000..4c281b3
--- /dev/null
@@ -0,0 +1,26 @@
+#include <aop.h>
+#include <stdio.h>
+#include <string.h>
+
+AOP_I_AM_GPL_COMPATIBLE();
+
+static void plugin_join_on_foo(struct aop_joinpoint *jp, void *data)
+{
+  aop_insert_advice(jp, "_advice_foo", AOP_INSERT_BEFORE, AOP_TERM_ARG);
+}
+
+static unsigned int plugin_noinstr()
+{
+  struct aop_pointcut *pc;
+
+  pc = aop_match_function_call();
+  aop_filter_call_pc_by_name (pc, "foo");
+  aop_join_on(pc, plugin_join_on_foo, NULL);
+
+  return 0;
+}
+
+AOP_MAIN_PROTO aop_main()
+{
+  aop_register_pass("noinstr", plugin_noinstr);
+}