From 48f3329afe60d491bbeb6a8b6ea54a5ca53ceb47 Mon Sep 17 00:00:00 2001 From: taijusti Date: Mon, 6 Jul 2015 12:05:18 -0400 Subject: [PATCH 1/6] changes for compatibility with Fedora 21 and gcc 4.9.2 --- gcc-c-api/gcc-callgraph.c | 2 -- tests/cpychecker/absinterp/comparisons/conditionals/stdout.txt | 2 +- tests/plugin/rtl/stdout.txt | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/gcc-c-api/gcc-callgraph.c b/gcc-c-api/gcc-callgraph.c index aa05a53d..ba2486b7 100644 --- a/gcc-c-api/gcc-callgraph.c +++ b/gcc-c-api/gcc-callgraph.c @@ -23,9 +23,7 @@ #include "ggc.h" #include "tree-ssa-alias.h" #include "basic-block.h" -#if (GCC_VERSION >= 5000) #include "gimple-expr.h" -#endif #include "gimple.h" /*********************************************************** diff --git a/tests/cpychecker/absinterp/comparisons/conditionals/stdout.txt b/tests/cpychecker/absinterp/comparisons/conditionals/stdout.txt index a305545f..b63a5447 100644 --- a/tests/cpychecker/absinterp/comparisons/conditionals/stdout.txt +++ b/tests/cpychecker/absinterp/comparisons/conditionals/stdout.txt @@ -23,4 +23,4 @@ Trace 0: 'taking True path' 'returning' Exception: - (struct PyObject *)0 from tests/cpychecker/absinterp/comparisons/conditionals/input.c:29 + (struct PyObject *)0 from tests/cpychecker/absinterp/comparisons/conditionals/input.c:32 diff --git a/tests/plugin/rtl/stdout.txt b/tests/plugin/rtl/stdout.txt index 46f5ad75..77c3c521 100644 --- a/tests/plugin/rtl/stdout.txt +++ b/tests/plugin/rtl/stdout.txt @@ -13,7 +13,7 @@ class Rtl(__builtin__.object) | Data descriptors defined here: | | loc - | Source code location of this expression, as a gcc.Location + | Source code location of this instruction, as a gcc.Location | | operands | Operands of this expression, as a tuple From 44ea4288e82a729d1a5c060044ee9e76b6372c11 Mon Sep 17 00:00:00 2001 From: taijusti Date: Mon, 6 Jul 2015 19:49:35 -0400 Subject: [PATCH 2/6] intermediate commit, having trouble converting python callable object to C function pointer --- Makefile | 1 + gcc-python-callbacks.c | 18 ++++++++++++++++++ gcc-python-pragma.c | 30 ++++++++++++++++++++++++++++++ gcc-python-wrappers.h | 4 ++++ gcc-python.c | 5 +++++ 5 files changed, 58 insertions(+) create mode 100644 gcc-python-pragma.c diff --git a/Makefile b/Makefile index fc8bbeee..d2d6e05f 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,7 @@ PLUGIN_SOURCE_FILES= \ gcc-python-option.c \ gcc-python-parameter.c \ gcc-python-pass.c \ + gcc-python-pragma.c \ gcc-python-pretty-printer.c \ gcc-python-rtl.c \ gcc-python-tree.c \ diff --git a/gcc-python-callbacks.c b/gcc-python-callbacks.c index e8a42aa8..d8a3bb8e 100644 --- a/gcc-python-callbacks.c +++ b/gcc-python-callbacks.c @@ -293,6 +293,17 @@ PyGcc_CallbackFor_GGC_END(void *gcc_data, void *user_data) user_data); } +static void +PyGcc_CallbackFor_PRAGMAS(void *gcc_data, void *user_data) +{ + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); + + PyGcc_FinishInvokingCallback(gstate, + 0, NULL, + user_data); +} PyObject* PyGcc_RegisterCallback(PyObject *self, PyObject *args, PyObject *kwargs) @@ -386,6 +397,13 @@ PyGcc_RegisterCallback(PyObject *self, PyObject *args, PyObject *kwargs) break; #endif /* GCC_PYTHON_PLUGIN_CONFIG_has_PLUGIN_FINISH_DECL */ + case PLUGIN_PRAGMAS: + register_callback("python", // FIXME + (enum plugin_event)event, + PyGcc_CallbackFor_PRAGMAS, + closure); + break; + default: PyErr_Format(PyExc_ValueError, "event type %i invalid (or not wired up yet)", event); return NULL; diff --git a/gcc-python-pragma.c b/gcc-python-pragma.c new file mode 100644 index 00000000..e1511cfb --- /dev/null +++ b/gcc-python-pragma.c @@ -0,0 +1,30 @@ +// TODO: copyright stuff + +#include +#include "gcc-python.h" +#include "gcc-python-wrappers.h" + +#include "plugin.h" +#include + +PyObject* +PyGcc_CRegisterPragma(PyObject *self, PyObject *args, PyObject *kwargs) +{ + const char *directive_space = NULL; + const char *directive = NULL; + PyObject *callback = NULL; + + if (!PyArg_ParseTuple(args, + "ssO:c_register_pragma", + &directive_space, + &directive, + &callback)) { + printf("error %s\n", __FUNCTION__); + return NULL; + } + + // TODO: error here. how do we pass a python callback to gcc? + c_register_pragma(directive_space, directive, (pragma_handler_1arg)callback); + + Py_RETURN_NONE; +} diff --git a/gcc-python-wrappers.h b/gcc-python-wrappers.h index 5cc6437b..ddab46a5 100644 --- a/gcc-python-wrappers.h +++ b/gcc-python-wrappers.h @@ -131,6 +131,10 @@ PyGcc_inform(PyObject *self, PyObject *args, PyObject *kwargs); extern PyObject * PyGccPass_New(struct opt_pass *pass); +/* gcc-python-pragmas.c */ +PyObject* +PyGcc_CRegisterPragma(PyObject *self, PyObject *args, PyObject *kwargs); + /* gcc-python-location.c: */ PyObject * PyGccLocation_repr(struct PyGccLocation * self); diff --git a/gcc-python.c b/gcc-python.c index 0e75313e..df92b2e1 100644 --- a/gcc-python.c +++ b/gcc-python.c @@ -400,6 +400,11 @@ static PyMethodDef GccMethods[] = { (METH_VARARGS | METH_KEYWORDS), "Pre-define a named value in the preprocessor."}, + {"c_register_pragma", + (PyCFunction)PyGcc_CRegisterPragma, + (METH_VARARGS | METH_KEYWORDS), + "Register a callback for whenever a user defined pragma is parsed."}, + /* Diagnostics: */ {"permerror", PyGcc_permerror, METH_VARARGS, NULL}, From 110461838c9eea97a3d49d0d29c1a92e95d6f629 Mon Sep 17 00:00:00 2001 From: taijusti Date: Tue, 7 Jul 2015 15:57:44 -0400 Subject: [PATCH 3/6] c_register_callback works, need to implement c_register_callback_with_data, etc. --- gcc-python-pragma.c | 16 +++++++++++----- gcc-python-wrappers.h | 4 ++-- gcc-python.c | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/gcc-python-pragma.c b/gcc-python-pragma.c index e1511cfb..6ddab218 100644 --- a/gcc-python-pragma.c +++ b/gcc-python-pragma.c @@ -7,24 +7,30 @@ #include "plugin.h" #include +void pragma_callback(struct cpp_reader * cpp_reader, void * data) { + PyObject * callback = (PyObject *) data; + PyObject_CallObject(callback, NULL); +} + PyObject* -PyGcc_CRegisterPragma(PyObject *self, PyObject *args, PyObject *kwargs) +PyGcc_CRegisterPragma(PyObject *self, PyObject *args) { + printf("%s\n", __FUNCTION__); + const char *directive_space = NULL; const char *directive = NULL; PyObject *callback = NULL; + //PyObject dummy; if (!PyArg_ParseTuple(args, "ssO:c_register_pragma", &directive_space, &directive, &callback)) { - printf("error %s\n", __FUNCTION__); return NULL; } - // TODO: error here. how do we pass a python callback to gcc? - c_register_pragma(directive_space, directive, (pragma_handler_1arg)callback); - + c_register_pragma_with_data(directive_space, directive, pragma_callback, (void *) callback); + Py_RETURN_NONE; } diff --git a/gcc-python-wrappers.h b/gcc-python-wrappers.h index ddab46a5..1f52d77e 100644 --- a/gcc-python-wrappers.h +++ b/gcc-python-wrappers.h @@ -131,9 +131,9 @@ PyGcc_inform(PyObject *self, PyObject *args, PyObject *kwargs); extern PyObject * PyGccPass_New(struct opt_pass *pass); -/* gcc-python-pragmas.c */ +/* gcc-python-pragma.c */ PyObject* -PyGcc_CRegisterPragma(PyObject *self, PyObject *args, PyObject *kwargs); +PyGcc_CRegisterPragma(PyObject *self, PyObject *args); /* gcc-python-location.c: */ PyObject * diff --git a/gcc-python.c b/gcc-python.c index df92b2e1..c01d274d 100644 --- a/gcc-python.c +++ b/gcc-python.c @@ -402,7 +402,7 @@ static PyMethodDef GccMethods[] = { {"c_register_pragma", (PyCFunction)PyGcc_CRegisterPragma, - (METH_VARARGS | METH_KEYWORDS), + METH_VARARGS, "Register a callback for whenever a user defined pragma is parsed."}, /* Diagnostics: */ From df200821a0b65c5eb2ce790dc6005e31d970e368 Mon Sep 17 00:00:00 2001 From: taijusti Date: Tue, 7 Jul 2015 16:16:35 -0400 Subject: [PATCH 4/6] cleanup --- gcc-python-callbacks.c | 14 +++++++------- gcc-python-pragma.c | 23 ++++++++++++++++------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/gcc-python-callbacks.c b/gcc-python-callbacks.c index d8a3bb8e..94931c70 100644 --- a/gcc-python-callbacks.c +++ b/gcc-python-callbacks.c @@ -387,6 +387,13 @@ PyGcc_RegisterCallback(PyObject *self, PyObject *args, PyObject *kwargs) closure); break; + case PLUGIN_PRAGMAS: + register_callback("python", // FIXME + (enum plugin_event)event, + PyGcc_CallbackFor_PRAGMAS, + closure); + break; + /* PLUGIN_FINISH_DECL was added in gcc 4.7 onwards: */ #ifdef GCC_PYTHON_PLUGIN_CONFIG_has_PLUGIN_FINISH_DECL case PLUGIN_FINISH_DECL: @@ -397,13 +404,6 @@ PyGcc_RegisterCallback(PyObject *self, PyObject *args, PyObject *kwargs) break; #endif /* GCC_PYTHON_PLUGIN_CONFIG_has_PLUGIN_FINISH_DECL */ - case PLUGIN_PRAGMAS: - register_callback("python", // FIXME - (enum plugin_event)event, - PyGcc_CallbackFor_PRAGMAS, - closure); - break; - default: PyErr_Format(PyExc_ValueError, "event type %i invalid (or not wired up yet)", event); return NULL; diff --git a/gcc-python-pragma.c b/gcc-python-pragma.c index 6ddab218..735dc906 100644 --- a/gcc-python-pragma.c +++ b/gcc-python-pragma.c @@ -1,4 +1,9 @@ -// TODO: copyright stuff +/* + FIXME: copyright stuff + FIXME: implement support for c_register_pragma_with_data, + c_register_pragma_with_expansion, + c_register_pragma_with_expansion_and_data + */ #include #include "gcc-python.h" @@ -7,20 +12,24 @@ #include "plugin.h" #include -void pragma_callback(struct cpp_reader * cpp_reader, void * data) { - PyObject * callback = (PyObject *) data; +void handle_python_pragma(struct cpp_reader *cpp_reader, void *data) { + PyObject * callback = (PyObject*)data; + + /* Debug code: */ + if (0) { + printf("handle_python_pragma called\n"); + fprintf(stderr, "cpp_reader: %p\n", cpp_reader); + } + PyObject_CallObject(callback, NULL); } PyObject* PyGcc_CRegisterPragma(PyObject *self, PyObject *args) { - printf("%s\n", __FUNCTION__); - const char *directive_space = NULL; const char *directive = NULL; PyObject *callback = NULL; - //PyObject dummy; if (!PyArg_ParseTuple(args, "ssO:c_register_pragma", @@ -30,7 +39,7 @@ PyGcc_CRegisterPragma(PyObject *self, PyObject *args) return NULL; } - c_register_pragma_with_data(directive_space, directive, pragma_callback, (void *) callback); + c_register_pragma_with_data(directive_space, directive, pragma_callback, (void*)callback); Py_RETURN_NONE; } From ec1520b22d64437ffff12b8989a74260db419943 Mon Sep 17 00:00:00 2001 From: taijusti Date: Tue, 7 Jul 2015 17:54:56 -0400 Subject: [PATCH 5/6] messy impementation, but works --- gcc-python-pragma.c | 47 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/gcc-python-pragma.c b/gcc-python-pragma.c index 735dc906..78845180 100644 --- a/gcc-python-pragma.c +++ b/gcc-python-pragma.c @@ -12,16 +12,59 @@ #include "plugin.h" #include +unsigned char * +parse_pragma_params (cpp_reader *pfile) +{ + const cpp_token *token; + unsigned int out = 0; + unsigned int alloced = 120 + out; + unsigned char *result = (unsigned char *) xmalloc (alloced); + + token = cpp_get_token (pfile); + while (token->type != CPP_EOF && token->type != CPP_PRAGMA_EOL) + { + unsigned char *last; + /* Include room for a possible space and the terminating nul. */ + unsigned int len = cpp_token_len (token) + 2; + + if (out + len > alloced) + { + alloced *= 2; + if (out + len > alloced) + alloced = out + len; + result = (unsigned char *) xrealloc (result, alloced); + } + + last = cpp_spell_token (pfile, token, &result[out], 0); + out = last - result; + + token = cpp_get_token (pfile); + if (token->flags & PREV_WHITE) + result[out++] = ' '; + + if (token->type == CPP_PRAGMA_EOL) + _cpp_backup_tokens(pfile, 1); + } + + result[out] = '\0'; + return result; +} + void handle_python_pragma(struct cpp_reader *cpp_reader, void *data) { PyObject * callback = (PyObject*)data; + /* Debug code: */ if (0) { printf("handle_python_pragma called\n"); fprintf(stderr, "cpp_reader: %p\n", cpp_reader); } - PyObject_CallObject(callback, NULL); + + const unsigned char * thing = parse_pragma_params(cpp_reader); + printf("%s\n", thing); + PyObject * args = Py_BuildValue("s", thing); + PyObject_CallObject(callback, args); } PyObject* @@ -39,7 +82,7 @@ PyGcc_CRegisterPragma(PyObject *self, PyObject *args) return NULL; } - c_register_pragma_with_data(directive_space, directive, pragma_callback, (void*)callback); + c_register_pragma_with_data(directive_space, directive, handle_python_pragma, (void*)callback); Py_RETURN_NONE; } From 4d7c7465ef0b450b576a8d0d53eb1855de7d992d Mon Sep 17 00:00:00 2001 From: taijusti Date: Tue, 7 Jul 2015 19:29:24 -0400 Subject: [PATCH 6/6] works for my own tests, but lto test fails because it can't find cpp_reader --- gcc-python-pragma.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/gcc-python-pragma.c b/gcc-python-pragma.c index 78845180..15083853 100644 --- a/gcc-python-pragma.c +++ b/gcc-python-pragma.c @@ -12,7 +12,7 @@ #include "plugin.h" #include -unsigned char * +static unsigned char * parse_pragma_params (cpp_reader *pfile) { const cpp_token *token; @@ -51,8 +51,11 @@ parse_pragma_params (cpp_reader *pfile) } void handle_python_pragma(struct cpp_reader *cpp_reader, void *data) { - PyObject * callback = (PyObject*)data; + PyObject *callback = NULL; + PyObject *user_args = NULL; + // unpack the {callback, args} tuple from the pragma registration + PyArg_ParseTuple((PyObject*)data, "OO", &callback, &user_args); /* Debug code: */ if (0) { @@ -60,11 +63,8 @@ void handle_python_pragma(struct cpp_reader *cpp_reader, void *data) { fprintf(stderr, "cpp_reader: %p\n", cpp_reader); } - - const unsigned char * thing = parse_pragma_params(cpp_reader); - printf("%s\n", thing); - PyObject * args = Py_BuildValue("s", thing); - PyObject_CallObject(callback, args); + PyObject * pragma_args = Py_BuildValue("s", parse_pragma_params(cpp_reader)); + PyObject_CallFunctionObjArgs(callback, pragma_args, user_args, NULL); } PyObject* @@ -73,16 +73,36 @@ PyGcc_CRegisterPragma(PyObject *self, PyObject *args) const char *directive_space = NULL; const char *directive = NULL; PyObject *callback = NULL; + PyObject *user_args = NULL; + unsigned char withExpansion = 0; + PyObject *packed_args = NULL; + // parse the python tuple if (!PyArg_ParseTuple(args, - "ssO:c_register_pragma", + "ssOOb:c_register_pragma", &directive_space, &directive, - &callback)) { + &callback, + &user_args, + &withExpansion)) { return NULL; } - c_register_pragma_with_data(directive_space, directive, handle_python_pragma, (void*)callback); + // pack callback and args so that they can be passed as a single argument + // to the pragma handler + packed_args = Py_BuildValue("OO", callback, user_args); + + // register the new callback + if (withExpansion) + { + c_register_pragma_with_expansion_and_data(directive_space, directive, + handle_python_pragma, (void*)packed_args); + } + else + { + c_register_pragma_with_data(directive_space, directive, handle_python_pragma, + (void*)packed_args); + } Py_RETURN_NONE; }