Skip to content

Add various features. Fix one bug. #191

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 19 commits into
base: master
Choose a base branch
from
Open
25 changes: 24 additions & 1 deletion gcc-python-callbacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,18 @@ PyGcc_CallbackFor_tree(void *gcc_data, void *user_data)
user_data);
}

static void
PyGcc_CallbackFor_string(void *gcc_data, void *user_data)
{
PyGILState_STATE gstate;
const char *str = (const char *)gcc_data;

gstate = PyGILState_Ensure();

PyGcc_FinishInvokingCallback(gstate,
1, PyGccString_FromString(str),
user_data);
}

static void
PyGcc_CallbackFor_PLUGIN_ATTRIBUTES(void *gcc_data, void *user_data)
Expand Down Expand Up @@ -375,7 +387,18 @@ PyGcc_RegisterCallback(PyObject *self, PyObject *args, PyObject *kwargs)
PyGcc_CallbackFor_GGC_END,
closure);
break;

case PLUGIN_FINISH_PARSE_FUNCTION:
register_callback("python", // FIXME
(enum plugin_event)event,
PyGcc_CallbackFor_tree,
closure);
break;
case PLUGIN_INCLUDE_FILE:
register_callback("python", // FIXME
(enum plugin_event)event,
PyGcc_CallbackFor_string,
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
2 changes: 1 addition & 1 deletion gcc-python-location.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ PyGccLocation_richcompare(PyObject *o1, PyObject *o2, int op)
long
PyGccLocation_hash(struct PyGccLocation * self)
{
return self->loc.inner;
return (unsigned long)(LOCATION_FILE(self->loc.inner)) ^ LOCATION_LINE(self->loc.inner);
}

#if (GCC_VERSION >= 5000)
Expand Down
168 changes: 168 additions & 0 deletions gcc-python-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "gcc-python.h"
#include "gcc-python-wrappers.h"
#include "gcc-python-compat.h"
#include "gcc-python-closure.h"
#include "cp/cp-tree.h"
#include "gimple.h"

Expand Down Expand Up @@ -121,6 +122,30 @@ do_pretty_print(struct PyGccTree * self, int spc, dump_flags_t flags)
if (!result) {
goto error;
}

Py_XDECREF(ppobj);
return result;

error:
Py_XDECREF(ppobj);
return NULL;
}

static PyObject *
do_decl_print(struct PyGccTree * self, int spc, dump_flags_t flags)
{
PyObject *ppobj = PyGccPrettyPrinter_New();
PyObject *result = NULL;
if (!ppobj) {
return NULL;
}

print_declaration (PyGccPrettyPrinter_as_pp(ppobj),
self->t.inner, spc, flags);
result = PyGccPrettyPrinter_as_string(ppobj);
if (!result) {
goto error;
}

Py_XDECREF(ppobj);
return result;
Expand Down Expand Up @@ -284,6 +309,12 @@ PyGccTree_get_str_no_uid(struct PyGccTree *self, void *closure)
return do_pretty_print(self, 0, TDF_NOUID);
}

PyObject *
PyGccTree_get_str_decl(struct PyGccTree *self, void *closure)
{
return do_decl_print(self, 0, TDF_NOUID);
}

PyObject *
PyGccTree_get_symbol(PyObject *cls, PyObject *args)
{
Expand All @@ -298,6 +329,84 @@ PyGccTree_get_symbol(PyObject *cls, PyObject *args)
return PyGccString_FromString(op_symbol_code(code));
}

static tree
tree_walk_callback(tree *tree_ptr, int *walk_subtree, void *data)
{
struct callback_closure *closure = (struct callback_closure*)data;
PyObject *tree_obj = NULL;
PyObject *args = NULL;
PyObject *result = NULL;

assert(closure);
assert(*tree_ptr);
tree_obj = PyGccTree_New(gcc_private_make_tree(*tree_ptr));
if (!tree_obj) {
goto error;
}

args = PyGcc_Closure_MakeArgs(closure, 0, tree_obj);
if (!args) {
goto error;
}

/* Invoke the python callback: */
result = PyObject_Call(closure->callback, args, closure->kwargs);
if (!result) {
goto error;
}

Py_DECREF(tree_obj);
Py_DECREF(args);

if (PyObject_IsTrue(result)) {
Py_DECREF(result);
return *tree_ptr;
} else {
Py_DECREF(result);
return NULL;
}

error:
/* On and exception, terminate the traversal: */
*walk_subtree = 0;
Py_XDECREF(tree_obj);
Py_XDECREF(args);
Py_XDECREF(result);
return NULL;
}

PyObject *
PyGccTree_walk_tree(struct PyGccTree * self, PyObject *args, PyObject *kwargs)
{
PyObject *callback;
PyObject *extraargs = NULL;
struct callback_closure *closure;
tree result;

callback = PyTuple_GetItem(args, 0);
extraargs = PyTuple_GetSlice(args, 1, PyTuple_Size(args));

closure = PyGcc_closure_new_generic(callback, extraargs, kwargs);

if (!closure) {
Py_DECREF(callback);
Py_DECREF(extraargs);
return NULL;
}

result = walk_tree (&self->t.inner,
tree_walk_callback,
closure, NULL);

PyGcc_closure_free(closure);

if (PyErr_Occurred()) {
return NULL;
}

return PyGccTree_New(gcc_private_make_tree(result));
}

PyObject *
PyGccDeclaration_repr(struct PyGccTree * self)
{
Expand Down Expand Up @@ -426,6 +535,56 @@ PyGccIdentifierNode_repr(struct PyGccTree * self)
}
}

