commit 0f987846ef9e059058673be4a32c5c26ae397e8a Author: David Malcolm dmalcolm@redhat.com Date: Thu Sep 29 15:39:42 2011 -0400
add a gcc.Gimple.walk_tree method
docs/gimple.rst | 16 ++++ gcc-python-closure.c | 24 ++++-- gcc-python-closure.h | 3 +- gcc-python-gimple.c | 78 ++++++++++++++++++++ gcc-python-wrappers.h | 3 + gcc-python.c | 2 +- generate-gimple-c.py | 8 ++ tests/plugin/gimple-walk-tree/dump-all/input.c | 55 ++++++++++++++ tests/plugin/gimple-walk-tree/dump-all/script.py | 36 +++++++++ tests/plugin/gimple-walk-tree/dump-all/stdout.txt | 70 ++++++++++++++++++ tests/plugin/gimple-walk-tree/exceptions/input.c | 55 ++++++++++++++ tests/plugin/gimple-walk-tree/exceptions/script.py | 36 +++++++++ .../plugin/gimple-walk-tree/exceptions/stderr.txt | 16 ++++ .../plugin/gimple-walk-tree/exceptions/stdout.txt | 4 + tests/plugin/gimple-walk-tree/find-one/input.c | 55 ++++++++++++++ tests/plugin/gimple-walk-tree/find-one/script.py | 40 ++++++++++ tests/plugin/gimple-walk-tree/find-one/stdout.txt | 22 ++++++ 17 files changed, 512 insertions(+), 11 deletions(-) --- diff --git a/docs/gimple.rst b/docs/gimple.rst index 31776bd..e0c8ae5 100644 --- a/docs/gimple.rst +++ b/docs/gimple.rst @@ -68,6 +68,22 @@ TODO
which won't arbitrarily change each time.
+ .. py:method:: walk_tree(callback, *args, **kwargs) + + Visit all :py:class:`gcc.Tree` nodes associated with this + statement, potentially more than once each. This will visit both the + left-hand-side and right-hand-side operands of the statement (if any), + and recursively visit any of their child nodes. + + For each node, the callback is invoked, supplying the node, and any + extra positional and keyword arguments passed to `walk_tree`:: + + callback(node, *args, **kwargs) + + If the callback returns a true value, the traversal stops, and that + `gcc.Tree` is the result of the call to `walk_tree`. Otherwise, the + traversal continues, and `walk_tree` eventually returns `None`. + .. py:class:: gcc.GimpleAssign
Subclass of :py:class:`gcc.Gimple`: an assignment of an expression to an l-value diff --git a/gcc-python-closure.c b/gcc-python-closure.c index 0e975a1..c6f83dc 100644 --- a/gcc-python-closure.c +++ b/gcc-python-closure.c @@ -63,7 +63,7 @@ gcc_python_closure_new(PyObject *callback, PyObject *extraargs, PyObject *kwargs }
PyObject * -gcc_python_closure_make_args(struct callback_closure * closure, PyObject *wrapped_gcc_data) +gcc_python_closure_make_args(struct callback_closure * closure, int add_cfun, PyObject *wrapped_gcc_data) { PyObject *args = NULL; PyObject *cfun_obj = NULL; @@ -76,26 +76,32 @@ gcc_python_closure_make_args(struct callback_closure * closure, PyObject *wrappe
if (wrapped_gcc_data) { /* - Equivalent to: + Equivalent to either: args = (gcc_data, cfun, ) + extraargs + or: + args = (gcc_data, ) + extraargs */ - args = PyTuple_New(2 + PyTuple_Size(closure->extraargs)); + args = PyTuple_New((add_cfun ? 2 : 1) + PyTuple_Size(closure->extraargs));
if (!args) { goto error; }
- cfun_obj = gcc_python_make_wrapper_function(cfun); - if (!cfun_obj) { - goto error; - } + if (add_cfun) { + cfun_obj = gcc_python_make_wrapper_function(cfun); + if (!cfun_obj) { + goto error; + } + }
PyTuple_SetItem(args, 0, wrapped_gcc_data); - PyTuple_SetItem(args, 1, cfun_obj); + if (add_cfun) { + PyTuple_SetItem(args, 1, cfun_obj); + } Py_INCREF(wrapped_gcc_data); for (i = 0; i < PyTuple_Size(closure->extraargs); i++) { PyObject *item = PyTuple_GetItem(closure->extraargs, i); - PyTuple_SetItem(args, i + 2, item); + PyTuple_SetItem(args, i + (add_cfun ? 2 : 1), item); Py_INCREF(item); } diff --git a/gcc-python-closure.h b/gcc-python-closure.h index 2297998..99dc170 100644 --- a/gcc-python-closure.h +++ b/gcc-python-closure.h @@ -31,7 +31,8 @@ struct callback_closure * gcc_python_closure_new(PyObject *callback, PyObject *extraargs, PyObject *kwargs);
PyObject * -gcc_python_closure_make_args(struct callback_closure * closure, PyObject *wrapped_gcc_data); +gcc_python_closure_make_args(struct callback_closure * closure, + int add_cfun, PyObject *wrapped_gcc_data);
/* PEP-7 diff --git a/gcc-python-gimple.c b/gcc-python-gimple.c index f5b739f..7baec2b 100644 --- a/gcc-python-gimple.c +++ b/gcc-python-gimple.c @@ -21,6 +21,7 @@ #include "gcc-python.h" #include "gcc-python-wrappers.h" #include "gcc-python-compat.h" +#include "gcc-python-closure.h" #include "gimple.h" #include "tree-flow.h" #include "tree-flow-inline.h" @@ -62,6 +63,83 @@ gcc_Gimple_str(struct PyGccGimple * self) return do_pretty_print(self, 0, 0); }
+static tree +gimple_walk_tree_callback(tree *tree_ptr, int *walk_subtrees, void *data) +{ + struct walk_stmt_info *wi = (struct walk_stmt_info*)data; + struct callback_closure *closure = (struct callback_closure *)wi->info; + PyObject *tree_obj = NULL; + PyObject *args = NULL; + PyObject *result = NULL; + + assert(closure); + assert(*tree_ptr); + tree_obj = gcc_python_make_wrapper_tree(*tree_ptr); + if (!tree_obj) { + goto error; + } + + args = gcc_python_closure_make_args(closure, 0, tree_obj); + if (!args) { + goto error; + } + + /* Invoke the python callback: */ + result = PyObject_Call(closure->callback, args, closure->kwargs); + if (!result) { + goto error; + } + + if (PyObject_IsTrue(result)) { + Py_DECREF(result); + return *tree_ptr; + } else { + Py_DECREF(result); + return NULL; + } + + error: + /* On an exception, terminate the traversal: */ + *walk_subtrees = 0; + Py_XDECREF(tree_obj); + Py_XDECREF(args); + Py_XDECREF(result); + return NULL; +} + +PyObject * +gcc_Gimple_walk_tree(struct PyGccGimple * self, PyObject *args, PyObject *kwargs) +{ + PyObject *callback; + PyObject *extraargs = NULL; + struct callback_closure *closure; + tree result; + struct walk_stmt_info wi; + + callback = PyTuple_GetItem(args, 0); + extraargs = PyTuple_GetSlice(args, 1, PyTuple_Size(args)); + + closure = gcc_python_closure_new(callback, extraargs, kwargs); + if (!closure) { + return NULL; + } + + memset(&wi, 0, sizeof(wi)); + wi.info = closure; + + result = walk_gimple_op (self->stmt, + gimple_walk_tree_callback, + &wi); + Py_DECREF(closure); + + /* Propagate exceptions: */ + if (PyErr_Occurred()) { + return NULL; + } + + return gcc_python_make_wrapper_tree(result); +} + PyObject * gcc_Gimple_get_rhs(struct PyGccGimple *self, void *closure) { diff --git a/gcc-python-wrappers.h b/gcc-python-wrappers.h index a9ca28f..b67320a 100644 --- a/gcc-python-wrappers.h +++ b/gcc-python-wrappers.h @@ -142,6 +142,9 @@ PyObject * gcc_Gimple_str(struct PyGccGimple * self);
PyObject * +gcc_Gimple_walk_tree(struct PyGccGimple * self, PyObject *args, PyObject *kwargs); + +PyObject * gcc_Gimple_get_rhs(struct PyGccGimple *self, void *closure);
PyObject * diff --git a/gcc-python.c b/gcc-python.c index f6c5f5f..69b5b49 100644 --- a/gcc-python.c +++ b/gcc-python.c @@ -172,7 +172,7 @@ gcc_python_finish_invoking_callback(PyGILState_STATE gstate, input_location = cfun->function_start_locus; }
- args = gcc_python_closure_make_args(closure, wrapped_gcc_data); + args = gcc_python_closure_make_args(closure, 1, wrapped_gcc_data); if (!args) { goto cleanup; } diff --git a/generate-gimple-c.py b/generate-gimple-c.py index 8e475ae..960915b 100644 --- a/generate-gimple-c.py +++ b/generate-gimple-c.py @@ -225,6 +225,14 @@ gcc_Gimple_get_block(struct PyGccGimple *self, void *closure) tp_repr = '(reprfunc)gcc_Gimple_repr', tp_str = '(reprfunc)gcc_Gimple_str', ) + methods = PyMethodTable('gcc_Gimple_methods', []) + methods.add_method('walk_tree', + '(PyCFunction)gcc_Gimple_walk_tree', + 'METH_VARARGS | METH_KEYWORDS', + "Visit all gcc.Tree nodes associated with this statement") + cu.add_defn(methods.c_defn()) + pytype.tp_methods = methods.identifier + cu.add_defn(pytype.c_defn()) modinit_preinit += pytype.c_invoke_type_ready() modinit_postinit += pytype.c_invoke_add_to_module() diff --git a/tests/plugin/gimple-walk-tree/dump-all/input.c b/tests/plugin/gimple-walk-tree/dump-all/input.c new file mode 100644 index 0000000..ca4b30f --- /dev/null +++ b/tests/plugin/gimple-walk-tree/dump-all/input.c @@ -0,0 +1,55 @@ +/* + Copyright 2011 David Malcolm dmalcolm@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/. +*/ + +/* + Trivial example code to be compiled, for testing purposes + */ + +#include <stdio.h> + +int +helper_function(void) +{ + printf("I am a helper function\n"); + return 42; +} + +int +main(int argc, char **argv) +{ + int i; + + printf("argc: %i\n", argc); + + for (i = 0; i < argc; i++) { + printf("argv[%i]: %s\n", argv[i]); + } + + helper_function(); + + return 0; +} + +/* + PEP-7 +Local variables: +c-basic-offset: 4 +indent-tabs-mode: nil +End: +*/ diff --git a/tests/plugin/gimple-walk-tree/dump-all/script.py b/tests/plugin/gimple-walk-tree/dump-all/script.py new file mode 100644 index 0000000..ec4fdb9 --- /dev/null +++ b/tests/plugin/gimple-walk-tree/dump-all/script.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2011 David Malcolm dmalcolm@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/. + +# Selftest for gcc.Gimple.walk_tree +import gcc + +class DumpTreeNodesPass(gcc.GimplePass): + def execute(self, fun): + # This is called per-function during compilation: + print('fun: %s' % fun) + for bb in fun.cfg.basic_blocks: + if bb.gimple: + for stmt in bb.gimple: + print(' stmt: %s' % stmt) + stmt.walk_tree(self.dump_node, stmt.loc) + + def dump_node(self, node, loc): + print(' node: %r (%s)' % (node, node)) + +ps = DumpTreeNodesPass(name='dump-tree-nodes') +ps.register_after('cfg') diff --git a/tests/plugin/gimple-walk-tree/dump-all/stdout.txt b/tests/plugin/gimple-walk-tree/dump-all/stdout.txt new file mode 100644 index 0000000..8a474dd --- /dev/null +++ b/tests/plugin/gimple-walk-tree/dump-all/stdout.txt @@ -0,0 +1,70 @@ +fun: gcc.Function('main') + stmt: D.3258 = (const char * restrict) &"argc: %i\n"[0]; + node: <gcc.AddrExpr object at 0xdeadbeef> (&"argc: %i\n"[0]) + node: <gcc.ArrayRef object at 0xdeadbeef> ("argc: %i\n"[0]) + node: gcc.StringCst('argc: %i\n') ("argc: %i\n") + node: gcc.IntegerCst(0) (0) + node: gcc.VarDecl(3258) (gcc.VarDecl(3258)) + stmt: printf (D.3258, argc); + node: <gcc.AddrExpr object at 0xdeadbeef> (printf) + node: gcc.FunctionDecl('printf') (gcc.FunctionDecl('printf')) + node: gcc.VarDecl(3258) (gcc.VarDecl(3258)) + node: gcc.ParmDecl('argc') (gcc.ParmDecl('argc')) + stmt: i = 0; + node: gcc.IntegerCst(0) (0) + node: gcc.VarDecl('i') (gcc.VarDecl('i')) + stmt: D.3259 = (long unsigned int) i; + node: gcc.VarDecl('i') (gcc.VarDecl('i')) + node: gcc.VarDecl(3259) (gcc.VarDecl(3259)) + stmt: D.3260 = D.3259 * 8; + node: gcc.VarDecl(3259) (gcc.VarDecl(3259)) + node: gcc.IntegerCst(8) (8) + node: gcc.VarDecl(3260) (gcc.VarDecl(3260)) + stmt: D.3261 = argv + D.3260; + node: gcc.ParmDecl('argv') (gcc.ParmDecl('argv')) + node: gcc.VarDecl(3260) (gcc.VarDecl(3260)) + node: gcc.VarDecl(3261) (gcc.VarDecl(3261)) + stmt: D.3262 = *D.3261; + node: <gcc.MemRef object at 0xdeadbeef> (*D.3261) + node: gcc.VarDecl(3261) (gcc.VarDecl(3261)) + node: gcc.IntegerCst(0) (0B) + node: gcc.VarDecl(3262) (gcc.VarDecl(3262)) + stmt: D.3263 = (const char * restrict) &"argv[%i]: %s\n"[0]; + node: <gcc.AddrExpr object at 0xdeadbeef> (&"argv[%i]: %s\n"[0]) + node: <gcc.ArrayRef object at 0xdeadbeef> ("argv[%i]: %s\n"[0]) + node: gcc.StringCst('argv[%i]: %s\n') ("argv[%i]: %s\n") + node: gcc.IntegerCst(0) (0) + node: gcc.VarDecl(3263) (gcc.VarDecl(3263)) + stmt: printf (D.3263, D.3262); + node: <gcc.AddrExpr object at 0xdeadbeef> (printf) + node: gcc.FunctionDecl('printf') (gcc.FunctionDecl('printf')) + node: gcc.VarDecl(3263) (gcc.VarDecl(3263)) + node: gcc.VarDecl(3262) (gcc.VarDecl(3262)) + stmt: i = i + 1; + node: gcc.VarDecl('i') (gcc.VarDecl('i')) + node: gcc.IntegerCst(1) (1) + node: gcc.VarDecl('i') (gcc.VarDecl('i')) + stmt: if (i < argc) + node: gcc.VarDecl('i') (gcc.VarDecl('i')) + node: gcc.ParmDecl('argc') (gcc.ParmDecl('argc')) + stmt: helper_function (); + node: <gcc.AddrExpr object at 0xdeadbeef> (helper_function) + node: gcc.FunctionDecl('helper_function') (gcc.FunctionDecl('helper_function')) + stmt: D.3264 = 0; + node: gcc.IntegerCst(0) (0) + node: gcc.VarDecl(3264) (gcc.VarDecl(3264)) + stmt: return D.3264; + node: gcc.VarDecl(3264) (gcc.VarDecl(3264)) +fun: gcc.Function('helper_function') + stmt: __builtin_puts (&"I am a helper function"[0]); + node: <gcc.AddrExpr object at 0xdeadbeef> (__builtin_puts) + node: gcc.FunctionDecl('__builtin_puts') (gcc.FunctionDecl('__builtin_puts')) + node: <gcc.AddrExpr object at 0xdeadbeef> (&"I am a helper function"[0]) + node: <gcc.ArrayRef object at 0xdeadbeef> ("I am a helper function"[0]) + node: gcc.StringCst('I am a helper function') ("I am a helper function") + node: gcc.IntegerCst(0) (0) + stmt: D.3266 = 42; + node: gcc.IntegerCst(42) (42) + node: gcc.VarDecl(3266) (gcc.VarDecl(3266)) + stmt: return D.3266; + node: gcc.VarDecl(3266) (gcc.VarDecl(3266)) diff --git a/tests/plugin/gimple-walk-tree/exceptions/input.c b/tests/plugin/gimple-walk-tree/exceptions/input.c new file mode 100644 index 0000000..ca4b30f --- /dev/null +++ b/tests/plugin/gimple-walk-tree/exceptions/input.c @@ -0,0 +1,55 @@ +/* + Copyright 2011 David Malcolm dmalcolm@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/. +*/ + +/* + Trivial example code to be compiled, for testing purposes + */ + +#include <stdio.h> + +int +helper_function(void) +{ + printf("I am a helper function\n"); + return 42; +} + +int +main(int argc, char **argv) +{ + int i; + + printf("argc: %i\n", argc); + + for (i = 0; i < argc; i++) { + printf("argv[%i]: %s\n", argv[i]); + } + + helper_function(); + + return 0; +} + +/* + PEP-7 +Local variables: +c-basic-offset: 4 +indent-tabs-mode: nil +End: +*/ diff --git a/tests/plugin/gimple-walk-tree/exceptions/script.py b/tests/plugin/gimple-walk-tree/exceptions/script.py new file mode 100644 index 0000000..ea20388 --- /dev/null +++ b/tests/plugin/gimple-walk-tree/exceptions/script.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2011 David Malcolm dmalcolm@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/. + +# Selftest for gcc.Gimple.walk_tree +import gcc + +class WalkTreeNodesPass(gcc.GimplePass): + def execute(self, fun): + # This is called per-function during compilation: + print('fun: %s' % fun) + for bb in fun.cfg.basic_blocks: + if bb.gimple: + for stmt in bb.gimple: + print(' stmt: %s' % stmt) + stmt.walk_tree(self.dump_node, stmt.loc) + + def dump_node(self, node, loc): + raise RuntimeError('this is a test error') + +ps = WalkTreeNodesPass(name='walk-tree-nodes') +ps.register_after('cfg') diff --git a/tests/plugin/gimple-walk-tree/exceptions/stderr.txt b/tests/plugin/gimple-walk-tree/exceptions/stderr.txt new file mode 100644 index 0000000..36c1cd1 --- /dev/null +++ b/tests/plugin/gimple-walk-tree/exceptions/stderr.txt @@ -0,0 +1,16 @@ +tests/plugin/gimple-walk-tree/exceptions/input.c: In function 'main': +tests/plugin/gimple-walk-tree/exceptions/input.c:35:1: error: Unhandled Python exception raised calling 'execute' method +Traceback (most recent call last): + File "tests/plugin/gimple-walk-tree/exceptions/script.py", line 30, in execute + stmt.walk_tree(self.dump_node, stmt.loc) + File "tests/plugin/gimple-walk-tree/exceptions/script.py", line 33, in dump_node + raise RuntimeError('this is a test error') +RuntimeError: this is a test error +tests/plugin/gimple-walk-tree/exceptions/input.c: In function 'helper_function': +tests/plugin/gimple-walk-tree/exceptions/input.c:28:1: error: Unhandled Python exception raised calling 'execute' method +Traceback (most recent call last): + File "tests/plugin/gimple-walk-tree/exceptions/script.py", line 30, in execute + stmt.walk_tree(self.dump_node, stmt.loc) + File "tests/plugin/gimple-walk-tree/exceptions/script.py", line 33, in dump_node + raise RuntimeError('this is a test error') +RuntimeError: this is a test error diff --git a/tests/plugin/gimple-walk-tree/exceptions/stdout.txt b/tests/plugin/gimple-walk-tree/exceptions/stdout.txt new file mode 100644 index 0000000..c4ee227 --- /dev/null +++ b/tests/plugin/gimple-walk-tree/exceptions/stdout.txt @@ -0,0 +1,4 @@ +fun: gcc.Function('main') + stmt: D.3258 = (const char * restrict) &"argc: %i\n"[0]; +fun: gcc.Function('helper_function') + stmt: __builtin_puts (&"I am a helper function"[0]); diff --git a/tests/plugin/gimple-walk-tree/find-one/input.c b/tests/plugin/gimple-walk-tree/find-one/input.c new file mode 100644 index 0000000..ca4b30f --- /dev/null +++ b/tests/plugin/gimple-walk-tree/find-one/input.c @@ -0,0 +1,55 @@ +/* + Copyright 2011 David Malcolm dmalcolm@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/. +*/ + +/* + Trivial example code to be compiled, for testing purposes + */ + +#include <stdio.h> + +int +helper_function(void) +{ + printf("I am a helper function\n"); + return 42; +} + +int +main(int argc, char **argv) +{ + int i; + + printf("argc: %i\n", argc); + + for (i = 0; i < argc; i++) { + printf("argv[%i]: %s\n", argv[i]); + } + + helper_function(); + + return 0; +} + +/* + PEP-7 +Local variables: +c-basic-offset: 4 +indent-tabs-mode: nil +End: +*/ diff --git a/tests/plugin/gimple-walk-tree/find-one/script.py b/tests/plugin/gimple-walk-tree/find-one/script.py new file mode 100644 index 0000000..bf2a0f5 --- /dev/null +++ b/tests/plugin/gimple-walk-tree/find-one/script.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# Copyright 2011 David Malcolm dmalcolm@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/. + +# Selftest for gcc.Gimple.walk_tree +import gcc + +class FindTreeNodesPass(gcc.GimplePass): + def execute(self, fun): + # This is called per-function during compilation: + print('fun: %s' % fun) + for bb in fun.cfg.basic_blocks: + if bb.gimple: + for stmt in bb.gimple: + print(' stmt: %s' % stmt) + node = stmt.walk_tree(self.find_node) + if node: + print(' node: %r (%s)' % (node, node)) + + def find_node(self, node): + # Locate the first string constant in each statement: + if isinstance(node, gcc.StringCst): + return True + +ps = FindTreeNodesPass(name='find-tree-nodes') +ps.register_after('cfg') diff --git a/tests/plugin/gimple-walk-tree/find-one/stdout.txt b/tests/plugin/gimple-walk-tree/find-one/stdout.txt new file mode 100644 index 0000000..5f924e4 --- /dev/null +++ b/tests/plugin/gimple-walk-tree/find-one/stdout.txt @@ -0,0 +1,22 @@ +fun: gcc.Function('main') + stmt: D.3258 = (const char * restrict) &"argc: %i\n"[0]; + node: gcc.StringCst('argc: %i\n') ("argc: %i\n") + stmt: printf (D.3258, argc); + stmt: i = 0; + stmt: D.3259 = (long unsigned int) i; + stmt: D.3260 = D.3259 * 8; + stmt: D.3261 = argv + D.3260; + stmt: D.3262 = *D.3261; + stmt: D.3263 = (const char * restrict) &"argv[%i]: %s\n"[0]; + node: gcc.StringCst('argv[%i]: %s\n') ("argv[%i]: %s\n") + stmt: printf (D.3263, D.3262); + stmt: i = i + 1; + stmt: if (i < argc) + stmt: helper_function (); + stmt: D.3264 = 0; + stmt: return D.3264; +fun: gcc.Function('helper_function') + stmt: __builtin_puts (&"I am a helper function"[0]); + node: gcc.StringCst('I am a helper function') ("I am a helper function") + stmt: D.3266 = 42; + stmt: return D.3266;