This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [plugins] Add user attribute(try #2)


Diego Novillo wrote:
On Wed, Apr 22, 2009 at 19:16, Taras Glek <tglek@mozilla.com> wrote:

+void
+register_attribute (const struct attribute_spec *attr)
+{

Needs comment.


--- a/gcc/gcc-plugin.h
+++ b/gcc/gcc-plugin.h
@@ -29,6 +29,7 @@ enum plugin_event
PLUGIN_CXX_CP_PRE_GENERICIZE, /* Allows to see low level AST in C++ FE. */
PLUGIN_FINISH, /* Called before GCC exits. */
PLUGIN_INFO, /* Information about the plugin */
+ PLUGIN_ATTRIBUTES, /* Called during attribute registration */

Needs to be added to plugins.texi.


Also, could you add a testcase and documentation on how plugins
should use this mechanism?

Finally, the patch needs a ChangeLog entry.
Docs + testcase made for a big changelog.

2009-05-12 Taras Glek <tglek@mozilla.com>
gcc/ChangeLog
* attribs.c moved out attribute registration into register_attribute
* doc/plugins.texi Documented register_attribute and PLUGIN_ATTRIBUTES
* gcc-plugin.h Added forward decl for register_attribute
* plugin.c Added PLUGIN_ATTRIBUTES boilerplate
* plugin.h Added PLUGIN_ATTRIBUTES


gcc/testsuite/ChangeLog
* g++.dg/plugin/attribute_plugin-test-1.C Testcase input for custom attributes and decl smashing
* g++.dg/plugin/attribute_plugin.c Testcase plugin to test user attributes
* g++.dg/plugin/dumb_plugin.c Fixed typo
* g++.dg/plugin/plugin.exp Added attribute_plugin test


The testcase has 2 XFails which will turn to PASSes once decl smashing fix lands (http://gcc.gnu.org/ml/gcc-patches/2009-05/msg00657.html)

Hope this is it,
Taras
diff --git a/gcc/attribs.c b/gcc/attribs.c
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.  
 #include "target.h"
 #include "langhooks.h"
 #include "hashtab.h"
+#include "plugin.h"
 
 static void init_attributes (void);
 
@@ -182,18 +183,27 @@ init_attributes (void)
   for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
     for (k = 0; attribute_tables[i][k].name != NULL; k++)
       {
+        register_attribute (&attribute_tables[i][k]);
+      }
+  invoke_plugin_callbacks (PLUGIN_ATTRIBUTES, NULL);
+  attributes_initialized = true;
+}
+
+/* Insert a single attribute into the attribute table */
+
+void
+register_attribute (const struct attribute_spec *attr) 
+{
 	struct substring str;
 	const void **slot;
 
-	str.str = attribute_tables[i][k].name;
-	str.length = strlen (attribute_tables[i][k].name);
+	str.str = attr->name;
+	str.length = strlen (str.str);
 	slot = (const void **)htab_find_slot_with_hash (attribute_hash, &str,
 					 substring_hash (str.str, str.length),
 					 INSERT);
 	gcc_assert (!*slot);
-	*slot = &attribute_tables[i][k];
-      }
-  attributes_initialized = true;
+	*slot = attr;
 }
 
 /* Return the spec for the attribute named NAME.  */
diff --git a/gcc/doc/plugins.texi b/gcc/doc/plugins.texi
--- a/gcc/doc/plugins.texi
+++ b/gcc/doc/plugins.texi
@@ -71,6 +71,7 @@ enum plugin_event
   PLUGIN_FINISH_UNIT,           /* Useful for summary processing.  */
   PLUGIN_CXX_CP_PRE_GENERICIZE, /* Allows to see low level AST in C++ FE.  */
   PLUGIN_FINISH,                /* Called before GCC exits.  */
+  PLUGIN_ATTRIBUTES,            /* Called during attribute registration */
   PLUGIN_EVENT_LAST             /* Dummy event used for indexing callback
                                    array.  */
 @};
@@ -135,3 +136,35 @@ plugin_init (const char *plugin_name, in
   ...
 @}
 @end smallexample
