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)