From 587fafb31a22d65199773abe25eeae8aba963b95 Mon Sep 17 00:00:00 2001 From: Shanpei Chen Date: Fri, 26 Nov 2021 14:51:01 +0800 Subject: [PATCH] First release to anolis Developed based on David Malcolm's latest commit 4deefc8. The new build contains serveral new features and bugfixes. Signed-off-by: Yihao Wu Signed-off-by: Shanpei Chen --- 0001-Fix-typo-in-release-notes.patch | 25 ++ 0002-Fix-typo-in-basics.rst.patch | 25 ++ ...ty-printer-fix-GCC-8.3-compatibility.patch | 27 ++ ...-get-the-result-of-DECL_ORIGINAL_TYP.patch | 67 +++++ ...-exercise-gcc.TypeDecl.original_type.patch | 79 ++++++ 0006-.travis.yml-add-gcc-9.patch | 33 +++ 0007-Build-on-Python-3.8.patch | 29 +++ ...ude-params.h-if-building-with-GCC-10.patch | 245 ++++++++++++++++++ ...-gcc-python-wrapper.c-for-Python-3.8.patch | 39 +++ 0010-Link-with-libpython3.8.so.patch | 34 +++ ...PLUGIN_FINISH_PARSE_FUNCTION-support.patch | 33 +++ 0012-Add-get_location.patch | 44 ++++ 0013-Add-main_input_filename.patch | 42 +++ 0014-Add-stub-for-types.patch | 69 +++++ 0015-Add-current_function_decl.patch | 51 ++++ 0016-Add-context.patch | 39 +++ 0017-Add-main_variant-for-types.patch | 71 +++++ ...ation-support-besides-dump_generic_n.patch | 94 +++++++ 0019-Make-static-attribute-writtable.patch | 48 ++++ 0020-Make-initial-attribute-writeable.patch | 50 ++++ 0021-Make-public-attribute-writable.patch | 38 +++ 0022-Add-external-attribute.patch | 36 +++ 0023-Make-location-hasher-robust.patch | 64 +++++ 0024-Add-PLUGIN_INCLUDE_FILE-callback.patch | 51 ++++ 0025-Add-decl.attributes.patch | 108 ++++++++ ...d-referring-and-referer-to-variables.patch | 102 ++++++++ ...VarDecl.node-points-to-varpool-nodes.patch | 30 +++ 0028-Add-general-purpose-walk_tree.patch | 145 +++++++++++ 0029-Add-inline-attr-to-function-decl.patch | 31 +++ LICENSE | 30 +++ gcc-python-plugin.spec | 167 ++++++++++++ 31 files changed, 1946 insertions(+) create mode 100644 0001-Fix-typo-in-release-notes.patch create mode 100644 0002-Fix-typo-in-basics.rst.patch create mode 100644 0003-gcc-python-pretty-printer-fix-GCC-8.3-compatibility.patch create mode 100644 0004-Added-ability-to-get-the-result-of-DECL_ORIGINAL_TYP.patch create mode 100644 0005-tests-exercise-gcc.TypeDecl.original_type.patch create mode 100644 0006-.travis.yml-add-gcc-9.patch create mode 100644 0007-Build-on-Python-3.8.patch create mode 100644 0008-Don-t-include-params.h-if-building-with-GCC-10.patch create mode 100644 0009-Update-gcc-python-wrapper.c-for-Python-3.8.patch create mode 100644 0010-Link-with-libpython3.8.so.patch create mode 100644 0011-Add-PLUGIN_FINISH_PARSE_FUNCTION-support.patch create mode 100644 0012-Add-get_location.patch create mode 100644 0013-Add-main_input_filename.patch create mode 100644 0014-Add-stub-for-types.patch create mode 100644 0015-Add-current_function_decl.patch create mode 100644 0016-Add-context.patch create mode 100644 0017-Add-main_variant-for-types.patch create mode 100644 0018-Add-print_declaration-support-besides-dump_generic_n.patch create mode 100644 0019-Make-static-attribute-writtable.patch create mode 100644 0020-Make-initial-attribute-writeable.patch create mode 100644 0021-Make-public-attribute-writable.patch create mode 100644 0022-Add-external-attribute.patch create mode 100644 0023-Make-location-hasher-robust.patch create mode 100644 0024-Add-PLUGIN_INCLUDE_FILE-callback.patch create mode 100644 0025-Add-decl.attributes.patch create mode 100644 0026-Add-referring-and-referer-to-variables.patch create mode 100644 0027-Add-VarDecl.node-points-to-varpool-nodes.patch create mode 100644 0028-Add-general-purpose-walk_tree.patch create mode 100644 0029-Add-inline-attr-to-function-decl.patch create mode 100644 LICENSE create mode 100644 gcc-python-plugin.spec diff --git a/0001-Fix-typo-in-release-notes.patch b/0001-Fix-typo-in-release-notes.patch new file mode 100644 index 0000000..6817d01 --- /dev/null +++ b/0001-Fix-typo-in-release-notes.patch @@ -0,0 +1,25 @@ +From c0db47453efdd274835a3ab5a6dc9c0e95e83ce0 Mon Sep 17 00:00:00 2001 +From: David Malcolm +Date: Wed, 23 Jan 2019 16:41:19 -0500 +Subject: [PATCH 01/28] Fix typo in release notes + +--- + docs/0.17.rst | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/docs/0.17.rst b/docs/0.17.rst +index 83d4792..16fa158 100644 +--- a/docs/0.17.rst ++++ b/docs/0.17.rst +@@ -18,7 +18,7 @@ + 0.17 + ~~~~ + +-This releases adds support for gcc 9 (along with continued support for ++This release adds support for gcc 9 (along with continued support for + gcc 4.6, 4.7, 4.8, 4.9, 5, 6, 7, and 8). + + Unfortunately, the reference-count checker no longer works for gcc 7 +-- +2.9.5 + diff --git a/0002-Fix-typo-in-basics.rst.patch b/0002-Fix-typo-in-basics.rst.patch new file mode 100644 index 0000000..7a09b73 --- /dev/null +++ b/0002-Fix-typo-in-basics.rst.patch @@ -0,0 +1,25 @@ +From 8fcf07626a1924c987b78e3df494117bc3d093cd Mon Sep 17 00:00:00 2001 +From: Jonathan Wakely +Date: Thu, 13 Jun 2019 13:19:56 +0100 +Subject: [PATCH 02/28] Fix typo in basics.rst + +--- + docs/basics.rst | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/docs/basics.rst b/docs/basics.rst +index 42229fc..c91c86d 100644 +--- a/docs/basics.rst ++++ b/docs/basics.rst +@@ -297,7 +297,7 @@ Accessing parameters + Adding new passes to the compiler + --------------------------------- + You can create new compiler passes by subclassing the appropriate +-:py:class:`gcc.Pass` subclasss. For example, here's how to wire up a new pass ++:py:class:`gcc.Pass` subclass. For example, here's how to wire up a new pass + that displays the control flow graph of each function: + + .. literalinclude:: ../examples/show-gimple.py +-- +2.9.5 + diff --git a/0003-gcc-python-pretty-printer-fix-GCC-8.3-compatibility.patch b/0003-gcc-python-pretty-printer-fix-GCC-8.3-compatibility.patch new file mode 100644 index 0000000..f59c184 --- /dev/null +++ b/0003-gcc-python-pretty-printer-fix-GCC-8.3-compatibility.patch @@ -0,0 +1,27 @@ +From b56342b0925b7685e4edc0fde12143548d215f76 Mon Sep 17 00:00:00 2001 +From: Jack Rosenthal +Date: Tue, 28 May 2019 19:30:42 -0600 +Subject: [PATCH 03/28] gcc-python-pretty-printer: fix GCC 8.3 compatibility + +GCC 8.3 eliminated the prefix parameter as well as GCC 9. This patch +is based on the diff posted by @doko42 in davidmalcom#173. +--- + gcc-python-pretty-printer.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/gcc-python-pretty-printer.c b/gcc-python-pretty-printer.c +index be56854..73f8f41 100644 +--- a/gcc-python-pretty-printer.c ++++ b/gcc-python-pretty-printer.c +@@ -46,7 +46,7 @@ PyGccPrettyPrinter_New(void) + Use placement new to run it on obj->pp. */ + new ((void*)&obj->pp) + pretty_printer( +-# if (GCC_VERSION < 9000) ++# if (GCC_VERSION < 8003) + /* GCC 9 eliminated the "prefix" param. */ + NULL, + # endif +-- +2.9.5 + diff --git a/0004-Added-ability-to-get-the-result-of-DECL_ORIGINAL_TYP.patch b/0004-Added-ability-to-get-the-result-of-DECL_ORIGINAL_TYP.patch new file mode 100644 index 0000000..fd0722d --- /dev/null +++ b/0004-Added-ability-to-get-the-result-of-DECL_ORIGINAL_TYP.patch @@ -0,0 +1,67 @@ +From 8d7b2108af19ed59120506b011331c93420e77b6 Mon Sep 17 00:00:00 2001 +From: bloff +Date: Sat, 18 Oct 2014 19:55:30 +0100 +Subject: [PATCH 04/28] Added ability to get the result of DECL_ORIGINAL_TYPE + +TypeDecl now has a "original_type" attribute which evaluates to the +outcome of DECL_ORIGINAL_TYPE(TYPE_NAME(t)). +--- + gcc-python-tree.c | 11 +++++++++++ + gcc-python-wrappers.h | 3 +++ + generate-tree-c.py | 4 ++++ + 3 files changed, 18 insertions(+) + +diff --git a/gcc-python-tree.c b/gcc-python-tree.c +index 369420a..e5f8101 100644 +--- a/gcc-python-tree.c ++++ b/gcc-python-tree.c +@@ -831,6 +831,17 @@ PyGccTypeDecl_get_pointer(struct PyGccTree *self, void *closure) + } + + PyObject * ++PyGccTypeDecl_get_original_type(struct PyGccTree *self, void *closure) ++{ ++ tree decl_type = TREE_TYPE(self->t.inner); ++ if (!decl_type) { ++ PyErr_SetString(PyExc_ValueError, "gcc.TypeDecl has no associated type"); ++ return NULL; ++ } ++ return PyGccTree_New(gcc_private_make_tree(DECL_ORIGINAL_TYPE(TYPE_NAME(decl_type)))); ++} ++ ++PyObject * + PyGccSsaName_repr(struct PyGccTree * self) + { + int version; +diff --git a/gcc-python-wrappers.h b/gcc-python-wrappers.h +index 2173ffb..1816b19 100644 +--- a/gcc-python-wrappers.h ++++ b/gcc-python-wrappers.h +@@ -326,6 +326,9 @@ PyObject * + PyGccTypeDecl_get_pointer(struct PyGccTree *self, void *closure); + + PyObject * ++PyGccTypeDecl_get_original_type(struct PyGccTree *self, void *closure); ++ ++PyObject * + PyGccSsaName_repr(struct PyGccTree * self); + + PyObject * +diff --git a/generate-tree-c.py b/generate-tree-c.py +index 7a0a92b..faf3faf 100644 +--- a/generate-tree-c.py ++++ b/generate-tree-c.py +@@ -545,6 +545,10 @@ def generate_tree_code_classes(): + 'PyGccTypeDecl_get_pointer', + None, + "The gcc.PointerType representing '(this_type *)'") ++ getsettable.add_gsdef('original_type', ++ 'PyGccTypeDecl_get_original_type', ++ None, ++ "The gcc.Type from which this type was typedef'd from.'") + + if tree_type.SYM == 'FUNCTION_TYPE': + getsettable.add_gsdef('argument_types', +-- +2.9.5 + diff --git a/0005-tests-exercise-gcc.TypeDecl.original_type.patch b/0005-tests-exercise-gcc.TypeDecl.original_type.patch new file mode 100644 index 0000000..7b5628f --- /dev/null +++ b/0005-tests-exercise-gcc.TypeDecl.original_type.patch @@ -0,0 +1,79 @@ +From a4f579c18046dc4f01e8e9d9554e05d1e74a76a3 Mon Sep 17 00:00:00 2001 +From: David Lamparter +Date: Sun, 12 May 2019 19:47:05 +0200 +Subject: [PATCH 05/28] tests: exercise gcc.TypeDecl.original_type + +--- + tests/plugin/types/input.c | 2 ++ + tests/plugin/types/script.py | 13 +++++++++++++ + tests/plugin/types/stdout.txt | 24 ++++++++++++++++++++++++ + 3 files changed, 39 insertions(+) + +diff --git a/tests/plugin/types/input.c b/tests/plugin/types/input.c +index 11e2e1d..330f4b3 100644 +--- a/tests/plugin/types/input.c ++++ b/tests/plugin/types/input.c +@@ -17,3 +17,5 @@ + . + */ + ++typedef int mytype; ++typedef mytype nestedtype; +diff --git a/tests/plugin/types/script.py b/tests/plugin/types/script.py +index 8026d04..bddf6b2 100644 +--- a/tests/plugin/types/script.py ++++ b/tests/plugin/types/script.py +@@ -55,5 +55,18 @@ def on_finish_unit(): + dump_real_type(gcc.Type.float()) + dump_real_type(gcc.Type.double()) + ++ def dump_typedef(td): ++ t = td.type ++ print('gcc.TypeDecl: %r' % str(td)) ++ print(' td.original_type: %r' % td.original_type) ++ print(' td.original_type is gcc.Type.int(): %r' % (td.original_type is gcc.Type.int())) ++ mytype = gccutils.get_global_typedef('mytype') ++ print(' td.original_type.name: %r' % td.original_type.name) ++ print(' td.original_type.name is mytype: %r' % (td.original_type.name is mytype)) ++ dump_integer_type(t) ++ ++ dump_typedef(gccutils.get_global_typedef('mytype')) ++ dump_typedef(gccutils.get_global_typedef('nestedtype')) ++ + gcc.register_callback(gcc.PLUGIN_FINISH_UNIT, + on_finish_unit) +diff --git a/tests/plugin/types/stdout.txt b/tests/plugin/types/stdout.txt +index 918279c..4e3888e 100644 +--- a/tests/plugin/types/stdout.txt ++++ b/tests/plugin/types/stdout.txt +@@ -25,3 +25,27 @@ gcc.Type: 'double' + t.const: False + t.precision: 64 + t.sizeof: 8 ++gcc.TypeDecl: 'mytype' ++ td.original_type: gcc.IntegerType(name=gcc.TypeDecl('int')) ++ td.original_type is gcc.Type.int(): True ++ td.original_type.name: gcc.TypeDecl('int') ++ td.original_type.name is mytype: False ++gcc.Type: 'mytype' ++ t.const: False ++ t.unsigned: False ++ t.precision: 32 ++ t.min_value.constant: -2147483648 ++ t.max_value.constant: 2147483647 ++ t.sizeof: 4 ++gcc.TypeDecl: 'nestedtype' ++ td.original_type: gcc.IntegerType(name=gcc.TypeDecl('mytype')) ++ td.original_type is gcc.Type.int(): False ++ td.original_type.name: gcc.TypeDecl('mytype') ++ td.original_type.name is mytype: True ++gcc.Type: 'nestedtype' ++ t.const: False ++ t.unsigned: False ++ t.precision: 32 ++ t.min_value.constant: -2147483648 ++ t.max_value.constant: 2147483647 ++ t.sizeof: 4 +-- +2.9.5 + diff --git a/0006-.travis.yml-add-gcc-9.patch b/0006-.travis.yml-add-gcc-9.patch new file mode 100644 index 0000000..c76a5e7 --- /dev/null +++ b/0006-.travis.yml-add-gcc-9.patch @@ -0,0 +1,33 @@ +From 8276f912b8123a99918baf5f5ff4933ccdb6c1a5 Mon Sep 17 00:00:00 2001 +From: David Malcolm +Date: Wed, 23 Jan 2019 14:10:16 -0500 +Subject: [PATCH 06/28] .travis.yml: add gcc-9 + +--- + .travis.yml | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/.travis.yml b/.travis.yml +index d36484f..b6b5acd 100644 +--- a/.travis.yml ++++ b/.travis.yml +@@ -64,6 +64,16 @@ matrix: + env: + - MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" + ++ - os: linux ++ addons: ++ apt: ++ sources: ++ - ubuntu-toolchain-r-test ++ packages: ++ - g++-9 gcc-9-plugin-dev ++ env: ++ - MATRIX_EVAL="CC=gcc-9 && CXX=g++-9" ++ + language: c + compiler: + - gcc +-- +2.9.5 + diff --git a/0007-Build-on-Python-3.8.patch b/0007-Build-on-Python-3.8.patch new file mode 100644 index 0000000..23813ff --- /dev/null +++ b/0007-Build-on-Python-3.8.patch @@ -0,0 +1,29 @@ +From 3a4b484eaeda215a086cca967421ca249f7d7b48 Mon Sep 17 00:00:00 2001 +From: Stefano Rivera +Date: Thu, 20 Feb 2020 16:37:40 -0800 +Subject: [PATCH 07/28] Build on Python 3.8 + +PEP-590 replaced tp_print with tp_vectorcall_offset +--- + cpybuilder.py | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/cpybuilder.py b/cpybuilder.py +index 8d8cab7..6740507 100644 +--- a/cpybuilder.py ++++ b/cpybuilder.py +@@ -254,7 +254,11 @@ class PyTypeObject(NamedEntity): + result += ' sizeof(%(struct_name)s), /*tp_basicsize*/\n' % self.__dict__ + result += ' 0, /*tp_itemsize*/\n' + result += self.c_ptr_field('tp_dealloc') ++ result += '#if PY_VERSION_HEX >= 0x03080000\n' ++ result += ' 0, /*tp_vectorcall_offset*/\n' ++ result += '#else\n' + result += self.c_ptr_field('tp_print') ++ result += '#endif\n' + result += self.c_ptr_field('tp_getattr') + result += self.c_ptr_field('tp_setattr') + result += '#if PY_MAJOR_VERSION < 3\n' % self.__dict__ +-- +2.9.5 + diff --git a/0008-Don-t-include-params.h-if-building-with-GCC-10.patch b/0008-Don-t-include-params.h-if-building-with-GCC-10.patch new file mode 100644 index 0000000..096c845 --- /dev/null +++ b/0008-Don-t-include-params.h-if-building-with-GCC-10.patch @@ -0,0 +1,245 @@ +From b6cb6bbf181ba91960208f7a7e911315c8d9ba97 Mon Sep 17 00:00:00 2001 +From: Frederik Harwath +Date: Fri, 3 Apr 2020 16:45:20 +0200 +Subject: [PATCH 08/28] Don't include "params.h" if building with GCC 10 + +The params.h header has been removed from GCC 10. +To allow building the plugin for GCC 10, the header +should be included conditionally for older GCC +versions only. +--- + gcc-c-api/gcc-cfg.c | 4 ++++ + gcc-c-api/gcc-function.c | 5 +++++ + gcc-c-api/gcc-gimple.c | 5 +++++ + gcc-python-option.c | 7 +++++++ + gcc-python-parameter.c | 7 +++++++ + gcc-python.c | 10 ++++++++++ + gcc-python.h | 11 +++++++++++ + generate-parameter-c.py | 11 +++++++++++ + 8 files changed, 60 insertions(+) + mode change 100644 => 100755 generate-parameter-c.py + +diff --git a/gcc-c-api/gcc-cfg.c b/gcc-c-api/gcc-cfg.c +index 8dc6be4..97fa16c 100644 +--- a/gcc-c-api/gcc-cfg.c ++++ b/gcc-c-api/gcc-cfg.c +@@ -37,7 +37,11 @@ + #include "gimple-iterator.h" + #endif + ++/* gcc 10 removed this header */ ++#if (GCC_VERSION < 10000) + #include "params.h" ++#endif ++ + #include "tree.h" + #include "diagnostic.h" + #include "cgraph.h" +diff --git a/gcc-c-api/gcc-function.c b/gcc-c-api/gcc-function.c +index 61a1565..ec9ed8b 100644 +--- a/gcc-c-api/gcc-function.c ++++ b/gcc-c-api/gcc-function.c +@@ -22,7 +22,12 @@ + + /* TODO: rationalize these headers */ + #include "tree.h" ++ ++/* gcc 10 removed this header */ ++#if (GCC_VERSION < 10000) + #include "params.h" ++#endif ++ + #include "tree.h" + #include "function.h" + #include "diagnostic.h" +diff --git a/gcc-c-api/gcc-gimple.c b/gcc-c-api/gcc-gimple.c +index 8ec55bd..72a6ae8 100644 +--- a/gcc-c-api/gcc-gimple.c ++++ b/gcc-c-api/gcc-gimple.c +@@ -35,7 +35,12 @@ + #include "gimple.h" + + #if 0 ++ ++/* gcc 10 removed this header */ ++#if (GCC_VERSION < 10000) + #include "params.h" ++#endif ++ + #include "cp/name-lookup.h" /* for global_namespace */ + #include "tree.h" + #include "diagnostic.h" +diff --git a/gcc-python-option.c b/gcc-python-option.c +index 0f27dc8..ab29cd6 100644 +--- a/gcc-python-option.c ++++ b/gcc-python-option.c +@@ -98,7 +98,14 @@ int PyGcc_option_is_enabled(enum opt_code opt_code) + { + /* Returns 1 if option OPT_IDX is enabled in OPTS, 0 if it is disabled, + or -1 if it isn't a simple on-off switch. */ ++#if (GCC_VERSION < 10000) + int i = option_enabled (opt_code, global_dc->option_state); ++#else ++ /* Starting with GCC 10, options can be distinguished by language. */ ++ /* TODO Expose the lang_mask to the user. */ ++ int i = option_enabled (opt_code, CL_LANG_ALL, global_dc->option_state); ++#endif ++ + if (i == 1) { + return 1; + } +diff --git a/gcc-python-parameter.c b/gcc-python-parameter.c +index bcd1af2..bc9c795 100644 +--- a/gcc-python-parameter.c ++++ b/gcc-python-parameter.c +@@ -17,10 +17,15 @@ + . + */ + ++ ++ + #include + #include "gcc-python.h" + #include "gcc-python-wrappers.h" + ++/* gcc 10 removed params.h */ ++#if (GCC_VERSION < 10000) ++ + /* + Wrapper for GCC's params.h. + We specifically wrap "compiler_param" (a typedef to an enum) +@@ -50,6 +55,8 @@ PyGcc_WrtpMarkForPyGccParameter(PyGccParameter *wrapper) + /* empty */ + } + ++#endif ++ + /* + PEP-7 + Local variables: +diff --git a/gcc-python.c b/gcc-python.c +index 9e75cd5..104d412 100644 +--- a/gcc-python.c ++++ b/gcc-python.c +@@ -225,6 +225,8 @@ PyGcc_get_option_dict(PyObject *self, PyObject *args) + return dict; + } + ++/* Function has been removed from GCC 10. */ ++#if (GCC_VERSION < 10000) + static PyObject * + PyGcc_get_parameters(PyObject *self, PyObject *args) + { +@@ -256,6 +258,7 @@ PyGcc_get_parameters(PyObject *self, PyObject *args) + Py_XDECREF(dict); + return NULL; + } ++#endif + + IMPL_APPENDER(add_var_to_list, + gcc_variable, +@@ -452,9 +455,12 @@ static PyMethodDef GccMethods[] = { + ("Get all command-line options, as a dict from command-line text strings " + "to gcc.Option instances")}, + ++/* Function has been removed from GCC 10. */ ++#if (GCC_VERSION < 10000) + {"get_parameters", PyGcc_get_parameters, METH_NOARGS, + "Get all tunable GCC parameters. Returns a dictionary, mapping from" + "option name -> gcc.Parameter instance"}, ++#endif + + {"get_variables", PyGcc_get_variables, METH_NOARGS, + "Get all variables in this compilation unit as a list of gcc.Variable"}, +@@ -811,7 +817,9 @@ plugin_init (struct plugin_name_args *plugin_info, + autogenerated_gimple_init_types(); /* FIXME: error checking! */ + autogenerated_location_init_types(); /* FIXME: error checking! */ + autogenerated_option_init_types(); /* FIXME: error checking! */ ++#if (GCC_VERSION < 10000) + autogenerated_parameter_init_types(); /* FIXME: error checking! */ ++#endif + autogenerated_pass_init_types(); /* FIXME: error checking! */ + autogenerated_pretty_printer_init_types(); /* FIXME: error checking! */ + autogenerated_rtl_init_types(); /* FIXME: error checking! */ +@@ -826,7 +834,9 @@ plugin_init (struct plugin_name_args *plugin_info, + autogenerated_gimple_add_types(PyGcc_globals.module); + autogenerated_location_add_types(PyGcc_globals.module); + autogenerated_option_add_types(PyGcc_globals.module); ++#if (GCC_VERSION < 10000) + autogenerated_parameter_add_types(PyGcc_globals.module); ++#endif + autogenerated_pass_add_types(PyGcc_globals.module); + autogenerated_pretty_printer_add_types(PyGcc_globals.module); + autogenerated_rtl_add_types(PyGcc_globals.module); +diff --git a/gcc-python.h b/gcc-python.h +index 521cbb7..599036b 100644 +--- a/gcc-python.h ++++ b/gcc-python.h +@@ -36,8 +36,13 @@ + #endif + #include "gimple.h" + ++ ++/* gcc 10 removed this header */ ++#if (GCC_VERSION < 10000) + #include "params.h" + #endif ++ ++#endif + #include "gcc-c-api/gcc-cfg.h" + + /* GCC doesn't seem to give us an ID for "invalid event", so invent one: */ +@@ -226,10 +231,13 @@ DECLARE_SIMPLE_WRAPPER(PyGccOption, + option, + gcc_option, opt) + ++/* gcc 10 removed params.h */ ++#if (GCC_VERSION < 10000) + DECLARE_SIMPLE_WRAPPER(PyGccParameter, + PyGccParameter_TypeObj, + param_num, + compiler_param, param_num) ++#endif + + DECLARE_SIMPLE_WRAPPER(PyGccRtl, + PyGccRtl_TypeObj, +@@ -276,9 +284,12 @@ void autogenerated_location_add_types(PyObject *m); + int autogenerated_option_init_types(void); + void autogenerated_option_add_types(PyObject *m); + ++/* GCC 10 removed params.h */ ++#if (GCC_VERSION < 10000) + /* autogenerated-parameter.c */ + int autogenerated_parameter_init_types(void); + void autogenerated_parameter_add_types(PyObject *m); ++#endif + + /* autogenerated-pass.c */ + int autogenerated_pass_init_types(void); +diff --git a/generate-parameter-c.py b/generate-parameter-c.py +old mode 100644 +new mode 100755 +index 6cef8a8..093af2a +--- a/generate-parameter-c.py ++++ b/generate-parameter-c.py +@@ -17,6 +17,17 @@ + + from cpybuilder import * + from wrapperbuilder import PyGccWrapperTypeObject ++import os, subprocess, sys ++ ++if not os.path.exists("./print-gcc-version"): ++ sys.stderr.write("Build make target 'print-gcc-version' before running this script.") ++ sys.exit(1) ++ ++gcc_version = int(subprocess.check_output("./print-gcc-version")) ++ ++if gcc_version >= 10000: ++ print("/* GCC10 has removed params.h; no need for this wrapper. */") ++ sys.exit(0) + + cu = CompilationUnit() + cu.add_include('gcc-python.h') +-- +2.9.5 + diff --git a/0009-Update-gcc-python-wrapper.c-for-Python-3.8.patch b/0009-Update-gcc-python-wrapper.c-for-Python-3.8.patch new file mode 100644 index 0000000..222b903 --- /dev/null +++ b/0009-Update-gcc-python-wrapper.c-for-Python-3.8.patch @@ -0,0 +1,39 @@ +From cdb70205bd5854c455dc1af205e9d5f7ce4afb66 Mon Sep 17 00:00:00 2001 +From: Nicolas Iooss +Date: Sun, 26 Apr 2020 13:58:17 +0200 +Subject: [PATCH 09/28] Update gcc-python-wrapper.c for Python 3.8 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Commit 3a4b484eaeda ("Build on Python 3.8") updated `cpybuilder.py` but +not `gcc-python-wrapper.c`. This results in the following error when +building with Python 3.8: + + gcc-python-wrapper.c:188:1: error: converting to non-pointer type + ‘long int’ from NULL [-Werror=conversion-null] + 188 | }; + | ^ +--- + gcc-python-wrapper.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/gcc-python-wrapper.c b/gcc-python-wrapper.c +index 951a04b..76e1db3 100644 +--- a/gcc-python-wrapper.c ++++ b/gcc-python-wrapper.c +@@ -137,7 +137,11 @@ PyTypeObject PyGccWrapperMeta_TypeObj = { + sizeof(PyGccWrapperTypeObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + NULL, /* tp_dealloc */ ++#if PY_VERSION_HEX >= 0x03080000 ++ 0, /*tp_vectorcall_offset*/ ++#else + NULL, /* tp_print */ ++#endif + NULL, /* tp_getattr */ + NULL, /* tp_setattr */ + #if PY_MAJOR_VERSION < 3 +-- +2.9.5 + diff --git a/0010-Link-with-libpython3.8.so.patch b/0010-Link-with-libpython3.8.so.patch new file mode 100644 index 0000000..2e0d50d --- /dev/null +++ b/0010-Link-with-libpython3.8.so.patch @@ -0,0 +1,34 @@ +From 4deefc840e69e3c2c42f8a50963b8fb69c17efee Mon Sep 17 00:00:00 2001 +From: Nicolas Iooss +Date: Sun, 26 Apr 2020 14:03:24 +0200 +Subject: [PATCH 10/28] Link with libpython3.8.so + +Since Python 3.8, python-config --libs no longer includes +/usr/lib/libpython3.8.so in the linked libraries. This results in the +following error when using plugins, for example in "make man": + + PYTHONPATH=./ CC_FOR_CPYCHECKER=cc LD_LIBRARY_PATH=gcc-c-api: CC=cc ./gcc-with-python generate-passes-svg.py test.c + cc1: error: cannot load plugin /usr/src/gcc-python-plugin/src/gcc-python-plugin-0.17/python.so + /usr/src/gcc-python-plugin/src/gcc-python-plugin-0.17/python.so: undefined symbol: PyUnicode_FromFormat + +Fix this by adding -lpython3.8 to $(PYTHON_LIBS) in Makefile. +--- + Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index c87ae8d..3a96257 100644 +--- a/Makefile ++++ b/Makefile +@@ -104,7 +104,7 @@ PYTHON_CONFIG=python-config + #PYTHON_CONFIG=python3.3dm-config + + PYTHON_INCLUDES=$(shell $(PYTHON_CONFIG) --includes) +-PYTHON_LIBS=$(shell $(PYTHON_CONFIG) --libs) ++PYTHON_LIBS=$(shell $(PYTHON) -c 'import sys;print("-lpython%d.%d" % sys.version_info[:2])') $(shell $(PYTHON_CONFIG) --libs) + + # Support having multiple named plugins + # e.g. "python2.7" "python3.2mu" "python 3.2dmu" etc: +-- +2.9.5 + diff --git a/0011-Add-PLUGIN_FINISH_PARSE_FUNCTION-support.patch b/0011-Add-PLUGIN_FINISH_PARSE_FUNCTION-support.patch new file mode 100644 index 0000000..8a1d50e --- /dev/null +++ b/0011-Add-PLUGIN_FINISH_PARSE_FUNCTION-support.patch @@ -0,0 +1,33 @@ +From b800b0622b80f7e60e6bb8cae747468ecd986ec0 Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Thu, 25 Nov 2021 22:12:48 +0800 +Subject: [PATCH 11/28] Add PLUGIN_FINISH_PARSE_FUNCTION support + +This is one great callbacks provided by GCC. + +Signed-off-by: Yihao Wu +--- + gcc-python-callbacks.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/gcc-python-callbacks.c b/gcc-python-callbacks.c +index e8a42aa..0d83d28 100644 +--- a/gcc-python-callbacks.c ++++ b/gcc-python-callbacks.c +@@ -375,7 +375,12 @@ PyGcc_RegisterCallback(PyObject *self, PyObject *args, PyObject *kwargs) + PyGcc_CallbackFor_GGC_END, + closure); + break; +- ++ case PLUGIN_FINISH_PARSE_FUNCTION: ++ register_callback("python", // FIXME ++ (enum plugin_event)event, ++ PyGcc_CallbackFor_tree, ++ closure); ++ break; + /* PLUGIN_FINISH_DECL was added in gcc 4.7 onwards: */ + #ifdef GCC_PYTHON_PLUGIN_CONFIG_has_PLUGIN_FINISH_DECL + case PLUGIN_FINISH_DECL: +-- +2.9.5 + diff --git a/0012-Add-get_location.patch b/0012-Add-get_location.patch new file mode 100644 index 0000000..13ad3b5 --- /dev/null +++ b/0012-Add-get_location.patch @@ -0,0 +1,44 @@ +From a8373e291991ef9f0acabf5cd426f1e780853fde Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Thu, 25 Nov 2021 22:13:45 +0800 +Subject: [PATCH 12/28] Add get_location + +We have set_location. Why not get_location? This tells us much information +on variable and function and more locations. + +Signed-off-by: Yihao Wu +--- + gcc-python.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/gcc-python.c b/gcc-python.c +index 104d412..3287d06 100644 +--- a/gcc-python.c ++++ b/gcc-python.c +@@ -134,6 +134,12 @@ PyGcc_define_macro(PyObject *self, + } + + static PyObject * ++PyGcc_get_location(PyObject *self, PyObject *args) ++{ ++ return PyGccLocation_New(gcc_private_make_location(input_location)); ++} ++ ++static PyObject * + PyGcc_set_location(PyObject *self, PyObject *args) + { + PyGccLocation *loc_obj; +@@ -438,6 +444,10 @@ static PyMethodDef GccMethods[] = { + (METH_VARARGS | METH_KEYWORDS), + ("Report an information message\n" + "FIXME\n")}, ++ {"get_location", ++ (PyCFunction)PyGcc_get_location, ++ METH_VARARGS, ++ ("Get the default location for error reports\n")}, + {"set_location", + (PyCFunction)PyGcc_set_location, + METH_VARARGS, +-- +2.9.5 + diff --git a/0013-Add-main_input_filename.patch b/0013-Add-main_input_filename.patch new file mode 100644 index 0000000..1643f79 --- /dev/null +++ b/0013-Add-main_input_filename.patch @@ -0,0 +1,42 @@ +From e9b93844bfecbc1cc60582e31f0bd6321f0b27f1 Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Thu, 25 Nov 2021 22:17:49 +0800 +Subject: [PATCH 13/28] Add main_input_filename + +We definitely want to know the filename we are compiling. + +Signed-off-by: Yihao Wu +--- + gcc-python.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/gcc-python.c b/gcc-python.c +index 3287d06..c18d3a3 100644 +--- a/gcc-python.c ++++ b/gcc-python.c +@@ -372,6 +372,12 @@ PyGcc_dump(PyObject *self, PyObject *arg) + } + + static PyObject * ++PyGcc_get_main_input_filename(PyObject *self, PyObject *args) ++{ ++ return PyGccStringOrNone(main_input_filename); ++} ++ ++static PyObject * + PyGcc_get_dump_file_name(PyObject *self, PyObject *noargs) + { + /* gcc/tree-pass.h declares: +@@ -494,6 +500,9 @@ static PyMethodDef GccMethods[] = { + {"get_callgraph_nodes", PyGcc_get_callgraph_nodes, METH_VARARGS, + "Get a list of all gcc.CallgraphNode instances"}, + ++ {"get_main_input_filename", PyGcc_get_main_input_filename, METH_NOARGS, ++ "Get main_input_filename"}, ++ + /* Dump files */ + {"dump", PyGcc_dump, METH_O, + "Dump str() of the argument to the current dump file (or silently discard it when no dump file is open)"}, +-- +2.9.5 + diff --git a/0014-Add-stub-for-types.patch b/0014-Add-stub-for-types.patch new file mode 100644 index 0000000..32cbfc9 --- /dev/null +++ b/0014-Add-stub-for-types.patch @@ -0,0 +1,69 @@ +From 5caf3852e16e362001c20c0085e8e28f5c53e826 Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Thu, 29 Oct 2020 17:18:14 +0800 +Subject: [PATCH 14/28] Add stub for types + +There are times we want to know where the structure is defined or sth. + +Signed-off-by: Yihao Wu +--- + gcc-python-tree.c | 5 +++++ + gcc-python-wrappers.h | 3 +++ + generate-tree-c.py | 6 ++++++ + 3 files changed, 14 insertions(+) + +diff --git a/gcc-python-tree.c b/gcc-python-tree.c +index e5f8101..fa160d3 100644 +--- a/gcc-python-tree.c ++++ b/gcc-python-tree.c +@@ -1103,6 +1103,11 @@ PyGcc_GetMethods(struct PyGccTree *self) + #endif + } + ++PyObject * PyGcc_GetStubDecl(struct PyGccTree *self) ++{ ++ return PyGccTree_New(gcc_private_make_tree(TYPE_STUB_DECL(self->t.inner))); ++} ++ + /* + GCC's debug_tree is implemented in: + gcc/print-tree.c +diff --git a/gcc-python-wrappers.h b/gcc-python-wrappers.h +index 1816b19..4a17e66 100644 +--- a/gcc-python-wrappers.h ++++ b/gcc-python-wrappers.h +@@ -355,6 +355,9 @@ PyGcc_GetFields(struct PyGccTree *self); + PyObject * + PyGcc_GetMethods(struct PyGccTree *self); + ++PyObject * ++PyGcc_GetStubDecl(struct PyGccTree *self); ++ + /* gcc-python-gimple.c: */ + extern gcc_gimple_asm + PyGccGimple_as_gcc_gimple_asm(struct PyGccGimple *self); +diff --git a/generate-tree-c.py b/generate-tree-c.py +index faf3faf..6eb3382 100644 +--- a/generate-tree-c.py ++++ b/generate-tree-c.py +@@ -484,11 +484,17 @@ def generate_tree_code_classes(): + add_simple_getter('methods', + 'PyGcc_GetMethods(self)', + "The methods of this type") ++ add_simple_getter('stub', ++ 'PyGcc_GetStubDecl(self)', ++ "The stub decl of this type") + + if tree_type.SYM == 'ENUMERAL_TYPE': + add_simple_getter('values', + 'PyGcc_TreeMakeListOfPairsFromTreeListChain(TYPE_VALUES(self->t.inner))', + "The values of this type") ++ add_simple_getter('stub', ++ 'PyGcc_GetStubDecl(self)', ++ "The stub decl of this type") + + if tree_type.SYM == 'IDENTIFIER_NODE': + add_simple_getter('name', +-- +2.9.5 + diff --git a/0015-Add-current_function_decl.patch b/0015-Add-current_function_decl.patch new file mode 100644 index 0000000..123be5c --- /dev/null +++ b/0015-Add-current_function_decl.patch @@ -0,0 +1,51 @@ +From 8da8d81b0bd73d557eec834d5c9df9d186b7b6d8 Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Fri, 6 Nov 2020 21:10:08 +0800 +Subject: [PATCH 15/28] Add current_function_decl + +This is very frequently used when working in all different callbacks. + +Signed-off-by: Yihao Wu +--- + gcc-python.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/gcc-python.c b/gcc-python.c +index c18d3a3..591142d 100644 +--- a/gcc-python.c ++++ b/gcc-python.c +@@ -28,6 +28,7 @@ + #include "gcc-c-api/gcc-declaration.h" + #include "gcc-c-api/gcc-diagnostics.h" + #include "gcc-c-api/gcc-option.h" ++#include "gcc-c-api/gcc-function.h" + + int plugin_is_GPL_compatible; + +@@ -154,6 +155,12 @@ PyGcc_set_location(PyObject *self, PyObject *args) + Py_RETURN_NONE; + } + ++static PyObject * ++PyGcc_get_current_function(PyObject *self, PyObject *args) ++{ ++ return PyGccFunction_New(gcc_get_current_function()); ++} ++ + static bool add_option_to_list(gcc_option opt, void *user_data) + { + PyObject *result = (PyObject*)user_data; +@@ -458,6 +465,10 @@ static PyMethodDef GccMethods[] = { + (PyCFunction)PyGcc_set_location, + METH_VARARGS, + ("Temporarily set the default location for error reports\n")}, ++ {"get_current_function", ++ (PyCFunction)PyGcc_get_current_function, ++ METH_VARARGS, ++ ("Get the current function declaration\n")}, + + /* Options: */ + {"get_option_list", +-- +2.9.5 + diff --git a/0016-Add-context.patch b/0016-Add-context.patch new file mode 100644 index 0000000..b837dda --- /dev/null +++ b/0016-Add-context.patch @@ -0,0 +1,39 @@ +From 6f92456ef9c81713f4013a8ec3c3ad88d650098b Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Thu, 25 Nov 2021 22:18:41 +0800 +Subject: [PATCH 16/28] Add context + +We want to know for example, is this variable defined in a translation unit +or in a function scope, or which struct contains this field. + +Signed-off-by: Yihao Wu +--- + generate-tree-c.py | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/generate-tree-c.py b/generate-tree-c.py +index 6eb3382..f3a66a2 100644 +--- a/generate-tree-c.py ++++ b/generate-tree-c.py +@@ -199,12 +199,18 @@ PyGccDeclaration_get_location(struct PyGccTree *self, void *closure) + add_simple_getter('is_artificial', + 'PyBool_FromLong(gcc_decl_is_artificial(PyGccTree_as_gcc_decl(self)))', + "Is this a compiler-generated entity?") ++ add_simple_getter('context', ++ 'PyGccTree_New(gcc_function_decl_as_gcc_tree(gcc_private_make_function_decl(DECL_CONTEXT (PyGccTree_as_gcc_decl(self).inner))))', ++ "context") + add_simple_getter('is_builtin', + 'PyBool_FromLong(gcc_decl_is_builtin(PyGccTree_as_gcc_decl(self)))', + "Is this declaration built in by the compiler?") + pytype.tp_repr = '(reprfunc)PyGccDeclaration_repr' + + if localname == 'Type': ++ add_simple_getter('context', ++ 'PyGccTree_New(gcc_function_decl_as_gcc_tree(gcc_private_make_function_decl(DECL_CONTEXT (PyGccTree_as_gcc_decl(self).inner))))', ++ "context") + add_simple_getter('name', + 'PyGccTree_New(gcc_type_get_name(PyGccTree_as_gcc_type(self)))', + "The name of the type as a gcc.Tree, or None") +-- +2.9.5 + diff --git a/0017-Add-main_variant-for-types.patch b/0017-Add-main_variant-for-types.patch new file mode 100644 index 0000000..53ce485 --- /dev/null +++ b/0017-Add-main_variant-for-types.patch @@ -0,0 +1,71 @@ +From 16579baf96d7c8d56379793bb884cacc5b27764f Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Mon, 2 Nov 2020 17:53:08 +0800 +Subject: [PATCH 17/28] Add main_variant for types + +This is useful when, for example we want to know what data structure +has a function accessed, without caring qualifiers. + +Signed-off-by: Yihao Wu +--- + gcc-python-tree.c | 4 ++++ + gcc-python-wrappers.h | 3 +++ + generate-tree-c.py | 6 ++++++ + 3 files changed, 13 insertions(+) + +diff --git a/gcc-python-tree.c b/gcc-python-tree.c +index fa160d3..ecfdf99 100644 +--- a/gcc-python-tree.c ++++ b/gcc-python-tree.c +@@ -1108,6 +1108,10 @@ PyObject * PyGcc_GetStubDecl(struct PyGccTree *self) + return PyGccTree_New(gcc_private_make_tree(TYPE_STUB_DECL(self->t.inner))); + } + ++PyObject * PyGcc_MainVariant(struct PyGccTree *self) ++{ ++ return PyGccTree_New(gcc_private_make_tree(TYPE_MAIN_VARIANT(self->t.inner))); ++} + /* + GCC's debug_tree is implemented in: + gcc/print-tree.c +diff --git a/gcc-python-wrappers.h b/gcc-python-wrappers.h +index 4a17e66..4c16ed0 100644 +--- a/gcc-python-wrappers.h ++++ b/gcc-python-wrappers.h +@@ -358,6 +358,9 @@ PyGcc_GetMethods(struct PyGccTree *self); + PyObject * + PyGcc_GetStubDecl(struct PyGccTree *self); + ++PyObject * ++PyGcc_MainVariant(struct PyGccTree *self); ++ + /* gcc-python-gimple.c: */ + extern gcc_gimple_asm + PyGccGimple_as_gcc_gimple_asm(struct PyGccGimple *self); +diff --git a/generate-tree-c.py b/generate-tree-c.py +index f3a66a2..9623c08 100644 +--- a/generate-tree-c.py ++++ b/generate-tree-c.py +@@ -404,6 +404,9 @@ def generate_tree_code_classes(): + add_simple_getter('%s_equivalent' % qual, + 'PyGccTree_New(gcc_private_make_tree(build_qualified_type(self->t.inner, TYPE_QUALS(self->t.inner) | TYPE_QUAL_%s)))' % qual.upper(), + 'The gcc.Type for the %s version of this type' % qual) ++ add_simple_getter('main_variant', ++ 'PyGcc_MainVariant(self)', ++ "The main vairant of this type") + add_simple_getter('unqualified_equivalent', + 'PyGccTree_New(gcc_private_make_tree(build_qualified_type(self->t.inner, 0)))', + 'The gcc.Type for the unqualified version of this type') +@@ -493,6 +496,9 @@ def generate_tree_code_classes(): + add_simple_getter('stub', + 'PyGcc_GetStubDecl(self)', + "The stub decl of this type") ++ add_simple_getter('main_variant', ++ 'PyGcc_MainVariant(self)', ++ "The main vairant of this type") + + if tree_type.SYM == 'ENUMERAL_TYPE': + add_simple_getter('values', +-- +2.9.5 + diff --git a/0018-Add-print_declaration-support-besides-dump_generic_n.patch b/0018-Add-print_declaration-support-besides-dump_generic_n.patch new file mode 100644 index 0000000..1721c5e --- /dev/null +++ b/0018-Add-print_declaration-support-besides-dump_generic_n.patch @@ -0,0 +1,94 @@ +From b149a22ff5e1e300a7d88186c306fe8048f25800 Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Mon, 2 Nov 2020 17:53:27 +0800 +Subject: [PATCH 18/28] Add print_declaration support besides dump_generic_node + +print_declaration gives much more graceful results than dump_generic_node +when the node is decl. On the other hand, dump_generic_node always gives +very ugly ones. + +Signed-off-by: Yihao Wu +--- + gcc-python-tree.c | 30 ++++++++++++++++++++++++++++++ + gcc-python-wrappers.h | 3 +++ + generate-tree-c.py | 2 ++ + 3 files changed, 35 insertions(+) + +diff --git a/gcc-python-tree.c b/gcc-python-tree.c +index ecfdf99..1fa76bf 100644 +--- a/gcc-python-tree.c ++++ b/gcc-python-tree.c +@@ -121,6 +121,30 @@ do_pretty_print(struct PyGccTree * self, int spc, dump_flags_t flags) + if (!result) { + goto error; + } ++ ++ Py_XDECREF(ppobj); ++ return result; ++ ++ error: ++ Py_XDECREF(ppobj); ++ return NULL; ++} ++ ++static PyObject * ++do_decl_print(struct PyGccTree * self, int spc, dump_flags_t flags) ++{ ++ PyObject *ppobj = PyGccPrettyPrinter_New(); ++ PyObject *result = NULL; ++ if (!ppobj) { ++ return NULL; ++ } ++ ++ print_declaration (PyGccPrettyPrinter_as_pp(ppobj), ++ self->t.inner, spc, flags); ++ result = PyGccPrettyPrinter_as_string(ppobj); ++ if (!result) { ++ goto error; ++ } + + Py_XDECREF(ppobj); + return result; +@@ -285,6 +309,12 @@ PyGccTree_get_str_no_uid(struct PyGccTree *self, void *closure) + } + + PyObject * ++PyGccTree_get_str_decl(struct PyGccTree *self, void *closure) ++{ ++ return do_decl_print(self, 0, TDF_NOUID); ++} ++ ++PyObject * + PyGccTree_get_symbol(PyObject *cls, PyObject *args) + { + enum tree_code code; +diff --git a/gcc-python-wrappers.h b/gcc-python-wrappers.h +index 4c16ed0..63cb12f 100644 +--- a/gcc-python-wrappers.h ++++ b/gcc-python-wrappers.h +@@ -245,6 +245,9 @@ PyObject * + PyGccTree_get_str_no_uid(struct PyGccTree *self, void *closure); + + PyObject * ++PyGccTree_get_str_decl(struct PyGccTree *self, void *closure); ++ ++PyObject * + PyGccTree_get_symbol(PyObject *cls, PyObject *args); + + PyObject * +diff --git a/generate-tree-c.py b/generate-tree-c.py +index 9623c08..b408b3d 100644 +--- a/generate-tree-c.py ++++ b/generate-tree-c.py +@@ -76,6 +76,8 @@ PyGccTree_get_addr(struct PyGccTree *self, void *closure) + 'Instance of gcc.Tree giving the type of the node'), + PyGetSetDef('addr', 'PyGccTree_get_addr', None, + 'The address of the underlying GCC object in memory'), ++ PyGetSetDef('str_decl', 'PyGccTree_get_str_decl', None, ++ 'A string representation of this declaration of the object.'), + PyGetSetDef('str_no_uid', 'PyGccTree_get_str_no_uid', None, + 'A string representation of this object, like str(), but without including any internal UID')], + identifier_prefix='PyGccTree', +-- +2.9.5 + diff --git a/0019-Make-static-attribute-writtable.patch b/0019-Make-static-attribute-writtable.patch new file mode 100644 index 0000000..bd6709d --- /dev/null +++ b/0019-Make-static-attribute-writtable.patch @@ -0,0 +1,48 @@ +From 3cc359ae7da22d5889f6c3c36f0c8e52b04ef9b1 Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Sat, 7 Nov 2020 18:08:50 +0800 +Subject: [PATCH 19/28] Make static attribute writtable + +This is needed when we want to use GCC's pretty print to do some code +generation work. + +Signed-off-by: Yihao Wu +--- + generate-tree-c.py | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/generate-tree-c.py b/generate-tree-c.py +index b408b3d..f17b8c1 100644 +--- a/generate-tree-c.py ++++ b/generate-tree-c.py +@@ -173,6 +173,17 @@ def generate_intermediate_tree_classes(): + doc) + + if localname == 'Declaration': ++ getter = cu.add_simple_getter('PyGccTree_get_static', ++ 'PyGccTree', ++ 'PyBool_FromLong(TREE_STATIC(self->t.inner))') ++ setter = cu.add_simple_int_setter('PyGccTree_set_static', ++ 'PyGccTree', ++ 'static', ++ 'TREE_STATIC(self->t.inner) = PyGccInt_AsLong(value)') ++ getsettable.add_gsdef('static', ++ getter, setter, ++ "(bool/bool)") ++ + cu.add_defn(""" + PyObject * + PyGccDeclaration_get_name(struct PyGccTree *self, void *closure) +@@ -520,9 +531,6 @@ def generate_tree_code_classes(): + add_simple_getter('initial', + 'PyGccTree_New(gcc_constructor_as_gcc_tree(gcc_var_decl_get_initial(PyGccTree_as_gcc_var_decl(self))))', + "The initial value for this variable as a gcc.Constructor, or None") +- add_simple_getter('static', +- 'PyBool_FromLong(gcc_var_decl_is_static(PyGccTree_as_gcc_var_decl(self)))', +- "Boolean: is this variable to be allocated with static storage") + + if tree_type.SYM == 'CONSTRUCTOR': + add_complex_getter('elements', +-- +2.9.5 + diff --git a/0020-Make-initial-attribute-writeable.patch b/0020-Make-initial-attribute-writeable.patch new file mode 100644 index 0000000..57e93f4 --- /dev/null +++ b/0020-Make-initial-attribute-writeable.patch @@ -0,0 +1,50 @@ +From 1b57fccfa9c08379e18645180342564d96356f5f Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Sat, 7 Nov 2020 20:59:09 +0800 +Subject: [PATCH 20/28] Make initial attribute writeable + +This is needed when we want to use GCC's pretty print to do some code +generation work. For example, assigning NULL to initial, makes it have +no initial value any more. + +Signed-off-by: Yihao Wu +--- + generate-tree-c.py | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/generate-tree-c.py b/generate-tree-c.py +index f17b8c1..9a3235a 100644 +--- a/generate-tree-c.py ++++ b/generate-tree-c.py +@@ -184,6 +184,17 @@ def generate_intermediate_tree_classes(): + getter, setter, + "(bool/bool)") + ++ getter = cu.add_simple_getter('PyGccTree_get_initial', ++ 'PyGccTree', ++ 'PyGccTree_New(gcc_constructor_as_gcc_tree(gcc_var_decl_get_initial(PyGccTree_as_gcc_var_decl(self))))') ++ setter = cu.add_simple_int_setter('PyGccTree_set_initial', ++ 'PyGccTree', ++ 'initial', ++ 'DECL_INITIAL(self->t.inner) = NULL;') ++ getsettable.add_gsdef('initial', ++ getter, setter, ++ "(ptr/None)") ++ + cu.add_defn(""" + PyObject * + PyGccDeclaration_get_name(struct PyGccTree *self, void *closure) +@@ -528,9 +539,7 @@ def generate_tree_code_classes(): + tp_repr = '(reprfunc)PyGccIdentifierNode_repr' + + if tree_type.SYM == 'VAR_DECL': +- add_simple_getter('initial', +- 'PyGccTree_New(gcc_constructor_as_gcc_tree(gcc_var_decl_get_initial(PyGccTree_as_gcc_var_decl(self))))', +- "The initial value for this variable as a gcc.Constructor, or None") ++ pass + + if tree_type.SYM == 'CONSTRUCTOR': + add_complex_getter('elements', +-- +2.9.5 + diff --git a/0021-Make-public-attribute-writable.patch b/0021-Make-public-attribute-writable.patch new file mode 100644 index 0000000..b38bba7 --- /dev/null +++ b/0021-Make-public-attribute-writable.patch @@ -0,0 +1,38 @@ +From 2a8a4731f4f44fa64a20e63152a294dec11f72f4 Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Mon, 11 Jan 2021 21:41:24 +0800 +Subject: [PATCH 21/28] Make public attribute writable + +This is needed when we want to use GCC's pretty print to do some code +generation work. + +Signed-off-by: Yihao Wu +--- + generate-tree-c.py | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/generate-tree-c.py b/generate-tree-c.py +index 9a3235a..bce582d 100644 +--- a/generate-tree-c.py ++++ b/generate-tree-c.py +@@ -194,6 +194,17 @@ def generate_intermediate_tree_classes(): + getsettable.add_gsdef('initial', + getter, setter, + "(ptr/None)") ++ getter = cu.add_simple_getter('PyGccTree_get_public', ++ 'PyGccTree', ++ 'PyBool_FromLong(TREE_PUBLIC(self->t.inner))') ++ setter = cu.add_simple_int_setter('PyGccTree_set_public', ++ 'PyGccTree', ++ 'public', ++ 'TREE_PUBLIC(self->t.inner) = PyGccInt_AsLong(value)') ++ getsettable.add_gsdef('public', ++ getter, setter, ++ "(bool/bool)") ++ + + cu.add_defn(""" + PyObject * +-- +2.9.5 + diff --git a/0022-Add-external-attribute.patch b/0022-Add-external-attribute.patch new file mode 100644 index 0000000..ce73a95 --- /dev/null +++ b/0022-Add-external-attribute.patch @@ -0,0 +1,36 @@ +From 324a3375d2bee33bbddc1707408ce179e1c88837 Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Sat, 7 Nov 2020 21:01:19 +0800 +Subject: [PATCH 22/28] Add external attribute + +This is provided by GCC, better have it. + +Signed-off-by: Yihao Wu +--- + generate-tree-c.py | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/generate-tree-c.py b/generate-tree-c.py +index bce582d..48dd1a3 100644 +--- a/generate-tree-c.py ++++ b/generate-tree-c.py +@@ -222,6 +222,16 @@ PyGccDeclaration_get_location(struct PyGccTree *self, void *closure) + return PyGccLocation_New(gcc_decl_get_location(PyGccTree_as_gcc_decl(self))); + } + """) ++ getter = cu.add_simple_getter('PyGccTree_get_external', ++ 'PyGccTree', ++ 'PyBool_FromLong(DECL_EXTERNAL(self->t.inner))') ++ setter = cu.add_simple_int_setter('PyGccTree_set_', ++ 'PyGccTree', ++ 'external', ++ 'DECL_EXTERNAL(self->t.inner) = PyGccInt_AsLong(value)') ++ getsettable.add_gsdef('external', ++ getter, setter, ++ "(bool/bool)") + + getsettable.add_gsdef('name', + 'PyGccDeclaration_get_name', +-- +2.9.5 + diff --git a/0023-Make-location-hasher-robust.patch b/0023-Make-location-hasher-robust.patch new file mode 100644 index 0000000..89224b0 --- /dev/null +++ b/0023-Make-location-hasher-robust.patch @@ -0,0 +1,64 @@ +From d6168389b77581807bf19f2ea5350dd2b475357a Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Sat, 7 Nov 2020 22:36:10 +0800 +Subject: [PATCH 23/28] Make location hasher robust + +I've encountered strange bugs caused by this location hasher. So better +not rely on pointer address, but the real content. As an example, the +find-global-state test case was wrong because of this wrong hasher. + +Notice these two snippets: + +1) +int test2(int p) +{ + static int q = 0; + q += p; + return p * q; +} + +2) +int test2(int p) +{ + static int q = 0; + q = q + p; + return p * q; +} + +These two are not identical in compilers eyes. With "q += p", q is only +acccessed once, the intermediate value q+p is nothing but a temporary value +asserted by the compiler, eg. "q.2". While with "q = q + p", q is accessed +twice, because q at both lhs and rhs are the original q, not temp variable. + +Signed-off-by: Yihao Wu +--- + gcc-python-location.c | 2 +- + tests/examples/find-global-state/stderr.txt | 1 - + 2 files changed, 1 insertion(+), 2 deletions(-) + +diff --git a/gcc-python-location.c b/gcc-python-location.c +index 0857694..696d370 100644 +--- a/gcc-python-location.c ++++ b/gcc-python-location.c +@@ -190,7 +190,7 @@ PyGccLocation_richcompare(PyObject *o1, PyObject *o2, int op) + long + PyGccLocation_hash(struct PyGccLocation * self) + { +- return self->loc.inner; ++ return (unsigned long)(LOCATION_FILE(self->loc.inner)) ^ LOCATION_LINE(self->loc.inner); + } + + #if (GCC_VERSION >= 5000) +diff --git a/tests/examples/find-global-state/stderr.txt b/tests/examples/find-global-state/stderr.txt +index 1385ef1..8a24a15 100644 +--- a/tests/examples/find-global-state/stderr.txt ++++ b/tests/examples/find-global-state/stderr.txt +@@ -1,5 +1,4 @@ + tests/examples/find-global-state/input.c:41:nn: note: use of global state "int q" here +-tests/examples/find-global-state/input.c:41:nn: note: use of global state "int q" here + tests/examples/find-global-state/input.c:42:nn: note: use of global state "int q" here + tests/examples/find-global-state/input.c:53:nn: note: use of global state "int foo" here + tests/examples/find-global-state/input.c:58:nn: note: use of global state "struct +-- +2.9.5 + diff --git a/0024-Add-PLUGIN_INCLUDE_FILE-callback.patch b/0024-Add-PLUGIN_INCLUDE_FILE-callback.patch new file mode 100644 index 0000000..612b72d --- /dev/null +++ b/0024-Add-PLUGIN_INCLUDE_FILE-callback.patch @@ -0,0 +1,51 @@ +From 08b6ae47fbf25ba6eb49576bdc19960b69807ddb Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Sun, 8 Nov 2020 01:44:45 +0800 +Subject: [PATCH 24/28] Add PLUGIN_INCLUDE_FILE callback + +Better support all callbacks which GCC supports. + +Signed-off-by: Yihao Wu +--- + gcc-python-callbacks.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/gcc-python-callbacks.c b/gcc-python-callbacks.c +index 0d83d28..1aeb865 100644 +--- a/gcc-python-callbacks.c ++++ b/gcc-python-callbacks.c +@@ -197,6 +197,18 @@ PyGcc_CallbackFor_tree(void *gcc_data, void *user_data) + user_data); + } + ++static void ++PyGcc_CallbackFor_string(void *gcc_data, void *user_data) ++{ ++ PyGILState_STATE gstate; ++ const char *str = (const char *)gcc_data; ++ ++ gstate = PyGILState_Ensure(); ++ ++ PyGcc_FinishInvokingCallback(gstate, ++ 1, PyGccString_FromString(str), ++ user_data); ++} + + static void + PyGcc_CallbackFor_PLUGIN_ATTRIBUTES(void *gcc_data, void *user_data) +@@ -381,6 +393,12 @@ PyGcc_RegisterCallback(PyObject *self, PyObject *args, PyObject *kwargs) + PyGcc_CallbackFor_tree, + closure); + break; ++ case PLUGIN_INCLUDE_FILE: ++ register_callback("python", // FIXME ++ (enum plugin_event)event, ++ PyGcc_CallbackFor_string, ++ closure); ++ break; + /* PLUGIN_FINISH_DECL was added in gcc 4.7 onwards: */ + #ifdef GCC_PYTHON_PLUGIN_CONFIG_has_PLUGIN_FINISH_DECL + case PLUGIN_FINISH_DECL: +-- +2.9.5 + diff --git a/0025-Add-decl.attributes.patch b/0025-Add-decl.attributes.patch new file mode 100644 index 0000000..ff25f02 --- /dev/null +++ b/0025-Add-decl.attributes.patch @@ -0,0 +1,108 @@ +From fdcd69cdf88d7b05cc604ebf7a39362e2b4413c7 Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Mon, 16 Nov 2020 00:08:45 +0800 +Subject: [PATCH 25/28] Add decl.attributes + +Of course we want this not only for types but declaraions too. +People give various attributes to functions and variables. + +Signed-off-by: Yihao Wu +--- + gcc-python-tree.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ + gcc-python-wrappers.h | 3 +++ + generate-tree-c.py | 4 ++++ + 3 files changed, 57 insertions(+) + +diff --git a/gcc-python-tree.c b/gcc-python-tree.c +index 1fa76bf..47d5a03 100644 +--- a/gcc-python-tree.c ++++ b/gcc-python-tree.c +@@ -457,6 +457,56 @@ PyGccIdentifierNode_repr(struct PyGccTree * self) + } + + PyObject * ++PyGccDeclaration_get_attributes(struct PyGccTree *self, void *closure) ++{ ++ /* gcc/tree.h defines TYPE_ATTRIBUTES(NODE) as: ++ "A TREE_LIST of IDENTIFIER nodes of the attributes that apply ++ to this type" ++ ++ Looking at: ++ typedef int (example3)(const char *, const char *, const char *) ++ __attribute__((nonnull(1))) ++ __attribute__((nonnull(3))); ++ (which is erroneous), we get this for TYPE_ATTRIBUTES: ++ gcc.TreeList(purpose=gcc.IdentifierNode(name='nonnull'), ++ value=gcc.TreeList(purpose=None, ++ value=gcc.IntegerCst(3), ++ chain=None), ++ chain=gcc.TreeList(purpose=gcc.IdentifierNode(name='nonnull'), ++ value=gcc.TreeList(purpose=None, ++ value=gcc.IntegerCst(1), ++ chain=None), ++ chain=None) ++ ) ++ */ ++ tree attr; ++ PyObject *result = PyDict_New(); ++ if (!result) { ++ return NULL; ++ } ++ for (attr = DECL_ATTRIBUTES(self->t.inner); attr; attr = TREE_CHAIN(attr)) { ++ const char *attrname = IDENTIFIER_POINTER(TREE_PURPOSE(attr)); ++ PyObject *values; ++ values = PyGcc_TreeMakeListFromTreeList(TREE_VALUE(attr)); ++ if (!values) { ++ goto error; ++ } ++ ++ if (-1 == PyDict_SetItemString(result, attrname, values)) { ++ Py_DECREF(values); ++ goto error; ++ } ++ Py_DECREF(values); ++ } ++ ++ return result; ++ ++ error: ++ Py_DECREF(result); ++ return NULL; ++} ++ ++PyObject * + PyGccType_get_attributes(struct PyGccTree *self, void *closure) + { + /* gcc/tree.h defines TYPE_ATTRIBUTES(NODE) as: +diff --git a/gcc-python-wrappers.h b/gcc-python-wrappers.h +index 63cb12f..7181535 100644 +--- a/gcc-python-wrappers.h ++++ b/gcc-python-wrappers.h +@@ -272,6 +272,9 @@ PyObject * + PyGccDeclaration_repr(struct PyGccTree * self); + + PyObject * ++PyGccDeclaration_get_attributes(struct PyGccTree *self, void *closure); ++ ++PyObject * + PyGccFunctionDecl_get_fullname(struct PyGccTree *self, void *closure); + + PyObject * +diff --git a/generate-tree-c.py b/generate-tree-c.py +index 48dd1a3..a1bb932 100644 +--- a/generate-tree-c.py ++++ b/generate-tree-c.py +@@ -241,6 +241,10 @@ PyGccDeclaration_get_location(struct PyGccTree *self, void *closure) + 'PyGccDeclaration_get_location', + None, + 'The gcc.Location for this declaration') ++ getsettable.add_gsdef('attributes', ++ 'PyGccDeclaration_get_attributes', ++ None, ++ 'The user-defined attributes on this decl') + add_simple_getter('is_artificial', + 'PyBool_FromLong(gcc_decl_is_artificial(PyGccTree_as_gcc_decl(self)))', + "Is this a compiler-generated entity?") +-- +2.9.5 + diff --git a/0026-Add-referring-and-referer-to-variables.patch b/0026-Add-referring-and-referer-to-variables.patch new file mode 100644 index 0000000..2da389d --- /dev/null +++ b/0026-Add-referring-and-referer-to-variables.patch @@ -0,0 +1,102 @@ +From 3d2e5d3f84147fe969810ab8fe600b187eb651dd Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Mon, 16 Nov 2020 00:09:25 +0800 +Subject: [PATCH 26/28] Add referring and referer to variables + +Cgraph gives us callers and callees, and Varpool gives us referring and +referred. It's good to have themtoo. + +Signed-off-by: Yihao Wu +--- + gcc-python-variable.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ + generate-variable-c.py | 13 +++++++++++++ + 2 files changed, 63 insertions(+) + +diff --git a/gcc-python-variable.c b/gcc-python-variable.c +index bab1ec2..198b268 100644 +--- a/gcc-python-variable.c ++++ b/gcc-python-variable.c +@@ -51,6 +51,56 @@ PyGcc_WrtpMarkForPyGccVariable(PyGccVariable *wrapper) + gcc_variable_mark_in_use(wrapper->var); + } + ++IMPL_APPENDER(add_var_to_list, ++ gcc_variable, ++ PyGccVariable_New) ++ ++ ++GCC_IMPLEMENT_PUBLIC_API (bool) gcc_variable_get_referring (gcc_variable var, ++ bool (*cb) (gcc_variable var, void *user_data), ++ void *user_data) ++{ ++ ipa_ref *ref = NULL; ++ int i; ++ for (i = 0; var.inner->iterate_referring(i, ref); i++) { ++ if (cb(gcc_private_make_variable((varpool_node*)ref->referring), user_data)) ++ return true; ++ } ++ ++ return false; ++} ++ ++GCC_IMPLEMENT_PUBLIC_API (PyObject *) ++PyGccVariable_get_referring(struct PyGccVariable * self) ++{ ++ IMPL_LIST_MAKER(gcc_variable_get_referring, ++ self->var, ++ add_var_to_list) ++} ++ ++ ++GCC_IMPLEMENT_PUBLIC_API (bool) gcc_variable_get_reference (gcc_variable var, ++ bool (*cb) (gcc_variable var, void *user_data), ++ void *user_data) ++{ ++ ipa_ref *ref = NULL; ++ int i; ++ for (i = 0; var.inner->iterate_reference(i, ref); i++) { ++ if (cb(gcc_private_make_variable((varpool_node*)ref->referred), user_data)) ++ return true; ++ } ++ ++ return false; ++} ++ ++GCC_IMPLEMENT_PUBLIC_API (PyObject *) ++PyGccVariable_get_reference(struct PyGccVariable * self) ++{ ++ IMPL_LIST_MAKER(gcc_variable_get_reference, ++ self->var, ++ add_var_to_list) ++} ++ + /* + PEP-7 + Local variables: +diff --git a/generate-variable-c.py b/generate-variable-c.py +index aed8955..498b2cb 100644 +--- a/generate-variable-c.py ++++ b/generate-variable-c.py +@@ -44,6 +44,19 @@ def generate_variable(): + 'PyGccTree_New(gcc_variable_get_decl(self->var))', + 'The declaration of this variable, as a gcc.Tree') + ++ cu.add_decl('GCC_IMPLEMENT_PUBLIC_API (PyObject *) PyGccVariable_get_referring(struct PyGccVariable * self);') ++ cu.add_decl('GCC_IMPLEMENT_PUBLIC_API (PyObject *) PyGccVariable_get_reference(struct PyGccVariable * self);') ++ ++ getsettable.add_gsdef('referring', ++ 'PyGccVariable_get_referring', ++ None, ++ 'Referencing this var') ++ ++ getsettable.add_gsdef('reference', ++ 'PyGccVariable_get_reference', ++ None, ++ 'Referenced by this var') ++ + cu.add_defn(getsettable.c_defn()) + + pytype = PyGccWrapperTypeObject(identifier = 'PyGccVariable_TypeObj', +-- +2.9.5 + diff --git a/0027-Add-VarDecl.node-points-to-varpool-nodes.patch b/0027-Add-VarDecl.node-points-to-varpool-nodes.patch new file mode 100644 index 0000000..4e70e6e --- /dev/null +++ b/0027-Add-VarDecl.node-points-to-varpool-nodes.patch @@ -0,0 +1,30 @@ +From afb65cbb6580c0a65a293dae2e3af6892f351a39 Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Thu, 25 Nov 2021 21:09:42 +0800 +Subject: [PATCH 27/28] Add VarDecl.node points to varpool nodes + +Just like FunctionDecl.node points to function nodes, they are similar. + +Signed-off-by: Yihao Wu +--- + generate-tree-c.py | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/generate-tree-c.py b/generate-tree-c.py +index a1bb932..6c8c031 100644 +--- a/generate-tree-c.py ++++ b/generate-tree-c.py +@@ -564,7 +564,9 @@ def generate_tree_code_classes(): + tp_repr = '(reprfunc)PyGccIdentifierNode_repr' + + if tree_type.SYM == 'VAR_DECL': +- pass ++ add_simple_getter('node', ++ 'PyGccVariable_New(gcc_private_make_variable(varpool_node::get (self->t.inner)))', ++ 'Node which contains this var decl') + + if tree_type.SYM == 'CONSTRUCTOR': + add_complex_getter('elements', +-- +2.9.5 + diff --git a/0028-Add-general-purpose-walk_tree.patch b/0028-Add-general-purpose-walk_tree.patch new file mode 100644 index 0000000..2b66e1d --- /dev/null +++ b/0028-Add-general-purpose-walk_tree.patch @@ -0,0 +1,145 @@ +From 99ab6a0d7facda19d96ad53fd80bb14fbf499379 Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Sat, 2 Jan 2021 13:10:10 +0800 +Subject: [PATCH 28/28] Add general purpose walk_tree + +GCC supports not only walking of gimple, but general purpose decl. +It's good to have them. For example we want to walk down the of +initializing tree a global data structure variable. + +Signed-off-by: Yihao Wu +--- + gcc-python-tree.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++ + gcc-python-wrappers.h | 3 ++ + generate-tree-c.py | 4 +++ + 3 files changed, 86 insertions(+) + +diff --git a/gcc-python-tree.c b/gcc-python-tree.c +index 47d5a03..c36d569 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 "gcc-python-closure.h" + #include "cp/cp-tree.h" + #include "gimple.h" + +@@ -328,6 +329,84 @@ PyGccTree_get_symbol(PyObject *cls, PyObject *args) + return PyGccString_FromString(op_symbol_code(code)); + } + ++static tree ++tree_walk_callback(tree *tree_ptr, int *walk_subtree, void *data) ++{ ++ struct callback_closure *closure = (struct callback_closure*)data; ++ PyObject *tree_obj = NULL; ++ PyObject *args = NULL; ++ PyObject *result = NULL; ++ ++ assert(closure); ++ assert(*tree_ptr); ++ tree_obj = PyGccTree_New(gcc_private_make_tree(*tree_ptr)); ++ if (!tree_obj) { ++ goto error; ++ } ++ ++ args = PyGcc_Closure_MakeArgs(closure, 0, tree_obj); ++ if (!args) { ++ goto error; ++ } ++ ++ /* Invoke the python callback: */ ++ result = PyObject_Call(closure->callback, args, closure->kwargs); ++ if (!result) { ++ goto error; ++ } ++ ++ Py_DECREF(tree_obj); ++ Py_DECREF(args); ++ ++ if (PyObject_IsTrue(result)) { ++ Py_DECREF(result); ++ return *tree_ptr; ++ } else { ++ Py_DECREF(result); ++ return NULL; ++ } ++ ++error: ++ /* On and exception, terminate the traversal: */ ++ *walk_subtree = 0; ++ Py_XDECREF(tree_obj); ++ Py_XDECREF(args); ++ Py_XDECREF(result); ++ return NULL; ++} ++ ++PyObject * ++PyGccTree_walk_tree(struct PyGccTree * self, PyObject *args, PyObject *kwargs) ++{ ++ PyObject *callback; ++ PyObject *extraargs = NULL; ++ struct callback_closure *closure; ++ tree result; ++ ++ callback = PyTuple_GetItem(args, 0); ++ extraargs = PyTuple_GetSlice(args, 1, PyTuple_Size(args)); ++ ++ closure = PyGcc_closure_new_generic(callback, extraargs, kwargs); ++ ++ if (!closure) { ++ Py_DECREF(callback); ++ Py_DECREF(extraargs); ++ return NULL; ++ } ++ ++ result = walk_tree (&self->t.inner, ++ tree_walk_callback, ++ closure, NULL); ++ ++ PyGcc_closure_free(closure); ++ ++ if (PyErr_Occurred()) { ++ return NULL; ++ } ++ ++ return PyGccTree_New(gcc_private_make_tree(result)); ++} ++ + PyObject * + PyGccDeclaration_repr(struct PyGccTree * self) + { +diff --git a/gcc-python-wrappers.h b/gcc-python-wrappers.h +index 7181535..8bc2e22 100644 +--- a/gcc-python-wrappers.h ++++ b/gcc-python-wrappers.h +@@ -269,6 +269,9 @@ PyObject * + PyGccDeclaration_get_name(struct PyGccTree *self, void *closure); + + PyObject * ++PyGccTree_walk_tree(struct PyGccTree * self, PyObject *args, PyObject *kwargs); ++ ++PyObject * + PyGccDeclaration_repr(struct PyGccTree * self); + + PyObject * +diff --git a/generate-tree-c.py b/generate-tree-c.py +index 6c8c031..37607d2 100644 +--- a/generate-tree-c.py ++++ b/generate-tree-c.py +@@ -96,6 +96,10 @@ PyGccTree_get_addr(struct PyGccTree *self, void *closure) + tp_str = '(reprfunc)PyGccTree_str', + tp_richcompare = 'PyGccTree_richcompare') + methods = PyMethodTable('PyGccTree_methods', []) ++ methods.add_method('walk_tree', ++ '(PyCFunction)PyGccTree_walk_tree', ++ 'METH_VARARGS | METH_KEYWORDS', ++ 'Walk the tree of the declaration') + methods.add_method('debug', + 'PyGccTree_debug', + 'METH_VARARGS', +-- +2.9.5 + diff --git a/0029-Add-inline-attr-to-function-decl.patch b/0029-Add-inline-attr-to-function-decl.patch new file mode 100644 index 0000000..6e86e9a --- /dev/null +++ b/0029-Add-inline-attr-to-function-decl.patch @@ -0,0 +1,31 @@ +From fcbc22bd2b50b1b027bc6d93443c9a8c0f13fa52 Mon Sep 17 00:00:00 2001 +From: Yihao Wu +Date: Wed, 7 Apr 2021 02:09:10 +0800 +Subject: [PATCH] Add inline attr to function decl + +To tell a function is inline or not. Note that this only indicates if the +functions is attributed with "inline", it can't tell whether gcc really +decides to inline it. + +Signed-off-by: Yihao Wu +--- + generate-tree-c.py | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/generate-tree-c.py b/generate-tree-c.py +index 37607d2..2f87c30 100644 +--- a/generate-tree-c.py ++++ b/generate-tree-c.py +@@ -652,6 +652,9 @@ def generate_tree_code_classes(): + add_simple_getter('result', + 'PyGccTree_New(gcc_private_make_tree(DECL_RESULT_FLD(self->t.inner)))', + 'The gcc.ResultDecl for the return value') ++ add_simple_getter('inline', ++ 'PyBool_FromLong(DECL_DECLARED_INLINE_P(self->t.inner))', ++ 'If function is declared as inline') + getsettable.add_gsdef('callgraph_node', + 'PyGccFunctionDecl_get_callgraph_node', + None, +-- +2.9.5 + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..170f2d2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,30 @@ +The C and Python code is licensed under the GPLv3 or later (see COPYING and the +per-file license information). + +There are copies of various JavaScript and CSS libraries embedded within the +source tree, which have their own licenses as follows: + + libcpychecker_html/extlib/jquery-1.7.1.min.js: + jquery.org/license (MIT or GPLv2) + + libcpychecker_html/extlib/prefixfree-1.0.4.min.js: + MIT license + + libcpychecker_html/extlib/reset-20110126.css: + Public Domain + +There are also various images within: + libcpychecke_/html/images +These were taken from: + http://code.google.com/p/fugue-icons-src/ +and are: + "© 2012 Yusuke Kamiyamane. All rights reserved. + These icons are available under a Creative Commons Attribution 3.0 + License. " + http://creativecommons.org/licenses/by/3.0/ + +The test code contains historical examples of reference-count bugs: + + * libcpychecker_html/test/example2 + contains an embedded copy of part of an old version of pylibmc, which + is under a 3-clause BSD license diff --git a/gcc-python-plugin.spec b/gcc-python-plugin.spec new file mode 100644 index 0000000..4e3ae61 --- /dev/null +++ b/gcc-python-plugin.spec @@ -0,0 +1,167 @@ +Name: gcc-python-plugin +Version: 0.17 +Release: 1.1%{?dist} +Summary: GCC plugin that embeds Python + +Group: Development/Languages +License: GPLv3+ +URL: https://github.com/davidmalcolm/gcc-python-plugin +Source0: %{name}-%{version}.tar.gz + +Patch0001: 0001-Fix-typo-in-release-notes.patch +Patch0002: 0002-Fix-typo-in-basics.rst.patch +Patch0003: 0003-gcc-python-pretty-printer-fix-GCC-8.3-compatibility.patch +Patch0004: 0004-Added-ability-to-get-the-result-of-DECL_ORIGINAL_TYP.patch +Patch0005: 0005-tests-exercise-gcc.TypeDecl.original_type.patch +Patch0006: 0006-.travis.yml-add-gcc-9.patch +Patch0007: 0007-Build-on-Python-3.8.patch +Patch0008: 0008-Don-t-include-params.h-if-building-with-GCC-10.patch +Patch0009: 0009-Update-gcc-python-wrapper.c-for-Python-3.8.patch +Patch0010: 0010-Link-with-libpython3.8.so.patch +Patch0011: 0011-Add-PLUGIN_FINISH_PARSE_FUNCTION-support.patch +Patch0012: 0012-Add-get_location.patch +Patch0013: 0013-Add-main_input_filename.patch +Patch0014: 0014-Add-stub-for-types.patch +Patch0015: 0015-Add-current_function_decl.patch +Patch0016: 0016-Add-context.patch +Patch0017: 0017-Add-main_variant-for-types.patch +Patch0018: 0018-Add-print_declaration-support-besides-dump_generic_n.patch +Patch0019: 0019-Make-static-attribute-writtable.patch +Patch0020: 0020-Make-initial-attribute-writeable.patch +Patch0021: 0021-Make-public-attribute-writable.patch +Patch0022: 0022-Add-external-attribute.patch +Patch0023: 0023-Make-location-hasher-robust.patch +Patch0024: 0024-Add-PLUGIN_INCLUDE_FILE-callback.patch +Patch0025: 0025-Add-decl.attributes.patch +Patch0026: 0026-Add-referring-and-referer-to-variables.patch +Patch0027: 0027-Add-VarDecl.node-points-to-varpool-nodes.patch +Patch0028: 0028-Add-general-purpose-walk_tree.patch +Patch0029: 0029-Add-inline-attr-to-function-decl.patch + +# gcc version should be more than 6.5.1 +BuildRequires: gcc >= 6.5.1 +BuildRequires: gcc-plugin-devel >= 6.5.1 +BuildRequires: gcc-c++ >= 6.5.1 + +# Various python runtimes to build the plugin against: +BuildRequires: python2 +BuildRequires: python2-devel + +# "six" is used at buildtime: +BuildRequires: python-six + +# pygments is used when running the selftests: +BuildRequires: python-pygments + +# lxml is used when running the selftests: +BuildRequires: python-lxml + +Requires: gcc-plugin-devel >= 6.5.1 +Requires: python-libs + +%global gcc_plugins_dir %(gcc --print-file-name=plugin) + +%description +Plugins for embedding various versions of Python within GCC + +%prep +%autosetup -p1 + +%build +make PYTHON=python2 PYTHON_CONFIG=python2-config PLUGIN_DSO=python.so plugin print-gcc-version + +%install +mkdir -p %{buildroot}/usr/lib64/plugsched-gcc-python-plugin +mkdir -p %{buildroot}/%{gcc_plugins_dir} + +install -m 755 python.so %{buildroot}/usr/lib64/plugsched-gcc-python-plugin/python.so +install -m 755 gcc-c-api/libgcc-c-api.so \ + %{buildroot}/%{gcc_plugins_dir}/libgcc-c-api.so + +%files +/usr/lib64/plugsched-gcc-python-plugin/python.so +%{gcc_plugins_dir}/libgcc-c-api.so + +%dir +/usr/lib64/plugsched-gcc-python-plugin + +%changelog +* Wed Feb 9 2022 Yihao Wu 0.17-1.1 +- Simplify the spec file to build only on Python2 +- Add inline attr to function decl +- Add general purpose walk_tree +- Add VarDecl.node points to varpool nodes +- Add referring and referer to variables +- Add decl.attributes +- Add PLUGIN_INCLUDE_FILE callback +- Make location hasher robust +- Add external attribute +- Make public attribute writable +- Make initial attribute writeable +- Make static attribute writtable +- Add print_declaration support besides dump_generic_node +- Add main_variant for types +- Add context +- Add current_function_decl +- Add stub for types +- Add main_input_filename +- Add get_location +- Add PLUGIN_FINISH_PARSE_FUNCTION support +- Link with libpython3.8.so +- Update gcc-python-wrapper.c for Python 3.8 +- Don't include "params.h" if building with GCC 10 +- Build on Python 3.8 +- .travis.yml: add gcc-9 +- tests: exercise gcc.TypeDecl.original_type +- Added ability to get the result of DECL_ORIGINAL_TYPE +- gcc-python-pretty-printer: fix GCC 8.3 compatibility + +* Thu Jan 24 2019 David Malcolm - 0.17-1 +- This releases adds support for gcc 9 (along with continued support for + gcc 4.6, 4.7, 4.8, 4.9, 5, 6, 7, and 8). +- Unfortunately, the reference-count checker no longer works for gcc 7 + onwards, so it is disabled when embedded in those builds of gcc. +- Additionally, this release contains the following improvements: + the plugin can now be built in a separate build directory from the + source directory (thanks to Tom de Vries) +- gcc-with-cpychecker gained a --cpychecker-verbose option + +* Sat May 5 2018 David Malcolm - 0.16-1 +- This releases adds support for gcc 7 and gcc 8 (along with continued support for gcc 4.6, 4.7, 4.8, 4.9, 5 and 6). +- The upstream location for the plugin has moved from fedorahosted.org to https://github.com/davidmalcolm/gcc-python-plugin +- Additionally, this release contains the following improvements: + add gcc.RichLocation for GCC 6 onwards + gcc.Location + add caret, start, finish attributes for GCC 7 onwards + add gcc.Location.offset_column() method + +* Mon Feb 6 2012 David Malcolm - 0.9-1 +- 0.9 + +* Tue Jan 10 2012 David Malcolm - 0.8-1 +- 0.8 + +* Tue Aug 2 2011 David Malcolm - 0.6-1 +- 0.6 + +* Wed Jul 27 2011 David Malcolm - 0.5-1 +- 0.5 +- examples are now in an "examples" subdirectory + +* Tue Jul 26 2011 David Malcolm - 0.4-1 +- 0.4 +- add requirement on pygments +- run the upstream test suites during %%check + +* Mon Jul 25 2011 David Malcolm - 0.3-1 +- add requirements on python-six and python3-six +- add %%check section (empty for now) +- set PYTHON and PLUGIN_PYTHONPATH during each build; install support files +into build-specific directories below the gcc plugin dir +- add helper gcc-with-python scripts, with man pages +- package the license +- add example scripts +- add explicit BR on gmp-devel (rhbz#725569) + +* Tue May 24 2011 David Malcolm - 0.1-1 +- initial packaging -- Gitee