summaryrefslogtreecommitdiff
path: root/gcc/type-walker.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/type-walker.c')
-rw-r--r--gcc/type-walker.c402
1 files changed, 402 insertions, 0 deletions
diff --git a/gcc/type-walker.c b/gcc/type-walker.c
new file mode 100644
index 00000000000..df672d8bdf0
--- /dev/null
+++ b/gcc/type-walker.c
@@ -0,0 +1,402 @@
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "tree.h"
+#include "gimple-expr.h"
+#include "predict.h"
+#include "alloc-pool.h"
+#include "tree-pass.h"
+#include "cgraph.h"
+#include "diagnostic.h"
+#include "fold-const.h"
+#include "gimple-fold.h"
+#include "symbol-summary.h"
+#include "tree-vrp.h"
+#include "ipa-prop.h"
+#include "tree-pretty-print.h"
+#include "tree-inline.h"
+#include "ipa-fnsummary.h"
+#include "ipa-utils.h"
+#include "tree-ssa-ccp.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "tree-ssa-alias.h"
+#include "tree-ssanames.h"
+#include "gimple.h"
+#include "cfg.h"
+#include "gimple-iterator.h"
+#include "gimple-ssa.h"
+
+#include "type-walker.hpp"
+#include "types-inlines.h"
+
+void
+TypeWalker::walk(const_tree t)
+{
+ gcc_assert(t);
+ this->tset.clear();
+ this->_walk(t, this->tset);
+}
+
+void
+TypeWalker::_walk(const_tree type, tset_t &tset)
+{
+ gcc_assert(type);
+ // Have we encountered this type before? If so, we are likely
+ // recurring...
+ const bool in_set = tset.find(type) != tset.end();
+ if (in_set) return;
+
+ const bool _is_memoized = is_memoized(type);
+ if (_is_memoized) return;
+
+ tset.insert(type);
+ const enum tree_code code = TREE_CODE(type);
+ switch (code)
+ {
+ case VOID_TYPE:
+ this->walk_void(type, tset);
+ break;
+ case INTEGER_TYPE:
+ this->walk_integer(type, tset);
+ break;
+ case REAL_TYPE:
+ this->walk_real(type, tset);
+ break;
+ case FIXED_POINT_TYPE:
+ this->walk_fixed_point(type, tset);
+ break;
+ case COMPLEX_TYPE:
+ this->walk_complex(type, tset);
+ break;
+ case ENUMERAL_TYPE:
+ this->walk_enumeral(type, tset);
+ break;
+ case BOOLEAN_TYPE:
+ this->walk_boolean(type, tset);
+ break;
+ case OFFSET_TYPE:
+ this->walk_offset(type, tset);
+ break;
+ case RECORD_TYPE:
+ this->walk_record(type, tset);
+ break;
+ case POINTER_TYPE:
+ this->walk_pointer(type, tset);
+ break;
+ case REFERENCE_TYPE:
+ this->walk_reference(type, tset);
+ break;
+ case ARRAY_TYPE:
+ this->walk_array(type, tset);
+ break;
+ case UNION_TYPE:
+ this->walk_union(type, tset);
+ break;
+ case FUNCTION_TYPE:
+ this->walk_function(type, tset);
+ break;
+ case METHOD_TYPE:
+ this->walk_method(type, tset);
+ break;
+ case QUAL_UNION_TYPE:
+ case LANG_TYPE:
+ default:
+ gcc_unreachable();
+ break;
+ }
+
+ tset.erase(type);
+}
+
+void
+TypeWalker::walk_void(const_tree t, tset_t &tset)
+{
+ assert_is_type(t, VOID_TYPE);
+ _walk_void_pre(t);
+ _walk_void(t, tset);
+ _walk_void_post(t);
+}
+
+void
+TypeWalker::_walk_void(const_tree t, tset_t &tset) {};
+
+void
+TypeWalker::walk_integer(const_tree t, tset_t &tset)
+{
+ assert_is_type(t, INTEGER_TYPE);
+ _walk_integer_pre(t);
+ _walk_integer(t, tset);
+ _walk_integer_post(t);
+}
+
+void
+TypeWalker::_walk_integer(const_tree t, tset_t &tset) {};
+
+void
+TypeWalker::walk_real(const_tree t, tset_t &tset)
+{
+ assert_is_type(t, REAL_TYPE);
+ _walk_real_pre(t);
+ _walk_real(t, tset);
+ _walk_real_post(t);
+}
+
+void
+TypeWalker::_walk_real(const_tree t, tset_t &tset) {};
+
+void
+TypeWalker::walk_boolean(const_tree t, tset_t &tset)
+{
+ assert_is_type(t, BOOLEAN_TYPE);
+ _walk_boolean_pre(t);
+ _walk_boolean(t, tset);
+ _walk_boolean_post(t);
+}
+
+void
+TypeWalker::_walk_boolean(const_tree t, tset_t &tset) {};
+
+void
+TypeWalker::walk_offset(const_tree t, tset_t &tset)
+{
+ assert_is_type(t, OFFSET_TYPE);
+ _walk_offset_pre(t);
+ _walk_offset(t, tset);
+ _walk_offset_post(t);
+}
+
+void
+TypeWalker::_walk_offset(const_tree t, tset_t &tset) {};
+
+void
+TypeWalker::walk_fixed_point(const_tree t, tset_t &tset)
+{
+ assert_is_type(t, FIXED_POINT_TYPE);
+ _walk_fixed_point_pre(t);
+ _walk_fixed_point(t, tset);
+ _walk_fixed_point_post(t);
+}
+
+void
+TypeWalker::_walk_fixed_point(const_tree t, tset_t &tset) {};
+
+void
+TypeWalker::walk_complex(const_tree t, tset_t &tset)
+{
+ assert_is_type(t, COMPLEX_TYPE);
+ _walk_complex_pre(t);
+ _walk_complex(t, tset);
+ _walk_complex_post(t);
+}
+
+void
+TypeWalker::_walk_complex(const_tree t, tset_t &tset) {};
+
+void
+TypeWalker::walk_enumeral(const_tree t, tset_t &tset)
+{
+ assert_is_type(t, ENUMERAL_TYPE);
+ _walk_enumeral_pre(t);
+ _walk_enumeral(t, tset);
+ _walk_enumeral_post(t);
+}
+
+void
+TypeWalker::_walk_enumeral(const_tree t, tset_t &tset) {};
+
+void
+TypeWalker::walk_pointer(const_tree t, tset_t &tset)
+{
+ assert_is_type(t, POINTER_TYPE);
+ _walk_pointer_pre(t);
+ _walk_pointer(t, tset);
+ _walk_pointer_post(t);
+}
+
+void
+TypeWalker::_walk_pointer(const_tree t, tset_t &tset)
+{
+ _walk_wrapper(t, tset);
+}
+
+void
+TypeWalker::walk_reference(const_tree t, tset_t &tset)
+{
+ assert_is_type(t, REFERENCE_TYPE);
+ _walk_reference_pre(t);
+ _walk_reference(t, tset);
+ _walk_reference_post(t);
+}
+
+void
+TypeWalker::_walk_reference(const_tree t, tset_t &tset)
+{
+ _walk_wrapper(t, tset);
+}
+
+void
+TypeWalker::walk_array(const_tree t, tset_t &tset)
+{
+ assert_is_type(t, ARRAY_TYPE);
+ _walk_array_pre(t);
+ _walk_array(t, tset);
+ _walk_array_post(t);
+}
+
+void
+TypeWalker::_walk_array(const_tree t, tset_t &tset)
+{
+ _walk_wrapper(t, tset);
+}
+
+void
+TypeWalker::_walk_wrapper(const_tree t, tset_t &tset)
+{
+ const_tree inner_type = TREE_TYPE(t);
+ gcc_assert(inner_type);
+ _walk(inner_type, tset);
+}
+
+void
+TypeWalker::walk_record(const_tree t, tset_t &tset)
+{
+ assert_is_type(t, RECORD_TYPE);
+ _walk_record_pre(t);
+ _walk_record(t, tset);
+ _walk_record_post(t);
+}
+
+void
+TypeWalker::_walk_record(const_tree t, tset_t &tset)
+{
+ _walk_record_or_union(t, tset);
+}
+
+void
+TypeWalker::walk_union(const_tree t, tset_t &tset)
+{
+ assert_is_type(t, UNION_TYPE);
+ _walk_union_pre(t);
+ _walk_union(t, tset);
+ _walk_union_post(t);
+}
+
+void
+TypeWalker::_walk_union(const_tree t, tset_t &tset)
+{
+ _walk_record_or_union(t, tset);
+}
+
+void
+TypeWalker::_walk_record_or_union(const_tree t, tset_t &tset)
+{
+ for (tree field = TYPE_FIELDS(t); field; field = DECL_CHAIN(field))
+ {
+ gcc_assert(field);
+ walk_field(field, tset);
+ }
+}
+
+void
+TypeWalker::walk_field(const_tree t, tset_t &tset)
+{
+ _walk_field_pre(t);
+ _walk_field(t, tset);
+ _walk_field_post(t);
+}
+
+void
+TypeWalker::_walk_field(const_tree t, tset_t &tset)
+{
+ const_tree inner_type = TREE_TYPE(t);
+ gcc_assert(inner_type);
+ _walk(inner_type, tset);
+}
+
+void
+TypeWalker::walk_function(const_tree t, tset_t &tset)
+{
+ assert_is_type(t, FUNCTION_TYPE);
+ _walk_function_pre(t);
+ _walk_function(t, tset);
+ _walk_function_post(t);
+}
+
+void
+TypeWalker::_walk_function(const_tree t, tset_t &tset)
+{
+ _walk_function_or_method(t, tset);
+}
+
+void
+TypeWalker::walk_method(const_tree t, tset_t &tset)
+{
+ assert_is_type(t, METHOD_TYPE);
+ _walk_method_pre(t);
+ _walk_method(t, tset);
+ _walk_method_post(t);
+}
+
+void
+TypeWalker::_walk_method(const_tree t, tset_t &tset)
+{
+ _walk_function_or_method(t, tset);
+}
+
+void
+TypeWalker::_walk_function_or_method(const_tree t, tset_t &tset)
+{
+ const_tree ret_type = TREE_TYPE(t);
+ walk_return(ret_type, tset);
+ walk_args(t, tset);
+}
+
+void
+TypeWalker::walk_return(const_tree t, tset_t &tset)
+{
+ _walk_return_pre(t);
+ _walk_return(t, tset);
+ _walk_return_post(t);
+}
+
+void
+TypeWalker::_walk_return(const_tree t, tset_t &tset)
+{
+ _walk(t, tset);
+}
+
+void
+TypeWalker::walk_args(const_tree t, tset_t &tset)
+{
+ _walk_args_pre(t);
+ _walk_args(t, tset);
+ _walk_args_post(t);
+}
+
+void
+TypeWalker::_walk_args(const_tree t, tset_t &tset)
+{
+ assert_is_type(t, FUNCTION_TYPE);
+ for (tree arg_node = TYPE_ARG_TYPES(t); NULL_TREE != arg_node; arg_node = TREE_CHAIN(arg_node))
+ {
+ tree arg_node_type = TREE_VALUE(arg_node);
+ gcc_assert(arg_node_type);
+ walk_arg(arg_node_type, tset);
+ }
+}
+
+void
+TypeWalker::walk_arg(const_tree t, tset_t &tset)
+{
+ _walk_arg_pre(t);
+ _walk_arg(t, tset);
+ _walk_arg_post(t);
+}
+
+void
+TypeWalker::_walk_arg(const_tree t, tset_t &tset)
+{
+ _walk(t, tset);
+}