Hello,

The following patch allows to use pragma in a MELT plugin.
For exemple we can recover the following pragmas:

#pragma GCCPLUGIN melt op
        or
#pragma GCCPLUGIN melt op (arg1, arg2, ...)
        with argX a name, a string, or a number.

It is easy to change the pragma space ("GCCPLUGIN") and name ("melt"), so I am open to suggestion.

This plugin works on the MELT heart and so It need to regenerate the source.

The first .diff (addPragma-warmelt-first) contains the gcc/melt/warmelt-first.melt file: I have added a field in the MELT class_system_data class which allows the user to add a function handling pragma.

After adding this diff, it is needed to use 'make upgrade-warmelt' in the gcc directory to regenerate gcc/melt/generated.

After this, it is possible to add the second diff (addPragma-runtime): it contains change in gcc/melt-runtime.c and gcc/melt-runtime.h: it adds the melt_pragma_callback which register the pragma handler defined in the same file. The pragma handler calls the function defined by the user and gives it the trees corresponding to the pragma operator and argument.

I have been obliged to use weak symbols for pragma_lex and c_register_pragma as they are not defined when using lto. This is a temporary solution that I commented.

I am going to send a test in the Testsuite, but I have already tried it successfully with something like that:

(defun my_simple_pragma_handler(val1 lstarg)
  (debug_msg val1 "debugging melt pragma")
)

(put_fields
 initial_system_data
 :sysdata_meltpragma_definer my_simple_pragma_handler
)

Pierre Vittet

Index: gcc/melt/warmelt-first.melt
===================================================================
--- gcc/melt/warmelt-first.melt (revision 174379)
+++ gcc/melt/warmelt-first.melt (working copy)
@@ -436,6 +436,7 @@ don't instanciate this class!}#
           sysdata_pass_dict            ;stringmap for passes
           sysdata_exit_finalizer       ;;closure to be called after the 
passes, at finalization
           sysdata_meltattr_definer     ;;closure to be called for melt 
attributes
+          sysdata_meltpragma_definer   ;;closure to be called for melt pragma
           sysdata_patmacro_exporter    ;closure to export a patmacro
           sysdata_debugmsg             ;closure for debugmsg
           sysdata_stdout               ;raw file for stdout
Index: gcc/melt-runtime.c
===================================================================
--- gcc/melt-runtime.c  (revision 174379)
+++ gcc/melt-runtime.c  (working copy)
@@ -75,6 +75,7 @@ along with GCC; see the file COPYING3.   If not se
 #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"
@@ -8930,7 +8931,124 @@ 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 *);
+extern void __attribute__((weak)) c_register_pragma (const char *, const char
+*, pragma_handler);
 
+#define GCC_BAD(gmsgid) \
+  do { warning (OPT_Wpragmas, gmsgid); goto end; } while (0)
+
+
+void melt_handle_melt_pragma (melt_ptr_t optreev, melt_ptr_t listargtreev);
+
+/* 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)
+    GCC_BAD("Cannot use pragma symbol at this level (maybe you use -flto which 
\
+is incompatible).");
+
+  token = pragma_lex (&x);
+  if(token != CPP_NAME)
+    GCC_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_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_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_BAD ("malformed #pragma melt, ignored");
+    
+  }
+end: MELT_EXITFRAME () ;
+#undef seqv
+#undef treev
+#undef optreev
+}
+
+/*Call the MELT function which handle pragma (sysdata_meltpragma_definer) 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
+}
+
+/* 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) 
+{
+  c_register_pragma ("GCCPLUGIN", "melt", handle_melt_pragma);
+}
+
+
+
 /* the plugin callback when starting a compilation unit */
 static void
 melt_startunit_callback(void *gcc_data ATTRIBUTE_UNUSED,
@@ -9187,6 +9305,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);
Index: gcc/melt-runtime.h
===================================================================
--- gcc/melt-runtime.h  (revision 174379)
+++ gcc/melt-runtime.h  (working copy)
@@ -2261,6 +2261,7 @@ enum
   FSYSDAT_PASS_DICT,           /* dictionnary of passes */
   FSYSDAT_EXIT_FINALIZER,      /* closure to call at exit */
   FSYSDAT_MELTATTR_DEFINER,    /* closure for melt attributes */
+  FSYSDAT_MELTPRAGMA_DEFINER, /* closure for melt pragma*/
   FSYSDAT_PATMACRO_EXPORTER,    /* closure to export patmacro */
   FSYSDAT_DEBUGMSG,            /* closure for debugmsg */
   FSYSDAT_STDOUT,              /* raw boxed file for stdout */
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in     (revision 174379)
+++ gcc/Makefile.in     (working copy)
@@ -359,6 +359,10 @@ 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@
@@ -1091,7 +1095,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)

Reply via email to