[gcc-python-plugin] docs: fix typos
by David Hugh Malcolm
commit 1e4eb818bf64cb2adb17da656ff411e68b81255c
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Fri Mar 30 17:30:08 2012 -0400
docs: fix typos
docs/tree.rst | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
---
diff --git a/docs/tree.rst b/docs/tree.rst
index d54131a..8c2c0a0 100644
--- a/docs/tree.rst
+++ b/docs/tree.rst
@@ -217,12 +217,12 @@ Declarations
The :py:class:`gcc.Location` for this declaration
- .. py:attribute:: is_artifical
+ .. py:attribute:: is_artificial
(bool) Is this declaration a compiler-generated entity, rather than
one provided by the user?
- An example of such an "artifical" declaration occurs within the
+ An example of such an "artificial" declaration occurs within the
arguments of C++ methods: the initial `this` argument is a
compiler-generated :py:class:`gcc.ParmDecl`.
12 years, 1 month
[gcc-python-plugin] cpychecker: cope with C++ destructors
by David Hugh Malcolm
commit d1a082fd6b825386460b43380fe1bc401d81fdb9
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Fri Mar 30 17:24:56 2012 -0400
cpychecker: cope with C++ destructors
libcpychecker/absinterp.py | 4 +-
.../refcounts/cplusplus/destructor/input.cc | 42 ++++++++++++++++++++
.../refcounts/cplusplus/destructor/script.py | 22 ++++++++++
.../refcounts/cplusplus/destructor/stdout.txt | 11 +++++
4 files changed, 78 insertions(+), 1 deletions(-)
---
diff --git a/libcpychecker/absinterp.py b/libcpychecker/absinterp.py
index 97e5d7f..0c71e76 100644
--- a/libcpychecker/absinterp.py
+++ b/libcpychecker/absinterp.py
@@ -1818,7 +1818,9 @@ class State(object):
def make_field_region(self, target, field):
check_isinstance(target, Region)
- check_isinstance(field, str)
+ if field:
+ # (field can be None for C++ destructors)
+ check_isinstance(field, str)
log('make_field_region(%r, %r)', target, field)
if field in target.fields:
log('reusing')
diff --git a/tests/cpychecker/refcounts/cplusplus/destructor/input.cc b/tests/cpychecker/refcounts/cplusplus/destructor/input.cc
new file mode 100644
index 0000000..b9a6fca
--- /dev/null
+++ b/tests/cpychecker/refcounts/cplusplus/destructor/input.cc
@@ -0,0 +1,42 @@
+/*
+ Copyright 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2012 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+
+/* Verify that the checker can cope with a C++ destructor */
+#include <Python.h>
+
+class Foo
+{
+public:
+ virtual ~Foo();
+};
+
+class Bar : public Foo
+{
+public:
+ ~Bar() {}
+};
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/tests/cpychecker/refcounts/cplusplus/destructor/script.py b/tests/cpychecker/refcounts/cplusplus/destructor/script.py
new file mode 100644
index 0000000..fdd5ba3
--- /dev/null
+++ b/tests/cpychecker/refcounts/cplusplus/destructor/script.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+# Copyright 2011 Red Hat, Inc.
+#
+# This is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+from libcpychecker import main
+main(verify_refcounting=True,
+ dump_traces=True,
+ show_traces=False)
diff --git a/tests/cpychecker/refcounts/cplusplus/destructor/stdout.txt b/tests/cpychecker/refcounts/cplusplus/destructor/stdout.txt
new file mode 100644
index 0000000..40cdaa9
--- /dev/null
+++ b/tests/cpychecker/refcounts/cplusplus/destructor/stdout.txt
@@ -0,0 +1,11 @@
+Trace 0:
+ Transitions:
+ 'taking False path'
+ 'returning'
+ Exception:
+ (struct PyObject *)0
+Trace 0:
+ Transitions:
+ 'returning'
+ Exception:
+ (struct PyObject *)0
12 years, 1 month
[gcc-python-plugin] cpychecker: in C++ code, "this" can't be NULL
by David Hugh Malcolm
commit 8abed6e97c9a35532939d5f0f102aeeb6068cde6
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Fri Mar 30 17:15:03 2012 -0400
cpychecker: in C++ code, "this" can't be NULL
docs/tree.rst | 8 ++++
generate-tree-c.py | 19 +++++----
libcpychecker/absinterp.py | 5 ++-
tests/cpychecker/refcounts/cplusplus/this/input.cc | 45 ++++++++++++++++++++
.../cpychecker/refcounts/cplusplus/this/script.py | 22 ++++++++++
.../cpychecker/refcounts/cplusplus/this/stdout.txt | 8 ++++
6 files changed, 98 insertions(+), 9 deletions(-)
---
diff --git a/docs/tree.rst b/docs/tree.rst
index 5edae87..d54131a 100644
--- a/docs/tree.rst
+++ b/docs/tree.rst
@@ -217,6 +217,14 @@ Declarations
The :py:class:`gcc.Location` for this declaration
+ .. py:attribute:: is_artifical
+
+ (bool) Is this declaration a compiler-generated entity, rather than
+ one provided by the user?
+
+ An example of such an "artifical" declaration occurs within the
+ arguments of C++ methods: the initial `this` argument is a
+ compiler-generated :py:class:`gcc.ParmDecl`.
.. py:class:: gcc.FieldDecl
diff --git a/generate-tree-c.py b/generate-tree-c.py
index 54ffdc6..457b2de 100644
--- a/generate-tree-c.py
+++ b/generate-tree-c.py
@@ -149,6 +149,14 @@ def generate_intermediate_tree_classes():
tp_getset = getsettable.identifier,
tp_methods = methods.identifier)
+ def add_simple_getter(name, c_expression, doc):
+ getsettable.add_gsdef(name,
+ cu.add_simple_getter('gcc_%s_get_%s' % (localname, name),
+ 'PyGccTree',
+ c_expression),
+ None,
+ doc)
+
if localname == 'Declaration':
cu.add_defn("""
PyObject *
@@ -175,16 +183,11 @@ gcc_Declaration_get_location(struct PyGccTree *self, void *closure)
'gcc_Declaration_get_location',
None,
'The gcc.Location for this declaration')
+ add_simple_getter('is_artificial',
+ 'PyBool_FromLong(DECL_ARTIFICIAL(self->t))',
+ "Is this a compiler-generated entity?")
pytype.tp_repr = '(reprfunc)gcc_Declaration_repr'
- def add_simple_getter(name, c_expression, doc):
- getsettable.add_gsdef(name,
- cu.add_simple_getter('gcc_%s_get_%s' % (localname, name),
- 'PyGccTree',
- c_expression),
- None,
- doc)
-
if localname == 'Type':
add_simple_getter('name',
'gcc_python_make_wrapper_tree(TYPE_NAME(self->t))',
diff --git a/libcpychecker/absinterp.py b/libcpychecker/absinterp.py
index 35c4103..97e5d7f 100644
--- a/libcpychecker/absinterp.py
+++ b/libcpychecker/absinterp.py
@@ -1916,9 +1916,12 @@ class State(object):
nonnull_args = get_nonnull_arguments(fun.decl.type)
for idx, parm in enumerate(fun.decl.arguments):
+ def parm_is_this():
+ if idx == 0 and parm.is_artificial and parm.name == 'this':
+ return True
region = RegionForLocal(parm, stack)
self.region_for_var[parm] = region
- if idx in nonnull_args:
+ if idx in nonnull_args or parm_is_this():
# Make a non-NULL ptr:
other = Region('region-for-arg-%r' % parm, None)
self.region_for_var[other] = other
diff --git a/tests/cpychecker/refcounts/cplusplus/this/input.cc b/tests/cpychecker/refcounts/cplusplus/this/input.cc
new file mode 100644
index 0000000..788af9f
--- /dev/null
+++ b/tests/cpychecker/refcounts/cplusplus/this/input.cc
@@ -0,0 +1,45 @@
+/*
+ Copyright 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2012 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+
+/* Verify that the checker can handle "this" in C++ code */
+#include <Python.h>
+
+class Foo
+{
+ int x;
+
+public:
+ int
+ get_x();
+};
+
+int Foo::get_x()
+{
+ /* the checker should assume that "this" is non-NULL */
+ return this->x;
+}
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/tests/cpychecker/refcounts/cplusplus/this/script.py b/tests/cpychecker/refcounts/cplusplus/this/script.py
new file mode 100644
index 0000000..fdd5ba3
--- /dev/null
+++ b/tests/cpychecker/refcounts/cplusplus/this/script.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+# Copyright 2011 Red Hat, Inc.
+#
+# This is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+from libcpychecker import main
+main(verify_refcounting=True,
+ dump_traces=True,
+ show_traces=False)
diff --git a/tests/cpychecker/refcounts/cplusplus/this/stdout.txt b/tests/cpychecker/refcounts/cplusplus/this/stdout.txt
new file mode 100644
index 0000000..9f488bd
--- /dev/null
+++ b/tests/cpychecker/refcounts/cplusplus/this/stdout.txt
@@ -0,0 +1,8 @@
+Trace 0:
+ Transitions:
+ 'returning'
+ Return value:
+ repr(): WithinRange(gcctype='int', loc=gcc.Location(file='tests/cpychecker/refcounts/cplusplus/this/input.cc', line=36), minvalue=-0x80000000, maxvalue=0x7fffffff)
+ str(): (int)val [-0x80000000 <= val <= 0x7fffffff] from tests/cpychecker/refcounts/cplusplus/this/input.cc:36
+ Exception:
+ (struct PyObject *)0 from tests/cpychecker/refcounts/cplusplus/this/input.cc:34
12 years, 1 month
[gcc-python-plugin/proposed-plugin-api] introduce GccFunctionI
by David Hugh Malcolm
commit d22fc2f43cb7b92f5ac1823620b51c1c19d752e4
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Thu Mar 29 23:27:48 2012 -0400
introduce GccFunctionI
Makefile | 1 +
gcc-python-closure.c | 4 +-
gcc-python-function.c | 13 ++--
gcc-python-pass.c | 5 +-
gcc-python.h | 2 +-
generate-function-c.py | 13 ++--
generate-tree-c.py | 2 +-
proposed-plugin-api/gcc-function.c | 90 +++++++++++++++++++++++++++
proposed-plugin-api/gcc-function.h | 49 +++++++++++++++
proposed-plugin-api/gcc-public-types.h | 3 +
proposed-plugin-api/gcc-semiprivate-types.h | 8 +++
11 files changed, 173 insertions(+), 17 deletions(-)
---
diff --git a/Makefile b/Makefile
index d0d6e8b..eb58f86 100644
--- a/Makefile
+++ b/Makefile
@@ -19,6 +19,7 @@
PLUGIN_SOURCE_FILES= \
proposed-plugin-api/gcc-cfg.c \
+ proposed-plugin-api/gcc-function.c \
proposed-plugin-api/gcc-gimple.c \
proposed-plugin-api/gcc-location.c \
proposed-plugin-api/gcc-rtl.c \
diff --git a/gcc-python-closure.c b/gcc-python-closure.c
index f238914..a8b7dc2 100644
--- a/gcc-python-closure.c
+++ b/gcc-python-closure.c
@@ -24,6 +24,8 @@
#include "gcc-python.h"
#include "function.h"
+#include "proposed-plugin-api/gcc-function.h"
+
struct callback_closure *
gcc_python_closure_new_generic(PyObject *callback, PyObject *extraargs, PyObject *kwargs)
{
@@ -102,7 +104,7 @@ gcc_python_closure_make_args(struct callback_closure * closure, int add_cfun, Py
}
if (add_cfun) {
- cfun_obj = gcc_python_make_wrapper_function(cfun);
+ cfun_obj = gcc_python_make_wrapper_function(Gcc_GetCurrentFunction());
if (!cfun_obj) {
goto error;
}
diff --git a/gcc-python-function.c b/gcc-python-function.c
index a4997d6..0ce3676 100644
--- a/gcc-python-function.c
+++ b/gcc-python-function.c
@@ -29,6 +29,7 @@
*/
#include "function.h"
+#include "proposed-plugin-api/gcc-function.h"
PyObject *
gcc_Function_repr(struct PyGccFunction * self)
@@ -37,8 +38,8 @@ gcc_Function_repr(struct PyGccFunction * self)
PyObject *result = NULL;
tree decl;
- assert(self->fun);
- decl = self->fun->decl;
+ assert(self->fun.inner);
+ decl = self->fun.inner->decl;
if (DECL_NAME(decl)) {
name = IDENTIFIER_POINTER (DECL_NAME(decl));
} else {
@@ -58,11 +59,11 @@ error:
}
PyObject *
-gcc_python_make_wrapper_function(struct function *fun)
+gcc_python_make_wrapper_function(GccFunctionI func)
{
struct PyGccFunction *obj;
- if (!fun) {
+ if (!func.inner) {
Py_RETURN_NONE;
}
@@ -117,7 +118,7 @@ gcc_python_make_wrapper_function(struct function *fun)
goto error;
}
- obj->fun = fun;
+ obj->fun = func;
return (PyObject*)obj;
@@ -129,7 +130,7 @@ void
wrtp_mark_for_PyGccFunction(PyGccFunction *wrapper)
{
/* Mark the underlying object (recursing into its fields): */
- gt_ggc_mx_function(wrapper->fun);
+ GccFunctionI_MarkInUse(wrapper->fun);
}
diff --git a/gcc-python-pass.c b/gcc-python-pass.c
index 8471222..c3eb401 100644
--- a/gcc-python-pass.c
+++ b/gcc-python-pass.c
@@ -21,6 +21,7 @@
#include "gcc-python.h"
#include "gcc-python-wrappers.h"
#include "diagnostic.h"
+#include "proposed-plugin-api/gcc-function.h"
#include "proposed-plugin-api/gcc-location.h"
/*
@@ -59,7 +60,7 @@ static bool impl_gate(void)
if (cfun) {
/* Temporarily override input_location to the top of the function: */
Gcc_SetInputLocation(GccPrivate_make_LocationI(cfun->function_start_locus));
- cfun_obj = gcc_python_make_wrapper_function(cfun);
+ cfun_obj = gcc_python_make_wrapper_function(Gcc_GetCurrentFunction());
if (!cfun_obj) {
gcc_python_print_exception("Unhandled Python exception raised calling 'gate' method");
Py_DECREF(pass_obj);
@@ -101,7 +102,7 @@ static unsigned int impl_execute(void)
if (cfun) {
/* Temporarily override input_location to the top of the function: */
Gcc_SetInputLocation(GccPrivate_make_LocationI(cfun->function_start_locus));
- cfun_obj = gcc_python_make_wrapper_function(cfun);
+ cfun_obj = gcc_python_make_wrapper_function(Gcc_GetCurrentFunction());
if (!cfun_obj) {
gcc_python_print_exception("Unhandled Python exception raised calling 'execute' method");
Py_DECREF(pass_obj);
diff --git a/gcc-python.h b/gcc-python.h
index a4f004e..11b215b 100644
--- a/gcc-python.h
+++ b/gcc-python.h
@@ -197,7 +197,7 @@ DECLARE_SIMPLE_WRAPPER(PyGccCfg,
DECLARE_SIMPLE_WRAPPER(PyGccFunction,
gcc_FunctionType,
function,
- struct function *, fun)
+ GccFunctionI, fun)
DECLARE_SIMPLE_WRAPPER(PyGccOption,
gcc_OptionType,
diff --git a/generate-function-c.py b/generate-function-c.py
index 67b007f..cce7238 100644
--- a/generate-function-c.py
+++ b/generate-function-c.py
@@ -23,6 +23,7 @@ cu.add_include('gcc-python.h')
cu.add_include('gcc-python-wrappers.h')
cu.add_include('gcc-plugin.h')
cu.add_include("function.h")
+cu.add_include("proposed-plugin-api/gcc-function.h")
modinit_preinit = ''
modinit_postinit = ''
@@ -37,7 +38,7 @@ def generate_function():
"static PyObject *\n"
"gcc_Function_get_cfg(struct PyGccFunction *self, void *closure)\n"
"{\n"
- " return gcc_python_make_wrapper_cfg(GccPrivate_make_CfgI(self->fun->cfg));\n"
+ " return gcc_python_make_wrapper_cfg(GccFunctionI_GetCfg(self->fun));\n"
"}\n"
"\n")
getsettable = PyGetSetDefTable('gcc_Function_getset_table',
@@ -48,23 +49,23 @@ def generate_function():
typename='PyGccFunction')
getsettable.add_simple_getter(cu,
'decl',
- 'gcc_python_make_wrapper_tree(self->fun->decl)',
+ 'gcc_python_make_wrapper_tree(self->fun.inner->decl)',
'The declaration of this function, as a gcc.FunctionDecl instance')
getsettable.add_simple_getter(cu,
'local_decls',
- 'VEC_tree_as_PyList(self->fun->local_decls)',
+ 'VEC_tree_as_PyList(self->fun.inner->local_decls)',
"List of gcc.VarDecl for the function's local variables")
getsettable.add_simple_getter(cu,
'funcdef_no',
- 'gcc_python_int_from_long(self->fun->funcdef_no)',
+ 'gcc_python_int_from_long(GccFunctionI_GetIndex(self->fun))',
'Function sequence number for profiling, debugging, etc.')
getsettable.add_simple_getter(cu,
'start',
- 'gcc_python_make_wrapper_location(GccPrivate_make_LocationI(self->fun->function_start_locus))',
+ 'gcc_python_make_wrapper_location(GccFunctionI_GetStart(self->fun))',
'Location of the start of the function')
getsettable.add_simple_getter(cu,
'end',
- 'gcc_python_make_wrapper_location(GccPrivate_make_LocationI(self->fun->function_end_locus))',
+ 'gcc_python_make_wrapper_location(GccFunctionI_GetEnd(self->fun))',
'Location of the end of the function')
cu.add_defn(getsettable.c_defn())
diff --git a/generate-tree-c.py b/generate-tree-c.py
index ef63e2d..737ff90 100644
--- a/generate-tree-c.py
+++ b/generate-tree-c.py
@@ -504,7 +504,7 @@ def generate_tree_code_classes():
None,
'C++ only: the full name of this function declaration')
add_simple_getter('function',
- 'gcc_python_make_wrapper_function(DECL_STRUCT_FUNCTION(self->t))',
+ 'gcc_python_make_wrapper_function(GccPrivate_make_FunctionI(DECL_STRUCT_FUNCTION(self->t)))',
'The gcc.Function (or None) for this declaration')
add_simple_getter('arguments',
'gcc_tree_list_from_chain(DECL_ARGUMENTS(self->t))',
diff --git a/proposed-plugin-api/gcc-function.c b/proposed-plugin-api/gcc-function.c
new file mode 100644
index 0000000..891330e
--- /dev/null
+++ b/proposed-plugin-api/gcc-function.c
@@ -0,0 +1,90 @@
+/*
+ Copyright 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2012 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include "proposed-plugin-api/gcc-common.h"
+
+/* TODO: rationalize these headers */
+#include "tree.h"
+#include "gimple.h"
+#include "params.h"
+#include "cp/name-lookup.h" /* for global_namespace */
+#include "tree.h"
+#include "function.h"
+#include "diagnostic.h"
+#include "cgraph.h"
+#include "opts.h"
+#include "c-family/c-pragma.h" /* for parse_in */
+#include "basic-block.h"
+#include "rtl.h"
+
+/* Declarations: functions */
+
+/* GccFunctionI */
+GCC_IMPLEMENT_PUBLIC_API(void)
+GccFunctionI_MarkInUse(GccFunctionI func)
+{
+ gt_ggc_mx_function(func.inner);
+}
+
+GCC_IMPLEMENT_PRIVATE_API(struct GccFunctionI)
+GccPrivate_make_FunctionI(struct function *inner)
+{
+ struct GccFunctionI result;
+ result.inner = inner;
+ return result;
+}
+
+GCC_IMPLEMENT_PUBLIC_API(GccCfgI)
+GccFunctionI_GetCfg(GccFunctionI func)
+{
+ return GccPrivate_make_CfgI(func.inner->cfg);
+}
+
+GCC_IMPLEMENT_PUBLIC_API(int)
+GccFunctionI_GetIndex(GccFunctionI func)
+{
+ return func.inner->funcdef_no;
+}
+
+GCC_IMPLEMENT_PUBLIC_API(GccLocationI)
+GccFunctionI_GetStart(GccFunctionI func)
+{
+ return GccPrivate_make_LocationI(func.inner->function_start_locus);
+}
+
+GCC_IMPLEMENT_PUBLIC_API(GccLocationI)
+GccFunctionI_GetEnd(GccFunctionI func)
+{
+ return GccPrivate_make_LocationI(func.inner->function_end_locus);
+}
+
+GCC_IMPLEMENT_PUBLIC_API(GccFunctionI)
+Gcc_GetCurrentFunction(void)
+{
+ return GccPrivate_make_FunctionI(cfun);
+}
+
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/proposed-plugin-api/gcc-function.h b/proposed-plugin-api/gcc-function.h
new file mode 100644
index 0000000..606b535
--- /dev/null
+++ b/proposed-plugin-api/gcc-function.h
@@ -0,0 +1,49 @@
+/*
+ Copyright 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2012 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include "proposed-plugin-api/gcc-common.h"
+
+/* Declarations: functions */
+
+/* GccFunctionI */
+GCC_PUBLIC_API(void)
+GccFunctionI_MarkInUse(GccFunctionI func);
+
+GCC_PUBLIC_API(GccCfgI)
+GccFunctionI_GetCfg(GccFunctionI func);
+
+GCC_PUBLIC_API(int)
+GccFunctionI_GetIndex(GccFunctionI func);
+
+GCC_PUBLIC_API(GccLocationI)
+GccFunctionI_GetStart(GccFunctionI func);
+
+GCC_PUBLIC_API(GccLocationI)
+GccFunctionI_GetEnd(GccFunctionI func);
+
+GCC_PUBLIC_API(GccFunctionI)
+Gcc_GetCurrentFunction(void);
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/proposed-plugin-api/gcc-public-types.h b/proposed-plugin-api/gcc-public-types.h
index 007c123..6a40489 100644
--- a/proposed-plugin-api/gcc-public-types.h
+++ b/proposed-plugin-api/gcc-public-types.h
@@ -40,4 +40,7 @@ typedef struct GccPrinterI GccPrinterI;
/* Opaque types: locations */
typedef struct GccLocationI GccLocationI;
+/* Opaque types: functions */
+typedef struct GccFunctionI GccFunctionI;
+
#endif /* INCLUDED__GCC_PUBLIC_TYPES_H */
diff --git a/proposed-plugin-api/gcc-semiprivate-types.h b/proposed-plugin-api/gcc-semiprivate-types.h
index c94e86c..d59e4a4 100644
--- a/proposed-plugin-api/gcc-semiprivate-types.h
+++ b/proposed-plugin-api/gcc-semiprivate-types.h
@@ -89,5 +89,13 @@ struct GccLocationI {
GCC_PRIVATE_API(struct GccLocationI)
GccPrivate_make_LocationI(location_t inner);
+/* Semiprivate types: functions */
+struct GccFunctionI {
+ struct function *inner;
+};
+
+GCC_PRIVATE_API(struct GccFunctionI)
+GccPrivate_make_FunctionI(struct function *inner);
+
#endif /* INCLUDED__GCC_SEMIPRIVATE_TYPES_H */
12 years, 1 month
[gcc-python-plugin/proposed-plugin-api] introduce GccLocationI
by David Hugh Malcolm
commit 653332428968519fa29d0e42bfa4360c6db7cd20
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Thu Mar 29 23:02:07 2012 -0400
introduce GccLocationI
Makefile | 1 +
gcc-python-callbacks.c | 8 ++-
gcc-python-diagnostics.c | 8 +-
gcc-python-location.c | 17 +++---
gcc-python-pass.c | 27 +++++----
gcc-python-rtl.c | 2 +-
gcc-python.c | 6 +-
gcc-python.h | 2 +-
generate-function-c.py | 4 +-
generate-gimple-c.py | 2 +-
generate-location-c.py | 10 +--
generate-tree-c.py | 4 +-
proposed-plugin-api/gcc-location.c | 82 +++++++++++++++++++++++++++
proposed-plugin-api/gcc-location.h | 52 +++++++++++++++++
proposed-plugin-api/gcc-public-types.h | 3 +
proposed-plugin-api/gcc-semiprivate-types.h | 11 ++++
16 files changed, 196 insertions(+), 43 deletions(-)
---
diff --git a/Makefile b/Makefile
index 86d24d5..d0d6e8b 100644
--- a/Makefile
+++ b/Makefile
@@ -20,6 +20,7 @@
PLUGIN_SOURCE_FILES= \
proposed-plugin-api/gcc-cfg.c \
proposed-plugin-api/gcc-gimple.c \
+ proposed-plugin-api/gcc-location.c \
proposed-plugin-api/gcc-rtl.c \
gcc-python.c \
gcc-python-attribute.c \
diff --git a/gcc-python-callbacks.c b/gcc-python-callbacks.c
index 5e23f58..ab17ce0 100644
--- a/gcc-python-callbacks.c
+++ b/gcc-python-callbacks.c
@@ -23,6 +23,8 @@
#include "gcc-python-closure.h"
#include "gcc-python-wrappers.h"
+#include "proposed-plugin-api/gcc-location.h"
+
/*
Notes on the passes
@@ -128,7 +130,7 @@ gcc_python_finish_invoking_callback(PyGILState_STATE gstate,
struct callback_closure *closure = (struct callback_closure *)user_data;
PyObject *args = NULL;
PyObject *result = NULL;
- location_t saved_loc = input_location;
+ GccLocationI saved_loc = Gcc_GetInputLocation();
enum plugin_event saved_event;
assert(closure);
@@ -141,7 +143,7 @@ gcc_python_finish_invoking_callback(PyGILState_STATE gstate,
if (cfun) {
/* Temporarily override input_location to the top of the function: */
- input_location = cfun->function_start_locus;
+ Gcc_SetInputLocation(GccPrivate_make_LocationI(cfun->function_start_locus));
}
args = gcc_python_closure_make_args(closure, 1, wrapped_gcc_data);
@@ -169,7 +171,7 @@ cleanup:
Py_XDECREF(result);
PyGILState_Release(gstate);
- input_location = saved_loc;
+ Gcc_SetInputLocation(saved_loc);
}
/*
diff --git a/gcc-python-diagnostics.c b/gcc-python-diagnostics.c
index 7b6f9db..2bdeef2 100644
--- a/gcc-python-diagnostics.c
+++ b/gcc-python-diagnostics.c
@@ -57,7 +57,7 @@ gcc_python_permerror(PyObject *self, PyObject *args)
}
/* Invoke the GCC function: */
- result_b = permerror(loc_obj->loc, "%s", msgid);
+ result_b = permerror(loc_obj->loc.inner, "%s", msgid);
result_obj = PyBool_FromLong(result_b);
@@ -80,7 +80,7 @@ gcc_python_error(PyObject *self, PyObject *args, PyObject *kwargs)
return NULL;
}
- error_at(loc_obj->loc, "%s", msg);
+ error_at(loc_obj->loc.inner, "%s", msg);
Py_RETURN_NONE;
}
@@ -135,7 +135,7 @@ gcc_python_warning(PyObject *self, PyObject *args, PyObject *kwargs)
}
}
- was_reported = warning_at(loc_obj->loc, opt_code, "%s", msg);
+ was_reported = warning_at(loc_obj->loc.inner, opt_code, "%s", msg);
return PyBool_FromLong(was_reported);
}
@@ -156,7 +156,7 @@ gcc_python_inform(PyObject *self, PyObject *args, PyObject *kwargs)
return NULL;
}
- inform(loc_obj->loc, "%s", msg);
+ inform(loc_obj->loc.inner, "%s", msg);
Py_RETURN_NONE;
}
diff --git a/gcc-python-location.c b/gcc-python-location.c
index 964c921..546455f 100644
--- a/gcc-python-location.c
+++ b/gcc-python-location.c
@@ -20,6 +20,7 @@
#include <Python.h>
#include "gcc-python.h"
#include "gcc-python-wrappers.h"
+#include "proposed-plugin-api/gcc-location.h"
/*
Wrapper for GCC's "location_t"
@@ -36,16 +37,16 @@ PyObject *
gcc_Location_repr(struct PyGccLocation * self)
{
return gcc_python_string_from_format("gcc.Location(file='%s', line=%i)",
- LOCATION_FILE(self->loc),
- LOCATION_LINE(self->loc));
+ GccLocationI_GetFilename(self->loc),
+ GccLocationI_GetLine(self->loc));
}
PyObject *
gcc_Location_str(struct PyGccLocation * self)
{
return gcc_python_string_from_format("%s:%i",
- LOCATION_FILE(self->loc),
- LOCATION_LINE(self->loc));
+ GccLocationI_GetFilename(self->loc),
+ GccLocationI_GetLine(self->loc));
}
PyObject *
@@ -68,11 +69,11 @@ gcc_Location_richcompare(PyObject *o1, PyObject *o2, int op)
switch (op) {
case Py_EQ:
- cond = (locobj1->loc == locobj2->loc);
+ cond = (locobj1->loc.inner == locobj2->loc.inner);
break;
case Py_NE:
- cond = (locobj1->loc != locobj2->loc);
+ cond = (locobj1->loc.inner != locobj2->loc.inner);
break;
default:
@@ -87,11 +88,11 @@ gcc_Location_richcompare(PyObject *o1, PyObject *o2, int op)
}
PyObject *
-gcc_python_make_wrapper_location(location_t loc)
+gcc_python_make_wrapper_location(GccLocationI loc)
{
struct PyGccLocation *location_obj = NULL;
- if (UNKNOWN_LOCATION == loc) {
+ if (GccLocationI_IsUnknown(loc)) {
Py_RETURN_NONE;
}
diff --git a/gcc-python-pass.c b/gcc-python-pass.c
index 5315df1..8471222 100644
--- a/gcc-python-pass.c
+++ b/gcc-python-pass.c
@@ -21,6 +21,7 @@
#include "gcc-python.h"
#include "gcc-python-wrappers.h"
#include "diagnostic.h"
+#include "proposed-plugin-api/gcc-location.h"
/*
Wrapper for GCC's (opt_pass *)
@@ -42,7 +43,7 @@ static bool impl_gate(void)
PyObject *cfun_obj = NULL;
PyObject* result_obj;
int result;
- location_t saved_loc = input_location;
+ GccLocationI saved_loc = Gcc_GetInputLocation();
assert(current_pass);
pass_obj = gcc_python_make_wrapper_pass(current_pass);
@@ -57,12 +58,12 @@ static bool impl_gate(void)
/* Supply the current function, if any */
if (cfun) {
/* Temporarily override input_location to the top of the function: */
- input_location = cfun->function_start_locus;
+ Gcc_SetInputLocation(GccPrivate_make_LocationI(cfun->function_start_locus));
cfun_obj = gcc_python_make_wrapper_function(cfun);
if (!cfun_obj) {
gcc_python_print_exception("Unhandled Python exception raised calling 'gate' method");
Py_DECREF(pass_obj);
- input_location = saved_loc;
+ Gcc_SetInputLocation(saved_loc);
return false;
}
result_obj = PyObject_CallMethod(pass_obj, "gate", "O", cfun_obj, NULL);
@@ -75,13 +76,13 @@ static bool impl_gate(void)
if (!result_obj) {
gcc_python_print_exception("Unhandled Python exception raised calling 'gate' method");
- input_location = saved_loc;
+ Gcc_SetInputLocation(saved_loc);
return false;
}
result = PyObject_IsTrue(result_obj);
Py_DECREF(result_obj);
- input_location = saved_loc;
+ Gcc_SetInputLocation(saved_loc);
return result;
}
@@ -90,7 +91,7 @@ static unsigned int impl_execute(void)
PyObject *pass_obj;
PyObject *cfun_obj = NULL;
PyObject* result_obj;
- location_t saved_loc = input_location;
+ GccLocationI saved_loc = Gcc_GetInputLocation();
assert(current_pass);
pass_obj = gcc_python_make_wrapper_pass(current_pass);
@@ -99,12 +100,12 @@ static unsigned int impl_execute(void)
/* Supply the current function, if any */
if (cfun) {
/* Temporarily override input_location to the top of the function: */
- input_location = cfun->function_start_locus;
+ Gcc_SetInputLocation(GccPrivate_make_LocationI(cfun->function_start_locus));
cfun_obj = gcc_python_make_wrapper_function(cfun);
if (!cfun_obj) {
gcc_python_print_exception("Unhandled Python exception raised calling 'execute' method");
Py_DECREF(pass_obj);
- input_location = saved_loc;
+ Gcc_SetInputLocation(saved_loc);
return false;
}
result_obj = PyObject_CallMethod(pass_obj, "execute", "O", cfun_obj, NULL);
@@ -117,13 +118,13 @@ static unsigned int impl_execute(void)
if (!result_obj) {
gcc_python_print_exception("Unhandled Python exception raised calling 'execute' method");
- input_location = saved_loc;
+ Gcc_SetInputLocation(saved_loc);
return 0;
}
if (result_obj == Py_None) {
Py_DECREF(result_obj);
- input_location = saved_loc;
+ Gcc_SetInputLocation(saved_loc);
return 0;
}
@@ -131,7 +132,7 @@ static unsigned int impl_execute(void)
if (PyInt_Check(result_obj)) {
long result = PyInt_AS_LONG(result_obj);
Py_DECREF(result_obj);
- input_location = saved_loc;
+ Gcc_SetInputLocation(saved_loc);
return result;
}
#endif
@@ -139,7 +140,7 @@ static unsigned int impl_execute(void)
if (PyLong_Check(result_obj)) {
long result = PyLong_AsLong(result_obj);
Py_DECREF(result_obj);
- input_location = saved_loc;
+ Gcc_SetInputLocation(saved_loc);
return result;
}
@@ -149,7 +150,7 @@ static unsigned int impl_execute(void)
Py_TYPE(result_obj)->tp_name);
Py_DECREF(result_obj);
gcc_python_print_exception("Unhandled Python exception raised calling 'execute' method");
- input_location = saved_loc;
+ Gcc_SetInputLocation(saved_loc);
return 0;
}
diff --git a/gcc-python-rtl.c b/gcc-python-rtl.c
index e499cdf..76114fd 100644
--- a/gcc-python-rtl.c
+++ b/gcc-python-rtl.c
@@ -31,7 +31,7 @@ gcc_Rtl_get_location(struct PyGccRtl *self, void *closure)
{
int locator = INSN_LOCATOR (self->insn.inner);
if (locator && insn_file (self->insn.inner)) {
- return gcc_python_make_wrapper_location(locator_location(locator));
+ return gcc_python_make_wrapper_location(GccPrivate_make_LocationI(locator_location(locator)));
}
Py_RETURN_NONE;
diff --git a/gcc-python.c b/gcc-python.c
index b837c1c..659e836 100644
--- a/gcc-python.c
+++ b/gcc-python.c
@@ -23,6 +23,8 @@
#include "gcc-python-closure.h"
#include "gcc-python-wrappers.h"
+#include "proposed-plugin-api/gcc-location.h"
+
int plugin_is_GPL_compatible;
#include "plugin-version.h"
@@ -124,7 +126,7 @@ gcc_python_set_location(PyObject *self, PyObject *args)
return NULL;
}
- input_location = loc_obj->loc;
+ Gcc_SetInputLocation(loc_obj->loc);
Py_RETURN_NONE;
}
@@ -912,7 +914,7 @@ void gcc_python_print_exception(const char *msg)
within passes is initialized to the top of the function; it can be
temporarily overridden using gcc.set_location()
*/
- error_at(input_location, "%s", msg);
+ error_at(Gcc_GetInputLocation().inner, "%s", msg);
/* Print the traceback: */
PyErr_PrintEx(1);
diff --git a/gcc-python.h b/gcc-python.h
index ff3ad4b..a4f004e 100644
--- a/gcc-python.h
+++ b/gcc-python.h
@@ -172,7 +172,7 @@ DECLARE_SIMPLE_WRAPPER(PyGccPass,
DECLARE_SIMPLE_WRAPPER(PyGccLocation,
gcc_LocationType,
location,
- location_t, loc)
+ GccLocationI, loc)
DECLARE_SIMPLE_WRAPPER(PyGccGimple,
gcc_GimpleType,
diff --git a/generate-function-c.py b/generate-function-c.py
index 9e03fb0..67b007f 100644
--- a/generate-function-c.py
+++ b/generate-function-c.py
@@ -60,11 +60,11 @@ def generate_function():
'Function sequence number for profiling, debugging, etc.')
getsettable.add_simple_getter(cu,
'start',
- 'gcc_python_make_wrapper_location(self->fun->function_start_locus)',
+ 'gcc_python_make_wrapper_location(GccPrivate_make_LocationI(self->fun->function_start_locus))',
'Location of the start of the function')
getsettable.add_simple_getter(cu,
'end',
- 'gcc_python_make_wrapper_location(self->fun->function_end_locus)',
+ 'gcc_python_make_wrapper_location(GccPrivate_make_LocationI(self->fun->function_end_locus))',
'Location of the end of the function')
cu.add_defn(getsettable.c_defn())
diff --git a/generate-gimple-c.py b/generate-gimple-c.py
index 4f859e1..4893b9e 100644
--- a/generate-gimple-c.py
+++ b/generate-gimple-c.py
@@ -192,7 +192,7 @@ def generate_gimple():
static PyObject *
gcc_Gimple_get_location(struct PyGccGimple *self, void *closure)
{
- return gcc_python_make_wrapper_location(gimple_location(self->stmt.inner));
+ return gcc_python_make_wrapper_location(GccPrivate_make_LocationI(gimple_location(self->stmt.inner)));
}
static PyObject *
diff --git a/generate-location-c.py b/generate-location-c.py
index 2fdf308..6312409 100644
--- a/generate-location-c.py
+++ b/generate-location-c.py
@@ -22,7 +22,7 @@ cu = CompilationUnit()
cu.add_include('gcc-python.h')
cu.add_include('gcc-python-wrappers.h')
cu.add_include('gcc-plugin.h')
-cu.add_include("tree.h")
+cu.add_include("proposed-plugin-api/gcc-location.h")
modinit_preinit = ''
modinit_postinit = ''
@@ -38,7 +38,7 @@ def generate_location():
static PyObject *
gcc_Location_get_file(struct PyGccLocation *self, void *closure)
{
- return gcc_python_string_from_string(LOCATION_FILE(self->loc));
+ return gcc_python_string_from_string(GccLocationI_GetFilename(self->loc));
}
""")
@@ -46,7 +46,7 @@ gcc_Location_get_file(struct PyGccLocation *self, void *closure)
static PyObject *
gcc_Location_get_line(struct PyGccLocation *self, void *closure)
{
- return gcc_python_int_from_long(LOCATION_LINE(self->loc));
+ return gcc_python_int_from_long(GccLocationI_GetLine(self->loc));
}
""")
@@ -54,9 +54,7 @@ gcc_Location_get_line(struct PyGccLocation *self, void *closure)
static PyObject *
gcc_Location_get_column(struct PyGccLocation *self, void *closure)
{
- expanded_location exploc = expand_location(self->loc);
-
- return gcc_python_int_from_long(exploc.column);
+ return gcc_python_int_from_long(GccLocationI_GetColumn(self->loc));
}
""")
diff --git a/generate-tree-c.py b/generate-tree-c.py
index f6fc0d3..ef63e2d 100644
--- a/generate-tree-c.py
+++ b/generate-tree-c.py
@@ -163,7 +163,7 @@ gcc_Declaration_get_name(struct PyGccTree *self, void *closure)
static PyObject *
gcc_Declaration_get_location(struct PyGccTree *self, void *closure)
{
- return gcc_python_make_wrapper_location(DECL_SOURCE_LOCATION(self->t));
+ return gcc_python_make_wrapper_location(GccPrivate_make_LocationI(DECL_SOURCE_LOCATION(self->t)));
}
""")
@@ -277,7 +277,7 @@ PyObject*
if localname in ('Reference', 'Comparison', 'Unary', 'Binary',
'Statement' 'VlExp', 'Expression'):
add_simple_getter('location',
- 'gcc_python_make_wrapper_location(EXPR_LOCATION(self->t))',
+ 'gcc_python_make_wrapper_location(GccPrivate_make_LocationI(EXPR_LOCATION(self->t)))',
"The source location of this expression")
methods.add_method('get_symbol',
diff --git a/proposed-plugin-api/gcc-location.c b/proposed-plugin-api/gcc-location.c
new file mode 100644
index 0000000..7ca8303
--- /dev/null
+++ b/proposed-plugin-api/gcc-location.c
@@ -0,0 +1,82 @@
+/*
+ Copyright 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2012 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include "proposed-plugin-api/gcc-cfg.h"
+
+/***********************************************************
+ GccLocationI
+************************************************************/
+GCC_IMPLEMENT_PRIVATE_API(struct GccLocationI)
+GccPrivate_make_LocationI(location_t inner)
+{
+ struct GccLocationI result;
+ result.inner = inner;
+ return result;
+}
+
+GCC_IMPLEMENT_PUBLIC_API(void)
+GccLocationI_MarkInUse(GccLocationI loc)
+{
+ /* empty */
+}
+
+GCC_IMPLEMENT_PUBLIC_API(void)
+Gcc_SetInputLocation(GccLocationI loc)
+{
+ input_location = loc.inner;
+}
+
+GCC_IMPLEMENT_PUBLIC_API(GccLocationI)
+Gcc_GetInputLocation(void)
+{
+ return GccPrivate_make_LocationI(input_location);
+}
+
+GCC_IMPLEMENT_PUBLIC_API(const char *)
+GccLocationI_GetFilename(GccLocationI loc)
+{
+ return LOCATION_FILE(loc.inner);
+}
+
+GCC_IMPLEMENT_PUBLIC_API(int)
+GccLocationI_GetLine(GccLocationI loc)
+{
+ return LOCATION_LINE(loc.inner);
+}
+
+GCC_IMPLEMENT_PUBLIC_API(int)
+GccLocationI_GetColumn(GccLocationI loc)
+{
+ expanded_location exploc = expand_location(loc.inner);
+ return exploc.column;
+}
+
+GCC_PUBLIC_API(bool)
+GccLocationI_IsUnknown(GccLocationI loc)
+{
+ return UNKNOWN_LOCATION == loc.inner;
+}
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/proposed-plugin-api/gcc-location.h b/proposed-plugin-api/gcc-location.h
new file mode 100644
index 0000000..c1a8e1c
--- /dev/null
+++ b/proposed-plugin-api/gcc-location.h
@@ -0,0 +1,52 @@
+/*
+ Copyright 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2012 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include "proposed-plugin-api/gcc-common.h"
+
+/* Declarations: locations */
+
+/* GccLocationI */
+GCC_PUBLIC_API(void)
+GccLocationI_MarkInUse(GccLocationI loc);
+
+GCC_PUBLIC_API(void)
+Gcc_SetInputLocation(GccLocationI loc);
+
+GCC_PUBLIC_API(GccLocationI)
+Gcc_GetInputLocation(void);
+
+GCC_PUBLIC_API(const char *)
+GccLocationI_GetFilename(GccLocationI loc);
+
+GCC_PUBLIC_API(int)
+GccLocationI_GetLine(GccLocationI loc);
+
+GCC_PUBLIC_API(int)
+GccLocationI_GetColumn(GccLocationI loc);
+
+GCC_PUBLIC_API(bool)
+GccLocationI_IsUnknown(GccLocationI loc);
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/proposed-plugin-api/gcc-public-types.h b/proposed-plugin-api/gcc-public-types.h
index 795463d..007c123 100644
--- a/proposed-plugin-api/gcc-public-types.h
+++ b/proposed-plugin-api/gcc-public-types.h
@@ -37,4 +37,7 @@ typedef struct GccRtlInsnI GccRtlInsnI;
/* Opaque types: pretty-printing */
typedef struct GccPrinterI GccPrinterI;
+/* Opaque types: locations */
+typedef struct GccLocationI GccLocationI;
+
#endif /* INCLUDED__GCC_PUBLIC_TYPES_H */
diff --git a/proposed-plugin-api/gcc-semiprivate-types.h b/proposed-plugin-api/gcc-semiprivate-types.h
index f0b7474..c94e86c 100644
--- a/proposed-plugin-api/gcc-semiprivate-types.h
+++ b/proposed-plugin-api/gcc-semiprivate-types.h
@@ -20,6 +20,8 @@
#ifndef INCLUDED__GCC_SEMIPRIVATE_TYPES_H
#define INCLUDED__GCC_SEMIPRIVATE_TYPES_H
+#include "input.h" /* for location_t */
+
/*
These "interface types" should be treated like pointers, only that
users are required to collaborate with the garbage-collector.
@@ -79,4 +81,13 @@ struct GccRtlInsnI {
GCC_PRIVATE_API(struct GccRtlInsnI)
GccPrivate_make_RtlInsnI(struct rtx_def *inner);
+/* Semiprivate types: locations */
+struct GccLocationI {
+ location_t inner;
+};
+
+GCC_PRIVATE_API(struct GccLocationI)
+GccPrivate_make_LocationI(location_t inner);
+
+
#endif /* INCLUDED__GCC_SEMIPRIVATE_TYPES_H */
12 years, 1 month
[gcc-python-plugin/proposed-plugin-api] implement GccCfgI_ForEachBlock; fix reference leak
by David Hugh Malcolm
commit 52146cfed277aee3ea33fbd565bb39440aafa5c2
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Thu Mar 29 22:11:39 2012 -0400
implement GccCfgI_ForEachBlock; fix reference leak
gcc-python-cfg.c | 60 ++++++++++++++++++++++------------------
proposed-plugin-api/gcc-cfg.c | 17 +++++++++++-
2 files changed, 49 insertions(+), 28 deletions(-)
---
diff --git a/gcc-python-cfg.c b/gcc-python-cfg.c
index 8c67e4a..ea2caec 100644
--- a/gcc-python-cfg.c
+++ b/gcc-python-cfg.c
@@ -79,8 +79,11 @@ static bool add_edge_to_list(GccCfgEdgeI edge, void *user_data)
if (-1 == PyList_Append(result, item)) {
Py_DECREF(item);
+ return true;
}
+ /* Success: */
+ Py_DECREF(item);
return false;
}
@@ -458,41 +461,44 @@ gcc_python_make_wrapper_basic_block(GccCfgBlockI bb)
real_make_basic_block_wrapper);
}
-/*
- "struct control_flow_graph" is declared in basic-block.h, c.f.:
- struct GTY(()) control_flow_graph {
- ... snip ...
- }
-*/
+static bool add_block_to_list(GccCfgBlockI block, void *user_data)
+{
+ PyObject *result = (PyObject*)user_data;
+ PyObject *item;
+
+ item = gcc_python_make_wrapper_basic_block(block);
+ if (!item) {
+ return true;
+ }
+
+ if (-1 == PyList_Append(result, item)) {
+ Py_DECREF(item);
+ return true;
+ }
+
+ /* Success: */
+ Py_DECREF(item);
+ return false;
+}
+
PyObject *
gcc_Cfg_get_basic_blocks(PyGccCfg *self, void *closure)
{
- PyObject *result = NULL;
- int i;
+ PyObject *result;
- result = PyList_New(self->cfg.inner->x_n_basic_blocks);
+ result = PyList_New(0);
if (!result) {
- goto error;
- }
-
- for (i = 0; i < self->cfg.inner->x_n_basic_blocks; i++) {
- PyObject *item;
- item = gcc_python_make_wrapper_basic_block(
- GccPrivate_make_CfgBlockI(
- VEC_index(basic_block,
- self->cfg.inner->x_basic_block_info,
- i)));
- if (!item) {
- goto error;
- }
- PyList_SetItem(result, i, item);
+ return NULL;
}
- return result;
+ if (GccCfgI_ForEachBlock(self->cfg,
+ add_block_to_list,
+ result)) {
+ Py_DECREF(result);
+ return NULL;
+ }
- error:
- Py_XDECREF(result);
- return NULL;
+ return result;
}
extern PyTypeObject gcc_LabelDeclType;
diff --git a/proposed-plugin-api/gcc-cfg.c b/proposed-plugin-api/gcc-cfg.c
index 0ff948c..0a4caba 100644
--- a/proposed-plugin-api/gcc-cfg.c
+++ b/proposed-plugin-api/gcc-cfg.c
@@ -64,7 +64,22 @@ GccCfgI_GetExit(GccCfgI cfg)
GCC_IMPLEMENT_PUBLIC_API(bool)
GccCfgI_ForEachBlock(GccCfgI cfg,
bool (*cb)(GccCfgBlockI block, void *user_data),
- void *user_data);
+ void *user_data)
+{
+ int i;
+
+ for (i = 0; i < cfg.inner->x_n_basic_blocks; i++) {
+ if (cb(GccPrivate_make_CfgBlockI(
+ VEC_index(basic_block,
+ cfg.inner->x_basic_block_info,
+ i)),
+ user_data)) {
+ return true;
+ }
+ }
+ return false;
+
+}
/***********************************************************
GccCfgBlockI
12 years, 1 month
[gcc-python-plugin/proposed-plugin-api] expose the cfg edge flags needed by the python plugin
by David Hugh Malcolm
commit 0519ff959476d77c1f650914e19d2b7aace37dcf
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Thu Mar 29 21:19:43 2012 -0400
expose the cfg edge flags needed by the python plugin
With this commit, the python plugin's full test suite passes
generate-cfg-c.py | 13 +++++--------
proposed-plugin-api/gcc-cfg.c | 11 ++++++++---
proposed-plugin-api/gcc-cfg.h | 14 ++++++--------
3 files changed, 19 insertions(+), 19 deletions(-)
---
diff --git a/generate-cfg-c.py b/generate-cfg-c.py
index dc69165..ea16843 100644
--- a/generate-cfg-c.py
+++ b/generate-cfg-c.py
@@ -50,19 +50,16 @@ def generate_edge():
'The destination gcc.BasicBlock of this edge')],
identifier_prefix = 'gcc_Edge',
typename = 'PyGccEdge')
- """
- for flag in ('EDGE_FALLTHRU', 'EDGE_ABNORMAL', 'EDGE_ABNORMAL_CALL',
- 'EDGE_EH', 'EDGE_FAKE', 'EDGE_DFS_BACK', 'EDGE_CAN_FALLTHRU',
- 'EDGE_IRREDUCIBLE_LOOP', 'EDGE_SIBCALL', 'EDGE_LOOP_EXIT',
- 'EDGE_TRUE_VALUE', 'EDGE_FALSE_VALUE', 'EDGE_EXECUTABLE',
- 'EDGE_CROSSING'):
+
+ # We only expose the subset of the flags exposed by the plugin API:
+ for flag in ('EDGE_TRUE_VALUE', 'EDGE_FALSE_VALUE'):
assert flag.startswith('EDGE_')
flagname = flag[5:].lower()
getsettable.add_simple_getter(cu,
flagname,
- 'PyBool_FromLong(gcc_edge_is_%s(self->e))' % flagname,
+ 'PyBool_FromLong(GccCfgEdgeI_Is%s(self->e))' % camel_case(flagname),
'Boolean, corresponding to flag %s' % flag)
- """
+
cu.add_defn(getsettable.c_defn())
pytype = PyGccWrapperTypeObject(identifier = 'gcc_EdgeType',
diff --git a/proposed-plugin-api/gcc-cfg.c b/proposed-plugin-api/gcc-cfg.c
index 0e98bc3..0ff948c 100644
--- a/proposed-plugin-api/gcc-cfg.c
+++ b/proposed-plugin-api/gcc-cfg.c
@@ -232,12 +232,17 @@ GccCfgEdgeI_GetDest(GccCfgEdgeI edge)
return GccPrivate_make_CfgBlockI(edge.inner->dest);
}
-GCC_IMPLEMENT_PUBLIC_API(bool)
-GccCfgEdgeI_IsFallthru(GccCfgEdgeI edge)
+GCC_PUBLIC_API(bool)
+GccCfgEdgeI_IsTrueValue(GccCfgEdgeI edge)
{
- return edge.inner->flags & EDGE_FALLTHRU;
+ return (edge.inner->flags & EDGE_TRUE_VALUE) == EDGE_TRUE_VALUE;
}
+GCC_PUBLIC_API(bool)
+GccCfgEdgeI_IsFalseValue(GccCfgEdgeI edge)
+{
+ return (edge.inner->flags & EDGE_FALSE_VALUE) == EDGE_FALSE_VALUE;
+}
/*
PEP-7
diff --git a/proposed-plugin-api/gcc-cfg.h b/proposed-plugin-api/gcc-cfg.h
index c06ab74..925dcdb 100644
--- a/proposed-plugin-api/gcc-cfg.h
+++ b/proposed-plugin-api/gcc-cfg.h
@@ -98,15 +98,13 @@ GccCfgEdgeI_GetDest(GccCfgEdgeI edge);
GCC_PUBLIC_API(void)
GccCfgEdgeI_MarkInUse(GccCfgEdgeI edge);
-/*
- for flag in ('EDGE_FALLTHRU', 'EDGE_ABNORMAL', 'EDGE_ABNORMAL_CALL',
- 'EDGE_EH', 'EDGE_FAKE', 'EDGE_DFS_BACK', 'EDGE_CAN_FALLTHRU',
- 'EDGE_IRREDUCIBLE_LOOP', 'EDGE_SIBCALL', 'EDGE_LOOP_EXIT',
- 'EDGE_TRUE_VALUE', 'EDGE_FALSE_VALUE', 'EDGE_EXECUTABLE',
- 'EDGE_CROSSING'):
-*/
+/* How many of the flags do we want to expose? */
GCC_PUBLIC_API(bool)
-GccCfgEdgeI_IsFallthru(GccCfgEdgeI edge);
+GccCfgEdgeI_IsTrueValue(GccCfgEdgeI edge);
+
+GCC_PUBLIC_API(bool)
+GccCfgEdgeI_IsFalseValue(GccCfgEdgeI edge);
+
/* etc */
/*
12 years, 1 month
[gcc-python-plugin/proposed-plugin-api] add gcc-gimple.{c|h} and gcc-rtl.{c|h}
by David Hugh Malcolm
commit 638ae5797f9658540bbdc539eb51900ea96f8d65
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Thu Mar 29 21:06:05 2012 -0400
add gcc-gimple.{c|h} and gcc-rtl.{c|h}
Makefile | 2 +
gcc-python-cfg.c | 166 ++++++++++++++-------------
gcc-python-gimple.c | 37 +++---
gcc-python-rtl.c | 25 +++--
gcc-python.h | 10 +-
generate-callgraph-c.py | 2 +-
generate-gimple-c.py | 38 +++---
generate-rtl-c.py | 4 +-
generate-tree-c.py | 2 +-
proposed-plugin-api/gcc-cfg.c | 76 ++++++++++++-
proposed-plugin-api/gcc-cfg.h | 10 +-
proposed-plugin-api/gcc-gimple.c | 74 ++++++++++++
proposed-plugin-api/gcc-gimple.h | 42 +++++++
proposed-plugin-api/gcc-public-types.h | 3 +
proposed-plugin-api/gcc-rtl.c | 46 ++++++++
proposed-plugin-api/gcc-rtl.h | 32 +++++
proposed-plugin-api/gcc-semiprivate-types.h | 14 ++-
17 files changed, 433 insertions(+), 150 deletions(-)
---
diff --git a/Makefile b/Makefile
index 08b5b86..86d24d5 100644
--- a/Makefile
+++ b/Makefile
@@ -19,6 +19,8 @@
PLUGIN_SOURCE_FILES= \
proposed-plugin-api/gcc-cfg.c \
+ proposed-plugin-api/gcc-gimple.c \
+ proposed-plugin-api/gcc-rtl.c \
gcc-python.c \
gcc-python-attribute.c \
gcc-python-callbacks.c \
diff --git a/gcc-python-cfg.c b/gcc-python-cfg.c
index 558e9ad..8c67e4a 100644
--- a/gcc-python-cfg.c
+++ b/gcc-python-cfg.c
@@ -21,6 +21,7 @@
#include "gcc-python.h"
#include "gcc-python-wrappers.h"
#include "proposed-plugin-api/gcc-cfg.h"
+#include "proposed-plugin-api/gcc-gimple.h"
#if 1
/* Ideally we wouldn't have these includes here: */
@@ -123,86 +124,113 @@ gcc_BasicBlock_get_succs(PyGccBasicBlock *self, void *closure)
return result;
}
-static PyObject *
-gcc_python_gimple_seq_to_list(gimple_seq seq)
+static bool
+append_gimple_to_list(GccGimpleI stmt, void *user_data)
+{
+ PyObject *result = (PyObject *)user_data;
+ PyObject *obj_stmt;
+
+ obj_stmt = gcc_python_make_wrapper_gimple(stmt);
+ if (!obj_stmt) {
+ return true;
+ }
+
+ if (PyList_Append(result, obj_stmt)) {
+ Py_DECREF(obj_stmt);
+ return true;
+ }
+
+ /* Success: */
+ Py_DECREF(obj_stmt);
+ return false;
+}
+
+PyObject *
+gcc_BasicBlock_get_gimple(PyGccBasicBlock *self, void *closure)
{
- gimple_stmt_iterator gsi;
PyObject *result = NULL;
+ assert(self);
+ assert(self->bb.inner);
+
result = PyList_New(0);
if (!result) {
- goto error;
+ return NULL;
}
- for (gsi = gsi_start (seq);
- !gsi_end_p (gsi);
- gsi_next (&gsi)) {
-
- gimple stmt = gsi_stmt(gsi);
- PyObject *obj_stmt;
+ if (GccCfgBlockI_ForEachGimple(self->bb,
+ append_gimple_to_list,
+ result)) {
+ Py_DECREF(result);
+ return NULL;
+ }
- obj_stmt = gcc_python_make_wrapper_gimple(stmt);
- if (!obj_stmt) {
- goto error;
- }
+ return result;
+}
- if (PyList_Append(result, obj_stmt)) {
- Py_DECREF(obj_stmt);
- goto error;
- }
- Py_DECREF(obj_stmt);
+static bool
+append_gimple_phi_to_list(GccGimplePhiI stmt, void *user_data)
+{
+ PyObject *result = (PyObject *)user_data;
+ PyObject *obj_stmt;
-#if 0
- printf(" gimple: %p code: %s (%i) %s:%i num_ops=%i\n",
- stmt,
- gimple_code_name[gimple_code(stmt)],
- gimple_code(stmt),
- gimple_filename(stmt),
- gimple_lineno(stmt),
- gimple_num_ops(stmt));
-#endif
+ obj_stmt = gcc_python_make_wrapper_gimple(GccGimplePhiI_Upcast(stmt));
+ if (!obj_stmt) {
+ return true;
}
- return result;
+ if (PyList_Append(result, obj_stmt)) {
+ Py_DECREF(obj_stmt);
+ return true;
+ }
- error:
- Py_XDECREF(result);
- return NULL;
+ /* Success: */
+ Py_DECREF(obj_stmt);
+ return false;
}
-
PyObject *
-gcc_BasicBlock_get_gimple(PyGccBasicBlock *self, void *closure)
+gcc_BasicBlock_get_phi_nodes(PyGccBasicBlock *self, void *closure)
{
+ PyObject *result = NULL;
+
assert(self);
assert(self->bb.inner);
- if (self->bb.inner->flags & BB_RTL) {
- Py_RETURN_NONE;
+ result = PyList_New(0);
+ if (!result) {
+ return NULL;
}
- if (NULL == self->bb.inner->il.gimple) {
- Py_RETURN_NONE;
+ if (GccCfgBlockI_ForEachGimplePhi(self->bb,
+ append_gimple_phi_to_list,
+ result)) {
+ Py_DECREF(result);
+ return NULL;
}
- return gcc_python_gimple_seq_to_list(self->bb.inner->il.gimple->seq);
+ return result;
}
-PyObject *
-gcc_BasicBlock_get_phi_nodes(PyGccBasicBlock *self, void *closure)
+static bool
+append_rtl_to_list(GccRtlInsnI insn, void *user_data)
{
- assert(self);
- assert(self->bb.inner);
+ PyObject *result = (PyObject *)user_data;
+ PyObject *obj;
- if (self->bb.inner->flags & BB_RTL) {
- Py_RETURN_NONE;
+ obj = gcc_python_make_wrapper_rtl(insn);
+ if (!obj) {
+ return true;
}
- if (NULL == self->bb.inner->il.gimple) {
- Py_RETURN_NONE;
+ if (PyList_Append(result, obj)) {
+ Py_DECREF(obj);
+ return true;
}
- return gcc_python_gimple_seq_to_list(self->bb.inner->il.gimple->phi_nodes);
+ /* Success: */
+ Py_DECREF(obj);
+ return false;
}
PyObject *
@@ -210,48 +238,22 @@ gcc_BasicBlock_get_rtl(PyGccBasicBlock *self, void *closure)
{
PyObject *result = NULL;
- rtx insn;
-
- if (!(self->bb.inner->flags & BB_RTL)) {
- Py_RETURN_NONE;
- }
-
-#if 0
- /* Debugging help: */
- {
- fprintf(stderr, "--BEGIN--\n");
- FOR_BB_INSNS(self->bb, insn) {
- print_rtl_single (stderr, insn);
- }
- fprintf(stderr, "-- END --\n");
- }
-#endif
+ assert(self);
+ assert(self->bb.inner);
result = PyList_New(0);
if (!result) {
- goto error;
+ return NULL;
}
- FOR_BB_INSNS(self->bb.inner, insn) {
- PyObject *obj;
-
- obj = gcc_python_make_wrapper_rtl(insn);
- if (!obj) {
- goto error;
- }
-
- if (PyList_Append(result, obj)) {
- Py_DECREF(obj);
- goto error;
- }
- Py_DECREF(obj);
+ if (GccCfgBlockI_ForEachRtlInsn(self->bb,
+ append_rtl_to_list,
+ result)) {
+ Py_DECREF(result);
+ return NULL;
}
return result;
-
- error:
- Py_XDECREF(result);
- return NULL;
}
diff --git a/gcc-python-gimple.c b/gcc-python-gimple.c
index b1ffcb0..7668446 100644
--- a/gcc-python-gimple.c
+++ b/gcc-python-gimple.c
@@ -25,6 +25,7 @@
#include "gimple.h"
#include "tree-flow.h"
#include "tree-flow-inline.h"
+#include "proposed-plugin-api/gcc-gimple.h"
static PyObject *
do_pretty_print(struct PyGccGimple * self, int spc, int flags)
@@ -36,8 +37,9 @@ do_pretty_print(struct PyGccGimple * self, int spc, int flags)
}
dump_gimple_stmt(gcc_python_pretty_printer_as_pp(ppobj),
- self->stmt,
- spc, flags);
+ self->stmt.inner,
+ spc, flags);
+
result = gcc_python_pretty_printer_as_string(ppobj);
if (!result) {
goto error;
@@ -132,7 +134,7 @@ gcc_Gimple_walk_tree(struct PyGccGimple * self, PyObject *args, PyObject *kwargs
memset(&wi, 0, sizeof(wi));
wi.info = closure;
- result = walk_gimple_op (self->stmt,
+ result = walk_gimple_op (self->stmt.inner,
gimple_walk_tree_callback,
&wi);
Py_XDECREF(closure->callback);
@@ -153,16 +155,16 @@ gcc_Gimple_get_rhs(struct PyGccGimple *self, void *closure)
PyObject * result = NULL;
int i;
- assert(gimple_has_ops(self->stmt));
+ assert(gimple_has_ops(self->stmt.inner));
- assert(gimple_num_ops(self->stmt) > 0);
- result = PyList_New(gimple_num_ops (self->stmt) - 1);
+ assert(gimple_num_ops(self->stmt.inner) > 0);
+ result = PyList_New(gimple_num_ops (self->stmt.inner) - 1);
if (!result) {
goto error;
}
- for (i = 1 ; i < gimple_num_ops(self->stmt); i++) {
- tree t = gimple_op(self->stmt, i);
+ for (i = 1 ; i < gimple_num_ops(self->stmt.inner); i++) {
+ tree t = gimple_op(self->stmt.inner, i);
PyObject *obj = gcc_python_make_wrapper_tree(t);
if (!obj) {
goto error;
@@ -187,7 +189,7 @@ PyObject *
gcc_GimpleCall_get_args(struct PyGccGimple *self, void *closure)
{
PyObject * result = NULL;
- int num_args = gimple_call_num_args (self->stmt);
+ int num_args = gimple_call_num_args (self->stmt.inner);
int i;
result = PyList_New(num_args);
@@ -196,7 +198,7 @@ gcc_GimpleCall_get_args(struct PyGccGimple *self, void *closure)
}
for (i = 0 ; i < num_args; i++) {
- tree t = gimple_call_arg(self->stmt, i);
+ tree t = gimple_call_arg(self->stmt.inner, i);
PyObject *obj = gcc_python_make_wrapper_tree(t);
if (!obj) {
goto error;
@@ -216,7 +218,7 @@ gcc_GimplePhi_get_args(struct PyGccGimple *self, void *closure)
{
/* See e.g. gimple-pretty-print.c:dump_gimple_phi */
PyObject * result = NULL;
- int num_args = gimple_phi_num_args (self->stmt);
+ int num_args = gimple_phi_num_args (self->stmt.inner);
int i;
result = PyList_New(num_args);
@@ -225,8 +227,8 @@ gcc_GimplePhi_get_args(struct PyGccGimple *self, void *closure)
}
for (i = 0 ; i < num_args; i++) {
- tree arg_def = gimple_phi_arg_def(self->stmt, i);
- edge arg_edge = gimple_phi_arg_edge(self->stmt, i);
+ tree arg_def = gimple_phi_arg_def(self->stmt.inner, i);
+ edge arg_edge = gimple_phi_arg_edge(self->stmt.inner, i);
/* fwiw, there's also gimple_phi_arg_has_location and gimple_phi_arg_location */
PyObject *tuple_obj;
tuple_obj = Py_BuildValue("O&O&",
@@ -249,7 +251,7 @@ PyObject *
gcc_GimpleSwitch_get_labels(struct PyGccGimple *self, void *closure)
{
PyObject * result = NULL;
- unsigned num_labels = gimple_switch_num_labels(self->stmt);
+ unsigned num_labels = gimple_switch_num_labels(self->stmt.inner);
int i;
result = PyList_New(num_labels);
@@ -258,7 +260,7 @@ gcc_GimpleSwitch_get_labels(struct PyGccGimple *self, void *closure)
}
for (i = 0 ; i < num_labels; i++) {
- tree t = gimple_switch_label(self->stmt, i);
+ tree t = gimple_switch_label(self->stmt.inner, i);
PyObject *obj = gcc_python_make_wrapper_tree(t);
if (!obj) {
goto error;
@@ -275,7 +277,7 @@ gcc_GimpleSwitch_get_labels(struct PyGccGimple *self, void *closure)
PyObject*
-gcc_python_make_wrapper_gimple(gimple stmt)
+gcc_python_make_wrapper_gimple(GccGimpleI stmt)
{
struct PyGccGimple *gimple_obj = NULL;
PyGccWrapperTypeObject* tp;
@@ -300,8 +302,7 @@ error:
void
wrtp_mark_for_PyGccGimple(PyGccGimple *wrapper)
{
- /* Mark the underlying object (recursing into its fields): */
- gt_ggc_mx_gimple_statement_d(wrapper->stmt);
+ GccGimpleI_MarkInUse(wrapper->stmt);
}
/*
diff --git a/gcc-python-rtl.c b/gcc-python-rtl.c
index 0eb23ba..e499cdf 100644
--- a/gcc-python-rtl.c
+++ b/gcc-python-rtl.c
@@ -24,12 +24,13 @@
#include "rtl.h"
#include "tree-flow.h"
#include "tree-flow-inline.h"
+#include "proposed-plugin-api/gcc-rtl.h"
PyObject *
gcc_Rtl_get_location(struct PyGccRtl *self, void *closure)
{
- int locator = INSN_LOCATOR (self->insn);
- if (locator && insn_file (self->insn)) {
+ int locator = INSN_LOCATOR (self->insn.inner);
+ if (locator && insn_file (self->insn.inner)) {
return gcc_python_make_wrapper_location(locator_location(locator));
}
@@ -59,7 +60,8 @@ get_operand_as_object(const_rtx in_rtx, int idx, char fmt)
case 'e': /* pointer to an rtl expression */
/* Nested expression: */
- return gcc_python_make_wrapper_rtl(XEXP (in_rtx, idx));
+ return gcc_python_make_wrapper_rtl(
+ GccPrivate_make_RtlInsnI(XEXP (in_rtx, idx)));
case 'E':
case 'V':
@@ -71,7 +73,8 @@ get_operand_as_object(const_rtx in_rtx, int idx, char fmt)
return NULL;
}
for (j = 0; j < XVECLEN (in_rtx, idx); j++) {
- PyObject *item = gcc_python_make_wrapper_rtl(XVECEXP (in_rtx, idx, j));
+ PyObject *item = gcc_python_make_wrapper_rtl(
+ GccPrivate_make_RtlInsnI(XVECEXP (in_rtx, idx, j)));
if (!item) {
Py_DECREF(list);
return NULL;
@@ -117,7 +120,7 @@ get_operand_as_object(const_rtx in_rtx, int idx, char fmt)
PyObject *
gcc_Rtl_get_operands(struct PyGccRtl *self, void *closure)
{
- const int length = GET_RTX_LENGTH (GET_CODE (self->insn));
+ const int length = GET_RTX_LENGTH (GET_CODE (self->insn.inner));
PyObject *result;
int i;
const char *format_ptr;
@@ -127,9 +130,9 @@ gcc_Rtl_get_operands(struct PyGccRtl *self, void *closure)
return NULL;
}
- format_ptr = GET_RTX_FORMAT (GET_CODE (self->insn));
+ format_ptr = GET_RTX_FORMAT (GET_CODE (self->insn.inner));
for (i = 0; i < length; i++) {
- PyObject *item = get_operand_as_object(self->insn, i, *format_ptr++);
+ PyObject *item = get_operand_as_object(self->insn.inner, i, *format_ptr++);
if (!item) {
Py_DECREF(result);
return NULL;
@@ -163,7 +166,7 @@ gcc_Rtl_str(struct PyGccRtl * self)
return PyErr_SetFromErrno(PyExc_IOError);
}
- print_rtl_single (f, self->insn);
+ print_rtl_single (f, self->insn.inner);
fclose(f);
@@ -171,12 +174,12 @@ gcc_Rtl_str(struct PyGccRtl * self)
}
PyObject*
-gcc_python_make_wrapper_rtl(struct rtx_def *insn)
+gcc_python_make_wrapper_rtl(GccRtlInsnI insn)
{
struct PyGccRtl *rtl_obj = NULL;
PyGccWrapperTypeObject* tp;
- if (!insn) {
+ if (!insn.inner) {
Py_RETURN_NONE;
}
@@ -199,7 +202,7 @@ void
wrtp_mark_for_PyGccRtl(PyGccRtl *wrapper)
{
/* Mark the underlying object (recursing into its fields): */
- gt_ggc_mx_rtx_def(wrapper->insn);
+ GccRtlInsnI_MarkInUse(wrapper->insn);
}
/*
diff --git a/gcc-python.h b/gcc-python.h
index d23fb47..ff3ad4b 100644
--- a/gcc-python.h
+++ b/gcc-python.h
@@ -177,7 +177,7 @@ DECLARE_SIMPLE_WRAPPER(PyGccLocation,
DECLARE_SIMPLE_WRAPPER(PyGccGimple,
gcc_GimpleType,
gimple,
- gimple, stmt);
+ GccGimpleI, stmt);
DECLARE_SIMPLE_WRAPPER(PyGccEdge,
gcc_EdgeType,
@@ -212,7 +212,7 @@ DECLARE_SIMPLE_WRAPPER(PyGccParameter,
DECLARE_SIMPLE_WRAPPER(PyGccRtl,
gcc_RtlType,
rtl,
- struct rtx_def *, insn)
+ GccRtlInsnI, insn)
DECLARE_SIMPLE_WRAPPER(PyGccTree,
gcc_TreeType,
@@ -238,7 +238,8 @@ void autogenerated_function_add_types(PyObject *m);
/* autogenerated-gimple.c */
int autogenerated_gimple_init_types(void);
void autogenerated_gimple_add_types(PyObject *m);
-PyGccWrapperTypeObject* gcc_python_autogenerated_gimple_type_for_stmt(gimple g);
+PyGccWrapperTypeObject*
+gcc_python_autogenerated_gimple_type_for_stmt(GccGimpleI stmt);
/* autogenerated-location.c */
int autogenerated_location_init_types(void);
@@ -268,7 +269,8 @@ void autogenerated_pretty_printer_add_types(PyObject *m);
/* autogenerated-rtl.c */
int autogenerated_rtl_init_types(void);
void autogenerated_rtl_add_types(PyObject *m);
-PyGccWrapperTypeObject * gcc_python_autogenerated_rtl_type_for_stmt(struct rtx_def *insn);
+PyGccWrapperTypeObject *
+gcc_python_autogenerated_rtl_type_for_stmt(GccRtlInsnI insn);
/* autogenerated-tree.c */
diff --git a/generate-callgraph-c.py b/generate-callgraph-c.py
index 143ee34..870b058 100644
--- a/generate-callgraph-c.py
+++ b/generate-callgraph-c.py
@@ -47,7 +47,7 @@ def generate_callgraph_edge():
'The function that is called here, as a gcc.CallgraphNode')
getsettable.add_simple_getter(cu,
'call_stmt',
- 'gcc_python_make_wrapper_gimple(self->edge->call_stmt)',
+ 'gcc_python_make_wrapper_gimple(GccPrivate_make_GimpleI(self->edge->call_stmt))',
'The gcc.GimpleCall statememt for the function call')
cu.add_defn(getsettable.c_defn())
diff --git a/generate-gimple-c.py b/generate-gimple-c.py
index 9643b00..4f859e1 100644
--- a/generate-gimple-c.py
+++ b/generate-gimple-c.py
@@ -192,13 +192,13 @@ def generate_gimple():
static PyObject *
gcc_Gimple_get_location(struct PyGccGimple *self, void *closure)
{
- return gcc_python_make_wrapper_location(gimple_location(self->stmt));
+ return gcc_python_make_wrapper_location(gimple_location(self->stmt.inner));
}
static PyObject *
gcc_Gimple_get_block(struct PyGccGimple *self, void *closure)
{
- return gcc_python_make_wrapper_tree(gimple_block(self->stmt));
+ return gcc_python_make_wrapper_tree(gimple_block(self->stmt.inner));
}
""")
@@ -208,7 +208,7 @@ gcc_Gimple_get_block(struct PyGccGimple *self, void *closure)
PyGetSetDef('exprtype',
cu.add_simple_getter('gcc_Gimple_get_exprtype',
'PyGccGimple',
- 'gcc_python_make_wrapper_tree(gimple_expr_type(self->stmt))'),
+ 'gcc_python_make_wrapper_tree(gimple_expr_type(self->stmt.inner))'),
None,
'The type of the main expression computed by this statement, as a gcc.Tree (which might be gcc.VoidType)'),
PyGetSetDef('str_no_uid',
@@ -250,7 +250,7 @@ def generate_gimple_subclasses():
exprcode_getter = PyGetSetDef('exprcode',
cu.add_simple_getter('gcc_Gimple_get_exprcode',
'PyGccGimple',
- '(PyObject*)gcc_python_autogenerated_tree_type_for_tree_code(gimple_expr_code(self->stmt), 0)'),
+ '(PyObject*)gcc_python_autogenerated_tree_type_for_tree_code(gimple_expr_code(self->stmt.inner), 0)'),
None,
'The kind of the expression, as an gcc.Tree subclass (the type itself, not an instance)')
@@ -266,7 +266,7 @@ def generate_gimple_subclasses():
'PyGccGimple')
getsettable.add_simple_getter(cu,
'string',
- 'gcc_python_string_from_string(gimple_asm_string(self->stmt))',
+ 'gcc_python_string_from_string(gimple_asm_string(self->stmt.inner))',
'The inline assembler as a string')
return getsettable
@@ -275,7 +275,7 @@ def generate_gimple_subclasses():
[PyGetSetDef('lhs',
cu.add_simple_getter('gcc_GimpleAssign_get_lhs',
'PyGccGimple',
- 'gcc_python_make_wrapper_tree(gimple_assign_lhs(self->stmt))'),
+ 'gcc_python_make_wrapper_tree(gimple_assign_lhs(self->stmt.inner))'),
None,
'Left-hand-side of the assignment, as a gcc.Tree'),
exprcode_getter,
@@ -286,20 +286,20 @@ def generate_gimple_subclasses():
[PyGetSetDef('lhs',
cu.add_simple_getter('gcc_GimpleCall_get_lhs',
'PyGccGimple',
- 'gcc_python_make_wrapper_tree(gimple_call_lhs(self->stmt))'),
+ 'gcc_python_make_wrapper_tree(gimple_call_lhs(self->stmt.inner))'),
None,
'Left-hand-side of the call, as a gcc.Tree'),
rhs_getter,
PyGetSetDef('fn',
cu.add_simple_getter('gcc_GimpleCall_get_fn',
'PyGccGimple',
- 'gcc_python_make_wrapper_tree(gimple_call_fn(self->stmt))'),
+ 'gcc_python_make_wrapper_tree(gimple_call_fn(self->stmt.inner))'),
None,
'The function being called, as a gcc.Tree'),
PyGetSetDef('fndecl',
cu.add_simple_getter('gcc_GimpleCall_get_fndecl',
'PyGccGimple',
- 'gcc_python_make_wrapper_tree(gimple_call_fndecl(self->stmt))'),
+ 'gcc_python_make_wrapper_tree(gimple_call_fndecl(self->stmt.inner))'),
None,
'The declaration of the function being called (if any), as a gcc.Tree'),
exprcode_getter,
@@ -310,7 +310,7 @@ def generate_gimple_subclasses():
PyGetSetDef('noreturn',
cu.add_simple_getter('gcc_GimpleCall_get_noreturn',
'PyGccGimple',
- 'PyBool_FromLong(gimple_call_noreturn_p(self->stmt))'),
+ 'PyBool_FromLong(gimple_call_noreturn_p(self->stmt.inner))'),
None,
'Has this call been marked as not returning, as a boolean'),
@@ -321,7 +321,7 @@ def generate_gimple_subclasses():
[PyGetSetDef('retval',
cu.add_simple_getter('gcc_GimpleReturn_get_retval',
'PyGccGimple',
- 'gcc_python_make_wrapper_tree(gimple_return_retval(self->stmt))'),
+ 'gcc_python_make_wrapper_tree(gimple_return_retval(self->stmt.inner))'),
None,
'The return value, as a gcc.Tree'),
])
@@ -334,19 +334,19 @@ def generate_gimple_subclasses():
'PyGccGimple')
getsettable.add_simple_getter(cu,
'lhs',
- 'gcc_python_make_wrapper_tree(gimple_cond_lhs(self->stmt))',
+ 'gcc_python_make_wrapper_tree(gimple_cond_lhs(self->stmt.inner))',
None)
getsettable.add_simple_getter(cu,
'rhs',
- 'gcc_python_make_wrapper_tree(gimple_cond_rhs(self->stmt))',
+ 'gcc_python_make_wrapper_tree(gimple_cond_rhs(self->stmt.inner))',
None)
getsettable.add_simple_getter(cu,
'true_label',
- 'gcc_python_make_wrapper_tree(gimple_cond_true_label(self->stmt))',
+ 'gcc_python_make_wrapper_tree(gimple_cond_true_label(self->stmt.inner))',
None)
getsettable.add_simple_getter(cu,
'false_label',
- 'gcc_python_make_wrapper_tree(gimple_cond_false_label(self->stmt))',
+ 'gcc_python_make_wrapper_tree(gimple_cond_false_label(self->stmt.inner))',
None)
return getsettable
@@ -357,7 +357,7 @@ def generate_gimple_subclasses():
'PyGccGimple')
getsettable.add_simple_getter(cu,
'lhs',
- 'gcc_python_make_wrapper_tree(gimple_phi_result(self->stmt))',
+ 'gcc_python_make_wrapper_tree(gimple_phi_result(self->stmt.inner))',
None)
getsettable.add_gsdef('args',
'gcc_GimplePhi_get_args',
@@ -372,7 +372,7 @@ def generate_gimple_subclasses():
'PyGccGimple')
getsettable.add_simple_getter(cu,
'indexvar',
- 'gcc_python_make_wrapper_tree(gimple_switch_index(self->stmt))',
+ 'gcc_python_make_wrapper_tree(gimple_switch_index(self->stmt.inner))',
'Get the index variable used by the switch statement, as a gcc.Tree')
getsettable.add_gsdef('labels',
'gcc_GimpleSwitch_get_labels',
@@ -430,9 +430,9 @@ def generate_gimple_code_map():
cu.add_defn("""
PyGccWrapperTypeObject*
-gcc_python_autogenerated_gimple_type_for_stmt(gimple g)
+gcc_python_autogenerated_gimple_type_for_stmt(GccGimpleI stmt)
{
- enum gimple_code code = gimple_code(g);
+ enum gimple_code code = gimple_code(stmt.inner);
/* printf("code:%i\\n", code); */
assert(code >= 0);
diff --git a/generate-rtl-c.py b/generate-rtl-c.py
index 6270298..a08f6fd 100644
--- a/generate-rtl-c.py
+++ b/generate-rtl-c.py
@@ -159,9 +159,9 @@ def generate_rtl_code_map():
cu.add_defn("""
PyGccWrapperTypeObject*
-gcc_python_autogenerated_rtl_type_for_stmt(struct rtx_def *insn)
+gcc_python_autogenerated_rtl_type_for_stmt(GccRtlInsnI insn)
{
- enum rtx_code code = insn->code;
+ enum rtx_code code = insn.inner->code;
/* printf("code:%i\\n", code); */
assert(code >= 0);
diff --git a/generate-tree-c.py b/generate-tree-c.py
index 54ffdc6..f6fc0d3 100644
--- a/generate-tree-c.py
+++ b/generate-tree-c.py
@@ -528,7 +528,7 @@ def generate_tree_code_classes():
'gcc_python_make_wrapper_tree(SSA_NAME_VAR(self->t))',
"The variable being referenced'")
add_simple_getter('def_stmt',
- 'gcc_python_make_wrapper_gimple(SSA_NAME_DEF_STMT(self->t))',
+ 'gcc_python_make_wrapper_gimple(GccPrivate_make_GimpleI(SSA_NAME_DEF_STMT(self->t)))',
"The gcc.Gimple statement which defines this SSA name'")
add_simple_getter('version',
'gcc_python_int_from_long(SSA_NAME_VERSION(self->t))',
diff --git a/proposed-plugin-api/gcc-cfg.c b/proposed-plugin-api/gcc-cfg.c
index 2f08d51..0e98bc3 100644
--- a/proposed-plugin-api/gcc-cfg.c
+++ b/proposed-plugin-api/gcc-cfg.c
@@ -29,6 +29,8 @@
#include "cgraph.h"
#include "opts.h"
#include "c-family/c-pragma.h" /* for parse_in */
+#include "basic-block.h"
+#include "rtl.h"
/***********************************************************
GccCfgI
@@ -121,21 +123,85 @@ GccCfgBlockI_ForEachSuccEdge(GccCfgBlockI block,
return for_each_edge(block.inner->succs, cb, user_data);
}
+
GCC_IMPLEMENT_PUBLIC_API(bool)
-GccCfgBlockI_ForEachPhiNode(GccCfgBlockI block,
- bool (*cb)(GccGimplePhiI phi, void *user_data),
- void *user_data);
+GccCfgBlockI_ForEachGimplePhi(GccCfgBlockI block,
+ bool (*cb)(GccGimplePhiI phi, void *user_data),
+ void *user_data)
+{
+ gimple_stmt_iterator gsi;
+
+ if (block.inner->flags & BB_RTL) {
+ return false;
+ }
+
+ if (NULL == block.inner->il.gimple) {
+ return false;
+ }
+
+ for (gsi = gsi_start(block.inner->il.gimple->seq);
+ !gsi_end_p(gsi);
+ gsi_next(&gsi)) {
+
+ gimple stmt = gsi_stmt(gsi);
+ if (cb(GccPrivate_make_GimplePhiI(stmt),
+ user_data)) {
+ return true;
+ }
+ }
+
+ return false;
+}
GCC_IMPLEMENT_PUBLIC_API(bool)
GccCfgBlockI_ForEachGimple(GccCfgBlockI block,
bool (*cb)(GccGimpleI stmt, void *user_data),
- void *user_data);
+ void *user_data)
+{
+ gimple_stmt_iterator gsi;
+
+ if (block.inner->flags & BB_RTL) {
+ return false;
+ }
+
+ if (NULL == block.inner->il.gimple) {
+ return false;
+ }
+
+ for (gsi = gsi_start(block.inner->il.gimple->seq);
+ !gsi_end_p(gsi);
+ gsi_next(&gsi)) {
+
+ gimple stmt = gsi_stmt(gsi);
+ if (cb(GccPrivate_make_GimpleI(stmt),
+ user_data)) {
+ return true;
+ }
+ }
+
+ return false;
+}
GCC_IMPLEMENT_PUBLIC_API(bool)
GccCfgBlockI_ForEachRtlInsn(GccCfgBlockI block,
bool (*cb)(GccRtlInsnI insn, void *user_data),
- void *user_data);
+ void *user_data)
+{
+ rtx insn;
+ if (!(block.inner->flags & BB_RTL)) {
+ return false;
+ }
+
+ FOR_BB_INSNS(block.inner, insn) {
+ if (cb(GccPrivate_make_RtlInsnI(insn),
+ user_data)) {
+ return true;
+ }
+ }
+
+ return false;
+}
/***********************************************************
GccCfgEdgeI
diff --git a/proposed-plugin-api/gcc-cfg.h b/proposed-plugin-api/gcc-cfg.h
index 1a2a4ba..c06ab74 100644
--- a/proposed-plugin-api/gcc-cfg.h
+++ b/proposed-plugin-api/gcc-cfg.h
@@ -62,13 +62,13 @@ GccCfgBlockI_ForEachSuccEdge(GccCfgBlockI block,
These will only exist at a certain phase of the compilation
*/
GCC_PUBLIC_API(bool)
-GccCfgBlockI_ForEachPhiNode(GccCfgBlockI block,
- bool (*cb)(GccGimplePhiI phi, void *user_data),
- void *user_data);
+GccCfgBlockI_ForEachGimplePhi(GccCfgBlockI block,
+ bool (*cb)(GccGimplePhiI phi, void *user_data),
+ void *user_data);
/*
- Iterate over GIMPLE statements (if any); terminate if the callback returns
- truth (for linear search)
+ Iterate over non-phi GIMPLE statements (if any); terminate if the callback
+ returns truth (for linear search)
These will only exist at a certain phase of the compilation
*/
GCC_PUBLIC_API(bool)
diff --git a/proposed-plugin-api/gcc-gimple.c b/proposed-plugin-api/gcc-gimple.c
new file mode 100644
index 0000000..a591666
--- /dev/null
+++ b/proposed-plugin-api/gcc-gimple.c
@@ -0,0 +1,74 @@
+/*
+ Copyright 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2012 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include "proposed-plugin-api/gcc-gimple.h"
+
+//#include "tree.h"
+#include "gimple.h"
+#if 0
+#include "params.h"
+#include "cp/name-lookup.h" /* for global_namespace */
+#include "tree.h"
+#include "function.h"
+#include "diagnostic.h"
+#include "cgraph.h"
+#include "opts.h"
+#include "c-family/c-pragma.h" /* for parse_in */
+#include "basic-block.h"
+#include "rtl.h"
+#endif
+
+#include <gcc-plugin.h>
+
+GCC_IMPLEMENT_PUBLIC_API(void)
+GccGimpleI_MarkInUse(GccGimpleI stmt)
+{
+ /* Mark the underlying object (recursing into its fields): */
+ gt_ggc_mx_gimple_statement_d(stmt.inner);
+}
+
+GCC_IMPLEMENT_PRIVATE_API(struct GccGimplePhiI)
+GccPrivate_make_GimplePhiI(gimple inner)
+{
+ struct GccGimplePhiI result;
+ result.inner = inner;
+ return result;
+}
+
+GCC_IMPLEMENT_PRIVATE_API(struct GccGimpleI)
+GccPrivate_make_GimpleI(gimple inner)
+{
+ struct GccGimpleI result;
+ result.inner = inner;
+ return result;
+}
+
+GCC_IMPLEMENT_PUBLIC_API(GccGimpleI)
+GccGimplePhiI_Upcast(GccGimplePhiI phi)
+{
+ return GccPrivate_make_GimpleI(phi.inner);
+}
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/proposed-plugin-api/gcc-gimple.h b/proposed-plugin-api/gcc-gimple.h
new file mode 100644
index 0000000..aff0168
--- /dev/null
+++ b/proposed-plugin-api/gcc-gimple.h
@@ -0,0 +1,42 @@
+/*
+ Copyright 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2012 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include "proposed-plugin-api/gcc-common.h"
+
+/* Gimple statements (generic) */
+GCC_PUBLIC_API(void)
+GccGimpleI_MarkInUse(GccGimpleI stmt);
+
+GCC_PUBLIC_API(void)
+GccGimpleI_Print(GccGimpleI stmt,
+ GccPrinterI printer,
+ int spc, /* FIXME: meaning of spc! */
+ int flags); /* FIXME: meaning of flags! */
+
+#if 0
+GCC_PUBLIC_API(bool)
+GccGimpleI_WalkTree(GccGimpleI stmt,);
+#endif
+
+
+/* Subclasses of gimple */
+
+/* Gimple phi nodes */
+GCC_PUBLIC_API(GccGimpleI)
+GccGimplePhiI_Upcast(GccGimplePhiI phi);
diff --git a/proposed-plugin-api/gcc-public-types.h b/proposed-plugin-api/gcc-public-types.h
index dcd3e91..795463d 100644
--- a/proposed-plugin-api/gcc-public-types.h
+++ b/proposed-plugin-api/gcc-public-types.h
@@ -34,4 +34,7 @@ typedef struct GccGimpleI GccGimpleI;
/* Opaque types: RTL representation */
typedef struct GccRtlInsnI GccRtlInsnI;
+/* Opaque types: pretty-printing */
+typedef struct GccPrinterI GccPrinterI;
+
#endif /* INCLUDED__GCC_PUBLIC_TYPES_H */
diff --git a/proposed-plugin-api/gcc-rtl.c b/proposed-plugin-api/gcc-rtl.c
new file mode 100644
index 0000000..c7a15bf
--- /dev/null
+++ b/proposed-plugin-api/gcc-rtl.c
@@ -0,0 +1,46 @@
+/*
+ Copyright 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2012 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include "proposed-plugin-api/gcc-rtl.h"
+
+#include <gcc-plugin.h>
+#include "tree.h"
+#include "rtl.h"
+
+GCC_IMPLEMENT_PUBLIC_API(void)
+GccRtlInsnI_MarkInUse(GccRtlInsnI insn)
+{
+ gt_ggc_mx_rtx_def(insn.inner);
+}
+
+GCC_IMPLEMENT_PRIVATE_API(struct GccRtlInsnI)
+GccPrivate_make_RtlInsnI(struct rtx_def *inner)
+{
+ struct GccRtlInsnI result;
+ result.inner = inner;
+ return result;
+}
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/proposed-plugin-api/gcc-rtl.h b/proposed-plugin-api/gcc-rtl.h
new file mode 100644
index 0000000..3ecc223
--- /dev/null
+++ b/proposed-plugin-api/gcc-rtl.h
@@ -0,0 +1,32 @@
+/*
+ Copyright 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2012 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+/* FIXME: rationalize these headers */
+#include <Python.h>
+#include "proposed-plugin-api/gcc-common.h"
+#include "gcc-python.h"
+#include "gcc-python-wrappers.h"
+#include "gcc-python-compat.h"
+#include "rtl.h"
+#include "tree-flow.h"
+#include "tree-flow-inline.h"
+
+/* RTL instructions */
+GCC_PUBLIC_API(void)
+GccRtlInsnI_MarkInUse(GccRtlInsnI insn);
diff --git a/proposed-plugin-api/gcc-semiprivate-types.h b/proposed-plugin-api/gcc-semiprivate-types.h
index fb36a8f..f0b7474 100644
--- a/proposed-plugin-api/gcc-semiprivate-types.h
+++ b/proposed-plugin-api/gcc-semiprivate-types.h
@@ -56,17 +56,27 @@ GCC_PRIVATE_API(struct GccCfgEdgeI)
GccPrivate_make_CfgEdgeI(edge inner);
-#if 0
/* Semiprivate types: GIMPLE representation */
struct GccGimplePhiI {
+ gimple inner;
};
+GCC_PRIVATE_API(struct GccGimplePhiI)
+GccPrivate_make_GimplePhiI(gimple inner);
+
struct GccGimpleI {
+ gimple inner;
};
+GCC_PRIVATE_API(struct GccGimpleI)
+GccPrivate_make_GimpleI(gimple inner);
+
/* Semiprivate types: RTL representation */
struct GccRtlInsnI {
+ struct rtx_def *inner;
};
-#endif
+
+GCC_PRIVATE_API(struct GccRtlInsnI)
+GccPrivate_make_RtlInsnI(struct rtx_def *inner);
#endif /* INCLUDED__GCC_SEMIPRIVATE_TYPES_H */
12 years, 1 month
[gcc-python-plugin/proposed-plugin-api] introduce gcc-common.h
by David Hugh Malcolm
commit 00a269fd8f7c7a3a0a27f9007913945fc3c8d81d
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Thu Mar 29 21:02:05 2012 -0400
introduce gcc-common.h
proposed-plugin-api/gcc-cfg.h | 16 +---------------
proposed-plugin-api/gcc-common.h | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 36 insertions(+), 15 deletions(-)
---
diff --git a/proposed-plugin-api/gcc-cfg.h b/proposed-plugin-api/gcc-cfg.h
index 8dbeed0..1a2a4ba 100644
--- a/proposed-plugin-api/gcc-cfg.h
+++ b/proposed-plugin-api/gcc-cfg.h
@@ -17,21 +17,7 @@
<http://www.gnu.org/licenses/>.
*/
-#include <gcc-plugin.h>
-
-/* see design.rst for notes */
-
-/* Compatibility macros */
-
-/* For declarations: */
-#define GCC_PUBLIC_API(RETURN_TYPE) extern RETURN_TYPE
-#define GCC_PRIVATE_API(RETURN_TYPE) extern RETURN_TYPE
-
-#include "gcc-public-types.h"
-
-/* For internal use: */
-#define GCC_IMPLEMENT_PUBLIC_API(RETURN_TYPE) RETURN_TYPE
-#define GCC_IMPLEMENT_PRIVATE_API(RETURN_TYPE) RETURN_TYPE
+#include "proposed-plugin-api/gcc-common.h"
/* Declarations: control flow graphs */
diff --git a/proposed-plugin-api/gcc-common.h b/proposed-plugin-api/gcc-common.h
new file mode 100644
index 0000000..9132beb
--- /dev/null
+++ b/proposed-plugin-api/gcc-common.h
@@ -0,0 +1,35 @@
+/*
+ Copyright 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2012 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include <gcc-plugin.h>
+
+/* see design.rst for notes */
+
+/* Compatibility macros */
+
+/* For declarations: */
+#define GCC_PUBLIC_API(RETURN_TYPE) extern RETURN_TYPE
+#define GCC_PRIVATE_API(RETURN_TYPE) extern RETURN_TYPE
+
+#include "gcc-public-types.h"
+
+/* For internal use: */
+#define GCC_IMPLEMENT_PUBLIC_API(RETURN_TYPE) RETURN_TYPE
+#define GCC_IMPLEMENT_PRIVATE_API(RETURN_TYPE) RETURN_TYPE
+
12 years, 1 month
[gcc-python-plugin/proposed-plugin-api] initial attempt at a plugin API
by David Hugh Malcolm
commit 36a0d6a45473c39db550915f8419a794f2f5653e
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Thu Mar 29 16:38:05 2012 -0400
initial attempt at a plugin API
Makefile | 1 +
gcc-python-cfg.c | 136 +++++++++++---------
gcc-python-rtl.c | 3 +-
gcc-python.c | 3 +
gcc-python.h | 11 +-
generate-cfg-c.py | 17 ++-
generate-function-c.py | 2 +-
proposed-plugin-api/design.rst | 44 +++++++
proposed-plugin-api/gcc-cfg.c | 182 +++++++++++++++++++++++++++
proposed-plugin-api/gcc-cfg.h | 132 +++++++++++++++++++
proposed-plugin-api/gcc-public-types.h | 37 ++++++
proposed-plugin-api/gcc-semiprivate-types.h | 72 +++++++++++
12 files changed, 566 insertions(+), 74 deletions(-)
---
diff --git a/Makefile b/Makefile
index ba0a48a..08b5b86 100644
--- a/Makefile
+++ b/Makefile
@@ -18,6 +18,7 @@
.PHONY: all clean debug dump_gimple plugin show-ssa tarball test-suite testcpychecker testcpybuilder
PLUGIN_SOURCE_FILES= \
+ proposed-plugin-api/gcc-cfg.c \
gcc-python.c \
gcc-python-attribute.c \
gcc-python-callbacks.c \
diff --git a/gcc-python-cfg.c b/gcc-python-cfg.c
index b72d298..558e9ad 100644
--- a/gcc-python-cfg.c
+++ b/gcc-python-cfg.c
@@ -20,9 +20,13 @@
#include <Python.h>
#include "gcc-python.h"
#include "gcc-python-wrappers.h"
+#include "proposed-plugin-api/gcc-cfg.h"
+#if 1
+/* Ideally we wouldn't have these includes here: */
#include "basic-block.h"
#include "rtl.h"
+#endif
/*
"struct edge_def" is declared in basic-block.h, c.f:
@@ -34,11 +38,11 @@
typedef const struct edge_def *const_edge;
*/
PyObject *
-gcc_python_make_wrapper_edge(edge e)
+gcc_python_make_wrapper_edge(GccCfgEdgeI e)
{
struct PyGccEdge *obj;
- if (!e) {
+ if (!e.inner) {
Py_RETURN_NONE;
}
@@ -59,58 +63,64 @@ void
wrtp_mark_for_PyGccEdge(PyGccEdge *wrapper)
{
/* Mark the underlying object (recursing into its fields): */
- gt_ggc_mx_edge_def(wrapper->e);
+ GccCfgEdgeI_MarkInUse(wrapper->e);
}
-
-/*
- "struct basic_block_def" is declared in basic-block.h, c.f:
- struct GTY((chain_next ("%h.next_bb"), chain_prev ("%h.prev_bb"))) basic_block_def {
- ... snip ...
- }
- and there are these typedefs to pointers defined in coretypes.h:
- typedef struct basic_block_def *basic_block;
- typedef const struct basic_block_def *const_basic_block;
- */
-PyObject *
-VEC_edge_as_PyList(VEC(edge,gc) *vec_edges)
+static bool add_edge_to_list(GccCfgEdgeI edge, void *user_data)
{
- PyObject *result = NULL;
- int i;
- edge e;
-
- result = PyList_New(VEC_length(edge, vec_edges));
- if (!result) {
- goto error;
- }
+ PyObject *result = (PyObject*)user_data;
+ PyObject *item;
- FOR_EACH_VEC_ELT(edge, vec_edges, i, e) {
- PyObject *item;
- item = gcc_python_make_wrapper_edge(e);
- if (!item) {
- goto error;
- }
- PyList_SetItem(result, i, item);
+ item = gcc_python_make_wrapper_edge(edge);
+ if (!item) {
+ return true;
}
- return result;
+ if (-1 == PyList_Append(result, item)) {
+ Py_DECREF(item);
+ }
- error:
- Py_XDECREF(result);
- return NULL;
+ return false;
}
-
PyObject *
gcc_BasicBlock_get_preds(PyGccBasicBlock *self, void *closure)
{
- return VEC_edge_as_PyList(self->bb->preds);
+ PyObject *result;
+
+ result = PyList_New(0);
+ if (!result) {
+ return NULL;
+ }
+
+ if (GccCfgBlockI_ForEachPredEdge(self->bb,
+ add_edge_to_list,
+ result)) {
+ Py_DECREF(result);
+ return NULL;
+ }
+
+ return result;
}
PyObject *
gcc_BasicBlock_get_succs(PyGccBasicBlock *self, void *closure)
{
- return VEC_edge_as_PyList(self->bb->succs);
+ PyObject *result;
+
+ result = PyList_New(0);
+ if (!result) {
+ return NULL;
+ }
+
+ if (GccCfgBlockI_ForEachSuccEdge(self->bb,
+ add_edge_to_list,
+ result)) {
+ Py_DECREF(result);
+ return NULL;
+ }
+
+ return result;
}
static PyObject *
@@ -165,34 +175,34 @@ PyObject *
gcc_BasicBlock_get_gimple(PyGccBasicBlock *self, void *closure)
{
assert(self);
- assert(self->bb);
+ assert(self->bb.inner);
- if (self->bb->flags & BB_RTL) {
+ if (self->bb.inner->flags & BB_RTL) {
Py_RETURN_NONE;
}
- if (NULL == self->bb->il.gimple) {
+ if (NULL == self->bb.inner->il.gimple) {
Py_RETURN_NONE;
}
- return gcc_python_gimple_seq_to_list(self->bb->il.gimple->seq);
+ return gcc_python_gimple_seq_to_list(self->bb.inner->il.gimple->seq);
}
PyObject *
gcc_BasicBlock_get_phi_nodes(PyGccBasicBlock *self, void *closure)
{
assert(self);
- assert(self->bb);
+ assert(self->bb.inner);
- if (self->bb->flags & BB_RTL) {
+ if (self->bb.inner->flags & BB_RTL) {
Py_RETURN_NONE;
}
- if (NULL == self->bb->il.gimple) {
+ if (NULL == self->bb.inner->il.gimple) {
Py_RETURN_NONE;
}
- return gcc_python_gimple_seq_to_list(self->bb->il.gimple->phi_nodes);
+ return gcc_python_gimple_seq_to_list(self->bb.inner->il.gimple->phi_nodes);
}
PyObject *
@@ -202,7 +212,7 @@ gcc_BasicBlock_get_rtl(PyGccBasicBlock *self, void *closure)
rtx insn;
- if (!(self->bb->flags & BB_RTL)) {
+ if (!(self->bb.inner->flags & BB_RTL)) {
Py_RETURN_NONE;
}
@@ -222,7 +232,7 @@ gcc_BasicBlock_get_rtl(PyGccBasicBlock *self, void *closure)
goto error;
}
- FOR_BB_INSNS(self->bb, insn) {
+ FOR_BB_INSNS(self->bb.inner, insn) {
PyObject *obj;
obj = gcc_python_make_wrapper_rtl(insn);
@@ -348,10 +358,10 @@ gcc_python_insert_new_wrapper_into_cache(PyObject **cache,
static PyObject *
real_make_basic_block_wrapper(void *ptr)
{
- basic_block bb = (basic_block)ptr;
+ GccCfgBlockI bb = GccPrivate_make_CfgBlockI(ptr);
struct PyGccBasicBlock *obj;
- if (!bb) {
+ if (!bb.inner) {
Py_RETURN_NONE;
}
@@ -433,16 +443,16 @@ void
wrtp_mark_for_PyGccBasicBlock(PyGccBasicBlock *wrapper)
{
/* Mark the underlying object (recursing into its fields): */
- gt_ggc_mx_basic_block_def(wrapper->bb);
+ GccCfgBlockI_MarkInUse(wrapper->bb);
}
static PyObject *basic_block_wrapper_cache = NULL;
PyObject *
-gcc_python_make_wrapper_basic_block(basic_block bb)
+gcc_python_make_wrapper_basic_block(GccCfgBlockI bb)
{
return gcc_python_lazily_create_wrapper(&basic_block_wrapper_cache,
- bb,
+ bb.inner,
real_make_basic_block_wrapper);
}
@@ -458,14 +468,18 @@ gcc_Cfg_get_basic_blocks(PyGccCfg *self, void *closure)
PyObject *result = NULL;
int i;
- result = PyList_New(self->cfg->x_n_basic_blocks);
+ result = PyList_New(self->cfg.inner->x_n_basic_blocks);
if (!result) {
goto error;
}
- for (i = 0; i < self->cfg->x_n_basic_blocks; i++) {
+ for (i = 0; i < self->cfg.inner->x_n_basic_blocks; i++) {
PyObject *item;
- item = gcc_python_make_wrapper_basic_block(VEC_index(basic_block, self->cfg->x_basic_block_info, i));
+ item = gcc_python_make_wrapper_basic_block(
+ GccPrivate_make_CfgBlockI(
+ VEC_index(basic_block,
+ self->cfg.inner->x_basic_block_info,
+ i)));
if (!item) {
goto error;
}
@@ -499,7 +513,7 @@ gcc_Cfg_get_block_for_label(PyObject *s, PyObject *args)
uid = LABEL_DECL_UID(label_decl->t);
if (uid < 0 ||
- (VEC_length (basic_block, self->cfg->x_label_to_block_map)
+ (VEC_length (basic_block, self->cfg.inner->x_label_to_block_map)
<=
(unsigned int) uid)
) {
@@ -507,17 +521,17 @@ gcc_Cfg_get_block_for_label(PyObject *s, PyObject *args)
"uid %i not found", uid);
}
- bb = VEC_index(basic_block, self->cfg->x_label_to_block_map, uid);
+ bb = VEC_index(basic_block, self->cfg.inner->x_label_to_block_map, uid);
- return gcc_python_make_wrapper_basic_block(bb);
+ return gcc_python_make_wrapper_basic_block(GccPrivate_make_CfgBlockI(bb));
}
PyObject *
-gcc_python_make_wrapper_cfg(struct control_flow_graph *cfg)
+gcc_python_make_wrapper_cfg(GccCfgI cfg)
{
struct PyGccCfg *obj;
- if (!cfg) {
+ if (!cfg.inner) {
Py_RETURN_NONE;
}
@@ -538,7 +552,7 @@ void
wrtp_mark_for_PyGccCfg(PyGccCfg *wrapper)
{
/* Mark the underlying object (recursing into its fields): */
- gt_ggc_mx_control_flow_graph(wrapper->cfg);
+ GccCfgI_MarkInUse(wrapper->cfg);
}
/*
diff --git a/gcc-python-rtl.c b/gcc-python-rtl.c
index 6695af5..0eb23ba 100644
--- a/gcc-python-rtl.c
+++ b/gcc-python-rtl.c
@@ -106,7 +106,8 @@ get_operand_as_object(const_rtx in_rtx, int idx, char fmt)
Py_RETURN_NONE; /* for now */
case 'B':
- return gcc_python_make_wrapper_basic_block(XBBDEF (in_rtx, idx));
+ return gcc_python_make_wrapper_basic_block(
+ GccPrivate_make_CfgBlockI(XBBDEF (in_rtx, idx)));
default:
gcc_unreachable ();
diff --git a/gcc-python.c b/gcc-python.c
index f037988..b837c1c 100644
--- a/gcc-python.c
+++ b/gcc-python.c
@@ -27,6 +27,8 @@ int plugin_is_GPL_compatible;
#include "plugin-version.h"
+#if 1
+/* Ideally we wouldn't have these includes here: */
#include "cp/name-lookup.h" /* for global_namespace */
#include "tree.h"
#include "function.h"
@@ -40,6 +42,7 @@ int plugin_is_GPL_compatible;
* subdirectory in newer versions of gcc.
*/
#include "c-pragma.h" /* for parse_in */
+#endif
#if 0
#define LOG(msg) \
diff --git a/gcc-python.h b/gcc-python.h
index 00dbcc6..d23fb47 100644
--- a/gcc-python.h
+++ b/gcc-python.h
@@ -22,9 +22,12 @@
#include <gcc-plugin.h>
#include "autogenerated-config.h"
+#if 1
#include "tree.h"
#include "gimple.h"
#include "params.h"
+#endif
+#include "proposed-plugin-api/gcc-cfg.h"
/* GCC doesn't seem to give us an ID for "invalid event", so invent one: */
#define GCC_PYTHON_PLUGIN_BAD_EVENT (0xffff)
@@ -176,20 +179,20 @@ DECLARE_SIMPLE_WRAPPER(PyGccGimple,
gimple,
gimple, stmt);
-DECLARE_SIMPLE_WRAPPER(PyGccEdge,
+DECLARE_SIMPLE_WRAPPER(PyGccEdge,
gcc_EdgeType,
edge,
- edge, e)
+ GccCfgEdgeI, e)
DECLARE_SIMPLE_WRAPPER(PyGccBasicBlock,
gcc_BasicBlockType,
basic_block,
- basic_block, bb)
+ GccCfgBlockI, bb)
DECLARE_SIMPLE_WRAPPER(PyGccCfg,
gcc_CfgType,
cfg,
- struct control_flow_graph *, cfg)
+ GccCfgI, cfg)
DECLARE_SIMPLE_WRAPPER(PyGccFunction,
gcc_FunctionType,
diff --git a/generate-cfg-c.py b/generate-cfg-c.py
index f855316..dc69165 100644
--- a/generate-cfg-c.py
+++ b/generate-cfg-c.py
@@ -22,7 +22,8 @@ cu = CompilationUnit()
cu.add_include('gcc-python.h')
cu.add_include('gcc-python-wrappers.h')
cu.add_include('gcc-plugin.h')
-cu.add_include("basic-block.h")
+cu.add_include('proposed-plugin-api/gcc-cfg.h')
+#cu.add_include("basic-block.h")
modinit_preinit = ''
modinit_postinit = ''
@@ -38,17 +39,18 @@ def generate_edge():
[PyGetSetDef('src',
cu.add_simple_getter('gcc_Edge_get_src',
'PyGccEdge',
- 'gcc_python_make_wrapper_basic_block(self->e->src)'),
+ 'gcc_python_make_wrapper_basic_block(GccCfgEdgeI_GetSrc(self->e))'),
None,
'The source gcc.BasicBlock of this edge'),
PyGetSetDef('dest',
cu.add_simple_getter('gcc_Edge_get_dest',
'PyGccEdge',
- 'gcc_python_make_wrapper_basic_block(self->e->dest)'),
+ 'gcc_python_make_wrapper_basic_block(GccCfgEdgeI_GetDest(self->e))'),
None,
'The destination gcc.BasicBlock of this edge')],
identifier_prefix = 'gcc_Edge',
typename = 'PyGccEdge')
+ """
for flag in ('EDGE_FALLTHRU', 'EDGE_ABNORMAL', 'EDGE_ABNORMAL_CALL',
'EDGE_EH', 'EDGE_FAKE', 'EDGE_DFS_BACK', 'EDGE_CAN_FALLTHRU',
'EDGE_IRREDUCIBLE_LOOP', 'EDGE_SIBCALL', 'EDGE_LOOP_EXIT',
@@ -58,8 +60,9 @@ def generate_edge():
flagname = flag[5:].lower()
getsettable.add_simple_getter(cu,
flagname,
- 'PyBool_FromLong(self->e->flags & %s)' % flag,
+ 'PyBool_FromLong(gcc_edge_is_%s(self->e))' % flagname,
'Boolean, corresponding to flag %s' % flag)
+ """
cu.add_defn(getsettable.c_defn())
pytype = PyGccWrapperTypeObject(identifier = 'gcc_EdgeType',
@@ -111,7 +114,7 @@ def generate_basic_block():
typename='PyGccBasicBlock')
getsettable.add_simple_getter(cu,
'index',
- 'gcc_python_int_from_long(self->bb->index)',
+ 'gcc_python_int_from_long(GccCfgBlockI_GetIndex(self->bb))',
None)
cu.add_defn(getsettable.c_defn())
@@ -146,13 +149,13 @@ def generate_cfg():
PyGetSetDef('entry',
cu.add_simple_getter('gcc_Cfg_get_entry',
'PyGccCfg',
- 'gcc_python_make_wrapper_basic_block(self->cfg->x_entry_block_ptr)'),
+ 'gcc_python_make_wrapper_basic_block(GccCfgI_GetEntry(self->cfg))'),
None,
'The initial gcc.BasicBlock in this graph'),
PyGetSetDef('exit',
cu.add_simple_getter('gcc_Cfg_get_exit',
'PyGccCfg',
- 'gcc_python_make_wrapper_basic_block(self->cfg->x_exit_block_ptr)'),
+ 'gcc_python_make_wrapper_basic_block(GccCfgI_GetExit(self->cfg))'),
None,
'The final gcc.BasicBlock in this graph'),
])
diff --git a/generate-function-c.py b/generate-function-c.py
index 6aea87e..9e03fb0 100644
--- a/generate-function-c.py
+++ b/generate-function-c.py
@@ -37,7 +37,7 @@ def generate_function():
"static PyObject *\n"
"gcc_Function_get_cfg(struct PyGccFunction *self, void *closure)\n"
"{\n"
- " return gcc_python_make_wrapper_cfg(self->fun->cfg);\n"
+ " return gcc_python_make_wrapper_cfg(GccPrivate_make_CfgI(self->fun->cfg));\n"
"}\n"
"\n")
getsettable = PyGetSetDefTable('gcc_Function_getset_table',
diff --git a/proposed-plugin-api/design.rst b/proposed-plugin-api/design.rst
new file mode 100644
index 0000000..31b960c
--- /dev/null
+++ b/proposed-plugin-api/design.rst
@@ -0,0 +1,44 @@
+Proposed GCC plugin API
+-----------------------
+
+All public functions are declared with GCC_PUBLIC_API, any private
+helper functions are declared with GCC_PRIVATE_API
+
+Different plugins are likely to want different lifetime-management
+policies for the wrapper objects: some plugins will want to
+garbage-collect, others will want to reference-count, etc.
+
+ence all types are "really" just pointers, but are hidden somewhat to
+emphasize that you must collaborate with the GCC garbage collector.
+
+Naming convention: a GccSomethingI is a GCC "something" interface
+e.g. GccGimplePhiI is an interface to a Gcc Gimple phi node. All types
+also have a standard varname (e.g. "edge" for a GccCfgEdgeI). All
+functions have a prefix relating to what they act on, e.g.:
+
+All such interface types have a "MarkInUse" function, e.g.::
+
+ GCC_PUBLIC_API(void)
+ GccCfgBlockI_MarkInUse(GccCfgBlockI block);
+
+If you're holding a pointer to one of these types, you *must* call this
+when GCC's garbage collector runs.
+
+Getters are named "TYPEPREFIX_GetATTR" e.g. "GccCfgBlockI_GetIndex"
+
+Iterators follow a common pattern. Here's one that iterates over all basic
+blocks within a control flow graph::
+
+ GCC_PUBLIC_API(bool)
+ GccCfgI_ForEachBlock(GccCfgI cfg,
+ bool (*cb)(GccCfgBlockI block, void *user_data),
+ void *user_data);
+
+The iteration terminates if the callback ever returns truth (allowing
+it also to be used for a linear search). The overall return value is truth
+if any callback returned truth (implying there was an early exit), or false
+if every callback returned falsehood (implying every element was visited).
+
+TODO: how to arrange for your code to be called when the GC runs?
+
+TODO: getting errors?
diff --git a/proposed-plugin-api/gcc-cfg.c b/proposed-plugin-api/gcc-cfg.c
new file mode 100644
index 0000000..2f08d51
--- /dev/null
+++ b/proposed-plugin-api/gcc-cfg.c
@@ -0,0 +1,182 @@
+/*
+ Copyright 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2012 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include "proposed-plugin-api/gcc-cfg.h"
+
+#include "tree.h"
+#include "gimple.h"
+#include "params.h"
+#include "cp/name-lookup.h" /* for global_namespace */
+#include "tree.h"
+#include "function.h"
+#include "diagnostic.h"
+#include "cgraph.h"
+#include "opts.h"
+#include "c-family/c-pragma.h" /* for parse_in */
+
+/***********************************************************
+ GccCfgI
+************************************************************/
+GCC_IMPLEMENT_PRIVATE_API(struct GccCfgI)
+GccPrivate_make_CfgI(struct control_flow_graph *inner)
+{
+ struct GccCfgI result;
+ result.inner = inner;
+ return result;
+}
+
+GCC_IMPLEMENT_PUBLIC_API(void)
+GccCfgI_MarkInUse(GccCfgI cfg)
+{
+ gt_ggc_mx_control_flow_graph(cfg.inner);
+}
+
+GCC_IMPLEMENT_PUBLIC_API(GccCfgBlockI)
+GccCfgI_GetEntry(GccCfgI cfg)
+{
+ return GccPrivate_make_CfgBlockI(cfg.inner->x_entry_block_ptr);
+}
+
+GCC_IMPLEMENT_PUBLIC_API(GccCfgBlockI)
+GccCfgI_GetExit(GccCfgI cfg)
+{
+ return GccPrivate_make_CfgBlockI(cfg.inner->x_exit_block_ptr);
+}
+
+GCC_IMPLEMENT_PUBLIC_API(bool)
+GccCfgI_ForEachBlock(GccCfgI cfg,
+ bool (*cb)(GccCfgBlockI block, void *user_data),
+ void *user_data);
+
+/***********************************************************
+ GccCfgBlockI
+************************************************************/
+GCC_IMPLEMENT_PRIVATE_API(struct GccCfgBlockI)
+GccPrivate_make_CfgBlockI(basic_block inner)
+{
+ struct GccCfgBlockI result;
+ result.inner = inner;
+ return result;
+}
+
+GCC_IMPLEMENT_PUBLIC_API(void)
+GccCfgBlockI_MarkInUse(GccCfgBlockI block)
+{
+ gt_ggc_mx_basic_block_def(block.inner);
+}
+
+GCC_IMPLEMENT_PUBLIC_API(int)
+GccCfgBlockI_GetIndex(GccCfgBlockI block)
+{
+ return block.inner->index;
+}
+
+static bool
+for_each_edge(VEC(edge,gc) *vec_edges,
+ bool (*cb)(GccCfgEdgeI edge, void *user_data),
+ void *user_data)
+{
+ int i;
+ edge e;
+
+ FOR_EACH_VEC_ELT(edge, vec_edges, i, e) {
+ if (cb(GccPrivate_make_CfgEdgeI(e),
+ user_data)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+GCC_IMPLEMENT_PUBLIC_API(bool)
+GccCfgBlockI_ForEachPredEdge(GccCfgBlockI block,
+ bool (*cb)(GccCfgEdgeI edge, void *user_data),
+ void *user_data)
+{
+ return for_each_edge(block.inner->preds, cb, user_data);
+}
+
+GCC_IMPLEMENT_PUBLIC_API(bool)
+GccCfgBlockI_ForEachSuccEdge(GccCfgBlockI block,
+ bool (*cb)(GccCfgEdgeI edge, void *user_data),
+ void *user_data)
+{
+ return for_each_edge(block.inner->succs, cb, user_data);
+}
+
+GCC_IMPLEMENT_PUBLIC_API(bool)
+GccCfgBlockI_ForEachPhiNode(GccCfgBlockI block,
+ bool (*cb)(GccGimplePhiI phi, void *user_data),
+ void *user_data);
+
+GCC_IMPLEMENT_PUBLIC_API(bool)
+GccCfgBlockI_ForEachGimple(GccCfgBlockI block,
+ bool (*cb)(GccGimpleI stmt, void *user_data),
+ void *user_data);
+
+GCC_IMPLEMENT_PUBLIC_API(bool)
+GccCfgBlockI_ForEachRtlInsn(GccCfgBlockI block,
+ bool (*cb)(GccRtlInsnI insn, void *user_data),
+ void *user_data);
+
+
+/***********************************************************
+ GccCfgEdgeI
+************************************************************/
+GCC_IMPLEMENT_PRIVATE_API(struct GccCfgEdgeI)
+GccPrivate_make_CfgEdgeI(edge inner)
+{
+ struct GccCfgEdgeI result;
+ result.inner = inner;
+ return result;
+}
+
+GCC_IMPLEMENT_PUBLIC_API(void)
+GccCfgEdgeI_MarkInUse(GccCfgEdgeI edge)
+{
+ gt_ggc_mx_edge_def(edge.inner);
+}
+
+GCC_IMPLEMENT_PUBLIC_API(GccCfgBlockI)
+GccCfgEdgeI_GetSrc(GccCfgEdgeI edge)
+{
+ return GccPrivate_make_CfgBlockI(edge.inner->src);
+}
+
+GCC_IMPLEMENT_PUBLIC_API(GccCfgBlockI)
+GccCfgEdgeI_GetDest(GccCfgEdgeI edge)
+{
+ return GccPrivate_make_CfgBlockI(edge.inner->dest);
+}
+
+GCC_IMPLEMENT_PUBLIC_API(bool)
+GccCfgEdgeI_IsFallthru(GccCfgEdgeI edge)
+{
+ return edge.inner->flags & EDGE_FALLTHRU;
+}
+
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/proposed-plugin-api/gcc-cfg.h b/proposed-plugin-api/gcc-cfg.h
new file mode 100644
index 0000000..8dbeed0
--- /dev/null
+++ b/proposed-plugin-api/gcc-cfg.h
@@ -0,0 +1,132 @@
+/*
+ Copyright 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2012 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include <gcc-plugin.h>
+
+/* see design.rst for notes */
+
+/* Compatibility macros */
+
+/* For declarations: */
+#define GCC_PUBLIC_API(RETURN_TYPE) extern RETURN_TYPE
+#define GCC_PRIVATE_API(RETURN_TYPE) extern RETURN_TYPE
+
+#include "gcc-public-types.h"
+
+/* For internal use: */
+#define GCC_IMPLEMENT_PUBLIC_API(RETURN_TYPE) RETURN_TYPE
+#define GCC_IMPLEMENT_PRIVATE_API(RETURN_TYPE) RETURN_TYPE
+
+/* Declarations: control flow graphs */
+
+/* GccCfgI */
+GCC_PUBLIC_API(void)
+GccCfgI_MarkInUse(GccCfgI cfg);
+
+GCC_PUBLIC_API(GccCfgBlockI)
+GccCfgI_GetEntry(GccCfgI cfg);
+
+GCC_PUBLIC_API(GccCfgBlockI)
+GccCfgI_GetExit(GccCfgI cfg);
+
+GCC_PUBLIC_API(bool)
+GccCfgI_ForEachBlock(GccCfgI cfg,
+ bool (*cb)(GccCfgBlockI block, void *user_data),
+ void *user_data);
+
+/* GccCfgBlockI: */
+GCC_PUBLIC_API(void)
+GccCfgBlockI_MarkInUse(GccCfgBlockI block);
+
+GCC_PUBLIC_API(int)
+GccCfgBlockI_GetIndex(GccCfgBlockI block);
+
+/* Iterate over predecessor edges; terminate if the callback returns truth
+ (for linear search) */
+GCC_PUBLIC_API(bool)
+GccCfgBlockI_ForEachPredEdge(GccCfgBlockI block,
+ bool (*cb)(GccCfgEdgeI edge, void *user_data),
+ void *user_data);
+
+/* Same, but for successor edges */
+GCC_PUBLIC_API(bool)
+GccCfgBlockI_ForEachSuccEdge(GccCfgBlockI block,
+ bool (*cb)(GccCfgEdgeI edge, void *user_data),
+ void *user_data);
+
+/*
+ Iterate over phi nodes (if any); terminate if the callback returns truth
+ (for linear search).
+ These will only exist at a certain phase of the compilation
+*/
+GCC_PUBLIC_API(bool)
+GccCfgBlockI_ForEachPhiNode(GccCfgBlockI block,
+ bool (*cb)(GccGimplePhiI phi, void *user_data),
+ void *user_data);
+
+/*
+ Iterate over GIMPLE statements (if any); terminate if the callback returns
+ truth (for linear search)
+ These will only exist at a certain phase of the compilation
+*/
+GCC_PUBLIC_API(bool)
+GccCfgBlockI_ForEachGimple(GccCfgBlockI block,
+ bool (*cb)(GccGimpleI stmt, void *user_data),
+ void *user_data);
+
+/*
+ Iterate over RTL instructions (if any); terminate if the callback returns
+ truth (for linear search)
+ These will only exist at a certain phase of the compilation
+*/
+GCC_PUBLIC_API(bool)
+GccCfgBlockI_ForEachRtlInsn(GccCfgBlockI block,
+ bool (*cb)(GccRtlInsnI insn, void *user_data),
+ void *user_data);
+
+/* GccCfgEdgeI: */
+GCC_PUBLIC_API(GccCfgBlockI)
+GccCfgEdgeI_GetSrc(GccCfgEdgeI edge);
+
+GCC_PUBLIC_API(GccCfgBlockI)
+GccCfgEdgeI_GetDest(GccCfgEdgeI edge);
+
+/* If you store a (gcc_cfg_edge*), you are explicitly responsible for calling
+ this during the "mark" phase of GCC's garbage collector */
+GCC_PUBLIC_API(void)
+GccCfgEdgeI_MarkInUse(GccCfgEdgeI edge);
+
+/*
+ for flag in ('EDGE_FALLTHRU', 'EDGE_ABNORMAL', 'EDGE_ABNORMAL_CALL',
+ 'EDGE_EH', 'EDGE_FAKE', 'EDGE_DFS_BACK', 'EDGE_CAN_FALLTHRU',
+ 'EDGE_IRREDUCIBLE_LOOP', 'EDGE_SIBCALL', 'EDGE_LOOP_EXIT',
+ 'EDGE_TRUE_VALUE', 'EDGE_FALSE_VALUE', 'EDGE_EXECUTABLE',
+ 'EDGE_CROSSING'):
+*/
+GCC_PUBLIC_API(bool)
+GccCfgEdgeI_IsFallthru(GccCfgEdgeI edge);
+/* etc */
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/proposed-plugin-api/gcc-public-types.h b/proposed-plugin-api/gcc-public-types.h
new file mode 100644
index 0000000..dcd3e91
--- /dev/null
+++ b/proposed-plugin-api/gcc-public-types.h
@@ -0,0 +1,37 @@
+/*
+ Copyright 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2012 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef INCLUDED__GCC_PUBLIC_TYPES_H
+#define INCLUDED__GCC_PUBLIC_TYPES_H
+
+#include "gcc-semiprivate-types.h"
+
+/* Opaque types: control flow graphs */
+typedef struct GccCfgI GccCfgI;
+typedef struct GccCfgBlockI GccCfgBlockI;
+typedef struct GccCfgEdgeI GccCfgEdgeI;
+
+/* Opaque types: GIMPLE representation */
+typedef struct GccGimplePhiI GccGimplePhiI;
+typedef struct GccGimpleI GccGimpleI;
+
+/* Opaque types: RTL representation */
+typedef struct GccRtlInsnI GccRtlInsnI;
+
+#endif /* INCLUDED__GCC_PUBLIC_TYPES_H */
diff --git a/proposed-plugin-api/gcc-semiprivate-types.h b/proposed-plugin-api/gcc-semiprivate-types.h
new file mode 100644
index 0000000..fb36a8f
--- /dev/null
+++ b/proposed-plugin-api/gcc-semiprivate-types.h
@@ -0,0 +1,72 @@
+/*
+ Copyright 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2012 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef INCLUDED__GCC_SEMIPRIVATE_TYPES_H
+#define INCLUDED__GCC_SEMIPRIVATE_TYPES_H
+
+/*
+ These "interface types" should be treated like pointers, only that
+ users are required to collaborate with the garbage-collector.
+
+ The internal details are exposed here so that the debugger is able to
+ identify the real types. Plugin developers should *not* rely on the
+ internal implementation details.
+
+ By being structs, the compiler will be able to complain if plugin code
+ directly pokes at a pointer.
+*/
+
+/* Semiprivate types: control flow graphs */
+struct GccCfgI {
+ struct control_flow_graph *inner;
+};
+
+GCC_PRIVATE_API(struct GccCfgI)
+GccPrivate_make_CfgI(struct control_flow_graph *inner);
+
+
+struct GccCfgBlockI {
+ basic_block inner;
+};
+
+GCC_PRIVATE_API(struct GccCfgBlockI)
+GccPrivate_make_CfgBlockI(basic_block inner);
+
+struct GccCfgEdgeI {
+ edge inner;
+};
+
+GCC_PRIVATE_API(struct GccCfgEdgeI)
+GccPrivate_make_CfgEdgeI(edge inner);
+
+
+#if 0
+/* Semiprivate types: GIMPLE representation */
+struct GccGimplePhiI {
+};
+
+struct GccGimpleI {
+};
+
+/* Semiprivate types: RTL representation */
+struct GccRtlInsnI {
+};
+#endif
+
+#endif /* INCLUDED__GCC_SEMIPRIVATE_TYPES_H */
12 years, 1 month