+@section Registering custom attributes
+
+For analysis purposes it is useful to be able to add custom attributes.
+
+The @code{PLUGIN_ATTRIBUTES} callback is called during attribute
+registration. Use the @code{register_attribute} function to register
+custom attributes.
+
+@smallexample
+/* Attribute handler callback */
+static tree
+handle_user_attribute (tree *node, tree name, tree args,
+			int flags, bool *no_add_attrs)
+@{
+  return NULL_TREE;
+@}
+
+/* Attribute definition */
+static struct attribute_spec user_attr =
+  @{ "user", 1, 1, false,  false, false, handle_user_attribute @};
+
+/* Plugin callback called during attribute registration.
+Registered with register_callback (plugin_name, PLUGIN_ATTRIBUTES, register_attributes, NULL)
+*/
+static void 
+register_attributes (void *event_data, void *data)
+@{
+  warning (0, G_("Callback to register attributes"));
+  register_attribute (&user_attr);
+@}
+
+@end smallexample
diff --git a/gcc/gcc-plugin.h b/gcc/gcc-plugin.h
--- a/gcc/gcc-plugin.h
+++ b/gcc/gcc-plugin.h
@@ -29,6 +29,7 @@ enum plugin_event
   PLUGIN_CXX_CP_PRE_GENERICIZE, /* Allows to see low level AST in C++ FE.  */
   PLUGIN_FINISH,                /* Called before GCC exits.  */
   PLUGIN_INFO,                  /* Information about the plugin */
+  PLUGIN_ATTRIBUTES,            /* Called during attribute registration */
   PLUGIN_EVENT_LAST             /* Dummy event used for indexing callback
                                    array.  */
 };
