summaryrefslogtreecommitdiff
path: root/gcc/name-types.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/name-types.c')
-rw-r--r--gcc/name-types.c420
1 files changed, 420 insertions, 0 deletions
diff --git a/gcc/name-types.c b/gcc/name-types.c
new file mode 100644
index 00000000000..800ba6cb1d2
--- /dev/null
+++ b/gcc/name-types.c
@@ -0,0 +1,420 @@
+#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"
+
+// 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)
+{
+ if (!type) return std::string("why");
+ 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();
+}
+};