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);