diff --git a/gcc/plugin.c b/gcc/plugin.c
--- a/gcc/plugin.c
+++ b/gcc/plugin.c
@@ -493,6 +493,7 @@ register_callback (const char *plugin_na
       case PLUGIN_FINISH_TYPE:
       case PLUGIN_FINISH_UNIT:
       case PLUGIN_CXX_CP_PRE_GENERICIZE:
+      case PLUGIN_ATTRIBUTES:
       case PLUGIN_FINISH:
         {
           struct callback_info *new_callback;
@@ -534,6 +535,7 @@ invoke_plugin_callbacks (enum plugin_eve
       case PLUGIN_FINISH_TYPE:
       case PLUGIN_FINISH_UNIT:
       case PLUGIN_CXX_CP_PRE_GENERICIZE:
+      case PLUGIN_ATTRIBUTES:
       case PLUGIN_FINISH:
         {
           /* Iterate over every callback registered with this event and
diff --git a/gcc/plugin.h b/gcc/plugin.h
--- a/gcc/plugin.h
+++ b/gcc/plugin.h
@@ -22,6 +22,8 @@ along with GCC; see the file COPYING3.  
 
 #include "gcc-plugin.h"
 
+struct attribute_spec;
+
 extern void add_new_plugin (const char *);
 extern void parse_plugin_arg_opt (const char *);
 extern void invoke_plugin_callbacks (enum plugin_event, void *);
@@ -33,4 +35,8 @@ extern void print_plugins_versions (FILE
 extern void print_plugins_help (FILE *file, const char *indent);
 extern void finalize_plugins (void);
 
+/* in attribs.c */
+
+extern void register_attribute (const struct attribute_spec *attr);
+
 #endif /* PLUGIN_H */
diff --git a/gcc/testsuite/g++.dg/plugin/attribute_plugin-test-1.C b/gcc/testsuite/g++.dg/plugin/attribute_plugin-test-1.C
new file mode 100644
--- /dev/null
+++ b/gcc/testsuite/g++.dg/plugin/attribute_plugin-test-1.C
@@ -0,0 +1,16 @@
+// { dg-warning "Callback to register attributes" }
+
+void normal_func (char c, char c2);
+void normal_func (char __attribute__((user("param"))) c, char);
+void normal_func (char c, char __attribute__((user("param"))) c2) 
+{
+} // { dg-warning "attribute 'user' on param 'c' of function normal_func" "" { xfail *-*-* } }
+// { dg-warning "attribute 'user' on param 'c2' of function normal_func" "" { target *-*-* } 7 }
+
+class Foo {
+  void method (char __attribute__((user("param"))) c);
+};
+
+void Foo::method(char c) 
+{
+} // { dg-warning "attribute 'user' on param 'c' of function method" "" { xfail *-*-* } }
diff --git a/gcc/testsuite/g++.dg/plugin/attribute_plugin.c b/gcc/testsuite/g++.dg/plugin/attribute_plugin.c
new file mode 100644
--- /dev/null
+++ b/gcc/testsuite/g++.dg/plugin/attribute_plugin.c
@@ -0,0 +1,66 @@
+/* Demonstrates how to add custom attributes */
+
+#include <stdlib.h>
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "tree-pass.h"
+#include "intl.h"
+#include "gcc-plugin.h"
+
+/* Attribute handler callback */
+
+static tree
+handle_user_attribute (tree *node, tree name, tree args,
+			int flags, bool *no_add_attrs)
+{
+  return NULL_TREE;
+}
+
+/* Attribute definition */
+
+static struct attribute_spec user_attr =
+  { "user", 1, 1, false,  false, false, handle_user_attribute };
+
+/* Plugin callback called during attribute registration */
+
+static void 
+register_attributes (void *event_data, void *data) 
+{
+  warning (0, G_("Callback to register attributes"));
+  register_attribute (&user_attr);
+}
+
+/* Callback function to invoke before the function body is genericized.  */ 
+
+void
+handle_pre_generic (void *event_data, void *data)
+{
+  tree fndecl = (tree) event_data;
+  tree arg;
+  for (arg = DECL_ARGUMENTS(fndecl); arg; arg = TREE_CHAIN (arg)) {
+      tree attr;
+      for (attr = DECL_ATTRIBUTES (arg); attr; attr = TREE_CHAIN (attr)) {
+          tree attrname = TREE_PURPOSE (attr);
+          tree attrargs = TREE_VALUE (attr);
+          warning (0, G_("attribute '%s' on param '%s' of function %s"),
+                   IDENTIFIER_POINTER (attrname),
+                   IDENTIFIER_POINTER (DECL_NAME (arg)),
+                   IDENTIFIER_POINTER (DECL_NAME (fndecl))
+                   );
+      }
+  }
+}
+
+int
+plugin_init (const char *plugin_name,
+             struct plugin_gcc_version *version,
+             int argc, struct plugin_argument *argv)
+{
+  register_callback (plugin_name, PLUGIN_CXX_CP_PRE_GENERICIZE,
+                     handle_pre_generic, NULL);
+
+  register_callback (plugin_name, PLUGIN_ATTRIBUTES, register_attributes, NULL);
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/plugin/dumb_plugin.c b/gcc/testsuite/g++.dg/plugin/dumb_plugin.c
--- a/gcc/testsuite/g++.dg/plugin/dumb_plugin.c
+++ b/gcc/testsuite/g++.dg/plugin/dumb_plugin.c
@@ -21,7 +21,7 @@ handle_struct (void *event_data, void *d
            IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
 }
 
-/* Callback function to invoke before the program is genericized.  */ 
+/* Callback function to invoke before the function body is genericized.  */ 
 
 void
 handle_pre_generic (void *event_data, void *data)
diff --git a/gcc/testsuite/g++.dg/plugin/plugin.exp b/gcc/testsuite/g++.dg/plugin/plugin.exp
--- a/gcc/testsuite/g++.dg/plugin/plugin.exp
+++ b/gcc/testsuite/g++.dg/plugin/plugin.exp
@@ -47,6 +47,7 @@ load_lib plugin-support.exp
 # Specify the plugin source file and the associated test files in a list.
 # plugin_test_list={ {plugin1 test1 test2 ...} {plugin2 test1 ...} ... }
 set plugin_test_list [list \
+    { attribute_plugin.c attribute_plugin-test-1.C } \
     { selfassign.c self-assign-test-1.C self-assign-test-2.C self-assign-test-3.C } \
     { dumb_plugin.c dumb-plugin-test-1.C } ]
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]