PyObject *
PyGccDeclaration_get_attributes(struct PyGccTree *self, void *closure)
{
/* gcc/tree.h defines TYPE_ATTRIBUTES(NODE) as:
"A TREE_LIST of IDENTIFIER nodes of the attributes that apply
to this type"

Looking at:
typedef int (example3)(const char *, const char *, const char *)
__attribute__((nonnull(1)))
__attribute__((nonnull(3)));
(which is erroneous), we get this for TYPE_ATTRIBUTES:
gcc.TreeList(purpose=gcc.IdentifierNode(name='nonnull'),
value=gcc.TreeList(purpose=None,
value=gcc.IntegerCst(3),
chain=None),
chain=gcc.TreeList(purpose=gcc.IdentifierNode(name='nonnull'),
value=gcc.TreeList(purpose=None,
value=gcc.IntegerCst(1),
chain=None),
chain=None)
)
*/
tree attr;
PyObject *result = PyDict_New();
if (!result) {
return NULL;
}
for (attr = DECL_ATTRIBUTES(self->t.inner); attr; attr = TREE_CHAIN(attr)) {
const char *attrname = IDENTIFIER_POINTER(TREE_PURPOSE(attr));
PyObject *values;
values = PyGcc_TreeMakeListFromTreeList(TREE_VALUE(attr));
if (!values) {
goto error;
}

if (-1 == PyDict_SetItemString(result, attrname, values)) {
Py_DECREF(values);
goto error;
}
Py_DECREF(values);
}

return result;

error:
Py_DECREF(result);
return NULL;
}

PyObject *
PyGccType_get_attributes(struct PyGccTree *self, void *closure)
{
Expand Down Expand Up @@ -1103,6 +1262,15 @@ PyGcc_GetMethods(struct PyGccTree *self)
#endif
}

PyObject * PyGcc_GetStubDecl(struct PyGccTree *self)
{
return PyGccTree_New(gcc_private_make_tree(TYPE_STUB_DECL(self->t.inner)));
}

PyObject * PyGcc_MainVariant(struct PyGccTree *self)
{
return PyGccTree_New(gcc_private_make_tree(TYPE_MAIN_VARIANT(self->t.inner)));
}
/*
GCC's debug_tree is implemented in:
gcc/print-tree.c
Expand Down
50 changes: 50 additions & 0 deletions gcc-python-variable.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,56 @@ PyGcc_WrtpMarkForPyGccVariable(PyGccVariable *wrapper)
gcc_variable_mark_in_use(wrapper->var);
}

IMPL_APPENDER(add_var_to_list,
gcc_variable,
PyGccVariable_New)


GCC_IMPLEMENT_PUBLIC_API (bool) gcc_variable_get_referring (gcc_variable var,
bool (*cb) (gcc_variable var, void *user_data),
void *user_data)
{
ipa_ref *ref = NULL;
int i;
for (i = 0; var.inner->iterate_referring(i, ref); i++) {
if (cb(gcc_private_make_variable((varpool_node*)ref->referring), user_data))
return true;
}

return false;
}

GCC_IMPLEMENT_PUBLIC_API (PyObject *)
PyGccVariable_get_referring(struct PyGccVariable * self)
{
IMPL_LIST_MAKER(gcc_variable_get_referring,
self->var,
add_var_to_list)
}


GCC_IMPLEMENT_PUBLIC_API (bool) gcc_variable_get_reference (gcc_variable var,
bool (*cb) (gcc_variable var, void *user_data),
void *user_data)
{
ipa_ref *ref = NULL;
int i;
for (i = 0; var.inner->iterate_reference(i, ref); i++) {
if (cb(gcc_private_make_variable((varpool_node*)ref->referred), user_data))
return true;
}

return false;
}

GCC_IMPLEMENT_PUBLIC_API (PyObject *)
PyGccVariable_get_reference(struct PyGccVariable * self)
{
IMPL_LIST_MAKER(gcc_variable_get_reference,
self->var,
add_var_to_list)
}

/*
PEP-7
Local variables:
Expand Down
15 changes: 15 additions & 0 deletions gcc-python-wrappers.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,9 @@ PyGccTree_richcompare(PyObject *o1, PyObject *o2, int op);
PyObject *
PyGccTree_get_str_no_uid(struct PyGccTree *self, void *closure);

PyObject *
PyGccTree_get_str_decl(struct PyGccTree *self, void *closure);

PyObject *
PyGccTree_get_symbol(PyObject *cls, PyObject *args);

Expand All @@ -265,9 +268,15 @@ PyGccComponentRef_repr(PyObject *self);
PyObject *
PyGccDeclaration_get_name(struct PyGccTree *self, void *closure);

PyObject *
PyGccTree_walk_tree(struct PyGccTree * self, PyObject *args, PyObject *kwargs);

PyObject *
PyGccDeclaration_repr(struct PyGccTree * self);

PyObject *
PyGccDeclaration_get_attributes(struct PyGccTree *self, void *closure);

PyObject *
PyGccFunctionDecl_get_fullname(struct PyGccTree *self, void *closure);

Expand Down Expand Up @@ -355,6 +364,12 @@ PyGcc_GetFields(struct PyGccTree *self);
PyObject *
PyGcc_GetMethods(struct PyGccTree *self);

PyObject *
PyGcc_GetStubDecl(struct PyGccTree *self);

PyObject *
PyGcc_MainVariant(struct PyGccTree *self);

/* gcc-python-gimple.c: */
extern gcc_gimple_asm
PyGccGimple_as_gcc_gimple_asm(struct PyGccGimple *self);
Expand Down
Loading