[gcc-python-plugin] fixlet for cfg_to_dot
by David Hugh Malcolm
commit 26be03f6217f46c916686227831db33109984ad5
Author: Tom Tromey <tromey(a)redhat.com>
Date: Tue Jun 19 10:12:00 2012 -0600
fixlet for cfg_to_dot
cfg_to_dot has its argument names reversed. This doesn't affect
anything, since it also reverses them in the call to CfgPrettyPrinter.
However, it is confusing.
I verified this by looking at all the calls to cfg_to_dot in the tree.
This then showed that there is a one-argument call in
test.py:my_pass_execution_callback:
dot = cfg_to_dot(fun.cfg)
So, I defaulted the 'name' argument to cfg_to_dot.
Tom
>From 123798567dec2478bc18db4d58b713d64873071b Mon Sep 17 00:00:00 2001
From: Tom Tromey <tromey(a)redhat.com>
Date: Tue, 19 Jun 2012 10:07:47 -0600
Subject: [PATCH] two fixes for cfg_to_dot
First, reverse the argument names. This just fixes some confusion.
Second, default the 'name' argument. This fixes a one-argument call
in test.py.
gccutils.py | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
---
diff --git a/gccutils.py b/gccutils.py
index 8e18077..496bfc5 100644
--- a/gccutils.py
+++ b/gccutils.py
@@ -533,8 +533,8 @@ class TreePrettyPrinter(DotPrettyPrinter):
result += '}\n'
return result
-def cfg_to_dot(name, cfg):
- pp = CfgPrettyPrinter(name, cfg)
+def cfg_to_dot(cfg, name = None):
+ pp = CfgPrettyPrinter(cfg, name)
return pp.to_dot()
11 years, 11 months
[gcc-python-plugin] add notes on Gentoo packages
by David Hugh Malcolm
commit 3ea0164101ab4ae18c6e964214d71aeea6bb0fb2
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Wed Jun 6 11:46:11 2012 -0400
add notes on Gentoo packages
docs/basics.rst | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
---
diff --git a/docs/basics.rst b/docs/basics.rst
index 8febbfb..a3787fe 100644
--- a/docs/basics.rst
+++ b/docs/basics.rst
@@ -59,6 +59,11 @@ as root for the Python 2 build of the plugin, or:
for the Python 3 build of the plugin.
+On Gentoo, use `layman` to add the `dMaggot` overlay and `emerge` the
+`gcc-python-plugin` package. This will build the plugin for Python 2 and
+Python 3 should you have both of them installed in your system. A live
+ebuild is also provided to install the plugin from git sources.
+
Building the plugin from source
===============================
11 years, 11 months
[gcc-python-plugin] fix missing Py_INCREF in gcc_NamespaceDecl_unalias
by David Hugh Malcolm
commit c9690c8a05733ed8bdf84a9d18ca5154ed85d18f
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Tue Jun 5 20:03:03 2012 -0400
fix missing Py_INCREF in gcc_NamespaceDecl_unalias
gcc-python-tree.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
---
diff --git a/gcc-python-tree.c b/gcc-python-tree.c
index 179c0b2..8e64216 100644
--- a/gcc-python-tree.c
+++ b/gcc-python-tree.c
@@ -615,6 +615,7 @@ gcc_NamespaceDecl_unalias(struct PyGccTree * self, PyObject *args, PyObject *kwa
tree t = self->t;
if (NULL == DECL_NAMESPACE_ALIAS(t)) {
+ Py_INCREF(self);
return (PyObject *)self;
}
11 years, 11 months
[gcc-python-plugin] add attributes/methods to gcc.NamespaceDecl and is_builtin to gcc.Declaration
by David Hugh Malcolm
commit 6aa5979fe81194a1a962fa6007930cafda268605
Author: matt rice <ratmice(a)gmail.com>
Date: Sun Jun 3 19:57:15 2012 -0700
add attributes/methods to gcc.NamespaceDecl and is_builtin to gcc.Declaration
gcc.NamespaceDecl:
add attributes: alias_of, namespaces, and declarations.
add methods: unalias
gcc.Declaration
add is_builtin attribute.
docs/tree.rst:
fix gcc.NamespaceDecl.lookup which was documented as .locate.
document new attributes/methods
tests/plugin/namespace: New tests.
docs/tree.rst | 32 ++++++++++++++++-
gcc-python-tree.c | 58 ++++++++++++++++++++++++++++++
gcc-python-wrappers.h | 10 +++++
generate-tree-c.py | 18 +++++++++
tests/plugin/namespace/input.cc | 22 +++++++++++
tests/plugin/namespace/script.py | 71 +++++++++++++++++++++++++++++++++++++
tests/plugin/namespace/stdout.txt | 56 +++++++++++++++++++++++++++++
7 files changed, 266 insertions(+), 1 deletions(-)
---
diff --git a/docs/tree.rst b/docs/tree.rst
index 8c2c0a0..100c4ae 100644
--- a/docs/tree.rst
+++ b/docs/tree.rst
@@ -226,6 +226,10 @@ Declarations
arguments of C++ methods: the initial `this` argument is a
compiler-generated :py:class:`gcc.ParmDecl`.
+ .. py:attribute:: is_builtin
+
+ (bool) Is this declaration a compiler-builtin?
+
.. py:class:: gcc.FieldDecl
A subclass of :py:class:`gcc.Declaration` indicating the declaration of a
@@ -332,11 +336,37 @@ Declarations
A subclass of :py:class:`gcc.Declaration` representing a C++ namespace
- .. py:method:: locate(name)
+ .. py:attribute:: alias_of
+
+ The :py:class:`gcc.NamespaceDecl` which this namespace is an alias of
+ or None if this namespace is not an alias.
+
+ .. py:attribute:: declarations
+
+ .. note:: This attribute is only usable with non-alias namespaces.
+ Accessing it on an alias will lead to a RuntimeError exception.
+
+ List of :py:class:`gcc.Declaration` objects in this namespace.
+ This attribute is only valid for non-aliases
+
+ .. py:attribute:: namespaces
+
+ .. note:: This attribute is only usable with non-alias namespaces.
+ Accessing it on an alias will lead to a RuntimeError exception.
+
+ List of :py:class:`gcc.NamespaceDecl` objects nested in this namespace.
+ This attribute is only valid for non-aliases
+
+ .. py:method:: lookup(name)
Locate the given name within the namespace, returning a
:py:class:`gcc.Tree` or `None`
+ .. py:method:: unalias()
+
+ Always returns a :py:class:`gcc.NamespaceDecl` object which is not an alias.
+ Returns self if this namespace is not an alias.
+
.. Declaration
.. ClassMethodDecl
diff --git a/gcc-python-tree.c b/gcc-python-tree.c
index db35be6..179c0b2 100644
--- a/gcc-python-tree.c
+++ b/gcc-python-tree.c
@@ -21,6 +21,7 @@
#include "gcc-python.h"
#include "gcc-python-wrappers.h"
#include "gcc-python-compat.h"
+#include "cp/cp-tree.h"
#include "gimple.h"
#include "cp/cp-tree.h" /* for TFF_* for use by gcc_FunctionDecl_get_fullname */
@@ -43,6 +44,9 @@ __typeof__ (decl_as_string) decl_as_string __attribute__ ((weak));
/* Similar for namespace_binding: */
__typeof__ (namespace_binding) namespace_binding __attribute__ ((weak));
+/* And for cp_namespace_decls: */
+__typeof__ (cp_namespace_decls) cp_namespace_decls __attribute__ ((weak));
+
static PyObject *
raise_cplusplus_only(const char *what)
{
@@ -605,6 +609,60 @@ gcc_NamespaceDecl_lookup(struct PyGccTree * self, PyObject *args, PyObject *kwar
return gcc_python_make_wrapper_tree(t_result);
}
+PyObject *
+gcc_NamespaceDecl_unalias(struct PyGccTree * self, PyObject *args, PyObject *kwargs)
+{
+ tree t = self->t;
+
+ if (NULL == DECL_NAMESPACE_ALIAS(t)) {
+ return (PyObject *)self;
+ }
+
+ while (DECL_NAMESPACE_ALIAS(t)) {
+ t = DECL_NAMESPACE_ALIAS(t);
+ }
+
+ return gcc_python_make_wrapper_tree(t);
+}
+
+static PyObject *
+raise_namespace_alias(const char *what)
+{
+ return PyErr_Format(PyExc_RuntimeError,
+ "%s is not valid for an alias",
+ what);
+}
+
+PyObject *
+gcc_python_namespace_decl_declarations(tree t)
+{
+ if (NULL == cp_namespace_decls)
+ return raise_cplusplus_only("gcc.NamespaceDecl.declarations");
+
+ /* throw if we are an alias,
+ if we unalias it, it may return a list containing itself. */
+ if (DECL_NAMESPACE_ALIAS(t))
+ return raise_namespace_alias("gcc.NamespaceDecl.declarations");
+
+ return gcc_tree_list_from_chain(cp_namespace_decls(t));
+}
+
+PyObject *
+gcc_python_namespace_decl_namespaces(tree t)
+{
+ /* We don't actually call cp_namespace_decls, but we only actually call
+ c++ specific macros, not sure what happens. */
+ if (NULL == cp_namespace_decls)
+ return raise_cplusplus_only("gcc.NamespaceDecl.namespaces");
+
+ /* throw if we are an alias,
+ if we unalias it, it may return a list containing itself. */
+ if (DECL_NAMESPACE_ALIAS(t))
+ return raise_namespace_alias("gcc.NamespaceDecl.namespaces");
+
+ return gcc_tree_list_from_chain(NAMESPACE_LEVEL(t)->namespaces);
+}
+
/*
GCC's debug_tree is implemented in:
gcc/print-tree.c
diff --git a/gcc-python-wrappers.h b/gcc-python-wrappers.h
index fb70fb4..f79a74b 100644
--- a/gcc-python-wrappers.h
+++ b/gcc-python-wrappers.h
@@ -185,6 +185,16 @@ gcc_TreeList_repr(struct PyGccTree * self);
PyObject *
gcc_NamespaceDecl_lookup(struct PyGccTree * self, PyObject *args, PyObject *kwargs);
+PyObject *
+gcc_NamespaceDecl_unalias(struct PyGccTree * self, PyObject *args, PyObject *kwargs);
+
+PyObject *
+gcc_python_namespace_decl_declarations(tree t);
+
+PyObject *
+gcc_python_namespace_decl_namespaces(tree t);
+
+
/* gcc-python-gimple.c: */
PyObject *
gcc_Gimple_repr(struct PyGccGimple * self);
diff --git a/generate-tree-c.py b/generate-tree-c.py
index 457b2de..2c07c71 100644
--- a/generate-tree-c.py
+++ b/generate-tree-c.py
@@ -31,7 +31,9 @@ cu.add_include('gcc-plugin.h')
cu.add_include("tree.h")
cu.add_include("function.h")
cu.add_include("basic-block.h")
+cu.add_include("cp/cp-tree.h")
cu.add_include("c-family/c-common.h")
+cu.add_include("cp/name-lookup.h")
modinit_preinit = ''
modinit_postinit = ''
@@ -186,6 +188,9 @@ gcc_Declaration_get_location(struct PyGccTree *self, void *closure)
add_simple_getter('is_artificial',
'PyBool_FromLong(DECL_ARTIFICIAL(self->t))',
"Is this a compiler-generated entity?")
+ add_simple_getter('is_builtin',
+ 'PyBool_FromLong(DECL_IS_BUILTIN(self->t))',
+ "Is this declaration built in by the compiler?")
pytype.tp_repr = '(reprfunc)gcc_Declaration_repr'
if localname == 'Type':
@@ -478,10 +483,23 @@ def generate_tree_code_classes():
"The list of gcc.Tree for the declarations and labels in this block")
if tree_type.SYM == 'NAMESPACE_DECL':
+ add_simple_getter('alias_of',
+ 'gcc_python_make_wrapper_tree(DECL_NAMESPACE_ALIAS(self->t))',
+ "None if not an alias, otherwise the gcc.NamespaceDecl we alias")
+ add_simple_getter('declarations',
+ 'gcc_python_namespace_decl_declarations(self->t)',
+ 'The list of gcc.Declarations within this namespace')
+ add_simple_getter('namespaces',
+ 'gcc_python_namespace_decl_namespaces(self->t)',
+ 'The list of gcc.NamespaceDecl objects and gcc.TypeDecl of Unions nested in this namespace')
methods.add_method('lookup',
'(PyCFunction)gcc_NamespaceDecl_lookup',
'METH_VARARGS|METH_KEYWORDS',
"Look up the given string within this namespace")
+ methods.add_method('unalias',
+ '(PyCFunction)gcc_NamespaceDecl_unalias',
+ 'METH_VARARGS|METH_KEYWORDS',
+ "A gcc.NamespaceDecl of this namespace that is not an alias")
if tree_type.SYM == 'TYPE_DECL':
getsettable.add_gsdef('pointer',
diff --git a/tests/plugin/namespace/input.cc b/tests/plugin/namespace/input.cc
new file mode 100644
index 0000000..16cf4ea
--- /dev/null
+++ b/tests/plugin/namespace/input.cc
@@ -0,0 +1,22 @@
+namespace top {
+ union top_union{
+ int i;
+ char c;
+ float f;
+ };
+ namespace sub {
+ int subs_int;
+ void subs_function(void);
+ void *foo;
+ namespace sub_sub {
+ void foo();
+ }
+ }
+ namespace sub_alias = sub;
+ namespace sub_alias_alias = sub_alias;
+ namespace foo {
+ namespace bar {
+ }
+ }
+};
+namespace top_alias_of_alias = top::sub;
diff --git a/tests/plugin/namespace/script.py b/tests/plugin/namespace/script.py
new file mode 100644
index 0000000..9080790
--- /dev/null
+++ b/tests/plugin/namespace/script.py
@@ -0,0 +1,71 @@
+# Copyright 2012 Matt Rice <ratmice(a)gmail.com>
+#
+# 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/>.
+
+# Test case for gcc.NamespaceDecl
+
+import gcc
+
+def indent_print(depth, thing):
+ for i in range(depth):
+ print " ",
+ print thing
+
+def print_namespace(ns, depth):
+ attributes = ("name", "alias_of", "declarations", "namespaces")
+ # [(method, arg),...]
+ methods = [(gcc.NamespaceDecl.unalias, None),
+ (gcc.NamespaceDecl.lookup, "foo")]
+
+ for attr in attributes:
+ try:
+ indent_print(depth, (attr, ns.__getattribute__(attr)))
+ except Exception as e:
+ indent_print(depth, (attr, e))
+
+ for t in methods:
+ method_name = t[0].__name__
+ method = t[0]
+ try:
+ indent_print(depth, (method_name, method(ns, t[1])))
+ except Exception as e:
+ indent_print(depth, (method_name, e))
+
+ print "\n",
+
+def dump_namespaces(ns, depth):
+
+ # ignore builtin's they would just make stdout.txt painful.
+ if ns.is_builtin == False:
+ print_namespace(ns, depth)
+
+ # aliases of namespaces in particular will occur
+ # within declarations, but we don't want to call
+ # declarations on them (here).
+ if ns.alias_of == None:
+ for decl in ns.declarations:
+ if type(decl) == gcc.NamespaceDecl:
+ dump_namespaces(decl, depth + 1)
+
+ # nested namespaces..
+ for namespace in ns.namespaces:
+ dump_namespaces(namespace, depth + 1)
+
+def finish_unit_cb(*args, **kwargs):
+ # depth of -1 to ignore the global namespace itself (because its a builtin).
+ dump_namespaces(gcc.get_global_namespace(), -1)
+
+
+gcc.register_callback(gcc.PLUGIN_FINISH_UNIT, finish_unit_cb)
diff --git a/tests/plugin/namespace/stdout.txt b/tests/plugin/namespace/stdout.txt
new file mode 100644
index 0000000..c31e942
--- /dev/null
+++ b/tests/plugin/namespace/stdout.txt
@@ -0,0 +1,56 @@
+('name', 'top_alias_of_alias')
+('alias_of', gcc.NamespaceDecl('sub'))
+('declarations', RuntimeError('gcc.NamespaceDecl.declarations is not valid for an alias',))
+('namespaces', RuntimeError('gcc.NamespaceDecl.namespaces is not valid for an alias',))
+('unalias', gcc.NamespaceDecl('sub'))
+('lookup', gcc.VarDecl('foo'))
+
+('name', 'top')
+('alias_of', None)
+('declarations', [gcc.NamespaceDecl('sub_alias_alias'), gcc.NamespaceDecl('sub_alias'), gcc.TypeDecl('top_union')])
+('namespaces', [gcc.NamespaceDecl('foo'), gcc.NamespaceDecl('sub')])
+('unalias', gcc.NamespaceDecl('top'))
+('lookup', gcc.NamespaceDecl('foo'))
+
+ ('name', 'sub_alias_alias')
+ ('alias_of', gcc.NamespaceDecl('sub'))
+ ('declarations', RuntimeError('gcc.NamespaceDecl.declarations is not valid for an alias',))
+ ('namespaces', RuntimeError('gcc.NamespaceDecl.namespaces is not valid for an alias',))
+ ('unalias', gcc.NamespaceDecl('sub'))
+ ('lookup', gcc.VarDecl('foo'))
+
+ ('name', 'sub_alias')
+ ('alias_of', gcc.NamespaceDecl('sub'))
+ ('declarations', RuntimeError('gcc.NamespaceDecl.declarations is not valid for an alias',))
+ ('namespaces', RuntimeError('gcc.NamespaceDecl.namespaces is not valid for an alias',))
+ ('unalias', gcc.NamespaceDecl('sub'))
+ ('lookup', gcc.VarDecl('foo'))
+
+ ('name', 'foo')
+ ('alias_of', None)
+ ('declarations', [])
+ ('namespaces', [gcc.NamespaceDecl('bar')])
+ ('unalias', gcc.NamespaceDecl('foo'))
+ ('lookup', None)
+
+ ('name', 'bar')
+ ('alias_of', None)
+ ('declarations', [])
+ ('namespaces', [])
+ ('unalias', gcc.NamespaceDecl('bar'))
+ ('lookup', None)
+
+ ('name', 'sub')
+ ('alias_of', None)
+ ('declarations', [gcc.VarDecl('foo'), gcc.FunctionDecl('subs_function'), gcc.VarDecl('subs_int')])
+ ('namespaces', [gcc.NamespaceDecl('sub_sub')])
+ ('unalias', gcc.NamespaceDecl('sub'))
+ ('lookup', gcc.VarDecl('foo'))
+
+ ('name', 'sub_sub')
+ ('alias_of', None)
+ ('declarations', [gcc.FunctionDecl('foo')])
+ ('namespaces', [])
+ ('unalias', gcc.NamespaceDecl('sub_sub'))
+ ('lookup', gcc.FunctionDecl('foo'))
+
11 years, 11 months
[gcc-python-plugin] use six to make generate-tables-of-passes-rst.py work with both Python 2 and 3
by David Hugh Malcolm
commit aa25da8d3ce0123f50f1b7b52e1e78a8df78caae
Author: David Narvaez <david.narvaez(a)computer.org>
Date: Tue Jun 5 17:29:02 2012 -0400
use six to make generate-tables-of-passes-rst.py work with both Python 2 and 3
generate-tables-of-passes-rst.py | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
---
diff --git a/generate-tables-of-passes-rst.py b/generate-tables-of-passes-rst.py
index 154276e..8bbf926 100644
--- a/generate-tables-of-passes-rst.py
+++ b/generate-tables-of-passes-rst.py
@@ -18,6 +18,7 @@
# We use this script to regenerate docs/tables-of-passes.rst
import gcc
import sys
+import six
from gccutils import Table
@@ -36,7 +37,7 @@ p_to_s = pass_properties_to_str
def foo(t, ps, indent):
name = ps.name.replace('*', '\\*')
- t.add_row(('%s%s' % (u'> ' * indent, name),
+ t.add_row(('%s%s' % (six.u('> ') * indent, name),
p_to_s(ps.properties_required),
p_to_s(ps.properties_provided),
p_to_s(ps.properties_destroyed)))
@@ -89,8 +90,7 @@ for rootname, reflabel, ps in zip(('The lowering passes',
t = Table(['Pass Name', 'Required properties', 'Provided properties', 'Destroyed properties'],
sepchar='=')
foo(t, ps, 0)
- from StringIO import StringIO
- s = StringIO()
+ s = six.StringIO()
t.write(s)
for line in s.getvalue().splitlines():
print(' ' + line.rstrip())
11 years, 11 months
[gcc-python-plugin] add a "man" target to the top-level Makefile
by David Hugh Malcolm
commit 9b03a75eb098f3339b7695aed21c4b873f428cf5
Author: David Narvaez <david.narvaez(a)computer.org>
Date: Tue Jun 5 17:18:25 2012 -0400
add a "man" target to the top-level Makefile
Makefile | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
---
diff --git a/Makefile b/Makefile
index 7468de3..05c147b 100644
--- a/Makefile
+++ b/Makefile
@@ -184,6 +184,9 @@ show-ssa: plugin
html: docs/tables-of-passes.rst docs/passes.svg
cd docs && $(MAKE) html
+man: plugin
+ cd docs && $(MAKE) man
+
# We commit this generated file to SCM to allow the docs to be built without
# needing to build the plugin:
docs/tables-of-passes.rst: plugin generate-tables-of-passes-rst.py
11 years, 11 months