diff options
author | Erick Ochoa <erick.ochoa@theobroma-systems.com> | 2020-06-04 16:56:18 +0200 |
---|---|---|
committer | Erick Ochoa <erick.ochoa@theobroma-systems.com> | 2020-06-04 16:56:18 +0200 |
commit | 1c721a6592240ec17c190daf0f5897ce6f3046c8 (patch) | |
tree | e81deba6896d8e73c5b18fd3cf500c0daddaf60c | |
parent | 2da29e3b3af58440a91bcad0c12585d5f1b9bd4c (diff) | |
parent | b49aa30869c09910acb6c6e83f37b7fec15b25c7 (diff) |
Merge branch 'erick/type-escape-analysis-refactor' into common/ipa-str-reorg
-rw-r--r-- | gcc/Makefile.in | 12 | ||||
-rw-r--r-- | gcc/collect-types.c | 4 | ||||
-rw-r--r-- | gcc/common.opt | 4 | ||||
-rw-r--r-- | gcc/compare-types.c | 467 | ||||
-rw-r--r-- | gcc/compare-types.h | 18 | ||||
-rw-r--r-- | gcc/expr-collector.c | 2 | ||||
-rw-r--r-- | gcc/expr-collector.hpp | 6 | ||||
-rw-r--r-- | gcc/expr-escaper.c | 52 | ||||
-rw-r--r-- | gcc/expr-escaper.hpp | 24 | ||||
-rw-r--r-- | gcc/expr-walker.c | 32 | ||||
-rw-r--r-- | gcc/expr-walker.hpp | 3 | ||||
-rw-r--r-- | gcc/gimple-collector.c | 116 | ||||
-rw-r--r-- | gcc/gimple-collector.hpp | 20 | ||||
-rw-r--r-- | gcc/gimple-escaper.c | 143 | ||||
-rw-r--r-- | gcc/gimple-escaper.hpp | 22 | ||||
-rw-r--r-- | gcc/gimple-walker.c | 218 | ||||
-rw-r--r-- | gcc/gimple-walker.hpp | 34 | ||||
-rw-r--r-- | gcc/ipa-prototype.c | 490 | ||||
-rw-r--r-- | gcc/ipa-type-collector.c | 594 | ||||
-rw-r--r-- | gcc/ipa-type-collector.h | 5 | ||||
-rw-r--r-- | gcc/name-types.c | 421 | ||||
-rw-r--r-- | gcc/name-types.h | 7 | ||||
-rw-r--r-- | gcc/passes.def | 1 | ||||
-rw-r--r-- | gcc/tree-pass.h | 1 | ||||
-rw-r--r-- | gcc/type-collector.c | 37 | ||||
-rw-r--r-- | gcc/type-collector.hpp | 6 | ||||
-rw-r--r-- | gcc/type-escaper.c | 121 | ||||
-rw-r--r-- | gcc/type-escaper.hpp | 95 | ||||
-rw-r--r-- | gcc/type-walker.hpp | 8 |
29 files changed, 836 insertions, 2127 deletions
diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 50cc85d4edc..f6333d1b3cc 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1410,15 +1410,17 @@ OBJS = \ ipa-type-escape-analysis.o \ ipa-hello-world.o \ ipa-prototype.o \ - ipa-type-collector.o \ - expr-walker.o \ - expr-collector.o \ type-walker.o \ + expr-walker.o \ + gimple-walker.o \ type-collector.o \ + expr-collector.o \ + gimple-collector.o \ + type-escaper.o \ + expr-escaper.o \ + gimple-escaper.o \ type-stringifier.o \ - compare-types.o \ collect-types.o \ - name-types.o \ ipa-cp.o \ ipa-sra.o \ ipa-devirt.o \ diff --git a/gcc/collect-types.c b/gcc/collect-types.c index 77257a8b8e0..b3febdd57d7 100644 --- a/gcc/collect-types.c +++ b/gcc/collect-types.c @@ -28,10 +28,8 @@ #include "gimple-iterator.h" #include "gimple-ssa.h" -#include "compare-types.h" #include "types-inlines.h" #include "type-stringifier.hpp" -#include "name-types.h" #include <set> #include "collect-types.h" @@ -43,10 +41,10 @@ points_to_record_sets_s::insert(const_tree type, bool in_points_to_record) gcc_assert(type); this->universe.insert(type); 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; + // sanity check... gcc_assert(_xor); } diff --git a/gcc/common.opt b/gcc/common.opt index 7442c91d232..7313513d08a 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -3452,10 +3452,6 @@ fipa-hello-world Common Report Var(flag_ipa_hello_world) Optimization Hello world -fipa-type-collector -Common Report Var(flag_ipa_type_collector) Optimization -TBD - ftp-types-compared= Common Joined Report Var(flag_tp_types_compared) Init(0) diff --git a/gcc/compare-types.c b/gcc/compare-types.c deleted file mode 100644 index 9a615c2dd2a..00000000000 --- a/gcc/compare-types.c +++ /dev/null @@ -1,467 +0,0 @@ -#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 "compare-types.h" -#include "types-inlines.h" -#include "name-types.h" - -static bool -is_incomplete_type(const_tree a) -{ - gcc_assert(a); - const_tree type_size = TYPE_SIZE(a); - return NULL_TREE == type_size; -} - -unsigned -eq_main_variant(const_tree a, const_tree b) -{ - gcc_assert(a && b); - const_tree main_variant_a = TYPE_MAIN_VARIANT(a); - const_tree main_variant_b = TYPE_MAIN_VARIANT(b); - gcc_assert(main_variant_a && main_variant_b); - const bool are_equal = main_variant_a == main_variant_b; - return are_equal; -} - -unsigned -eq_canonical_internal(const_tree a, const_tree b) -{ - gcc_assert(a && b); - const_tree canonical_a = TYPE_CANONICAL(a); - const_tree canonical_b = TYPE_CANONICAL(b); - const bool are_equal = canonical_a == canonical_b; - return are_equal; -} - -static bool -eq_record_or_union_types(const_tree a, const_tree b, const bool force_structural) -{ - gcc_assert(a && b); - - tree field_a = TYPE_FIELDS(a); - tree field_b = TYPE_FIELDS(b); - while (field_a || field_b) - { - const bool different_lengths = (bool)field_a != (bool)field_b; - if (different_lengths) return false; - - const_tree field_type_a = TREE_TYPE(field_a); - const_tree field_type_b = TREE_TYPE(field_b); - gcc_assert(field_type_a && field_type_b); - const bool same_field_types = eq_types(field_type_a, field_type_b, force_structural); - if (!same_field_types) return false; - - field_a = DECL_CHAIN(field_a); - field_b = DECL_CHAIN(field_b); - } - - return true; -} - -static bool -eq_record_types(const_tree a, const_tree b, const bool force_structural) -{ - gcc_assert(a && b); - assert_is_type(a, RECORD_TYPE); - assert_is_type(b, RECORD_TYPE); - return eq_record_or_union_types(a, b, force_structural); -} - -static bool -eq_union_types(const_tree a, const_tree b, const bool force_structural) -{ - gcc_assert(a && b); - assert_is_type(a, UNION_TYPE); - assert_is_type(b, UNION_TYPE); - return eq_record_or_union_types(a, b, force_structural); -} - -static bool -eq_wrapper_types(const_tree a, const_tree b, const bool force_structural) -{ - gcc_assert(a && b); - const_tree inner_type_a = TREE_TYPE(a); - const_tree inner_type_b = TREE_TYPE(b); - gcc_assert(inner_type_a && inner_type_b); - return eq_types(inner_type_a, inner_type_b, force_structural); -} - -static bool -eq_pointer_types(const_tree a, const_tree b, const bool force_structural) -{ - gcc_assert(a && b); - assert_is_type(a, POINTER_TYPE); - assert_is_type(b, POINTER_TYPE); - return eq_wrapper_types(a, b, force_structural); -} - -static bool -eq_reference_types(const_tree a, const_tree b, const bool force_structural) -{ - gcc_assert(a && b); - assert_is_type(a, REFERENCE_TYPE); - assert_is_type(b, REFERENCE_TYPE); - return eq_wrapper_types(a, b, force_structural); -} - -static bool -eq_array_types(const_tree a, const_tree b, const bool force_structural) -{ - gcc_assert(a && b); - assert_is_type(a, ARRAY_TYPE); - assert_is_type(b, ARRAY_TYPE); - return eq_wrapper_types(a, b, force_structural); -} - -static bool -eq_function_or_method_types(const_tree a, const_tree b, const bool force_structural) -{ - gcc_assert(a && b); - const_tree return_type_a = TREE_TYPE(a); - const_tree return_type_b = TREE_TYPE(b); - const bool is_return_equal = eq_types(return_type_a, return_type_b, force_structural); - if (!is_return_equal) return false; - - tree parm_a = TYPE_ARG_TYPES(a); - tree parm_b = TYPE_ARG_TYPES(b); - - while (parm_a || parm_b) - { - const bool different_lengths = (bool)parm_a != (bool)parm_b; - if (different_lengths) return false; - - const_tree parm_type_a = TREE_VALUE(parm_a); - const_tree parm_type_b = TREE_VALUE(parm_b); - gcc_assert(parm_type_a && parm_type_b); - const bool same_field_types = eq_types(parm_type_a, parm_type_b, force_structural); - if (!same_field_types) return false; - - parm_a = TREE_CHAIN(parm_a); - parm_b = TREE_CHAIN(parm_b); - } - - return true; -} - -static bool -eq_function_types(const_tree a, const_tree b, const bool force_structural) -{ - gcc_assert(a && b); - assert_is_type(a, FUNCTION_TYPE); - assert_is_type(b, FUNCTION_TYPE); - return eq_function_or_method_types(a, b, force_structural); -} - -static bool -eq_method_types(const_tree a, const_tree b, const bool force_structural) -{ - gcc_assert(a && b); - assert_is_type(a, METHOD_TYPE); - assert_is_type(b, METHOD_TYPE); - - const_tree base_type_a = TYPE_METHOD_BASETYPE(a); - const_tree base_type_b = TYPE_METHOD_BASETYPE(b); - const bool eq_base_types = eq_types(base_type_a, base_type_b, force_structural); - return eq_base_types && eq_function_or_method_types(a, b, force_structural); -} - -static bool eq_structural(const_tree a, const_tree b, const bool force_structural = false); - -unsigned -eq_pointer(const_tree a, const_tree b) -{ - return a == b; -} - -unsigned -eq_identifier(const_tree a, const_tree b) -{ - // TODO: Note, we have had the following miscomparison: - // comparing 0,0: {} == 0,64:void_type* - // since at least one of these two types is incomplete - // and both lack an identifier... - std::string name_a = get_type_identifier(a); - std::string name_b = get_type_identifier(b); - const int length_a = name_a.length(); - const int length_b = name_b.length(); - const bool is_sound_input = length_a > 0 || length_b > 0; - const bool retval = is_sound_input && name_a.compare(name_b) == 0; - return retval; -} - -static bool -eq_structural(const_tree a, const_tree b, const bool force_structural) -{ - gcc_assert(a && b); - const enum tree_code code_a = TREE_CODE(a); - const enum tree_code code_b = TREE_CODE(b); - const bool equal_code = code_a == code_b; - if (!equal_code) return false; - - const enum tree_code code = code_a; - switch (code) - { - //FIXME: Just because two codes are the same - //doesn't mean they are the same type - //E.g. short != int - // float != double - // enum a != enum b - 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: - return true; - break; - default: - break; - } - - switch (code) - { - case RECORD_TYPE: - return eq_record_types(a, b, force_structural); - break; - case POINTER_TYPE: - return eq_pointer_types(a, b, force_structural); - break; - case REFERENCE_TYPE: - return eq_reference_types(a, b, force_structural); - break; - case ARRAY_TYPE: - return eq_array_types(a, b, force_structural); - break; - case UNION_TYPE: - return eq_union_types(a, b, force_structural); - break; - case FUNCTION_TYPE: - return eq_function_types(a, b, force_structural); - break; - case METHOD_TYPE: - return eq_method_types(a, b, force_structural); - break; - case QUAL_UNION_TYPE: - case LANG_TYPE: - default: - // Unimplemented - gcc_unreachable(); - break; - } - - gcc_unreachable(); - return false; -} - -unsigned -eq_canonical(const_tree a, const_tree b) -{ - gcc_assert(a && b); - const bool struct_eq_a = TYPE_STRUCTURAL_EQUALITY_P(a); - const bool struct_eq_b = TYPE_STRUCTURAL_EQUALITY_P(b); - const bool use_structural_equality = struct_eq_a || struct_eq_b; - const bool are_equal = use_structural_equality ? eq_structural(a, b) : eq_canonical_internal(a, b); - return are_equal; -} - - -unsigned -eq_type_compare(const_tree a, const_tree b) -{ - return eq_types(a, b); -} - -unsigned -eq_type_structural(const_tree a, const_tree b) -{ - return eq_types(a, b, true); -} - -unsigned -eq_types(const_tree a, const_tree b, const bool force_structural) -{ - gcc_assert(a && b); - // This should be before comparing incomplete types. - // This is not enabled by default, and it is used for - // testing structural equality limitations. - if (force_structural) return eq_structural(a, b, force_structural); - - // eq_structural (a-incomplete, a-complete) = false - // eq_main_variant(a-incomplete, a-complete) = false - // eq_canonical (a-incomplete, a-complete) = false - // Fallback to eq_identifier only here. - // This should be the only static call to eq_identifier! - - const bool is_a_incomplete = is_incomplete_type(a); - const bool is_b_incomplete = is_incomplete_type(b); - const bool compare_incomplete_types = is_a_incomplete || is_b_incomplete; - if (compare_incomplete_types) return eq_identifier(a, b); - - - // Main variant is unreliable when we are comparing builtin types? - // comparing 0,64: {}* == 0,64:__gcov_info {0,32:integer_type;8,72: {}*;16,48:integer_type;24,88:integer_type*;32,544:void_type(0,64:integer_type*, 0,32:integer_type, 0,0:void_type)*[];96,128:integer_type;104,168:__gcov_fn_info {0,64: {}*;8,40:integer_type;12,44:integer_type;16,48:integer_type;24,280:__gcov_ctr_info {0,32:integer_type;8,72:integer_type*;}[];}**;}* - if (eq_main_variant(a, b) && eq_structural(a, b)) return true; - - if (!eq_canonical(a, b)) return false; - - // optimistic... - // maybe we should have a MAYBE? - return eq_structural(a, b); -} - -namespace test_type_equality { - -static void -test_main_variant() -{ - tree void_a = make_node(VOID_TYPE); - tree void_b = build_variant_type_copy(void_a); - const bool expected = true; - const bool observed = eq_types(void_a, void_b); - const bool success = expected == observed; - gcc_assert(success); -} - -static void -test_pointer_types_eq() -{ - tree pointer_a = make_node(POINTER_TYPE); - tree inner_type = make_node(INTEGER_TYPE); - TREE_TYPE(pointer_a) = inner_type; - tree pointer_b = build_variant_type_copy(pointer_a); - const bool expected = true; - const bool observed = eq_types(pointer_a, pointer_b); - const bool success = expected == observed; - gcc_assert(success); -} - -static void -test_pointer_types_ne() -{ - tree pointer_a = make_node(POINTER_TYPE); - tree inner_type_a = make_node(INTEGER_TYPE); - TREE_TYPE(pointer_a) = inner_type_a; - tree pointer_b = make_node(POINTER_TYPE); - tree inner_type_b = make_node(VOID_TYPE); - TREE_TYPE(pointer_b) = inner_type_b; - const bool expected = false; - const bool observed = eq_types(pointer_a, pointer_b, true); - const bool success = expected == observed; - gcc_assert(success); -} - -static void -test_pointer_types_eq_structurally() -{ - tree pointer_a = make_node(POINTER_TYPE); - tree inner_type_a = make_node(INTEGER_TYPE); - TREE_TYPE(pointer_a) = inner_type_a; - tree pointer_b = make_node(POINTER_TYPE); - tree inner_type_b = make_node(INTEGER_TYPE); - TREE_TYPE(pointer_b) = inner_type_b; - const bool expected = true; - const bool observed = eq_types(pointer_a, pointer_b, true); - const bool success = expected == observed; - gcc_assert(success); -} - -static void -test_void_eq() -{ - tree void_a = make_node(VOID_TYPE); - tree void_b = build_variant_type_copy(void_a); - const bool expected = true; - const bool observed = eq_types(void_a, void_b, true); - const bool success = expected == observed; - gcc_assert(success); -} - -static void -test_structural_equality_different_types() -{ - tree type_a = make_node(VOID_TYPE); - tree type_b = make_node(RECORD_TYPE); - const bool expected = false; - const bool observed = eq_types(type_a, type_b, true); - const bool success = expected == observed; - gcc_assert(success); -} - -static void -test_different_record_types() -{ - tree type_a = make_node(RECORD_TYPE); - tree type_b = make_node(RECORD_TYPE); - tree field_a = make_node(FIELD_DECL); - tree field_b = make_node(FIELD_DECL); - tree type_field_a = make_node(VOID_TYPE); - tree type_field_b = make_node(RECORD_TYPE); - TREE_TYPE(field_a) = type_field_a; - TREE_TYPE(field_b) = type_field_b; - TYPE_FIELDS(type_a) = field_a; - TYPE_FIELDS(type_b) = field_b; - const bool expected = false; - const bool observed = eq_types(type_a, type_b, true); - const bool success = expected == observed; - gcc_assert(success); -} - -static void -test_same_record_types() -{ - tree type_a = make_node(RECORD_TYPE); - tree field_a = make_node(FIELD_DECL); - tree type_field_a = make_node(VOID_TYPE); - TREE_TYPE(field_a) = type_field_a; - TYPE_FIELDS(type_a) = field_a; - tree type_b = build_variant_type_copy(type_a); - const bool expected = true; - const bool observed = eq_types(type_a, type_b, true); - const bool success = expected == observed; - gcc_assert(success); -} - -void -run_tests() -{ - test_main_variant(); - test_void_eq(); - test_structural_equality_different_types(); - test_different_record_types(); - test_same_record_types(); - test_pointer_types_eq_structurally(); - test_pointer_types_ne(); - test_pointer_types_eq(); - -} -} // test_type_equality diff --git a/gcc/compare-types.h b/gcc/compare-types.h deleted file mode 100644 index 384819ce2d7..00000000000 --- a/gcc/compare-types.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - - -namespace test_type_equality { void run_tests(); }; - -static constexpr unsigned not_equal = 0; -static constexpr unsigned equal_incomplete = 1 << 1; -// equal should be the last one -static constexpr unsigned equal = 1 << 2; - -extern unsigned eq_identifier(const_tree a, const_tree b); -extern unsigned eq_pointer(const_tree a, const_tree b); -extern unsigned eq_main_variant(const_tree a, const_tree b); -extern unsigned eq_canonical(const_tree a, const_tree b); -extern unsigned eq_canonical_internal(const_tree a, const_tree b); -extern unsigned eq_type_compare(const_tree a, const_tree b); -extern unsigned eq_type_structural(const_tree a, const_tree b); -extern unsigned eq_types(const_tree a, const_tree b, const bool force_structural = false); diff --git a/gcc/expr-collector.c b/gcc/expr-collector.c index 2e20ba5100a..1271c63cfdf 100644 --- a/gcc/expr-collector.c +++ b/gcc/expr-collector.c @@ -34,5 +34,5 @@ ExprCollector::_walk_pre(const_tree e) { const_tree t = TREE_TYPE(e); gcc_assert(t); - typeCollector->collect(t); + typeCollector.collect(t); } diff --git a/gcc/expr-collector.hpp b/gcc/expr-collector.hpp index aba79d64307..7b3ca3ccd6a 100644 --- a/gcc/expr-collector.hpp +++ b/gcc/expr-collector.hpp @@ -4,11 +4,11 @@ #include "type-collector.hpp" class ExprCollector : public ExprWalker { +private: + TypeCollector typeCollector; public: ExprCollector() {}; - // TODO: You can get rid of this pointer - // if you make ExprCollector a singleton. - static TypeCollector* typeCollector; + ptrset_t get_pointer_set() { return typeCollector.get_pointer_set(); } private: virtual void _walk_pre(const_tree e) final; }; diff --git a/gcc/expr-escaper.c b/gcc/expr-escaper.c new file mode 100644 index 00000000000..31e66582c21 --- /dev/null +++ b/gcc/expr-escaper.c @@ -0,0 +1,52 @@ +#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" // needed for gimple-iterator.h +#include "gimple-iterator.h" +#include "gimple-ssa.h" +#include <stdbool.h> + + +#include "types-inlines.h" +#include "type-escaper.hpp" +#include "expr-escaper.hpp" + +void +ExprEscaper::update(const_tree t, Reason r) +{ + gcc_assert(t); + _r = r; + walk(t); +} + +void +ExprEscaper::_walk_pre(const_tree e) +{ + const_tree t = TREE_TYPE(e); + gcc_assert(t); + typeEscaper.update(t, _r); +} + diff --git a/gcc/expr-escaper.hpp b/gcc/expr-escaper.hpp index cae97ccea11..75e4de23196 100644 --- a/gcc/expr-escaper.hpp +++ b/gcc/expr-escaper.hpp @@ -1,31 +1,19 @@ +#pragma once + #include "ipa-prototype.h" #include "expr-walker.hpp" +#include "type-escaper.hpp" +#include "collect-types.h" class ExprEscaper : public ExprWalker { public: - ExprEscaper() {}; + TypeEscaper typeEscaper; + ExprEscaper(ptrset_t &types) : typeEscaper(types) {}; void update(const_tree t, Reason r); - static TypeEscaper *typeEscaper; private: Reason _r; virtual void _walk_pre(const_tree e); }; -void -ExprEscaper::update(const_tree t, Reason r) -{ - gcc_assert(t); - _r = r; - walk(t); -} - -void -ExprEscaper::_walk_pre(const_tree e) -{ - const_tree t = TREE_TYPE(e); - gcc_assert(t); - typeEscaper->update(t, _r); -} - diff --git a/gcc/expr-walker.c b/gcc/expr-walker.c index 235e80dce96..2b6dd7230d9 100644 --- a/gcc/expr-walker.c +++ b/gcc/expr-walker.c @@ -96,6 +96,15 @@ ExprWalker::_walk(const_tree e) case CONSTRUCTOR: walk_CONSTRUCTOR(e); break; + case LE_EXPR: + walk_LE_EXPR(e); + break; + case EQ_EXPR: + walk_EQ_EXPR(e); + break; + case GT_EXPR: + walk_GT_EXPR(e); + break; default: { log("missing %s\n", get_tree_code_name(code)); @@ -132,6 +141,9 @@ ExprWalkerFuncDef(VAR_DECL) ExprWalkerFuncDef(RESULT_DECL) ExprWalkerFuncDef(PARM_DECL) ExprWalkerFuncDef(FUNCTION_DECL) +ExprWalkerFuncDef(LE_EXPR) +ExprWalkerFuncDef(EQ_EXPR) +ExprWalkerFuncDef(GT_EXPR) void ExprWalker::_walk_leaf(const_tree e, const enum tree_code c) @@ -159,6 +171,7 @@ void ExprWalker::_walk_op_1(const_tree e, const enum tree_code c) { assert_is_type(e, c); + _walk_op_n(e, 0); _walk_op_n(e, 1); } @@ -171,6 +184,25 @@ ExprWalker::_walk_CONSTRUCTOR(const_tree e) } void +ExprWalker::_walk_LE_EXPR(const_tree e) +{ + _walk_op_1(e, LE_EXPR); +} + +void +ExprWalker::_walk_EQ_EXPR(const_tree e) +{ + _walk_op_1(e, EQ_EXPR); +} + +void +ExprWalker::_walk_GT_EXPR(const_tree e) +{ + _walk_op_1(e, GT_EXPR); +} + + +void ExprWalker::_walk_INTEGER_CST(const_tree e) { _walk_leaf(e, INTEGER_CST); diff --git a/gcc/expr-walker.hpp b/gcc/expr-walker.hpp index 1ff3ca4dadc..42702bbf28d 100644 --- a/gcc/expr-walker.hpp +++ b/gcc/expr-walker.hpp @@ -40,5 +40,8 @@ private: ExprWalkerFuncDecl(RESULT_DECL); ExprWalkerFuncDecl(PARM_DECL); ExprWalkerFuncDecl(FUNCTION_DECL); + ExprWalkerFuncDecl(LE_EXPR); + ExprWalkerFuncDecl(EQ_EXPR); + ExprWalkerFuncDecl(GT_EXPR); }; diff --git a/gcc/gimple-collector.c b/gcc/gimple-collector.c new file mode 100644 index 00000000000..2e23fc1e3ab --- /dev/null +++ b/gcc/gimple-collector.c @@ -0,0 +1,116 @@ +#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 "types-inlines.h" +#include <set> +#include <string> +#include <map> + +#include "collect-types.h" +#include "type-stringifier.hpp" + +#include "type-collector.hpp" +#include "expr-walker.hpp" +#include "expr-collector.hpp" +#include "gimple-collector.hpp" + +void +GimpleTypeCollector::_walk_pre(const_tree t) +{ + exprCollector.walk(t); +} + +void +GimpleTypeCollector::_walk_pre(gassign *s) +{ + const_tree lhs = gimple_assign_lhs(s); + exprCollector.walk(lhs); + + const enum gimple_rhs_class gclass = gimple_assign_rhs_class(s); + switch (gclass) + { + case GIMPLE_TERNARY_RHS: + { + const_tree rhs = gimple_assign_rhs3(s); + exprCollector.walk(rhs); + } + /* fall-through */ + case GIMPLE_BINARY_RHS: + { + const_tree rhs = gimple_assign_rhs2(s); + exprCollector.walk(rhs); + } + /* fall-through */ + case GIMPLE_UNARY_RHS: + case GIMPLE_SINGLE_RHS: + { + const_tree rhs = gimple_assign_rhs1(s); + exprCollector.walk(rhs); + } + break; + default: + gcc_unreachable(); + break; + } +} + +void +GimpleTypeCollector::_walk_pre(greturn *s) +{ + const_tree retval = gimple_return_retval(s); + if (!retval) return; + + exprCollector.walk(retval); +} + +void +GimpleTypeCollector::_walk_pre(gcond *s) +{ + const_tree lhs = gimple_cond_lhs(s); + exprCollector.walk(lhs); + const_tree rhs = gimple_cond_rhs(s); + exprCollector.walk(rhs); +} + +void +GimpleTypeCollector::_walk_pre(gcall *s) +{ + unsigned n = gimple_call_num_args(s); + for (unsigned i = 0; i < n; i++) + { + const_tree a = gimple_call_arg(s, i); + exprCollector.walk(a); + } + + const_tree lhs = gimple_call_lhs(s); + if (!lhs) return; + + exprCollector.walk(lhs); +} diff --git a/gcc/gimple-collector.hpp b/gcc/gimple-collector.hpp new file mode 100644 index 00000000000..23b5fe1276f --- /dev/null +++ b/gcc/gimple-collector.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "gimple-walker.hpp" +#include "expr-collector.hpp" + +class GimpleTypeCollector : public GimpleWalker +{ +private: + ExprCollector exprCollector; +public: + GimpleTypeCollector() {}; + ptrset_t get_pointer_set() { return exprCollector.get_pointer_set(); } +private: + virtual void _walk_pre(const_tree) final; + virtual void _walk_pre(gassign *s) final; + virtual void _walk_pre(greturn *s) final; + virtual void _walk_pre(gcond *s) final; + virtual void _walk_pre(gcall *s) final; +}; + diff --git a/gcc/gimple-escaper.c b/gcc/gimple-escaper.c new file mode 100644 index 00000000000..4e5794e6300 --- /dev/null +++ b/gcc/gimple-escaper.c @@ -0,0 +1,143 @@ +#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" // needed for gimple-iterator.h +#include "gimple-iterator.h" +#include "gimple-ssa.h" +#include <stdbool.h> + +#include "gimple-escaper.hpp" + +void +GimpleEscaper::_init() +{ + cgraph_node *cnode = NULL; + FOR_EACH_FUNCTION(cnode) + { + gcc_assert(cnode); + const bool filter = GimpleEscaper::filter_known_function(cnode); + if (filter) continue; + + const_tree decl = cnode->decl; + gcc_assert(decl); + undefined.insert(decl); + } + + FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(cnode) + { + gcc_assert(cnode); + cnode->get_untransformed_body(); + const_tree decl = cnode->decl; + gcc_assert(decl); + undefined.erase(decl); + } +} + +bool +GimpleEscaper::is_function_escaping(cgraph_node *cnode) +{ + const bool filter = GimpleEscaper::filter_known_function(cnode); + if (filter) return false; + + gcc_assert(cnode); + return cnode->externally_visible; +} + +bool +GimpleEscaper::filter_known_function(cgraph_node *node) +{ + gcc_assert(node); + bool filter = false; + const char *_free = "free"; + const char *_malloc = "malloc"; + const char *_realloc = "realloc"; + const char *_calloc = "calloc"; + const char *_memset = "memset"; + const char *name = node->name(); + gcc_assert(name); + filter |= strcmp(_free, name) == 0; + filter |= strcmp(_malloc, name) == 0; + filter |= strcmp(_realloc, name) == 0; + filter |= strcmp(_memset, name) == 0; + filter |= strcmp(_calloc, name) == 0; + return filter; +} + +void +GimpleEscaper::_walk_pre(const_tree t) +{ + // Is any global variable escaping? + Reason reason; + //exprEscaper.update(expr, reason); +} + +void +GimpleEscaper::_walk_pre(gassign *s) +{ + Reason reason; + // We really should also walk over the different assigns... + //exprEscaper.update(expr, reason); +} + +void +GimpleEscaper::_walk_pre(greturn *s) +{ + Reason reason; + //exprEscaper.update(expr, reason); +} + +void +GimpleEscaper::_walk_pre(gcond *s) +{ + Reason reason; + //exprEscaper.update(expr, reason); +} + +void +GimpleEscaper::_walk_pre(gcall *s) +{ + tree fn = gimple_call_fndecl(s); + const bool is_undefined = undefined.find(fn) != undefined.end(); + + Reason arg_reason; + arg_reason.is_escaping = is_undefined; + arg_reason.parameter_is_visible = is_undefined; + unsigned n = gimple_call_num_args(s); + for (unsigned i = 0; i < n; i++) + { + const_tree a = gimple_call_arg(s, i); + gcc_assert(a); + exprEscaper.update(a, arg_reason); + } + + const_tree lhs = gimple_call_lhs(s); + if (!lhs) return; + + Reason return_reason; + return_reason.is_escaping = is_undefined; + return_reason.return_is_visible = is_undefined; + exprEscaper.update(lhs, return_reason); +} diff --git a/gcc/gimple-escaper.hpp b/gcc/gimple-escaper.hpp new file mode 100644 index 00000000000..7ed2a89907e --- /dev/null +++ b/gcc/gimple-escaper.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "gimple-walker.hpp" +#include "expr-escaper.hpp" + +class GimpleEscaper : public GimpleWalker +{ +public: + GimpleEscaper(ptrset_t &types) : exprEscaper(types) { _init(); }; + ExprEscaper exprEscaper; +private: + typedef std::set<const_tree> undefset; + undefset undefined; + void _init(); + static bool filter_known_function(cgraph_node *); + static bool is_function_escaping(cgraph_node *); + virtual void _walk_pre(const_tree) final; + virtual void _walk_pre(gassign *s) final; + virtual void _walk_pre(greturn *s) final; + virtual void _walk_pre(gcond *s) final; + virtual void _walk_pre(gcall *s) final; +}; diff --git a/gcc/gimple-walker.c b/gcc/gimple-walker.c new file mode 100644 index 00000000000..4735960c076 --- /dev/null +++ b/gcc/gimple-walker.c @@ -0,0 +1,218 @@ +#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 "types-inlines.h" +#include <set> +#include <string> +#include <map> + +#include "collect-types.h" +#include "type-stringifier.hpp" + +#include "type-collector.hpp" +#include "expr-walker.hpp" +#include "expr-collector.hpp" +#include "gimple-walker.hpp" + +void +GimpleWalker::walk() +{ + _walk_globals(); + + cgraph_node *node = NULL; + long unsigned i = 0; + FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(node) + { + node->get_untransformed_body(); + _walk_cnode(node); + } +} + +void +GimpleWalker::_walk_globals() +{ + varpool_node *vnode = NULL; + unsigned long i = 0; + FOR_EACH_VARIABLE(vnode) + { + gcc_assert(vnode); + struct ipa_ref *ref = NULL; + for (unsigned i = 0; vnode->iterate_referring(i, ref); i++) + { + tree var_decl = vnode->decl; + walk(var_decl); + } + } +} + +void +GimpleWalker::_walk_ssa_names(cgraph_node *cnode) +{ + const_tree decl = cnode->decl; + gcc_assert(decl); + function *func = DECL_STRUCT_FUNCTION(decl); + gcc_assert(func); + size_t i = 0; + tree ssa_name = NULL; + push_cfun(func); + FOR_EACH_SSA_NAME(i, ssa_name, cfun) + { + gcc_assert(ssa_name); + walk(ssa_name); + } + pop_cfun(); +} + +void +GimpleWalker::_walk_cnode(cgraph_node *cnode) +{ + gcc_assert(cnode); + _walk_decl(cnode); + _walk_locals(cnode); + _walk_ssa_names(cnode); + _walk_bb(cnode); +} + +void +GimpleWalker::_walk_decl(cgraph_node *cnode) +{ + const_tree decl = cnode->decl; + gcc_assert(decl); + walk(decl); +} + +void +GimpleWalker::_walk_locals(cgraph_node *cnode) +{ + const_tree decl = cnode->decl; + gcc_assert(decl); + function *func = DECL_STRUCT_FUNCTION(decl); + gcc_assert(func); + int i = 0; + tree var_decl = NULL; + FOR_EACH_LOCAL_DECL(func, i, var_decl) + { + gcc_assert(var_decl); + walk(var_decl); + } +} + + +void +GimpleWalker::_walk_bb(cgraph_node* cnode) +{ + gcc_assert(cnode); + cnode->get_untransformed_body(); + const_tree decl = cnode->decl; + gcc_assert(decl); + function *func = DECL_STRUCT_FUNCTION(decl); + gcc_assert(func); + basic_block bb = NULL; + push_cfun(func); + FOR_EACH_BB_FN(bb, func) + { + _walk(bb); + } + pop_cfun(); +} + +void +GimpleWalker::_walk(basic_block bb) +{ + gcc_assert(bb); + for (auto gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) + { + gimple *stmt = gsi_stmt(gsi); + walk(stmt); + } +} + +void +GimpleWalker::walk(gimple *stmt) +{ + _walk_pre(stmt); + _walk(stmt); + _walk_post(stmt); +} + +void +GimpleWalker::_walk(gimple *stmt) +{ + gcc_assert(stmt); + +#define GimpleWalkerWalk(type) \ + if (type s = dyn_cast< type >(stmt)) \ + { \ + _walk_pre(stmt); \ + walk(s); \ + _walk_post(stmt); \ + return; \ + } + + GimpleWalkerWalk(gassign*); + GimpleWalkerWalk(greturn*); + GimpleWalkerWalk(gcond*); + GimpleWalkerWalk(gcall*); + GimpleWalkerWalk(glabel*); + GimpleWalkerWalk(gswitch*); + + + const enum gimple_code code = gimple_code (stmt); + switch (code) + { + case GIMPLE_PREDICT: return; + default: break; + } + const char* name = gimple_code_name[code]; + log("gimple code name %s\n", name); + gcc_unreachable(); +} + +#define GimpleWalkerFuncDef(type) \ +void \ +GimpleWalker::walk (type e) \ +{ \ + _walk_pre (e); \ + _walk (e); \ + _walk_post (e); \ +} \ +\ +void \ +GimpleWalker::_walk (type e) \ +{ \ +} + +GimpleWalkerFuncDef(const_tree); +GimpleWalkerFuncDef(gassign *); +GimpleWalkerFuncDef(greturn *); +GimpleWalkerFuncDef(gcond *); +GimpleWalkerFuncDef(gcall *); +GimpleWalkerFuncDef(glabel *); +GimpleWalkerFuncDef(gswitch *); diff --git a/gcc/gimple-walker.hpp b/gcc/gimple-walker.hpp new file mode 100644 index 00000000000..7604cb7f505 --- /dev/null +++ b/gcc/gimple-walker.hpp @@ -0,0 +1,34 @@ +#pragma once + +class GimpleWalker +{ +public: + GimpleWalker() {}; + void walk(); + +private: + + void _walk_globals(); + void _walk_ssa_names(cgraph_node *cnode); + void _walk_cnode(cgraph_node *cnode); + void _walk_decl(cgraph_node *cnode); + void _walk_locals(cgraph_node *cnode); + void _walk_bb(cgraph_node *cnode); + void _walk(basic_block bb); + +#define GimpleWalkerFuncDecl(type) \ + virtual void _walk_pre(type stmt) {}; \ + void walk(type stmt); \ + void _walk(type stmt); \ + virtual void _walk_post(type stmt) {} + + GimpleWalkerFuncDecl(const_tree); + GimpleWalkerFuncDecl(gimple*); + GimpleWalkerFuncDecl(gassign*); + GimpleWalkerFuncDecl(greturn*); + GimpleWalkerFuncDecl(gcond*); + GimpleWalkerFuncDecl(gcall*); + GimpleWalkerFuncDecl(glabel*); + GimpleWalkerFuncDecl(gswitch*); +}; + diff --git a/gcc/ipa-prototype.c b/gcc/ipa-prototype.c index ca8b77268a1..0017e9d71b1 100644 --- a/gcc/ipa-prototype.c +++ b/gcc/ipa-prototype.c @@ -31,9 +31,6 @@ #include "types-inlines.h" -#include "name-types.h" -#include "compare-types.h" -#include "ipa-type-collector.h" #include "ipa-prototype.h" #include "type-collector.hpp" #include "type-stringifier.hpp" @@ -41,6 +38,9 @@ #include <vector> #include "type-escaper.hpp" #include "expr-escaper.hpp" +#include "gimple-walker.hpp" +#include "gimple-collector.hpp" +#include "gimple-escaper.hpp" //#define OPTIMIZED #define SANITY_CHECKS @@ -99,8 +99,6 @@ assert_type_is_in_ptrset(const_tree type, ptrset_t &types) } -static void update_escape_info( const_tree type, ptrset_t &types, Reason reason, typemap &calc); - static bool is_variable_escaping(varpool_node *vnode) { @@ -108,453 +106,6 @@ is_variable_escaping(varpool_node *vnode) return vnode->externally_visible; } -static void update_escape_info_expr(ptrset_t &types, typemap &calc, const_tree expr, Reason reason); - -static void -calculate_escaping_types_globals(ptrset_t &types, typemap &calc) -{ - varpool_node *vnode = NULL; - FOR_EACH_VARIABLE(vnode) - { - bool is_escaping = is_variable_escaping(vnode); - -#ifdef OPTIMIZED - if (!is_escaping) continue; -#endif - - Reason reason {}; // Not sure why {} works but () doesn't... It believes it is a function? - reason.is_escaping = is_escaping; - reason.global_is_visible = is_escaping; - update_escape_info_expr (types, calc, vnode->decl, reason); - } -} - -static bool -filter_known_function(cgraph_node *node) -{ - gcc_assert(node); - bool filter = false; - const char *_free = "free"; - const char *_malloc = "malloc"; - const char *_realloc = "realloc"; - const char *_calloc = "calloc"; - const char *_memset = "memset"; - const char *name = node->name(); - gcc_assert(name); - filter |= strcmp(_free, name) == 0; - filter |= strcmp(_malloc, name) == 0; - filter |= strcmp(_realloc, name) == 0; - filter |= strcmp(_memset, name) == 0; - filter |= strcmp(_calloc, name) == 0; - return filter; -} - -static bool -is_function_escaping(cgraph_node *cnode) -{ - const bool filter = filter_known_function(cnode); - if (filter) return false; - - gcc_assert(cnode); - return cnode->externally_visible; -} - -static void -mark_escaping_parameters(ptrset_t &types, typemap &calc, cgraph_node *cnode, Reason reason) -{ - gcc_assert(cnode); - const_tree decl = cnode->decl; - gcc_assert(decl); - assert_is_type(decl, FUNCTION_DECL); -#ifdef OPTIMIZED - if (!reason.is_escaping) return; -#endif - - update_escape_info_expr(types, calc, decl, reason); -} - -static void -mark_escaping_return_type(ptrset_t &types, typemap &calc, cgraph_node *cnode, Reason reason) -{ - gcc_assert(cnode); - const_tree decl = cnode->decl; - gcc_assert(decl); - assert_is_type(decl, FUNCTION_DECL); -#ifdef OPTIMIZED - if (!reason.is_escaping) return; -#endif - - const_tree func_type = TREE_TYPE(decl); - assert_is_type(func_type, FUNCTION_TYPE); - const_tree ret_type = TREE_TYPE(func_type); - gcc_assert(ret_type); - update_escape_info(ret_type, types, reason, calc); -} - -static void -mark_escaping_function(ptrset_t &types, typemap &calc, cgraph_node *cnode) -{ - gcc_assert(cnode); - const bool is_escaping = is_function_escaping(cnode); -#ifdef OPTIMIZED - if (!is_escaping) return; -#endif - - Reason reason1 {}; - reason1.is_escaping = is_escaping; - reason1.parameter_is_visible = is_escaping; - mark_escaping_parameters(types, calc, cnode, reason1); - - Reason reason2 {}; - reason2.is_escaping = is_escaping; - reason2.return_is_visible = is_escaping; - mark_escaping_return_type(types, calc, cnode, reason2); -} - -static void -calculate_escaping_types_from_cast(ptrset_t &types, typemap &calc, gimple *stmt) -{ - is_gimple_code(stmt, GIMPLE_ASSIGN); - const_tree lhs = gimple_assign_lhs(stmt); - gcc_assert(lhs); - const_tree rhs = gimple_assign_rhs1(stmt); - gcc_assert(rhs); -} - -static void -calculate_escaping_types_from_assign_lhs(ptrset_t &types, typemap &calc, gimple *stmt) -{ - is_gimple_code(stmt, GIMPLE_ASSIGN); - const_tree lhs = gimple_assign_lhs(stmt); - gcc_assert(lhs); - Reason reason {}; - update_escape_info_expr(types, calc, lhs, reason); -} - -static void -calculate_escaping_types_from_assign_rhs3(ptrset_t &types, typemap &calc, gimple *stmt) -{ - is_gimple_rhs_class(stmt, GIMPLE_TERNARY_RHS); - const_tree rhs = gimple_assign_rhs3(stmt); - gcc_assert(rhs); - Reason reason {}; - update_escape_info_expr(types, calc, rhs, reason); -} - -static void -calculate_escaping_types_from_assign_rhs2(ptrset_t &types, typemap &calc, gimple *stmt) -{ - const_tree rhs = gimple_assign_rhs2(stmt); - gcc_assert(rhs); - Reason reason {}; - update_escape_info_expr(types, calc, rhs, reason); -} - -static void -calculate_escaping_types_from_assign_rhs1(ptrset_t &types, typemap &calc, gimple *stmt) -{ - const_tree rhs = gimple_assign_rhs1(stmt); - gcc_assert(rhs); - Reason reason {}; - update_escape_info_expr(types, calc, rhs, reason); -} - -static void -calculate_escaping_types_from_assign(ptrset_t &types, typemap &calc, gimple *stmt) -{ - is_gimple_code(stmt, GIMPLE_ASSIGN); - calculate_escaping_types_from_assign_lhs(types, calc, stmt); - // If it is a cast, we must look at the lhs and the rhs... - const enum gimple_rhs_class gclass = gimple_assign_rhs_class(stmt); - switch(gclass) - { - case GIMPLE_TERNARY_RHS: - calculate_escaping_types_from_assign_rhs3(types, calc, stmt); - /* fall-through */ - case GIMPLE_BINARY_RHS: - calculate_escaping_types_from_assign_rhs2(types, calc, stmt); - /* fall-through */ - case GIMPLE_UNARY_RHS: - case GIMPLE_SINGLE_RHS: - calculate_escaping_types_from_assign_rhs1(types, calc, stmt); - calculate_escaping_types_from_cast(types, calc, stmt); - break; - default: - gcc_unreachable(); - break; - } -} - -static void -calculate_escaping_types_from_call_lhs(ptrset_t &types, typemap &calc, undefset &undef, gimple *stmt) -{ - gcall *call = dyn_cast<gcall*>(stmt); - if (!call) return; - - const_tree lhs = gimple_call_lhs(stmt); - if (!lhs) return; - - tree fn = gimple_call_fndecl(stmt); - const bool is_undefined = undef.find(fn) != undef.end(); -#ifdef OPTIMIZED - if (!is_undefined) return; -#endif - - Reason reason {}; - reason.is_escaping = is_undefined; - reason.return_is_visible = is_undefined; - update_escape_info_expr(types, calc, lhs, reason); -} - -static void -calculate_escaping_types_from_call_rhs(ptrset_t &types, typemap &calc, undefset &undef, gimple *stmt) -{ - - tree fn = gimple_call_fndecl(stmt); - const bool is_undefined = undef.find(fn) != undef.end(); -#ifdef OPTIMIZED - if (!is_undefined) return; -#endif - - //tree decl_name = DECL_NAME(fn); - //const char* identifier = IDENTIFIER_POINTER(decl_name); - // What about gcov? - - Reason reason {}; - reason.is_escaping = is_undefined; - reason.parameter_is_visible = is_undefined; - - unsigned num_args = gimple_call_num_args(stmt); - for (unsigned i = 0; i < num_args; i++) - { - const_tree arg_i = gimple_call_arg(stmt, i); - gcc_assert(arg_i); - const_tree type_i = TREE_TYPE(arg_i); - update_escape_info(type_i, types, reason, calc); - } -} - -static void -calculate_escaping_types_from_call(ptrset_t &types, typemap &calc, undefset &undef, gimple *stmt) -{ - is_gimple_code(stmt, GIMPLE_CALL); - gcall *call = dyn_cast<gcall*>(stmt); - tree fn = gimple_call_fndecl(stmt); - - const bool in_set = undef.find(fn) != undef.end(); -#ifdef OPTIMIZED - if (!in_set) return; -#endif - - calculate_escaping_types_from_call_lhs(types, calc, undef, stmt); - calculate_escaping_types_from_call_rhs(types, calc, undef, stmt); -} - -static void -calculate_escaping_types_from_cond_lhs(ptrset_t &types, typemap &calc, gimple *stmt) -{ - is_gimple_code(stmt, GIMPLE_COND); - const_tree lhs = gimple_cond_lhs(stmt); - gcc_assert(lhs); - Reason reason {}; - update_escape_info_expr(types, calc, lhs, reason); -} - -static void -calculate_escaping_types_from_cond_rhs(ptrset_t &types, typemap &calc, gimple *stmt) -{ - is_gimple_code(stmt, GIMPLE_COND); - const_tree rhs = gimple_cond_rhs(stmt); - Reason reason {}; - update_escape_info_expr(types, calc, rhs, reason); -} - -static void -calculate_escaping_types_from_cond(ptrset_t &types, typemap &calc, gimple *stmt) -{ - is_gimple_code(stmt, GIMPLE_COND); - calculate_escaping_types_from_cond_lhs(types, calc, stmt); - calculate_escaping_types_from_cond_rhs(types, calc, stmt); -} - -static void -calculate_escaping_types_from_return(ptrset_t &types, typemap &calc, gimple *stmt) -{ - is_gimple_code(stmt, GIMPLE_RETURN); - const_tree retval = gimple_return_retval(stmt); - if (!retval) return; - - Reason reason {}; - update_escape_info_expr(types, calc, retval, reason); -} - -static void -calculate_escaping_types_from_stmt(ptrset_t &types, typemap &calc, undefset &undef, gimple *stmt) -{ - // Should be the same as ipa-type-collector.c - // Otherwise, we might be skipping exploring some paths... - gcc_assert(stmt); - const enum gimple_code code = gimple_code (stmt); - switch (code) - { - case GIMPLE_ASSIGN: - calculate_escaping_types_from_assign(types, calc, stmt); - break; - case GIMPLE_CALL: - calculate_escaping_types_from_call(types, calc, undef, stmt); - break; - case GIMPLE_COND: - calculate_escaping_types_from_cond(types, calc, stmt); - break; - case GIMPLE_RETURN: - calculate_escaping_types_from_return(types, calc, stmt); - break; - case GIMPLE_LABEL: - case GIMPLE_PREDICT: - case GIMPLE_DEBUG: - case GIMPLE_SWITCH: -#ifdef FUZZ_MODE - gcc_unreachable(); -#endif - break; - default: - { - const char* name = gimple_code_name[code]; - log("gimple code name %s\n", name); - gcc_unreachable(); - } - break; - } -} - -static void -calculate_escaping_types_from_bb(ptrset_t &types, typemap &calc, undefset &undef, basic_block bb) -{ - gcc_assert(bb); - for (auto gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) - { - gimple *stmt = gsi_stmt(gsi); - calculate_escaping_types_from_stmt(types, calc, undef, stmt); - } -} - -static void -calculate_escaping_types_from_cnode(ptrset_t &types, typemap &calc, cgraph_node *cnode, undefset &undef) -{ - gcc_assert(cnode); - cnode->get_untransformed_body(); - const_tree decl = cnode->decl; - gcc_assert(decl); - function *func = DECL_STRUCT_FUNCTION(decl); - gcc_assert(func); - basic_block bb = NULL; - push_cfun(func); - FOR_EACH_BB_FN(bb, func) - { - calculate_escaping_types_from_bb(types, calc, undef, bb); - } - pop_cfun(); -} - -static void -calculate_escaping_ssa_names(ptrset_t &types, typemap &calc, cgraph_node *cnode) -{ - gcc_assert(cnode); - const_tree decl = cnode->decl; - gcc_assert(decl); - function *func = DECL_STRUCT_FUNCTION(decl); - gcc_assert(func); - size_t i = 0; - tree ssa_name = NULL; - push_cfun(func); - Reason reason {}; - FOR_EACH_SSA_NAME(i, ssa_name, cfun) - { - gcc_assert(ssa_name); - const_tree ssa_name_type = TREE_TYPE(ssa_name); - update_escape_info(ssa_name_type, types, reason, calc); - } - pop_cfun(); -} - -static void -calculate_escaping_locals(ptrset_t &types, typemap &calc, cgraph_node *cnode) -{ - gcc_assert(cnode); - const_tree decl = cnode->decl; - gcc_assert(decl); - function *func = DECL_STRUCT_FUNCTION(decl); - gcc_assert(func); - Reason reason {}; - const_tree func_type = TREE_TYPE(decl); - assert_is_type(func_type, FUNCTION_TYPE); - update_escape_info_expr(types, calc, decl, reason); - if (types.in_points_to_record(func_type)) update_escape_info(func_type, types, reason, calc); - int i = 0; - tree var_decl = NULL; - FOR_EACH_LOCAL_DECL(func, i, var_decl) - { - gcc_assert(var_decl); - update_escape_info_expr(types, calc, var_decl, reason); - } -} - - - -static void -calculate_escaping_functions(ptrset_t &types, typemap &calc) -{ - cgraph_node *cnode = NULL; - undefset undefined_functions; - FOR_EACH_FUNCTION(cnode) - { - gcc_assert(cnode); - const bool filter = filter_known_function(cnode); - if (filter) continue; - - const_tree decl = cnode->decl; - gcc_assert(decl); - undefined_functions.insert(decl); - } - - FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(cnode) - { - gcc_assert(cnode); - cnode->get_untransformed_body(); - const_tree decl = cnode->decl; - gcc_assert(decl); - undefined_functions.erase(decl); - mark_escaping_function(types, calc, cnode); - calculate_escaping_locals(types, calc, cnode); - calculate_escaping_ssa_names(types, calc, cnode); - } - - FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(cnode) - { - gcc_assert(cnode); - calculate_escaping_types_from_cnode(types, calc, cnode, undefined_functions); - } -} - -static void -calculate_escaping_types(ptrset_t &types, typemap &calc) -{ - calculate_escaping_types_globals(types, calc); - calculate_escaping_functions(types, calc); -} - -static void -print_escaping_types(typemap &calc) -{ - for (auto i = calc.cbegin(), e = calc.cend(); i != e; ++i) - { - const_tree type = i->first; - const Reason reason = i->second; - log ("escaping: %s (or %s) = %s\n", get_type_identifier(type).c_str(), type_to_string(type).c_str(), reason.is_escaping ? "true" : "false"); - reason.print(); - } -} - static void place_escaping_types_in_set(ptrset_t &types, typemap &calc) { @@ -690,39 +241,22 @@ print_escaping_types_in_set(ptrset_t &types) } -ptrset_t *TypeEscaper::types = NULL; -typemap TypeEscaper::calc; -static TypeEscaper _typeEscaper; -static ExprEscaper exprEscaper; -TypeEscaper *ExprEscaper::typeEscaper = NULL; - -static void -update_escape_info( const_tree type, ptrset_t &types, Reason reason, typemap &calc) -{ - _typeEscaper.update(type, reason); -} - -static void -update_escape_info_expr(ptrset_t &types, typemap &calc, const_tree expr, Reason reason) -{ - exprEscaper.update(expr, reason); -} - - static unsigned int iphw_execute() { - ptrset_t types; - TypeCollector::ptrset = &types; - TypeEscaper::types = &types; - ExprEscaper::typeEscaper = &_typeEscaper; - collect_types(types); + + GimpleTypeCollector collector; + collector.walk(); + ptrset_t types = collector.get_pointer_set(); + + GimpleEscaper gimpleEscaper(types); + gimpleEscaper.walk(); typemap eacalc; // Escape Analysis Calculation // Intermediate results // Do not read escape analysis results from here - calculate_escaping_types(types, eacalc); - place_escaping_types_in_set(types, _typeEscaper.calc); + //calculate_escaping_types(types, eacalc); + place_escaping_types_in_set(types, gimpleEscaper.exprEscaper.typeEscaper.calc); fix_escaping_types_in_set(types); print_escaping_types_in_set(types); sanity_check_escape_xor_not(types); diff --git a/gcc/ipa-type-collector.c b/gcc/ipa-type-collector.c deleted file mode 100644 index f532a7f3e48..00000000000 --- a/gcc/ipa-type-collector.c +++ /dev/null @@ -1,594 +0,0 @@ -#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 "compare-types.h" -#include "types-inlines.h" -#include <set> -#include <string> -#include <map> - -#include "collect-types.h" -#include "name-types.h" -#include "type-stringifier.hpp" - -#include "ipa-type-collector.h" -#include "type-collector.hpp" -#include "expr-walker.hpp" -#include "expr-collector.hpp" - -//#define FUZZ_MODE 1 -static void collect_types(const_tree t); - -namespace type_playground { -enum type_comparison_func_enum { - EQ_POINTER = 0, - EQ_IDENTIFIER, - EQ_MAIN_VARIANT, - EQ_CANONICAL, - EQ_STRUCTURAL, - EQ_CANONICAL_STRICT, - EQ_COMPARE, - EQ_END -}; -static unsigned const type_comparisons = EQ_END; -static const char* names[type_comparisons] = { - "EQ_POINTER", - "EQ_IDENTIFIER", - "EQ_MAIN_VARIANT", - "EQ_CANONICAL", - "EQ_CANONICAL_STRICT", - "EQ_STRUCTURAL", - "EQ_COMPARE" -}; -typedef unsigned (*type_comparison_func_t)(const_tree, const_tree); -static type_comparison_func_t comparisons[type_comparisons] = { - eq_pointer, - eq_identifier, - eq_main_variant, - eq_canonical, - eq_canonical_internal, - eq_type_structural, - eq_type_compare -}; -} - - - -static void collect_types_from_expr(const_tree expr, ptrset_t &types); - - -static void -collect_types_from_stmt_assign_lhs(gimple *stmt, ptrset_t &types) -{ - is_gimple_code(stmt, GIMPLE_ASSIGN); - const_tree lhs = gimple_assign_lhs(stmt); - gcc_assert(lhs); - collect_types_from_expr(lhs, types); -} - -static void -collect_types_from_stmt_assign_rhs3(gimple *stmt, ptrset_t &types) -{ - is_gimple_rhs_class(stmt, GIMPLE_TERNARY_RHS); - const_tree rhs = gimple_assign_rhs3(stmt); - gcc_assert(rhs); - collect_types_from_expr(rhs, types); -} - -static void -collect_types_from_stmt_assign_rhs2(gimple *stmt, ptrset_t &types) -{ - is_gimple_code(stmt, GIMPLE_ASSIGN); - const enum gimple_rhs_class gclass = gimple_assign_rhs_class(stmt); - const bool is_ternary = GIMPLE_TERNARY_RHS == gclass; - const bool is_binary = GIMPLE_BINARY_RHS == gclass; - const bool is_valid_input = is_ternary || is_binary; - gcc_assert(is_valid_input); - const_tree rhs = gimple_assign_rhs2(stmt); - gcc_assert(rhs); - collect_types_from_expr(rhs, types); -} - -static void -collect_types_from_stmt_assign_rhs1(gimple *stmt, ptrset_t &types) -{ - is_gimple_code(stmt, GIMPLE_ASSIGN); - const enum gimple_rhs_class gclass = gimple_assign_rhs_class(stmt); - const bool is_ternary = GIMPLE_TERNARY_RHS == gclass; - const bool is_binary = GIMPLE_BINARY_RHS == gclass; - const bool is_unary = GIMPLE_UNARY_RHS == gclass; - const bool is_single = GIMPLE_SINGLE_RHS == gclass; - const bool is_valid_input = is_ternary || is_binary || is_unary || is_single; - gcc_assert(is_valid_input); - const_tree rhs = gimple_assign_rhs1(stmt); - gcc_assert(rhs); - collect_types_from_expr(rhs, types); -} - -static void -collect_types_from_stmt_assign_rhs(gimple *stmt, ptrset_t &types) -{ - is_gimple_code(stmt, GIMPLE_ASSIGN); - const enum gimple_rhs_class gclass = gimple_assign_rhs_class(stmt); - switch (gclass) - { - case GIMPLE_TERNARY_RHS: - collect_types_from_stmt_assign_rhs3(stmt, types); - /* fall-through */ - case GIMPLE_BINARY_RHS: - collect_types_from_stmt_assign_rhs2(stmt, types); - /* fall-through */ - case GIMPLE_UNARY_RHS: - case GIMPLE_SINGLE_RHS: - collect_types_from_stmt_assign_rhs1(stmt, types); - break; - default: - gcc_unreachable(); - break; - } -} - -static void -collect_types_from_stmt_assign(gimple *stmt, ptrset_t &types) -{ - is_gimple_code(stmt, GIMPLE_ASSIGN); - collect_types_from_stmt_assign_lhs(stmt, types); - collect_types_from_stmt_assign_rhs(stmt, types); -} - -static void -collect_types_from_stmt_call_lhs(gimple *stmt, ptrset_t &types) -{ - is_gimple_code(stmt, GIMPLE_CALL); - const_tree lhs = gimple_call_lhs(stmt); - if (!lhs) return; - - tree fn = gimple_call_fndecl(stmt); - if (!fn) return; - - const_tree decl_name = DECL_NAME(fn); - const char *identifier = decl_name ? IDENTIFIER_POINTER(decl_name) : ""; - collect_types_from_expr(lhs, types); -} - -static void -collect_types_from_stmt_call_rhs(gimple *stmt, ptrset_t &types) -{ - is_gimple_code(stmt, GIMPLE_CALL); - unsigned num_args = gimple_call_num_args(stmt); - for (unsigned i = 0; i < num_args; i++) - { - const_tree arg_i = gimple_call_arg(stmt, i); - collect_types_from_expr(arg_i, types); - } -} - -static void -collect_types_from_stmt_call(gimple *stmt, ptrset_t &types) -{ - is_gimple_code(stmt, GIMPLE_CALL); - collect_types_from_stmt_call_lhs(stmt, types); - collect_types_from_stmt_call_rhs(stmt, types); -} - -static void -collect_types_from_stmt_cond_lhs(gimple *stmt, ptrset_t &types) -{ - is_gimple_code(stmt, GIMPLE_COND); - const_tree lhs = gimple_cond_lhs(stmt); - gcc_assert(lhs); - collect_types_from_expr(lhs, types); -} - -static void -collect_types_from_stmt_cond_rhs(gimple *stmt, ptrset_t &types) -{ - is_gimple_code(stmt, GIMPLE_COND); - const_tree rhs = gimple_cond_rhs(stmt); - gcc_assert(rhs); - collect_types_from_expr(rhs, types); -} - -static void -collect_types_from_stmt_cond(gimple *stmt, ptrset_t &types) -{ - is_gimple_code(stmt, GIMPLE_COND); - collect_types_from_stmt_cond_lhs(stmt, types); - collect_types_from_stmt_cond_rhs(stmt, types); -} - -static void -collect_types_from_stmt_return(gimple *stmt, ptrset_t &types) -{ - is_gimple_code(stmt, GIMPLE_RETURN); - const_tree retval = gimple_return_retval(stmt); - if (!retval) return; - - collect_types_from_expr(retval, types); -} - -static void -collect_types_from_stmt(gimple *stmt, ptrset_t &types) -{ - gcc_assert(stmt); - const enum gimple_code code = gimple_code(stmt); - switch (code) { - case GIMPLE_ASSIGN: - collect_types_from_stmt_assign(stmt, types); - break; - case GIMPLE_CALL: - collect_types_from_stmt_call(stmt, types); - break; - case GIMPLE_COND: - collect_types_from_stmt_cond(stmt, types); - break; - case GIMPLE_RETURN: - collect_types_from_stmt_return(stmt, types); - break; - case GIMPLE_LABEL: - case GIMPLE_PREDICT: - case GIMPLE_DEBUG: - case GIMPLE_SWITCH: -#ifdef FUZZ_MODE - gcc_unreachable(); -#endif - break; - default: - { - const char* name = gimple_code_name[code]; - log("gimple code name %s\n", name); - gcc_unreachable(); - } - break; - } -} - - -static void -collect_types_from_cnode_decl(cgraph_node *cnode, ptrset_t &types) -{ - gcc_assert(cnode); - const_tree decl = cnode->decl; - gcc_assert(decl); - //collect_types_from_function_decl(decl, types); -} - -static void -collect_types_from_cnode_locals(cgraph_node *cnode, ptrset_t &types) -{ - gcc_assert(cnode); - const_tree decl = cnode->decl; - gcc_assert(decl); - collect_types_from_expr(decl, types); - function *func = DECL_STRUCT_FUNCTION (decl); - gcc_assert(func); - int i = 0; - tree var_decl = NULL; - FOR_EACH_LOCAL_DECL(func, i, var_decl) - { - gcc_assert(var_decl); - collect_types_from_expr(var_decl, types); - } -} - -static void -collect_types_from_cnode_ssa_names(cgraph_node *cnode, ptrset_t &types) -{ - gcc_assert(cnode); - const_tree decl = cnode->decl; - gcc_assert(decl); - function *func = DECL_STRUCT_FUNCTION (decl); - gcc_assert(func); - size_t i = 0; - tree ssa_name = NULL; - push_cfun(func); - FOR_EACH_SSA_NAME(i, ssa_name, cfun) - { - gcc_assert(ssa_name); - collect_types_from_expr(ssa_name, types); - } - pop_cfun(); -} - -static void -collect_types_from_bb(basic_block bb, ptrset_t &types) -{ - gcc_assert(bb); - for (auto gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) - { - gimple *stmt = gsi_stmt(gsi); - gcc_assert(stmt); - collect_types_from_stmt(stmt, types); - } -} - -static void -collect_types_from_cnode_bb(cgraph_node *cnode, ptrset_t &types) -{ - gcc_assert(cnode); - cnode->get_untransformed_body(); - tree decl = cnode->decl; - gcc_assert(decl); - function *func = DECL_STRUCT_FUNCTION(decl); - gcc_assert(func); - basic_block bb = NULL; - push_cfun(func); - FOR_EACH_BB_FN(bb, func) - { - gcc_assert(bb); - collect_types_from_bb(bb, types); - } - pop_cfun(); -} - -static void -collect_types_from_global(varpool_node *vnode, ptrset_t &types) -{ - gcc_assert(vnode); - struct ipa_ref *ref = NULL; - for (unsigned i = 0; vnode->iterate_referring(i, ref); i++) - { - tree decl = vnode->decl; - gcc_assert(decl); - collect_types_from_expr(decl, types); - } -} - -static void -collect_types_from_globals(ptrset_t &types) -{ - varpool_node *vnode = NULL; - unsigned long i = 0; - FOR_EACH_VARIABLE (vnode) - { - collect_types_from_global(vnode, types); - } -} - -static void -collect_types_from_functions_with_gimple_body(cgraph_node *cnode, ptrset_t &types) -{ - gcc_assert(cnode); - collect_types_from_cnode_decl(cnode, types); - collect_types_from_cnode_locals(cnode, types); - collect_types_from_cnode_ssa_names(cnode, types); - collect_types_from_cnode_bb(cnode, types); -} - -static void -print_types_in_set(ptrset_t &types) -{ - for (auto it = types.points_to_record.cbegin(); it != types.points_to_record.cend(); ++it) - { - const_tree type = *it; - std::string name = type_to_string(type); - } -} - -static const bool -filter_comparisons_functions_char(const char* function_name) -{ - // Everything should run - if (!flag_tp_comparison_functions) return true; - - const size_t buffer_size = 1024; - const size_t cli_length = strlen(flag_tp_comparison_functions); - gcc_assert(buffer_size > cli_length); - char whitelist[buffer_size]; - strcpy(whitelist, flag_tp_comparison_functions); - - - char* saveptr = whitelist; - char* token = NULL; - while (token = strtok_r(saveptr, ",", &saveptr)) - { - const bool name_allowed = strcmp(token, function_name) == 0; - if (name_allowed) return true; - } - - return false; -} - -static const bool -filter_comparisons_functions_int(unsigned function_id) -{ - if (!flag_tp_comparison_functions) return true; - - const char* function_name = type_playground::names[function_id]; - return filter_comparisons_functions_char(function_name); -} - -static const bool -filter_comparisons_functions(type_playground::type_comparison_func_t func) -{ - if (!flag_tp_comparison_functions) return true; - - for (unsigned i = 0; i < type_playground::type_comparisons; i++) - { - if (func != type_playground::comparisons[i]) continue; - - return filter_comparisons_functions_int(i); - } - - return false; -} - - -static void -compare_types_in_set(ptrset_t &types) -{ - for (auto i = types.points_to_record.cbegin(); i != types.points_to_record.cend(); ++i) - { - for (auto j = types.points_to_record.cbegin(); j != types.points_to_record.cend(); ++j) - { - const_tree a = *i; - const_tree b = *j; - for (unsigned k = 0; k < type_playground::type_comparisons; k++) - { - type_playground::type_comparison_func_t comparison = type_playground::comparisons[k]; - const bool allowed_to_run = filter_comparisons_functions(comparison); - if (!allowed_to_run) continue; - - const bool result = comparison(a, b); - } - } - } -} - -static void -filter_out_types_in_set(ptrset_t &types) -{ - // compare everything - if (!flag_tp_types_compared) return; - - const size_t buffer_size = 1024; - const size_t cli_length = strlen(flag_tp_comparison_functions); - gcc_assert(buffer_size > cli_length); - char whitelist[buffer_size]; - strcpy(whitelist, flag_tp_types_compared); - - bool name_allowed = false; - for (auto it = types.points_to_record.cbegin(); it != types.points_to_record.cend(); name_allowed ? ++it : it = types.points_to_record.erase(it)) - { - const_tree type = *it; - std::string observed_name = get_type_identifier(type); - char* saveptr = whitelist; - char* expected_name = NULL; - name_allowed = false; - - while (expected_name = strtok_r(saveptr, ",", &saveptr)) - { - name_allowed |= strcmp(expected_name, observed_name.c_str()) == 0; - } - } - -} - -static void -sanity_check_ptr_xor_complement(ptrset_t &types) -{ - for (auto i = types.points_to_record.cbegin(), e = types.points_to_record.cend(); i != e; ++i) - { - for (auto j = types.complement.cbegin(), f = types.complement.cend(); j != f; ++j) - { - const_tree type_ptr = *i; - gcc_assert(type_ptr); - const_tree type_com = *j; - gcc_assert(type_com); - const bool valid_sets = type_ptr != type_com; - if (valid_sets) continue; - // Normally, we want a stronger type comparison - // that is not just the pointer address - // but this is the first sanity check and then we will need to determine - // the stronger type comparison. - // But first we will need to fix the types... - TypeStringifier stringifier; - std::string name_ptr = stringifier.stringify(type_ptr); - std::string name_com = stringifier.stringify(type_com); - log("%p %s == %p %s\n", type_ptr, name_ptr.c_str(), type_com, name_com.c_str()); - gcc_unreachable(); - } - } -} - -void -collect_types(ptrset_t &types) -{ - collect_types_from_globals(types); - - cgraph_node *node = NULL; - long unsigned i = 0; - FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(node) - { - node->get_untransformed_body(); - collect_types_from_functions_with_gimple_body(node, types); - // We still need to collect types from - // the function signatures of functions without gimple bodies... - } - sanity_check_ptr_xor_complement(types); -} - -static TypeCollector _typeCollector; -ptrset_t *TypeCollector::ptrset = NULL; -static ExprCollector exprCollector; -TypeCollector * ExprCollector::typeCollector = &_typeCollector; - -static void -collect_types_from_expr(const_tree expr, ptrset_t &types) -{ - exprCollector.walk(expr); -} - - -static unsigned int -iphw_execute() -{ - //test_type_equality::run_tests(); - //test_naming_types::run_tests(); - ptrset_t types; - //ExprCollector::typeCollector = &_typeCollector; - TypeCollector::ptrset = &types; - collect_types(types); - filter_out_types_in_set(types); - compare_types_in_set(types); - return 0; -} - -namespace { -const pass_data pass_data_ipa_type_collector = -{ - SIMPLE_IPA_PASS, - "type-collector", - OPTGROUP_NONE, - TV_NONE, - (PROP_cfg | PROP_ssa), - 0, - 0, - TODO_rebuild_alias, - 0, -}; - -class pass_ipa_type_collector : public simple_ipa_opt_pass -{ -public: - pass_ipa_type_collector (gcc::context *ctx) - : simple_ipa_opt_pass(pass_data_ipa_type_collector, ctx) - {} - - virtual bool gate(function*) { return flag_ipa_type_collector; } - virtual unsigned execute (function*) { return iphw_execute(); } -}; -} // anon namespace - -simple_ipa_opt_pass* -make_pass_ipa_type_collector (gcc::context *ctx) -{ - return new pass_ipa_type_collector (ctx); -} diff --git a/gcc/ipa-type-collector.h b/gcc/ipa-type-collector.h deleted file mode 100644 index 16611c2db56..00000000000 --- a/gcc/ipa-type-collector.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "collect-types.h" - -void collect_types(ptrset_t &types); diff --git a/gcc/name-types.c b/gcc/name-types.c deleted file mode 100644 index fe8f6c5575b..00000000000 --- a/gcc/name-types.c +++ /dev/null @@ -1,421 +0,0 @@ -#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 "types-inlines.h" -#include <set> -#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. -// Also that's why we are returning a value rather than a -// pointer... - -static const std::string -type_to_string_simple(const_tree type) -{ - gcc_assert(type); - const enum tree_code code = TREE_CODE(type); - bool valid_input = false; - 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: - valid_input = true; - break; - default: - valid_input = false; - break; - } - gcc_assert(valid_input); - - - return std::string(get_tree_code_name(code)); -} - -static const std::string -type_to_string_get_field_name(const_tree field) -{ - assert_is_type(field, FIELD_DECL); - const_tree decl_name = DECL_NAME(field); - if (!decl_name) return std::string(""); - - const char* identifier = IDENTIFIER_POINTER(decl_name); - return std::string(identifier); -} - -static const unsigned -type_to_string_get_field_offset(const_tree field) -{ - assert_is_type(field, FIELD_DECL); - tree cst = byte_position(field); - gcc_assert(cst); - unsigned offset = tree_to_uhwi (cst); - return offset; -} - -static const unsigned -type_to_string_get_type_size(const_tree type) -{ - gcc_assert(type); - const_tree type_size = TYPE_SIZE(type); - const bool is_incomplete = NULL_TREE == type_size; - if (is_incomplete) return 0; - - const bool fits_uhwi = tree_fits_uhwi_p(type_size); - if (fits_uhwi) return tree_to_uhwi (type_size); - - const bool fits_shwi = tree_fits_shwi_p(type_size); - if (fits_shwi) return tree_to_shwi (type_size); - - return 0; -} - -const std::string -get_type_identifier(const_tree type) -{ - tree name = TYPE_NAME(type); - // The TYPE_NAME will be NULL_TREE for a type - // that is not a built-in type, the result of a typedef - // or a named class type. - const bool no_name = NULL_TREE == name; - if (no_name) return std::string(""); - - const enum tree_code name_code = TREE_CODE(name); - const bool is_name_type_decl = TYPE_DECL == name_code; - name = is_name_type_decl ? DECL_NAME(name) : name; - const char* identifier_ptr = IDENTIFIER_POINTER(name); - gcc_assert(identifier_ptr); - return std::string(identifier_ptr); -} - -static const std::string -type_to_string_get_record_name(const_tree type) -{ - assert_is_type(type, RECORD_TYPE); - tree name = TYPE_NAME(type); - // The TYPE_NAME will be NULL_TREE for a type - // that is not a built-in type, the result of a typedef - // or a named class type. - const bool no_name = NULL_TREE == name; - if (no_name) return std::string(""); - - const enum tree_code name_code = TREE_CODE(name); - const bool is_name_type_decl = TYPE_DECL == name_code; - name = is_name_type_decl ? DECL_NAME(name) : name; - const char* identifier_ptr = IDENTIFIER_POINTER(name); - gcc_assert(identifier_ptr); - return std::string(identifier_ptr); -} - -static const std::string -type_to_string_get_record_or_union_name(const_tree type) -{ - - const enum tree_code code = TREE_CODE(type); - const bool is_record = RECORD_TYPE == code; - const bool is_union = UNION_TYPE == code; - const bool is_valid_input = is_record || is_union; - gcc_assert(is_valid_input); - tree name = TYPE_NAME(type); - - // The TYPE_NAME will be NULL_TREE for a type - // that is not a built-in type, the result of a typedef - // or a named class type. - const bool no_name = NULL_TREE == name; - if (no_name) return std::string(""); - - const enum tree_code name_code = TREE_CODE(name); - const bool is_name_type_decl = TYPE_DECL == name_code; - name = is_name_type_decl ? DECL_NAME(name) : name; - const char* identifier_ptr = IDENTIFIER_POINTER(name); - gcc_assert(identifier_ptr); - return std::string(identifier_ptr); -} - -/* - * The idea behind this function is to receive either - * a record or a union type and return a string that - * represents this type. - * The output should look something like this: - * 0: astruct { - * 0: int a - * 8: int b - * 16: bstruct* - * 24: cstruct { - * 0: int a - * } - * 32: { - * } - * } - * The question I have now... is... should we follos bstruct* - * to see what it points to? Because, maybe there's two bstruct*s - * defined in different TU? - * So maybe more like this: - * 0: astruct { - * 0: int a - * 8: int b - * 16: bstruct { - * 0: int a - * }* - * 24: cstruct { - * 0: int a - * } - * 32: { - * } - */ -static const std::string -type_to_string_record_or_union(const_tree type) -{ - gcc_assert(type); - const enum tree_code code = TREE_CODE(type); - const bool is_record = RECORD_TYPE == code; - const bool is_union = UNION_TYPE == code; - const bool is_valid_input = is_record || is_union; - gcc_assert(is_valid_input); - - std::string name = type_to_string_get_record_or_union_name(type); - std::string aggregate = name + std::string(" {"); - - for (tree field = TYPE_FIELDS(type); field; field = DECL_CHAIN(field)) - { - //std::string field_name = type_to_string_get_field_name(field); - const_tree field_type = TREE_TYPE(field); - const unsigned field_offset = type_to_string_get_field_offset(field); - std::string field_type_name = type_to_string(field_type, field_offset); - aggregate += field_type_name + std::string(";"); - } - - aggregate += "}"; - return aggregate; -} - -static const std::string -type_to_string_record(const_tree type) -{ - assert_is_type(type, RECORD_TYPE); - return type_to_string_record_or_union(type); -} - -static const std::string -type_to_string_union(const_tree type) -{ - assert_is_type(type, UNION_TYPE); - return type_to_string_record_or_union(type); -} - -static const std::string -type_to_string_wrapper(const_tree type) -{ - gcc_assert(type); - const enum tree_code code = TREE_CODE(type); - bool is_valid_input = false; - switch (code) - { - case POINTER_TYPE: - case ARRAY_TYPE: - case REFERENCE_TYPE: - is_valid_input = true; - break; - default: - is_valid_input = false; - break; - } - gcc_assert(is_valid_input); - - const_tree inner_type = TREE_TYPE(type); - return type_to_string(inner_type, 0, false); -} - -static const std::string -type_to_string_pointer(const_tree type) -{ - assert_is_type(type, POINTER_TYPE); - return type_to_string_wrapper(type) + std::string("*"); -} - -static const std::string -type_to_string_array(const_tree type) -{ - assert_is_type(type, ARRAY_TYPE); - return type_to_string_wrapper(type) + std::string("[]"); -} - -static const std::string -type_to_string_reference(const_tree type) -{ - assert_is_type(type, REFERENCE_TYPE); - return type_to_string_wrapper(type) + std::string("&"); -} - -static const std::string -type_to_string_function_or_method(const_tree type) -{ - gcc_assert(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 = is_function || is_method; - gcc_assert(is_valid); - - const_tree return_type = TREE_TYPE(type); - gcc_assert(return_type); - - const std::string return_type_name = type_to_string(return_type, 0, false); - - std::string aggregate(""); - - for(tree param = TYPE_ARG_TYPES(type); param; param = TREE_CHAIN(param)) - { - const_tree param_type = TREE_VALUE(param); - //TODO: Why no param type? - //gcc_assert(param_type); - const bool has_more_params = TREE_CHAIN(param); - aggregate += type_to_string(param_type); - if (!has_more_params) break; - - aggregate += std::string(", "); - } - - //TODO: Add base_type for method types - std::string retval = return_type_name + std::string("(") + aggregate + std::string(")"); - return retval; -} - -static const std::string -type_to_string_function(const_tree type) -{ - assert_is_type(type, FUNCTION_TYPE); - return type_to_string_function_or_method(type); -} - -static const std::string -type_to_string_method(const_tree type) -{ - assert_is_type(type, METHOD_TYPE); - return type_to_string_function_or_method(type); -} - - -const std::string -type_to_string(const_tree type, const unsigned field_offset, const bool add_prelude) -{ - gcc_assert(type); - const enum tree_code code = TREE_CODE(type); - const unsigned size = type_to_string_get_type_size(type); - std::string prelude = add_prelude ? std::to_string(field_offset) + std::string(",") + std::to_string(field_offset + size) + std::string(":") : std::string(""); - - 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: - return prelude + type_to_string_simple(type); - break; - default: - break; - } - - switch (code) - { - case RECORD_TYPE: - return prelude + type_to_string_record(type); - break; - case UNION_TYPE: - return prelude + type_to_string_union(type); - break; - case POINTER_TYPE: - return prelude + type_to_string_pointer(type); - break; - case REFERENCE_TYPE: - return prelude + type_to_string_reference(type); - break; - case ARRAY_TYPE: - return prelude + type_to_string_array(type); - break; - case FUNCTION_TYPE: - return prelude + type_to_string_function(type); - break; - case METHOD_TYPE: - return prelude + type_to_string_method(type); - break; - case QUAL_UNION_TYPE: - case LANG_TYPE: - default: - // unimplemented - gcc_unreachable(); - break; - } - - gcc_unreachable(); - return std::string("you shouldn't ever see this"); -} - -namespace test_naming_types { - -void test_generic_to_string(const enum tree_code code, const char * expected_char_array) -{ - std::string expected_value(expected_char_array); - tree type = make_node(code); - std::string observed_value = type_to_string(type); - const bool success = expected_value.compare(observed_value) == 0; - gcc_assert(success); - -} -void test_simple_to_string() -{ - test_generic_to_string(VOID_TYPE, "0:void_type"); - test_generic_to_string(INTEGER_TYPE, "0:integer_type"); - test_generic_to_string(REAL_TYPE, "0:real_type"); - test_generic_to_string(FIXED_POINT_TYPE, "0:fixed_point_type"); - test_generic_to_string(COMPLEX_TYPE, "0:complex_type"); - test_generic_to_string(ENUMERAL_TYPE, "0:enumeral_type"); - test_generic_to_string(BOOLEAN_TYPE, "0:boolean_type"); - test_generic_to_string(OFFSET_TYPE, "0:offset_type"); -} - -void run_tests() -{ - test_simple_to_string(); -} -}; diff --git a/gcc/name-types.h b/gcc/name-types.h deleted file mode 100644 index b127bef17ac..00000000000 --- a/gcc/name-types.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "tree.h" -#include <string> - -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); diff --git a/gcc/passes.def b/gcc/passes.def index 08a863fe617..b4c0fa0d3c1 100644 --- a/gcc/passes.def +++ b/gcc/passes.def @@ -151,7 +151,6 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_ipa_devirt); NEXT_PASS (pass_ipa_type_escape_analysis); NEXT_PASS (pass_ipa_hello_world); - NEXT_PASS (pass_ipa_type_collector); NEXT_PASS (pass_ipa_cp); NEXT_PASS (pass_ipa_sra); NEXT_PASS (pass_ipa_cdtor_merge); diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index bdb349b398c..25fccb80f31 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -504,7 +504,6 @@ extern simple_ipa_opt_pass *make_pass_ipa_free_lang_data (gcc::context *ctxt); extern simple_ipa_opt_pass *make_pass_ipa_free_fn_summary (gcc::context *ctxt); extern simple_ipa_opt_pass *make_pass_ipa_type_escape_analysis (gcc::context *ctxt); extern simple_ipa_opt_pass *make_pass_ipa_hello_world (gcc::context *ctxt); -extern simple_ipa_opt_pass *make_pass_ipa_type_collector (gcc::context *ctxt); extern simple_ipa_opt_pass *make_pass_ipa_prototype (gcc::context *ctxt); extern ipa_opt_pass_d *make_pass_ipa_cp (gcc::context *ctxt); extern ipa_opt_pass_d *make_pass_ipa_sra (gcc::context *ctxt); diff --git a/gcc/type-collector.c b/gcc/type-collector.c index 3def624c4ac..d17dde42933 100644 --- a/gcc/type-collector.c +++ b/gcc/type-collector.c @@ -35,10 +35,10 @@ void TypeCollector::collect(const_tree t) { - const bool in_set = ptrset->in_universe(t); + const bool in_set = ptrset.in_universe(t); // memoization... if (in_set) return; - gcc_assert(ptrset && t); + gcc_assert(t); if (!ptr.empty()) { @@ -50,13 +50,40 @@ TypeCollector::collect(const_tree t) walk(t); } +void +TypeCollector::_sanity_check() +{ + for (auto i = ptrset.points_to_record.cbegin(), e = ptrset.points_to_record.cend(); i != e; ++i) + { + for (auto j = ptrset.complement.cbegin(), f = ptrset.complement.cend(); j != f; ++j) + { + const_tree type_ptr = *i; + gcc_assert(type_ptr); + const_tree type_com = *j; + gcc_assert(type_com); + const bool valid_sets = type_ptr != type_com; + if (valid_sets) continue; + // Normally, we want a stronger type comparison + // that is not just the pointer address + // but this is the first sanity check and then we will need to determine + // the stronger type comparison. + // But first we will need to fix the types... + TypeStringifier stringifier; + std::string name_ptr = stringifier.stringify(type_ptr); + std::string name_com = stringifier.stringify(type_com); + log("%p %s == %p %s\n", type_ptr, name_ptr.c_str(), type_com, name_com.c_str()); + gcc_unreachable(); + } + } +} + bool TypeCollector::is_memoized(const_tree t) { - const bool in_set = ptrset->in_universe(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); + const bool points_to_record = ptrset.in_points_to_record(t); for (auto i = ptr.begin(), e = ptr.end(); i != e; ++i) { i->second |= points_to_record; @@ -151,7 +178,7 @@ TypeCollector::_walk_boolean_post(const_tree t) void TypeCollector::_collect_simple(const_tree t) { - ptrset->insert(t, ptr[t]); + ptrset.insert(t, ptr[t]); ptr.erase(t); } diff --git a/gcc/type-collector.hpp b/gcc/type-collector.hpp index 98b08d99f83..44d7695ccc5 100644 --- a/gcc/type-collector.hpp +++ b/gcc/type-collector.hpp @@ -9,11 +9,11 @@ class TypeCollector : public TypeWalker { public: void collect(const_tree t); TypeCollector() {}; - - static ptrset_t* ptrset; + ptrset_t get_pointer_set() { _sanity_check(); return ptrset; } private: std::map<const_tree, bool> ptr; - + ptrset_t ptrset; + void _sanity_check(); void _collect_simple(const_tree t); virtual bool is_memoized(const_tree t); diff --git a/gcc/type-escaper.c b/gcc/type-escaper.c new file mode 100644 index 00000000000..32d39611ea1 --- /dev/null +++ b/gcc/type-escaper.c @@ -0,0 +1,121 @@ +#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" // needed for gimple-iterator.h +#include "gimple-iterator.h" +#include "gimple-ssa.h" +#include <stdbool.h> +#include "types-inlines.h" + +#include "type-escaper.hpp" + +bool +TypeEscaper::is_memoized(const_tree t) +{ + const bool in_set = calc.find(t) != calc.end(); + if (!in_set) return false; + + const bool will_not_escape = !_reason.is_escaping; + if (will_not_escape) return true; + + const bool already_escaping = in_set && calc[t].is_escaping; + if (already_escaping) return true; + + return false; +} + +void +TypeEscaper::update(const_tree t, Reason r) +{ + gcc_assert(t); + _reason = r; + walk(t); +} + +void +TypeEscaper::_update(const_tree t) +{ + gcc_assert(t); + // assert type is in universe + const bool already_in_typemap = calc.find(t) != calc.end(); + already_in_typemap ? calc[t] |= _reason : calc[t] = _reason; +} + +void +TypeEscaper::_walk_array_pre(const_tree t) +{ + _update(t); +} + +void +TypeEscaper::_walk_pointer_pre(const_tree t) +{ + _update(t); +} + +void +TypeEscaper::_walk_reference_pre(const_tree t) +{ + _update(t); +} + +void +TypeEscaper::_walk_record_pre(const_tree t) +{ + _update(t); +} + +void +TypeEscaper::_walk_union_pre(const_tree t) +{ + _inside_union++; + bool is_escaping = _inside_union > 0; + _update(t); + // After us... so that we can see what is our previous value + _reason.type_is_in_union |= is_escaping; + _reason.is_escaping |= is_escaping; +} + +void +TypeEscaper::_walk_union_post(const_tree t) +{ + _inside_union--; + Reason prev = calc[t]; + _update(t); + _reason = prev; +} + +void +TypeEscaper::_walk_function_pre(const_tree t) +{ + _update(t); +} + +void +TypeEscaper::_walk_method_pre(const_tree t) +{ + _update(t); +} diff --git a/gcc/type-escaper.hpp b/gcc/type-escaper.hpp index c0bea8383fa..ccd7534e293 100644 --- a/gcc/type-escaper.hpp +++ b/gcc/type-escaper.hpp @@ -1,14 +1,16 @@ #pragma once +#include "type-walker.hpp" #include "ipa-prototype.h" +#include "collect-types.h" class TypeEscaper : public TypeWalker { public: - TypeEscaper() : _inside_union(0) {}; + TypeEscaper(ptrset_t &p) : _inside_union(0), _ptrset(p) {}; void update(const_tree t, Reason r); - static ptrset_t *types; - static typemap calc; + ptrset_t &_ptrset; + typemap calc; private: virtual void _walk_pointer_pre(const_tree t); virtual void _walk_reference_pre(const_tree t); @@ -24,90 +26,3 @@ private: void _update(const_tree t); }; -bool -TypeEscaper::is_memoized(const_tree t) -{ - const bool in_set = calc.find(t) != calc.end(); - if (!in_set) return false; - - const bool will_not_escape = !_reason.is_escaping; - if (will_not_escape) return true; - - const bool already_escaping = in_set && calc[t].is_escaping; - if (already_escaping) return true; - - return false; -} - -void -TypeEscaper::update(const_tree t, Reason r) -{ - gcc_assert(t && types); - _reason = r; - walk(t); -} - -void -TypeEscaper::_update(const_tree t) -{ - gcc_assert(t); - // assert type is in universe - const bool already_in_typemap = calc.find(t) != calc.end(); - already_in_typemap ? calc[t] |= _reason : calc[t] = _reason; -} - -void -TypeEscaper::_walk_array_pre(const_tree t) -{ - _update(t); -} - -void -TypeEscaper::_walk_pointer_pre(const_tree t) -{ - _update(t); -} - -void -TypeEscaper::_walk_reference_pre(const_tree t) -{ - _update(t); -} - -void -TypeEscaper::_walk_record_pre(const_tree t) -{ - _update(t); -} - -void -TypeEscaper::_walk_union_pre(const_tree t) -{ - _inside_union++; - bool is_escaping = _inside_union > 0; - _update(t); - // After us... so that we can see what is our previous value - _reason.type_is_in_union |= is_escaping; - _reason.is_escaping |= is_escaping; -} - -void -TypeEscaper::_walk_union_post(const_tree t) -{ - _inside_union--; - Reason prev = calc[t]; - _update(t); - _reason = prev; -} - -void -TypeEscaper::_walk_function_pre(const_tree t) -{ - _update(t); -} - -void -TypeEscaper::_walk_method_pre(const_tree t) -{ - _update(t); -} diff --git a/gcc/type-walker.hpp b/gcc/type-walker.hpp index 0f775d170e8..2484843d135 100644 --- a/gcc/type-walker.hpp +++ b/gcc/type-walker.hpp @@ -3,8 +3,13 @@ #include <set> class TypeWalker { +public: + TypeWalker() {}; + void walk(const_tree t); + protected: typedef std::set<const_tree> tset_t; + private: tset_t tset; @@ -90,8 +95,5 @@ private: void walk_method(const_tree t, tset_t &tset); void _walk_method(const_tree t, tset_t &tset); virtual void _walk_method_post(const_tree t) {}; -public: - void walk(const_tree t); - TypeWalker() {}; }; |