Skip to content

Add support for PLUGIN_PRAGMA event to gcc-python-plugin #29

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
2 changes: 0 additions & 2 deletions gcc-c-api/gcc-callgraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

/***********************************************************
Expand Down
18 changes: 18 additions & 0 deletions gcc-python-callbacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -376,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:
Expand Down
108 changes: 108 additions & 0 deletions gcc-python-pragma.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
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 <Python.h>
#include "gcc-python.h"
#include "gcc-python-wrappers.h"

#include "plugin.h"
#include <c-family/c-pragma.h>

static 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 = 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) {
printf("handle_python_pragma called\n");
fprintf(stderr, "cpp_reader: %p\n", cpp_reader);
}

PyObject * pragma_args = Py_BuildValue("s", parse_pragma_params(cpp_reader));
PyObject_CallFunctionObjArgs(callback, pragma_args, user_args, NULL);
}

PyObject*
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,
"ssOOb:c_register_pragma",
&directive_space,
&directive,
&callback,
&user_args,
&withExpansion)) {
return NULL;
}

// 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;
}
4 changes: 4 additions & 0 deletions gcc-python-wrappers.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ PyGcc_inform(PyObject *self, PyObject *args, PyObject *kwargs);
extern PyObject *
PyGccPass_New(struct opt_pass *pass);

/* gcc-python-pragma.c */
PyObject*
PyGcc_CRegisterPragma(PyObject *self, PyObject *args);

/* gcc-python-location.c: */
PyObject *
PyGccLocation_repr(struct PyGccLocation * self);
Expand Down
5 changes: 5 additions & 0 deletions gcc-python.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
"Register a callback for whenever a user defined pragma is parsed."},

/* Diagnostics: */
{"permerror", PyGcc_permerror, METH_VARARGS,
NULL},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion tests/plugin/rtl/stdout.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down