commit 36a0d6a45473c39db550915f8419a794f2f5653e Author: David Malcolm dmalcolm@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@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@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@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@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 */
gcc-python-plugin-commits@lists.stg.fedorahosted.org