diff options
author | Erick Ochoa <erick.ochoa@theobroma-systems.com> | 2020-06-02 16:53:52 +0200 |
---|---|---|
committer | Erick Ochoa <erick.ochoa@theobroma-systems.com> | 2020-06-02 16:53:52 +0200 |
commit | b13fddcb84484838ab31e3bc29263a2da3197cd9 (patch) | |
tree | 6eb0fd153a06378abbccd6c6f7e22fe9f765016a | |
parent | 71e7fa841fc569af0d7fabf3303a26df84eefcc6 (diff) |
type walkererick/type-playground
-rw-r--r-- | gcc/Makefile.in | 2 | ||||
-rw-r--r-- | gcc/collect-types.c | 377 | ||||
-rw-r--r-- | gcc/collect-types.h | 2 | ||||
-rw-r--r-- | gcc/ipa-hello-world.c | 2 | ||||
-rw-r--r-- | gcc/ipa-type-collector.c | 21 | ||||
-rw-r--r-- | gcc/name-types.c | 1 | ||||
-rw-r--r-- | gcc/name-types.h | 4 | ||||
-rw-r--r-- | gcc/type-collector.c | 237 | ||||
-rw-r--r-- | gcc/type-collector.hpp | 49 | ||||
-rw-r--r-- | gcc/type-stringifier.hpp | 113 | ||||
-rw-r--r-- | gcc/type-walker.c | 402 | ||||
-rw-r--r-- | gcc/type-walker.hpp | 333 |
12 files changed, 821 insertions, 722 deletions
diff --git a/gcc/Makefile.in b/gcc/Makefile.in index a9c188e6e03..da6f7fb4f93 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1401,6 +1401,8 @@ OBJS = \ internal-fn.o \ ipa-hello-world.o \ ipa-type-collector.o \ + type-walker.o \ + type-collector.o \ compare-types.o \ collect-types.o \ name-types.o \ diff --git a/gcc/collect-types.c b/gcc/collect-types.c index 3ebd6ff975e..da66bb11fa2 100644 --- a/gcc/collect-types.c +++ b/gcc/collect-types.c @@ -30,324 +30,29 @@ #include "compare-types.h" #include "types-inlines.h" +#include "type-stringifier.hpp" #include "name-types.h" #include <set> #include "collect-types.h" -static bool filter_boring_types(const_tree type, ptrset_t &); - -static bool -filter_boring_types_wrapper(const_tree type, ptrset_t &types) -{ - gcc_assert(type); - const_tree inner_type = TREE_TYPE(type); - gcc_assert(inner_type); - return filter_boring_types(inner_type, types); -} - -static bool -filter_boring_types_array(const_tree type, ptrset_t &types) -{ - assert_is_type(type, ARRAY_TYPE); - return filter_boring_types_wrapper(type, types); -} - -static bool -filter_boring_types_reference(const_tree type, ptrset_t &types) -{ - assert_is_type(type, REFERENCE_TYPE); - return filter_boring_types_wrapper(type, types); -} - -static bool -filter_boring_types_pointer(const_tree type, ptrset_t &types) -{ - assert_is_type(type, POINTER_TYPE); - return filter_boring_types_wrapper(type, types); -} - -static bool -filter_boring_types_union_or_record(const_tree type, ptrset_t &types) -{ - const enum tree_code code = TREE_CODE(type); - const bool is_union = UNION_TYPE == code; - const bool is_qual_union = QUAL_UNION_TYPE == code; - const bool is_record = RECORD_TYPE == code; - const bool is_valid_input = is_union || is_qual_union || is_record; - gcc_assert(is_valid_input); - - bool is_interesting = is_record; - for (tree field = TYPE_FIELDS(type) ; field ; field = DECL_CHAIN(field)) - { - // TYPE_FIELDS contains the items contained in this type, each of which can be a FIELD_DECL, VAR_DECL, CONST_DECL, or TYPE_DECL - const_tree field_type = TREE_TYPE(field); - gcc_assert(field_type); - is_interesting |= filter_boring_types(field_type, types); - } - - return !is_interesting; -} - -static bool -filter_boring_types_record(const_tree type, ptrset_t &types) -{ - return filter_boring_types_union_or_record(type, types); -} - -static bool -filter_boring_types_unions(const_tree type, ptrset_t &types) -{ - return filter_boring_types_union_or_record(type, types); -} - -static bool -filter_boring_types_union(const_tree type, ptrset_t &types) -{ - assert_is_type(type, UNION_TYPE); - return filter_boring_types_unions(type, types); -} - -static bool -filter_boring_types_qual_union(const_tree type, ptrset_t &types) -{ - assert_is_type(type, QUAL_UNION_TYPE); - return filter_boring_types_unions(type, types); -} - -static bool -filter_boring_types_function_or_method(const_tree type, ptrset_t &types) -{ - const enum tree_code code = TREE_CODE(type); - const bool is_function = FUNCTION_TYPE == code; - const bool is_method = METHOD_TYPE == code; - const bool is_valid_input = is_function || is_method; - gcc_assert(is_valid_input); - - const_tree ret_type = TREE_TYPE(type); - gcc_assert(ret_type); - const bool retval_is_boring = filter_boring_types(ret_type, types); - //if (!retval_is_boring) return retval_is_boring; - - tree arg_node = TYPE_ARG_TYPES(type); - while (NULL_TREE != arg_node) - { - tree arg_node_type = TREE_VALUE(arg_node); - gcc_assert(arg_node_type); - const bool arg_is_boring = filter_boring_types(arg_node_type, types); - arg_node = TREE_CHAIN(arg_node); - //if (!arg_is_boring) return arg_is_boring; - } - - return true; -} - -static bool -filter_boring_types_function(const_tree type, ptrset_t &types) -{ - assert_is_type(type, FUNCTION_TYPE); - return filter_boring_types_function_or_method(type, types); -} - -static bool -filter_boring_types_method(const_tree type, ptrset_t &types) -{ - assert_is_type(type, METHOD_TYPE); - return filter_boring_types_function_or_method(type, types); -} - -static bool -filter_boring_types(const_tree type, ptrset_t &types) -{ - // boring types are those that do not point to - // a struct - gcc_assert(type); - - // Optimization to speed up the filter. - // Memoization - const bool seen_before = types.in_universe(type); - if (seen_before) - { - const bool in_points_to_record = types.in_points_to_record(type); - const bool in_complement = types.in_complement(type); - const bool _xor = in_points_to_record != in_complement; - gcc_assert(_xor); - return in_complement; - } - - - bool is_boring = true; - enum tree_code code = TREE_CODE(type); - switch (code) - { - case VOID_TYPE: - case INTEGER_TYPE: - case REAL_TYPE: - case FIXED_POINT_TYPE: - case COMPLEX_TYPE: - case ENUMERAL_TYPE: - case BOOLEAN_TYPE: - case OFFSET_TYPE: - is_boring = true; - break; - case ARRAY_TYPE: - is_boring = filter_boring_types_array(type, types); - break; - case RECORD_TYPE: - is_boring = filter_boring_types_record(type, types); - is_boring = false; - break; - case UNION_TYPE: - is_boring = filter_boring_types_union(type, types); - break; - case QUAL_UNION_TYPE: - is_boring = filter_boring_types_qual_union(type, types); - break; - case REFERENCE_TYPE: - is_boring = filter_boring_types_reference(type, types); - break; - case POINTER_TYPE: - is_boring = filter_boring_types_pointer(type, types); - break; - case FUNCTION_TYPE: - is_boring = filter_boring_types_function(type, types); - break; - case METHOD_TYPE: - is_boring = filter_boring_types_method(type, types); - break; - default: - log("tree_code: %s\n", get_tree_code_name(code)); - gcc_unreachable(); - break; - } - - // This should be one the two only times we call insert! - types.insert(type, !is_boring); - - return is_boring; -} - -static const unsigned filter_buffer_size = 1; -typedef bool (*filter_t)(const_tree, ptrset_t&); -const extern filter_t filter[filter_buffer_size] = -{ - filter_boring_types, -}; - -static void -collect_types_from_record_or_union_type(const_tree type, ptrset_t &types) -{ - gcc_assert(type); - const enum tree_code code = TREE_CODE(type); - const bool is_union = UNION_TYPE == code; - const bool is_record = RECORD_TYPE == code; - const bool is_qual_union = QUAL_UNION_TYPE == code; - const bool is_valid_input = is_record || is_union || is_qual_union; - gcc_assert(is_valid_input); - - for (tree field = TYPE_FIELDS(type) ; field ; field = DECL_CHAIN(field)) - { - const_tree field_type = TREE_TYPE(field); - gcc_assert(field_type); - collect_types(field_type, types); - } -} - -static void -collect_types_from_record_type(const_tree type, ptrset_t &types) -{ - assert_is_complete_type(type, RECORD_TYPE); - collect_types_from_record_or_union_type(type, types); -} - -static void -collect_types_from_union_type(const_tree type, ptrset_t &types) -{ - assert_is_complete_type(type, UNION_TYPE); - collect_types_from_record_or_union_type(type, types); -} - -static void -collect_types_from_wrapper_type(const_tree type, ptrset_t &types) -{ - gcc_assert(type); - //assert_is_complete(type); - const_tree inner_type = TREE_TYPE(type); - gcc_assert(inner_type); - collect_types(inner_type, types); -} - -static void -collect_types_from_pointer_type(const_tree type, ptrset_t &types) -{ - assert_is_type(type, POINTER_TYPE); - assert_is_complete(type); - collect_types_from_wrapper_type(type, types); -} - -static void -collect_types_from_reference_type(const_tree type, ptrset_t &types) -{ - assert_is_complete_type(type, REFERENCE_TYPE); - collect_types_from_wrapper_type(type, types); -} - -static void -collect_types_from_array_type(const_tree type, ptrset_t &types) -{ - assert_is_complete_type(type, ARRAY_TYPE); - collect_types_from_wrapper_type(type, types); -} - -static void -collect_types_from_function_or_method_type(const_tree type, ptrset_t &types) -{ - gcc_assert(type); - assert_is_complete(type); - const enum tree_code code = TREE_CODE(type); - const bool is_function = FUNCTION_TYPE == code; - const bool is_method = METHOD_TYPE == code; - const bool is_valid_input = is_function || is_method; - gcc_assert(is_valid_input); - - const_tree ret_type = TREE_TYPE(type); - gcc_assert(ret_type); - collect_types(ret_type, types); - - tree arg_node = TYPE_ARG_TYPES(type); - while (NULL_TREE != arg_node) - { - tree arg_node_type = TREE_VALUE(arg_node); - gcc_assert(arg_node_type); - collect_types(arg_node_type, types); - arg_node = TREE_CHAIN(arg_node); - } -} - -static void -collect_types_from_function_type(const_tree type, ptrset_t &types) -{ - assert_is_complete_type(type, FUNCTION_TYPE); - collect_types_from_function_or_method_type(type, types); -} - -static void -collect_types_from_method_type(const_tree type, ptrset_t &types) -{ - assert_is_complete_type(type, METHOD_TYPE); - collect_types_from_function_or_method_type(type, types); -} void points_to_record_sets_s::insert(const_tree type, bool in_points_to_record) { gcc_assert(type); this->universe.insert(type); + TypeStringifier stringifier; + std::string name = stringifier.stringify(type); + log("points_to_record %s type %s\n", in_points_to_record ? "t" : "f", name.c_str()); in_points_to_record ? this->points_to_record.insert(type) : this->complement.insert(type); // let's just double check... const bool in_points_to_set = this->in_points_to_record(type); const bool in_complement = this->in_complement(type); const bool _xor = in_points_to_set != in_complement; + if (!_xor) { + log("points_to_record %s type %s != %s %s\n", in_points_to_record ? "t" : "f", in_points_to_set ? "t" : "f", in_complement ? "t": "f", name.c_str()); + } gcc_assert(_xor); } @@ -375,71 +80,3 @@ points_to_record_sets_s::in_complement(const_tree type) const return seen_before; } -void -collect_types(const_tree type, ptrset_t &types) -{ - if (!type) return; - - // This should be the only case we call to find if - // we have seen the type before! - const bool in_set = types.in_universe(type); - // memoized. - if (in_set) return; - - // we should have filters here - // such that if we are processing a type - // which we know somehow that it is not a type we are interested - // then we just return immediately. - // maybe even add it to a set of blacklisted types so that we - // memoize and do things faster... - bool is_boring = false; - for (unsigned i = 0; i < filter_buffer_size; i++) - { - is_boring |= filter[i](type, types); - } - - const enum tree_code code = TREE_CODE(type); - switch (code) - { - case VOID_TYPE: - case INTEGER_TYPE: - case REAL_TYPE: - case FIXED_POINT_TYPE: - case COMPLEX_TYPE: - case ENUMERAL_TYPE: - case BOOLEAN_TYPE: - case OFFSET_TYPE: - // simple cases and we want to allow them - break; - case RECORD_TYPE: - collect_types_from_record_type(type, types); - break; - case POINTER_TYPE: - collect_types_from_pointer_type(type, types); - break; - case REFERENCE_TYPE: - collect_types_from_reference_type(type, types); - break; - case ARRAY_TYPE: - collect_types_from_array_type(type, types); - break; - case UNION_TYPE: - collect_types_from_union_type(type, types); - break; - case FUNCTION_TYPE: - collect_types_from_function_type(type, types); - break; - case METHOD_TYPE: - collect_types_from_method_type(type, types); - break; - case QUAL_UNION_TYPE: - case LANG_TYPE: - default: - log("%s\n", get_tree_code_name(code)); - gcc_unreachable(); - break; - } - - // This should be one the two only times we call insert! - types.insert(type, !is_boring); -} diff --git a/gcc/collect-types.h b/gcc/collect-types.h index c366b321443..1a6126f6a6d 100644 --- a/gcc/collect-types.h +++ b/gcc/collect-types.h @@ -18,5 +18,3 @@ struct points_to_record_sets_s { }; typedef struct points_to_record_sets_s ptrset_t; - -extern void collect_types(const_tree type, ptrset_t &ptrset_t); diff --git a/gcc/ipa-hello-world.c b/gcc/ipa-hello-world.c index c8eb7a0ae6a..6d31926eab1 100644 --- a/gcc/ipa-hello-world.c +++ b/gcc/ipa-hello-world.c @@ -35,6 +35,7 @@ #include "compare-types.h" #include "ipa-type-collector.h" #include "ipa-hello-world.h" +#include "type-collector.hpp" #include <map> #include <vector> @@ -1033,6 +1034,7 @@ static unsigned int iphw_execute() { ptrset_t types; + TypeCollector::ptrset = &types; collect_types(types); typemap eacalc; // Escape Analysis Calculation diff --git a/gcc/ipa-type-collector.c b/gcc/ipa-type-collector.c index 85dc71b60ed..9638913d1fe 100644 --- a/gcc/ipa-type-collector.c +++ b/gcc/ipa-type-collector.c @@ -37,8 +37,10 @@ #include "name-types.h" #include "ipa-type-collector.h" +#include "type-collector.hpp" //#define FUZZ_MODE 1 +static void collect_types(const_tree t); namespace type_playground { enum type_comparison_func_enum { @@ -128,7 +130,7 @@ collect_types_from_leaf_expr(const_tree expr, ptrset_t &types, const enum tree_c assert_is_type(expr, ex_code); const_tree type = TREE_TYPE(expr); gcc_assert(type); - collect_types(type, types); + collect_types(type); } static void @@ -285,7 +287,7 @@ collect_types_from_function_decl(const_tree expr, ptrset_t &types) const_tree decl_type = TREE_TYPE(expr); gcc_assert(decl_type); // This will collect return, arguments and decl_type itself - collect_types(decl_type, types); + collect_types(decl_type); } static void @@ -295,7 +297,7 @@ collect_types_from_expr(const_tree expr, ptrset_t &types) gcc_assert(expr); const_tree type = TREE_TYPE(expr); gcc_assert(type); - collect_types(type, types); + collect_types(type); const enum tree_code code = TREE_CODE(expr); switch (code) { @@ -567,7 +569,7 @@ collect_types_from_cnode_locals(cgraph_node *cnode, ptrset_t &types) { gcc_assert(var_decl); const_tree var_decl_type = TREE_TYPE(var_decl); - collect_types(var_decl_type, types); + collect_types(var_decl_type); } } @@ -586,7 +588,7 @@ collect_types_from_cnode_ssa_names(cgraph_node *cnode, ptrset_t &types) { gcc_assert(ssa_name); const_tree ssa_name_type = TREE_TYPE(ssa_name); - collect_types(ssa_name_type, types); + collect_types(ssa_name_type); } pop_cfun(); } @@ -799,6 +801,14 @@ collect_types(ptrset_t &types) sanity_check_ptr_xor_complement(types); } +static TypeCollector typeCollector; +ptrset_t *TypeCollector::ptrset = NULL; + +static void +collect_types(const_tree t) +{ + typeCollector.collect(t); +} static unsigned int iphw_execute() @@ -806,6 +816,7 @@ iphw_execute() //test_type_equality::run_tests(); //test_naming_types::run_tests(); ptrset_t types; + TypeCollector::ptrset = &types; collect_types(types); filter_out_types_in_set(types); compare_types_in_set(types); diff --git a/gcc/name-types.c b/gcc/name-types.c index 23c6a120456..fe8f6c5575b 100644 --- a/gcc/name-types.c +++ b/gcc/name-types.c @@ -33,6 +33,7 @@ #include <string> #include "name-types.h" +#include "type-walker.hpp" // Using std::string because it will manage memory for us // And we don't know whether the user will free the memory. diff --git a/gcc/name-types.h b/gcc/name-types.h index 538956fdd5d..b127bef17ac 100644 --- a/gcc/name-types.h +++ b/gcc/name-types.h @@ -5,7 +5,3 @@ const std::string type_to_string(const_tree type, const unsigned field_offset=0, const bool add_prelude=true); const std::string get_type_identifier(const_tree type); - -namespace test_naming_types { -void run_tests(); -}; diff --git a/gcc/type-collector.c b/gcc/type-collector.c new file mode 100644 index 00000000000..af8778b8554 --- /dev/null +++ b/gcc/type-collector.c @@ -0,0 +1,237 @@ +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "backend.h" +#include "tree.h" +#include "gimple-expr.h" +#include "predict.h" +#include "alloc-pool.h" +#include "tree-pass.h" +#include "cgraph.h" +#include "diagnostic.h" +#include "fold-const.h" +#include "gimple-fold.h" +#include "symbol-summary.h" +#include "tree-vrp.h" +#include "ipa-prop.h" +#include "tree-pretty-print.h" +#include "tree-inline.h" +#include "ipa-fnsummary.h" +#include "ipa-utils.h" +#include "tree-ssa-ccp.h" +#include "stringpool.h" +#include "attribs.h" +#include "tree-ssa-alias.h" +#include "tree-ssanames.h" +#include "gimple.h" +#include "cfg.h" +#include "gimple-iterator.h" +#include "gimple-ssa.h" + +#include "type-collector.hpp" + +void +TypeCollector::collect(const_tree t) +{ + const bool in_set = ptrset->in_universe(t); + // memoization... + if (in_set) return; + this->_points_to_record = false; + gcc_assert(ptrset && t); + gcc_assert(ptr.size() == 0); + walk(t); +} + +bool +TypeCollector::is_memoized(const_tree t) +{ + const bool in_set = ptrset->in_universe(t); + if (!in_set) return false; + + const bool points_to_record = ptrset->in_points_to_record(t); + for (auto i = ptr.begin(), e = ptr.end(); i != e; ++i) + { + i->second = true; + } + return true; +} + +void +TypeCollector::_walk_void_pre(const_tree t) +{ + ptr[t] = false; +} + +void +TypeCollector::_walk_void_post(const_tree t) +{ + _collect_simple(t); +} + +void +TypeCollector::_walk_integer_pre(const_tree t) +{ + ptr[t] = false; +} + +void +TypeCollector::_walk_integer_post(const_tree t) +{ + _collect_simple(t); +} + +void +TypeCollector::_walk_real_pre(const_tree t) +{ + ptr[t] = false; +} + +void +TypeCollector::_walk_real_post(const_tree t) +{ + _collect_simple(t); +} + +void +TypeCollector::_walk_fixed_point_pre(const_tree t) +{ + ptr[t] = false; +} + +void +TypeCollector::_walk_fixed_point_post(const_tree t) +{ + _collect_simple(t); +} + +void +TypeCollector::_walk_complex_pre(const_tree t) +{ + ptr[t] = false; +} + +void +TypeCollector::_walk_complex_post(const_tree t) +{ + _collect_simple(t); +} + +void +TypeCollector::_walk_enumeral_pre(const_tree t) +{ + ptr[t] = false; +} + +void +TypeCollector::_walk_enumeral_post(const_tree t) +{ + _collect_simple(t); +} + +void +TypeCollector::_walk_boolean_pre(const_tree t) +{ + ptr[t] = false; +} + +void +TypeCollector::_walk_boolean_post(const_tree t) +{ + _collect_simple(t); +} + +void +TypeCollector::_collect_simple(const_tree t) +{ + ptrset->insert(t, ptr[t]); + ptr.erase(t); +} + +void +TypeCollector::_walk_array_pre(const_tree t) +{ + ptr[t] = false; +} + +void +TypeCollector::_walk_array_post(const_tree t) +{ + _collect_simple(t); +} + +void +TypeCollector::_walk_pointer_pre(const_tree t) +{ + ptr[t] = false; +} + +void +TypeCollector::_walk_pointer_post(const_tree t) +{ + _collect_simple(t); +} + +void +TypeCollector::_walk_reference_pre(const_tree t) +{ + ptr[t] = false; +} + +void +TypeCollector::_walk_reference_post(const_tree t) +{ + _collect_simple(t); +} + +void +TypeCollector::_walk_record_post(const_tree t) +{ + // All in ptr point to record + for (auto i = ptr.begin(), e = ptr.end(); i != e; ++i) + { + i->second = true; + } + _collect_simple(t); +} + +void +TypeCollector::_walk_record_pre(const_tree t) +{ + ptr[t] = false; +} + +void +TypeCollector::_walk_union_pre(const_tree t) +{ + ptr[t] = false; +} + +void +TypeCollector::_walk_union_post(const_tree t) +{ + _collect_simple(t); +} + +void +TypeCollector::_walk_function_post(const_tree t) +{ + _collect_simple(t); +} + +void +TypeCollector::_walk_function_pre(const_tree t) +{ + ptr[t] = false; +} + +void +TypeCollector::_walk_method_post(const_tree t) +{ + _collect_simple(t); +} + +void +TypeCollector::_walk_method_pre(const_tree t) +{ + ptr[t] = false; +} diff --git a/gcc/type-collector.hpp b/gcc/type-collector.hpp new file mode 100644 index 00000000000..425b54c5062 --- /dev/null +++ b/gcc/type-collector.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include "type-walker.hpp" +#include "collect-types.h" +#include <map> + +class TypeCollector : public TypeWalker { +public: + static ptrset_t* ptrset; +private: + bool _points_to_record; + std::map<const_tree, bool> ptr; + + void _collect_simple(const_tree t); + virtual bool is_memoized(const_tree t); + + virtual void _walk_void_pre(const_tree t); + virtual void _walk_void_post(const_tree t); + virtual void _walk_integer_pre(const_tree t); + virtual void _walk_integer_post(const_tree t); + virtual void _walk_real_pre(const_tree t); + virtual void _walk_real_post(const_tree t); + virtual void _walk_fixed_point_pre(const_tree t); + virtual void _walk_fixed_point_post(const_tree t); + virtual void _walk_complex_pre(const_tree t); + virtual void _walk_complex_post(const_tree t); + virtual void _walk_enumeral_pre(const_tree t); + virtual void _walk_enumeral_post(const_tree t); + virtual void _walk_boolean_pre(const_tree t); + virtual void _walk_boolean_post(const_tree t); + virtual void _walk_array_pre(const_tree t); + virtual void _walk_array_post(const_tree t); + virtual void _walk_pointer_pre(const_tree t); + virtual void _walk_pointer_post(const_tree t); + virtual void _walk_reference_pre(const_tree t); + virtual void _walk_reference_post(const_tree t); + virtual void _walk_record_pre(const_tree t); + virtual void _walk_record_post(const_tree t); + virtual void _walk_union_pre(const_tree t); + virtual void _walk_union_post(const_tree t); + virtual void _walk_function_pre(const_tree t); + virtual void _walk_function_post(const_tree t); + virtual void _walk_method_pre(const_tree t); + virtual void _walk_method_post(const_tree t); +public: + void collect(const_tree t); + TypeCollector() : _points_to_record(false) {}; +}; + diff --git a/gcc/type-stringifier.hpp b/gcc/type-stringifier.hpp index 33f5cb359cb..98e0546b8d7 100644 --- a/gcc/type-stringifier.hpp +++ b/gcc/type-stringifier.hpp @@ -1,6 +1,7 @@ #pragma once #include "type-walker.hpp" +#include <string> class TypeStringifier : public TypeWalker { @@ -8,10 +9,11 @@ private: std::string _stringification; static std::string get_type_identifier(const_tree t); + static std::string get_field_identifier(const_tree t); - void _stringifiy_simple(const_tree t); - void _stringifiy_aggregate_pre(const_tree t); - void _stringifiy_aggregate_post(const_tree t); + void _stringify_simple(const_tree t); + void _stringify_aggregate_pre(const_tree t); + void _stringify_aggregate_post(const_tree t); void _stringify_fm_pre(const_tree t); void _stringify_fm_post(const_tree t); @@ -29,109 +31,119 @@ private: virtual void _walk_record_post(const_tree t); virtual void _walk_union_pre(const_tree t); virtual void _walk_union_post(const_tree t); + virtual void _walk_field_post(const_tree t); + virtual void _walk_return_pre(const_tree t); + virtual void _walk_return_post(const_tree t); + virtual void _walk_args_pre(const_tree t); + virtual void _walk_args_post(const_tree t); + virtual void _walk_arg_post(const_tree t); virtual void _walk_method_pre(const_tree t); virtual void _walk_method_post(const_tree t); virtual void _walk_function_pre(const_tree t); virtual void _walk_function_post(const_tree t); public: - std::string stringifiy(const_tree t); + std::string stringify(const_tree t); TypeStringifier() {}; }; std::string TypeStringifier::stringify(const_tree t) { + _stringification.clear(); gcc_assert(t); walk(t); + return _stringification; } -virtual void +void TypeStringifier::_walk_void_pre(const_tree t) { - _stringifiy_simple(t); + _stringify_simple(t); } -virtual void +void TypeStringifier::_walk_integer_pre(const_tree t) { - _stringifiy_simple(t); + _stringify_simple(t); } -virtual void +void TypeStringifier::_walk_real_pre(const_tree t) { - _stringifiy_simple(t); + _stringify_simple(t); } -virtual void +void TypeStringifier::_walk_fixed_point_pre(const_tree t) { - _stringifiy_simple(t); + _stringify_simple(t); } -virtual void +void TypeStringifier::_walk_complex_pre(const_tree t) { - _stringifiy_simple(t); + _stringify_simple(t); } -virtual void +void TypeStringifier::_walk_offset_pre(const_tree t) { - _stringifiy_simple(t); + _stringify_simple(t); } -virtual void +void TypeStringifier::_walk_boolean_pre(const_tree t) { - _stringifiy_simple(t); + _stringify_simple(t); } void -TypeStringifier::_stringifiy_simple(const_tree t) +TypeStringifier::_stringify_simple(const_tree t) { gcc_assert(t); const enum tree_code code = TREE_CODE(t); this->_stringification += std::string(get_tree_code_name(code)); } -virtual void +void TypeStringifier::_walk_pointer_post(const_tree t) { this->_stringification += std::string("*"); } -virtual void +void TypeStringifier::_walk_array_post(const_tree t) { this->_stringification += std::string("[]"); } -virtual void +void TypeStringifier::_walk_reference_post(const_tree t) { this->_stringification += std::string("&"); } -virtual void +void TypeStringifier::_walk_union_pre(const_tree t) { + this->_stringification += std::string(" union "); _stringify_aggregate_pre(t); } -virtual void +void TypeStringifier::_walk_union_post(const_tree t) { _stringify_aggregate_post(t); } -virtual void +void TypeStringifier::_walk_record_pre(const_tree t) { + this->_stringification += std::string(" record "); _stringify_aggregate_pre(t); } -virtual void +void TypeStringifier::_walk_record_post(const_tree t) { _stringify_aggregate_post(t); @@ -150,6 +162,12 @@ TypeStringifier::_stringify_aggregate_post(const_tree t) } void +TypeStringifier::_walk_field_post(const_tree t) +{ + this->_stringification += std::string(" ") + TypeStringifier::get_field_identifier(t) + std::string(";"); +} + +void TypeStringifier::_walk_method_pre(const_tree t) { _stringify_fm_pre(t); @@ -176,7 +194,6 @@ TypeStringifier::_walk_function_post(const_tree t) void TypeStringifier::_stringify_fm_pre(const_tree t) { - this->_stringification += std::string("function { "); } @@ -186,7 +203,37 @@ TypeStringifier::_stringify_fm_post(const_tree t) this->_stringification += std::string("}"); } -static std::string +void +TypeStringifier::_walk_return_pre(const_tree t) +{ + this->_stringification += std::string("("); +} + +void +TypeStringifier::_walk_return_post(const_tree t) +{ + this->_stringification += std::string(")"); +} + +void +TypeStringifier::_walk_args_pre(const_tree t) +{ + this->_stringification += std::string("("); +} + +void +TypeStringifier::_walk_args_post(const_tree t) +{ + this->_stringification += std::string(")"); +} + +void +TypeStringifier::_walk_arg_post(const_tree t) +{ + this->_stringification += std::string(", "); +} + +std::string TypeStringifier::get_type_identifier(const_tree t) { tree name = TYPE_NAME(t); @@ -201,3 +248,13 @@ TypeStringifier::get_type_identifier(const_tree t) return std::string(identifier_ptr); } +std::string +TypeStringifier::get_field_identifier(const_tree t) +{ + assert_is_type(t, FIELD_DECL); + const_tree decl_name = DECL_NAME(t); + if (!decl_name) return std::string(""); + + const char* identifier = IDENTIFIER_POINTER(decl_name); + return std::string(identifier); +} diff --git a/gcc/type-walker.c b/gcc/type-walker.c new file mode 100644 index 00000000000..df672d8bdf0 --- /dev/null +++ b/gcc/type-walker.c @@ -0,0 +1,402 @@ +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "backend.h" +#include "tree.h" +#include "gimple-expr.h" +#include "predict.h" +#include "alloc-pool.h" +#include "tree-pass.h" +#include "cgraph.h" +#include "diagnostic.h" +#include "fold-const.h" +#include "gimple-fold.h" +#include "symbol-summary.h" +#include "tree-vrp.h" +#include "ipa-prop.h" +#include "tree-pretty-print.h" +#include "tree-inline.h" +#include "ipa-fnsummary.h" +#include "ipa-utils.h" +#include "tree-ssa-ccp.h" +#include "stringpool.h" +#include "attribs.h" +#include "tree-ssa-alias.h" +#include "tree-ssanames.h" +#include "gimple.h" +#include "cfg.h" +#include "gimple-iterator.h" +#include "gimple-ssa.h" + +#include "type-walker.hpp" +#include "types-inlines.h" + +void +TypeWalker::walk(const_tree t) +{ + gcc_assert(t); + this->tset.clear(); + this->_walk(t, this->tset); +} + +void +TypeWalker::_walk(const_tree type, tset_t &tset) +{ + gcc_assert(type); + // Have we encountered this type before? If so, we are likely + // recurring... + const bool in_set = tset.find(type) != tset.end(); + if (in_set) return; + + const bool _is_memoized = is_memoized(type); + if (_is_memoized) return; + + tset.insert(type); + const enum tree_code code = TREE_CODE(type); + switch (code) + { + case VOID_TYPE: + this->walk_void(type, tset); + break; + case INTEGER_TYPE: + this->walk_integer(type, tset); + break; + case REAL_TYPE: + this->walk_real(type, tset); + break; + case FIXED_POINT_TYPE: + this->walk_fixed_point(type, tset); + break; + case COMPLEX_TYPE: + this->walk_complex(type, tset); + break; + case ENUMERAL_TYPE: + this->walk_enumeral(type, tset); + break; + case BOOLEAN_TYPE: + this->walk_boolean(type, tset); + break; + case OFFSET_TYPE: + this->walk_offset(type, tset); + break; + case RECORD_TYPE: + this->walk_record(type, tset); + break; + case POINTER_TYPE: + this->walk_pointer(type, tset); + break; + case REFERENCE_TYPE: + this->walk_reference(type, tset); + break; + case ARRAY_TYPE: + this->walk_array(type, tset); + break; + case UNION_TYPE: + this->walk_union(type, tset); + break; + case FUNCTION_TYPE: + this->walk_function(type, tset); + break; + case METHOD_TYPE: + this->walk_method(type, tset); + break; + case QUAL_UNION_TYPE: + case LANG_TYPE: + default: + gcc_unreachable(); + break; + } + + tset.erase(type); +} + +void +TypeWalker::walk_void(const_tree t, tset_t &tset) +{ + assert_is_type(t, VOID_TYPE); + _walk_void_pre(t); + _walk_void(t, tset); + _walk_void_post(t); +} + +void +TypeWalker::_walk_void(const_tree t, tset_t &tset) {}; + +void +TypeWalker::walk_integer(const_tree t, tset_t &tset) +{ + assert_is_type(t, INTEGER_TYPE); + _walk_integer_pre(t); + _walk_integer(t, tset); + _walk_integer_post(t); +} + +void +TypeWalker::_walk_integer(const_tree t, tset_t &tset) {}; + +void +TypeWalker::walk_real(const_tree t, tset_t &tset) +{ + assert_is_type(t, REAL_TYPE); + _walk_real_pre(t); + _walk_real(t, tset); + _walk_real_post(t); +} + +void +TypeWalker::_walk_real(const_tree t, tset_t &tset) {}; + +void +TypeWalker::walk_boolean(const_tree t, tset_t &tset) +{ + assert_is_type(t, BOOLEAN_TYPE); + _walk_boolean_pre(t); + _walk_boolean(t, tset); + _walk_boolean_post(t); +} + +void +TypeWalker::_walk_boolean(const_tree t, tset_t &tset) {}; + +void +TypeWalker::walk_offset(const_tree t, tset_t &tset) +{ + assert_is_type(t, OFFSET_TYPE); + _walk_offset_pre(t); + _walk_offset(t, tset); + _walk_offset_post(t); +} + +void +TypeWalker::_walk_offset(const_tree t, tset_t &tset) {}; + +void +TypeWalker::walk_fixed_point(const_tree t, tset_t &tset) +{ + assert_is_type(t, FIXED_POINT_TYPE); + _walk_fixed_point_pre(t); + _walk_fixed_point(t, tset); + _walk_fixed_point_post(t); +} + +void +TypeWalker::_walk_fixed_point(const_tree t, tset_t &tset) {}; + +void +TypeWalker::walk_complex(const_tree t, tset_t &tset) +{ + assert_is_type(t, COMPLEX_TYPE); + _walk_complex_pre(t); + _walk_complex(t, tset); + _walk_complex_post(t); +} + +void +TypeWalker::_walk_complex(const_tree t, tset_t &tset) {}; + +void +TypeWalker::walk_enumeral(const_tree t, tset_t &tset) +{ + assert_is_type(t, ENUMERAL_TYPE); + _walk_enumeral_pre(t); + _walk_enumeral(t, tset); + _walk_enumeral_post(t); +} + +void +TypeWalker::_walk_enumeral(const_tree t, tset_t &tset) {}; + +void +TypeWalker::walk_pointer(const_tree t, tset_t &tset) +{ + assert_is_type(t, POINTER_TYPE); + _walk_pointer_pre(t); + _walk_pointer(t, tset); + _walk_pointer_post(t); +} + +void +TypeWalker::_walk_pointer(const_tree t, tset_t &tset) +{ + _walk_wrapper(t, tset); +} + +void +TypeWalker::walk_reference(const_tree t, tset_t &tset) +{ + assert_is_type(t, REFERENCE_TYPE); + _walk_reference_pre(t); + _walk_reference(t, tset); + _walk_reference_post(t); +} + +void +TypeWalker::_walk_reference(const_tree t, tset_t &tset) +{ + _walk_wrapper(t, tset); +} + +void +TypeWalker::walk_array(const_tree t, tset_t &tset) +{ + assert_is_type(t, ARRAY_TYPE); + _walk_array_pre(t); + _walk_array(t, tset); + _walk_array_post(t); +} + +void +TypeWalker::_walk_array(const_tree t, tset_t &tset) +{ + _walk_wrapper(t, tset); +} + +void +TypeWalker::_walk_wrapper(const_tree t, tset_t &tset) +{ + const_tree inner_type = TREE_TYPE(t); + gcc_assert(inner_type); + _walk(inner_type, tset); +} + +void +TypeWalker::walk_record(const_tree t, tset_t &tset) +{ + assert_is_type(t, RECORD_TYPE); + _walk_record_pre(t); + _walk_record(t, tset); + _walk_record_post(t); +} + +void +TypeWalker::_walk_record(const_tree t, tset_t &tset) +{ + _walk_record_or_union(t, tset); +} + +void +TypeWalker::walk_union(const_tree t, tset_t &tset) +{ + assert_is_type(t, UNION_TYPE); + _walk_union_pre(t); + _walk_union(t, tset); + _walk_union_post(t); +} + +void +TypeWalker::_walk_union(const_tree t, tset_t &tset) +{ + _walk_record_or_union(t, tset); +} + +void +TypeWalker::_walk_record_or_union(const_tree t, tset_t &tset) +{ + for (tree field = TYPE_FIELDS(t); field; field = DECL_CHAIN(field)) + { + gcc_assert(field); + walk_field(field, tset); + } +} + +void +TypeWalker::walk_field(const_tree t, tset_t &tset) +{ + _walk_field_pre(t); + _walk_field(t, tset); + _walk_field_post(t); +} + +void +TypeWalker::_walk_field(const_tree t, tset_t &tset) +{ + const_tree inner_type = TREE_TYPE(t); + gcc_assert(inner_type); + _walk(inner_type, tset); +} + +void +TypeWalker::walk_function(const_tree t, tset_t &tset) +{ + assert_is_type(t, FUNCTION_TYPE); + _walk_function_pre(t); + _walk_function(t, tset); + _walk_function_post(t); +} + +void +TypeWalker::_walk_function(const_tree t, tset_t &tset) +{ + _walk_function_or_method(t, tset); +} + +void +TypeWalker::walk_method(const_tree t, tset_t &tset) +{ + assert_is_type(t, METHOD_TYPE); + _walk_method_pre(t); + _walk_method(t, tset); + _walk_method_post(t); +} + +void +TypeWalker::_walk_method(const_tree t, tset_t &tset) +{ + _walk_function_or_method(t, tset); +} + +void +TypeWalker::_walk_function_or_method(const_tree t, tset_t &tset) +{ + const_tree ret_type = TREE_TYPE(t); + walk_return(ret_type, tset); + walk_args(t, tset); +} + +void +TypeWalker::walk_return(const_tree t, tset_t &tset) +{ + _walk_return_pre(t); + _walk_return(t, tset); + _walk_return_post(t); +} + +void +TypeWalker::_walk_return(const_tree t, tset_t &tset) +{ + _walk(t, tset); +} + +void +TypeWalker::walk_args(const_tree t, tset_t &tset) +{ + _walk_args_pre(t); + _walk_args(t, tset); + _walk_args_post(t); +} + +void +TypeWalker::_walk_args(const_tree t, tset_t &tset) +{ + assert_is_type(t, FUNCTION_TYPE); + for (tree arg_node = TYPE_ARG_TYPES(t); NULL_TREE != arg_node; arg_node = TREE_CHAIN(arg_node)) + { + tree arg_node_type = TREE_VALUE(arg_node); + gcc_assert(arg_node_type); + walk_arg(arg_node_type, tset); + } +} + +void +TypeWalker::walk_arg(const_tree t, tset_t &tset) +{ + _walk_arg_pre(t); + _walk_arg(t, tset); + _walk_arg_post(t); +} + +void +TypeWalker::_walk_arg(const_tree t, tset_t &tset) +{ + _walk(t, tset); +} diff --git a/gcc/type-walker.hpp b/gcc/type-walker.hpp index df09fcdb2b0..0f775d170e8 100644 --- a/gcc/type-walker.hpp +++ b/gcc/type-walker.hpp @@ -1,17 +1,18 @@ #pragma once -#include "types-inlines.h" #include <set> class TypeWalker { -private: +protected: typedef std::set<const_tree> tset_t; +private: tset_t tset; void _walk(const_tree t, tset_t &tset); void _walk_wrapper(const_tree t, tset_t &tset); void _walk_record_or_union(const_tree t, tset_t &tset); void _walk_function_or_method(const_tree t, tset_t &tset); + virtual bool is_memoized(const_tree t) { return false; }; virtual void _walk_void_pre(const_tree t) {}; void walk_void(const_tree t, tset_t &tset); @@ -30,7 +31,7 @@ private: void _walk_fixed_point(const_tree t, tset_t &tset); virtual void _walk_fixed_point_post(const_tree t) {}; virtual void _walk_complex_pre(const_tree t) {}; - void _walk_complex(const_tree t, tset &tset); + void _walk_complex(const_tree t, tset_t &tset); void walk_complex(const_tree t, tset_t &tset); virtual void _walk_complex_post(const_tree t) {}; virtual void _walk_enumeral_pre(const_tree t) {}; @@ -65,6 +66,22 @@ private: void walk_union(const_tree t, tset_t &tset); void _walk_union(const_tree t, tset_t &tset); virtual void _walk_union_post(const_tree t) {}; + virtual void _walk_field_pre(const_tree) {}; + void walk_field(const_tree t, tset_t &tset); + void _walk_field(const_tree t, tset_t &tset); + virtual void _walk_field_post(const_tree t) {}; + virtual void _walk_return_pre(const_tree t) {}; + void walk_return(const_tree, tset_t &tset); + void _walk_return(const_tree, tset_t &tset); + virtual void _walk_return_post(const_tree t) {}; + virtual void _walk_args_pre(const_tree t) {}; + void walk_args(const_tree t, tset_t &tset); + void _walk_args(const_tree t, tset_t &tset); + virtual void _walk_args_post(const_tree t) {}; + virtual void _walk_arg_pre(const_tree t) {}; + void walk_arg(const_tree t, tset_t &tset); + void _walk_arg(const_tree t, tset_t &tset); + virtual void _walk_arg_post(const_tree t) {}; virtual void _walk_function_pre(const_tree t) {}; void walk_function(const_tree t, tset_t &tset); void _walk_function(const_tree t, tset_t &tset); @@ -78,313 +95,3 @@ public: TypeWalker() {}; }; -void -TypeWalker::walk(const_tree t) -{ - gcc_assert(t); - this->tset.clear(); - this->_walk(t, this->tset); -} - -void -TypeWalker::_walk(const_tree type, tset_t &tset) -{ - gcc_assert(type); - // Have we encountered this type before? If so, we are likely - // recurring... - const bool in_set = tset.find(type) != tset.end(); - if (in_set) return; - - tset.insert(type); - const enum tree_code code = TREE_CODE(type); - switch (code) - { - case VOID_TYPE: - this->walk_void(type, tset); - break; - case INTEGER_TYPE: - this->walk_integer(type, tset); - break; - case REAL_TYPE: - this->walk_real(type, tset); - break; - case FIXED_POINT_TYPE: - this->walk_fixed_point(type, tset); - break; - case COMPLEX_TYPE: - this->walk_complex(type, tset); - break; - case ENUMERAL_TYPE: - this->walk_enumeral(type, tset); - break; - case BOOLEAN_TYPE: - this->walk_boolean(type, tset); - break; - case OFFSET_TYPE: - this->walk_offset(type, tset); - break; - case RECORD_TYPE: - this->walk_record(type, tset); - break; - case POINTER_TYPE: - this->walk_pointer(type, tset); - break; - case REFERENCE_TYPE: - this->walk_reference(type, tset); - break; - case ARRAY_TYPE: - this->walk_array(type, tset); - break; - case UNION_TYPE: - this->walk_union(type, tset); - break; - case FUNCTION_TYPE: - this->walk_function(type, tset); - break; - case METHOD_TYPE: - this->walk_method(type, tset); - break; - case QUAL_UNION_TYPE: - case LANG_TYPE: - default: - gcc_unreachable(); - break; - } - - tset.clear(type); -} - -void -TypeWalker::walk_void(const_tree t, tset_t &tset) -{ - assert_is_type(t, VOID_TYPE); - _walk_void_pre(t); - _walk_void(t, tset); - _walk_void_post(t); -} - -void -TypeWalker::_walk_void(const_tree t, tset_t &tset) {}; - -void -TypeWalker::walk_integer(const_tree t, tset_t &tset) -{ - assert_is_type(t, INTEGER_TYPE); - _walk_integer_pre(t); - _walk_integer(t, tset); - _walk_integer_post(t); -} - -void -TypeWalker::_walk_integer(const_tree t, tset_t &tset) {}; - -void -TypeWalker::walk_real(const_tree t, tset_t &tset) -{ - assert_is_type(t, REAL_TYPE); - _walk_real_pre(t); - _walk_real(t, tset); - _walk_real_post(t); -} - -void -TypeWalker::_walk_real(const_tree t, tset_t &tset) {}; - -void -TypeWalker::walk_boolean(const_tree t, tset_t &tset) -{ - assert_is_type(t, BOOLEAN_TYPE); - _walk_boolean_pre(t); - _walk_boolean(t, tset); - _walk_boolean_post(t); -} - -void -TypeWalker::_walk_boolean(const_tree t, tset &tset) {}; - -void -TypeWalker::walk_offset(const_tree t, tset_t &tset) -{ - assert_is_type(t, OFFSET_TYPE); - _walk_offset_pre(t); - _walk_offset(t, tset); - _walk_offset_post(t); -} - -void -TypeWalker::_walk_offset(const_tree t, tset_t &tset) {}; - -void -TypeWalker::walk_fixed_point(const_tree t, tset_t &tset) -{ - assert_is_type(t, FIXED_POINT); - _walk_fixed_point_pre(t); - _walk_fixed_point(t, tset); - _walk_fixed_point_post(t); -} - -void -TypeWalker::_walk_fixed_point(const_tree t, tset_t &tset) {}; - -void -TypeWalker::walk_complex(const_tree t, tset_t &tset) -{ - assert_is_type(t, COMPLEX_TYPE); - _walk_complex_pre(t); - _walk_complex(t, tset); - _walk_complex_post(t); -} - -void -TypeWalker::_walk_complex(const_tree t, tset_t &tset) {}; - -void -TypeWalker::walk_enumeral(const_tree t, tset_t &tset) -{ - assert_is_type(t, ENUMERAL_TYPE); - _walk_enumeral_pre(t); - _walk_enumeral(t, tset); - _walk_enumeral_post(t); -} - -void -TypeWalker::_walk_enumeral(const_tree t, tset_t &tset) {}; - -void -TypeWalker::walk_pointer(const_tree t, tset_t &tset) -{ - assert_is_type(t, POINTER_TYPE); - _walk_pointer_pre(t); - _walk_pointer(t, tset); - _walk_pointer_post(t); -} - -void -TypeWalker::_walk_pointer(const_tree t, tset_t &tset) -{ - _walk_wrapper(t, tset); -} - -void -TypeWalker::walk_reference(const_tree t, tset_t &tset) -{ - assert_is_type(t, REFERENCE_TYPE); - _walk_reference_pre(t); - _walk_reference(t, tset); - _walk_reference_post(t); -} - -void -TypeWalker::_walk_reference(const_tree t, tset_t &tset) -{ - _walk_wrapper(t, tset); -} - -void -TypeWalker::walk_array(const_tree t, tset_t &tset) -{ - assert_is_type(t, ARRAY_TYPE); - _walk_array_pre(t); - _walk_array(t, tset); - _walk_array_post(t); -} - -void -TypeWalker::_walk_array(const_tree t, tset_t &tset) -{ - _walk_wrapper(t, tset); -} - -void -TypeWalker::_walk_wrapper(const_tree t, tset_t &tset) -{ - const_tree inner_type = TREE_TYPE(t); - gcc_assert(inner_type); - _walk(inner_type, tset); -} - -void -TypeWalker::walk_record(const_tree t, tset_t &tset) -{ - assert_is_type(t, RECORD_TYPE); - _walk_record_pre(t); - _walk_record(t, tset); - _walk_record_post(t); -} - -void -TypeWalker::_walk_record(const_tree t, tset_t &tset) -{ - _walk_record_or_union(t, tset); -} - -void -TypeWalker::walk_union(const_tree t, tset_t &tset) -{ - assert_is_type(t, UNION_TYPE); - _walk_union_pre(t); - _walk_union(t, tset); - _walk_union_post(t); -} - -void -TypeWalker::walk_union(const_tree t, tset_t &tset) -{ - _walk_record_or_union(t, tset); -} - -void -TypeWalker::_walk_record_or_union(const_tree t, tset_t &tset) -{ - for (tree field = TYPE_FIELDS(t); field; field = DECL_CHAIN(field)) - { - const_tree field_type = TREE_TYPE(field); - gcc_assert(field_type); - _walk(field_type, tset); - } -} - -void -TypeWalker::walk_function(const_tree t, tset_t &tset) -{ - assert_is_type(t, FUNCTION_TYPE); - _walk_function_pre(t); - _walk_function(t, tset); - _walk_union_post(t); -} - -void -TypeWalker::_walk_function(const_tree t, tset_t &tset) -{ - _walk_function_or_method(t, tset); -} - -void -TypeWalker::walk_method(const_tree t, tset_t &tset) -{ - assert_is_type(t, METHOD_TYPE); - _walk_method_pre(t); - _walk_method(t, tset); - _walk_method_post(t); -} - -void -TypeWalker::_walk_method(const_tree t, tset_t &tset) -{ - _walk_function_or_method(t, tset); -} - -void -TypeWalker::_walk_function_or_method(const_tree t, tset_t &tset) -{ - const_tree ret_type = TREE_TYPE(t); - gcc_assert(ret_type); - _walk(ret_type, tset); - - for (tree arg_node = TYPE_ARG_TYPES(t); NULL_TREE != arg_node; arg_node = TREE_CHAIN(arg_node)) - { - tree arg_node_type = TREE_VALUE(arg_node); - gcc_assert(arg_node_type); - _walk(arg_node_type); - } -} |