Hello,

This patch completes the pragma support in MELT. Now, a plugin can register several pragmas (with different name) in the following format (for GCC > 4.6):

#pragma MELT <name> <op> (<arg1>,...<argN>).

This pragma can be easily handle in a MELT function, giving the operator and the list of arguments as parameters.

For GCC<=4.6, there is a minimal pragma support, we can handle following pragma:

#pragma GCCPLUGIN melt <op> (<arg1>,...<argN>)

with only melt as name.

ChangeLog:

2011-06-24  Pierre Vittet <pier...@pvittet.com>

    * melt-runtime.c (GCC_PRAGMA_BAD): Macro to return an error from the
    pragma handling system.
    [__GNUC__>4.6](melt_handle_melt_pragma, handle_melt_pragma,
    melt_pragma_callback): Add functions for full pragma handling.
    [__GNUC__<=4.6](melt_handle_melt_pragma, handle_melt_pragma,
    melt_pragma_callback): Add functions for limited pragma handling.
    (melt_startunit_callback): Register a callback for pragma.
* Makefile.in (CFAMILYINC): We need c-family header in include headers.
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in     (revision 175348)
+++ gcc/Makefile.in     (working copy)
@@ -359,6 +359,9 @@ DECNUMFMT = $(srcdir)/../libdecnumber/$(enable_dec
 DECNUMINC = -I$(DECNUM) -I$(DECNUMFMT) -I../libdecnumber
 LIBDECNUMBER = ../libdecnumber/libdecnumber.a
 
+#c-family header
+CFAMILYINC=-I$(srcdir)/c-family
+
 # Target to use when installing include directory.  Either
 # install-headers-tar, install-headers-cpio or install-headers-cp.
 INSTALL_HEADERS_DIR = @build_install_headers_dir@
@@ -1096,8 +1099,8 @@ INCLUDES = -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@
           -I$(srcdir)/melt/generated \
           -I$(srcdir)/../include @INCINTL@ \
           $(CPPINC) $(GMPINC) $(DECNUMINC) \
-          $(PPLINC) $(CLOOGINC)
-
+          $(PPLINC) $(CLOOGINC) \
+          $(CFAMILYINC)
 .c.o:
        $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $< $(OUTPUT_OPTION)
 
Index: gcc/melt-runtime.c
===================================================================
--- gcc/melt-runtime.c  (revision 175348)
+++ gcc/melt-runtime.c  (working copy)
@@ -74,7 +74,9 @@ along with GCC; see the file COPYING3.   If not se
 #include "md5.h"
 #include "plugin.h"
 #include "cppdefault.h"
+#include "c-pragma.h"
 
+
 #if BUILDING_GCC_VERSION > 4005
 /* GCC 4.6 has realmpfr.h which includes <mpfr.h>  */
 #include "realmpfr.h"
@@ -8938,7 +8940,284 @@ melt_attribute_callback(void *gcc_data ATTRIBUTE_U
   register_attribute(&melt_attr_spec);
 }
 
+/* We declare weak functions because they cannot be linked when we use lto (it
+   loses langage specific informations).
+   If you use one of those functions you must check them to be not NULL.
+*/
+extern enum cpp_ttype __attribute__((weak)) pragma_lex (tree *);
 
+
+
+#define GCC_PRAGMA_BAD(gmsgid) \
+  do { warning (OPT_Wpragmas, gmsgid); goto end; } while (0)
+
+
+
+/* Test for GCC > 4.6.0 */
+#if __GNUC__ > 4 || \
+    (__GNUC__ == 4 && (__GNUC_MINOR__ > 6))
+/*Full pragma with data support.*/
+
+void melt_handle_melt_pragma (melt_ptr_t optreev, melt_ptr_t listargtreev,
+                              int indice_handler);
+
+extern void __attribute__((weak)) c_register_pragma_with_expansion_and_data
+                                    (const char *space, const char *name,
+                                     pragma_handler_2arg handler, void *data);
+
+/* handle a melt pragma: data contain the name of the command (as a string)*/
+static void
+handle_melt_pragma (cpp_reader *ARG_UNUSED(dummy), void * data)
+{
+  enum cpp_ttype token;
+  /*list containing the pragma argument*/
+  tree x;
+  int ihandler = (int) data;
+  MELT_ENTERFRAME (3, NULL);
+#define seqv      meltfram__.mcfr_varptr[0]
+#define treev     meltfram__.mcfr_varptr[1]
+#define optreev   meltfram__.mcfr_varptr[2]
+  if(! pragma_lex || ! c_register_pragma_with_expansion_and_data)
+    GCC_PRAGMA_BAD("Cannot use pragma symbol at this level \
+                   (maybe you use -flto which is incompatible).");
+
+  token = pragma_lex (&x);
+  if(token != CPP_NAME)
+    GCC_PRAGMA_BAD ("malformed #pragma melt, ignored");
+  optreev = meltgc_new_tree((meltobject_ptr_t) MELT_PREDEF (DISCR_TREE), x);
+  /*If the pragma has the form #pragma PLUGIN melt id (...) then optreev is the
+  tree containing "id".
+  Next element should be a parenthese opening. */
+  token = pragma_lex (&x);
+  if (token != CPP_OPEN_PAREN){
+    if (token != CPP_EOF)
+      GCC_PRAGMA_BAD ("malformed #pragma melt, ignored");
+
+    else{ /* we have a pragma of the type '#pragma PLUGIN melt instr' */
+      melt_handle_melt_pragma ((melt_ptr_t ) optreev, (melt_ptr_t ) NULL,
+                               ihandler);
+    }
+  }
+  else{/* opening parenthesis */
+    seqv = meltgc_new_list ((meltobject_ptr_t) MELT_PREDEF (DISCR_LIST));
+    do {
+      token = pragma_lex (&x);
+      if(token != CPP_NAME && token != CPP_STRING && token != CPP_NUMBER)
+        GCC_PRAGMA_BAD ("malformed #pragma melt, ignored");
+      /* convert gcc tree into a boxed tree */
+      treev = meltgc_new_tree((meltobject_ptr_t) MELT_PREDEF (DISCR_TREE), x);
+      /* put the arg in IDENTIFIER_POINTER (x) in a list */
+      meltgc_append_list ((melt_ptr_t) seqv, (melt_ptr_t) treev);
+      
+      token = pragma_lex (&x);
+      
+    } while (token == CPP_COMMA);
+
+    if (token == CPP_CLOSE_PAREN && pragma_lex(&x) == CPP_EOF)
+      melt_handle_melt_pragma ((melt_ptr_t ) optreev, (melt_ptr_t ) seqv,
+                               ihandler);
+    else
+      GCC_PRAGMA_BAD ("malformed #pragma melt, ignored");
+    
+  }
+end: MELT_EXITFRAME () ;
+#undef seqv
+#undef treev
+#undef optreev
+}
+
+/*We accept a full pragma handling, with the possibility of having the name
+  defined by the plugin. The name can be given to the handler using a data
+  field.  */
+
+/* The plugin callback to register melt pragmas: 
+To be accepted the pragma must have the following form:
+    #pragma GCCPLUGIN plugin_name op
+        or
+    #pragma GCCPLUGIN plugin_name op (arg1, arg2 , ...)
+        with argX as a name, a string or a number.
+*/
+static void
+melt_pragma_callback (void *gcc_data ATTRIBUTE_UNUSED,
+                      void* user_data ATTRIBUTE_UNUSED)
+{
+  int ihandler, nb_pragma = 0;
+  /*recover the sysdata_meltpragma_list */
+  MELT_ENTERFRAME (4, NULL);
+#define mulpragmav meltfram__.mcfr_varptr[0]
+#define cgccpragmav meltfram__.mcfr_varptr[1]
+#define pragmastrv meltfram__.mcfr_varptr[2]
+  mulpragmav = melt_get_inisysdata (FSYSDAT_MELTPRAGMAS);
+  if (melt_magic_discr ((melt_ptr_t) mulpragmav) != MELTOBMAG_MULTIPLE)
+    goto end;
+  nb_pragma = (int) (((meltmultiple_ptr_t) mulpragmav)->nbval);
+  for (ihandler = 0; ihandler < (int) nb_pragma; ihandler++)
+    {
+      cgccpragmav = (( struct meltmultiple_st *) mulpragmav)->tabval[ihandler];
+      if(!melt_is_instance_of ( (melt_ptr_t) cgccpragmav ,
+                              ( melt_ptr_t) MELT_PREDEF (CLASS_GCC_PRAGMA)))
+        {
+          GCC_PRAGMA_BAD("FSYSDAT_MELTPRAGMAS must contains only \
+          CLASS_GCC_PRAGMA object.");
+        }
+    pragmastrv = melt_object_nth_field((melt_ptr_t) cgccpragmav, FNAMED_NAME);
+    /*Register a new pass with the name registered in gcc_pragma object.  We
+      give it as data too, in order to use it in the handler.  */
+    c_register_pragma_with_expansion_and_data ("MELT", melt_string_str
+                               ((melt_ptr_t) pragmastrv), handle_melt_pragma,
+                                ((void *) ihandler));
+    }
+
+end: MELT_EXITFRAME () ;
+#undef mulpragmav
+#undef cgccpragmav
+#undef pragmastrv
+}
+
+/* Call the MELT function which handle pragma: it is one of the handler of the
+   list sysdata_meltpragmas.  First argument is a tree containing the operator
+   and the second argument contains a list of tree (the argument of the 
pragma). 
+   Third argument is the name of the handler to use.  */
+void melt_handle_melt_pragma (melt_ptr_t optreev, melt_ptr_t listargtreev,
+                              int indice_handler)
+{
+MELT_ENTERFRAME (4, NULL);
+#define pragclov     meltfram__.mcfr_varptr[0]
+#define cgccpragmav  meltfram__.mcfr_varptr[1]
+#define seqv         meltfram__.mcfr_varptr[2]
+#define mulpragmav   meltfram__.mcfr_varptr[3]
+  seqv = listargtreev;
+  /* We first recover the list of the handler.  */
+  mulpragmav = melt_get_inisysdata (FSYSDAT_MELTPRAGMAS);
+  if (melt_magic_discr ((melt_ptr_t) mulpragmav) != MELTOBMAG_MULTIPLE)
+    goto end;
+  /* We use the indice_handler to find the good handler.  */
+  cgccpragmav = melt_multiple_nth ((melt_ptr_t) mulpragmav, indice_handler);
+  pragclov= melt_object_nth_field((melt_ptr_t) cgccpragmav,
+                                     FGCCPRAGMA_HANDLER);
+  /* We have the good handler, so we apply it.  */
+  if (melt_magic_discr ((melt_ptr_t) pragclov) == MELTOBMAG_CLOSURE)
+    {
+      union meltparam_un pararg[1];
+      pararg[0].meltbp_aptr = (melt_ptr_t *) &seqv;
+
+      (void) melt_apply ((meltclosure_ptr_t) pragclov,
+          (melt_ptr_t) optreev,
+          MELTBPARSTR_PTR , pararg, "", NULL);
+      goto end;
+    }
+end: 
+  MELT_EXITFRAME ();
+#undef mulpragmav
+#undef pragclov
+#undef cgccpragmav
+#undef seqv
+}
+
+#else
+/*Limited pragma handling*/
+
+void melt_handle_melt_pragma (melt_ptr_t optreev, melt_ptr_t listargtreev);
+
+extern void __attribute__((weak)) c_register_pragma_with_expansion 
+                                      (const char *, const char *,
+                                       pragma_handler_1arg);
+
+/* handle a melt pragma*/
+static void
+handle_melt_pragma (cpp_reader *ARG_UNUSED(dummy))
+{
+  enum cpp_ttype token;
+  /*list containing the pragma argument*/
+  tree x;
+  MELT_ENTERFRAME (3, NULL);
+#define seqv      meltfram__.mcfr_varptr[0]
+#define treev     meltfram__.mcfr_varptr[1]
+#define optreev   meltfram__.mcfr_varptr[2]
+  if(! pragma_lex || ! c_register_pragma_with_expansion)
+    GCC_PRAGMA_BAD("Cannot use pragma symbol at this level (maybe you use 
-flto which \
+is incompatible).");
+
+  token = pragma_lex (&x);
+  if(token != CPP_NAME)
+    GCC_PRAGMA_BAD ("malformed #pragma melt, ignored");
+  optreev = meltgc_new_tree((meltobject_ptr_t) MELT_PREDEF (DISCR_TREE), x);
+  /*If the pragma has the form #pragma PLUGIN melt id (...) then optreev is the
+  tree containing "id".
+  Next element should be a parenthese opening. */
+  token = pragma_lex (&x);
+  if (token != CPP_OPEN_PAREN){
+    if (token != CPP_EOF)
+      GCC_PRAGMA_BAD ("malformed #pragma melt, ignored");
+    else{ /* we have a pragma of the type '#pragma PLUGIN melt instr' */
+      melt_handle_melt_pragma ((melt_ptr_t ) optreev, (melt_ptr_t ) NULL);
+    }
+  }
+  else{/* opening parenthesis */
+    seqv = meltgc_new_list ((meltobject_ptr_t) MELT_PREDEF (DISCR_LIST));
+    do {
+      token = pragma_lex (&x);
+      if(token != CPP_NAME && token != CPP_STRING && token != CPP_NUMBER)
+        GCC_PRAGMA_BAD ("malformed #pragma melt, ignored");
+      /* convert gcc tree into a boxed tree */
+      treev = meltgc_new_tree((meltobject_ptr_t) MELT_PREDEF (DISCR_TREE), x);
+      /* put the arg in IDENTIFIER_POINTER (x) in a list */
+      meltgc_append_list ((melt_ptr_t) seqv, (melt_ptr_t) treev);
+      
+      token = pragma_lex (&x);
+      
+    } while (token == CPP_COMMA);
+
+    if (token == CPP_CLOSE_PAREN && pragma_lex(&x) == CPP_EOF)
+      melt_handle_melt_pragma ((melt_ptr_t ) optreev, (melt_ptr_t ) seqv);
+    else
+      GCC_PRAGMA_BAD ("malformed #pragma melt, ignored");
+    
+  }
+end: MELT_EXITFRAME () ;
+#undef seqv
+#undef treev
+#undef optreev
+}
+
+
+/*Call the MELT function which handle pragma (sysdata_meltpragmas) and
+give as first argument a tree containing the operator and a second argument
+containing a list of tree (the argument of the pragma). */
+void melt_handle_melt_pragma (melt_ptr_t optreev, melt_ptr_t listargtreev)
+{
+MELT_ENTERFRAME (2, NULL);
+#define pragclov     meltfram__.mcfr_varptr[0]
+#define seqv    meltfram__.mcfr_varptr[1]
+  seqv = listargtreev;
+  /*Use the closure defined by the user wuth FSYSDAT_MELTPRAGMA_DEFINER */
+  pragclov = melt_get_inisysdata (FSYSDAT_MELTPRAGMA_DEFINER);
+  if (melt_magic_discr ((melt_ptr_t) pragclov) == MELTOBMAG_CLOSURE)
+    {
+      union meltparam_un pararg[1];
+      pararg[0].meltbp_aptr = (melt_ptr_t *) & seqv;
+
+
+      (void) melt_apply ((meltclosure_ptr_t) pragclov,
+          (melt_ptr_t) optreev,
+          MELTBPARSTR_PTR , pararg, "", NULL);
+      goto end;
+    }
+end: 
+  MELT_EXITFRAME ();
+#undef pragclov
+#undef seqv
+}
+
+static void 
+melt_pragma_callback (void *gcc_data ATTRIBUTE_UNUSED,
+                      void* user_data ATTRIBUTE_UNUSED) 
+{
+  c_register_pragma_with_expansion ("GCCPLUGIN", "melt", handle_melt_pragma);
+}
+
+#endif  /*GCC >4.6 for handling pragma support*/
+
 /* the plugin callback when starting a compilation unit */
 static void
 melt_startunit_callback(void *gcc_data ATTRIBUTE_UNUSED,
@@ -9195,6 +9474,8 @@ melt_really_initialize (const char* pluginame, con
   register_callback (melt_plugin_name, PLUGIN_ATTRIBUTES,
     melt_attribute_callback,
     NULL);
+  register_callback (melt_plugin_name, PLUGIN_PRAGMAS, melt_pragma_callback,
+    NULL);
   register_callback (melt_plugin_name, PLUGIN_START_UNIT,
     melt_startunit_callback,
     NULL);

Reply via email to