summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErick Ochoa <erick.ochoa@theobroma-systems.com>2020-06-04 16:56:18 +0200
committerErick Ochoa <erick.ochoa@theobroma-systems.com>2020-06-04 16:56:18 +0200
commit1c721a6592240ec17c190daf0f5897ce6f3046c8 (patch)
treee81deba6896d8e73c5b18fd3cf500c0daddaf60c
parent2da29e3b3af58440a91bcad0c12585d5f1b9bd4c (diff)
parentb49aa30869c09910acb6c6e83f37b7fec15b25c7 (diff)
Merge branch 'erick/type-escape-analysis-refactor' into common/ipa-str-reorg
-rw-r--r--gcc/Makefile.in12
-rw-r--r--gcc/collect-types.c4
-rw-r--r--gcc/common.opt4
-rw-r--r--gcc/compare-types.c467
-rw-r--r--gcc/compare-types.h18
-rw-r--r--gcc/expr-collector.c2
-rw-r--r--gcc/expr-collector.hpp6
-rw-r--r--gcc/expr-escaper.c52
-rw-r--r--gcc/expr-escaper.hpp24
-rw-r--r--gcc/expr-walker.c32
-rw-r--r--gcc/expr-walker.hpp3
-rw-r--r--gcc/gimple-collector.c116
-rw-r--r--gcc/gimple-collector.hpp20
-rw-r--r--gcc/gimple-escaper.c143
-rw-r--r--gcc/gimple-escaper.hpp22
-rw-r--r--gcc/gimple-walker.c218
-rw-r--r--gcc/gimple-walker.hpp34
-rw-r--r--gcc/ipa-prototype.c490
-rw-r--r--gcc/ipa-type-collector.c594
-rw-r--r--gcc/ipa-type-collector.h5
-rw-r--r--gcc/name-types.c421
-rw-r--r--gcc/name-types.h7
-rw-r--r--gcc/passes.def1
-rw-r--r--gcc/tree-pass.h1
-rw-r--r--gcc/type-collector.c37
-rw-r--r--gcc/type-collector.hpp6
-rw-r--r--gcc/type-escaper.c121
-rw-r--r--gcc/type-escaper.hpp95
-rw-r--r--gcc/type-walker.hpp8
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() {};
};