summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErick Ochoa <erick.ochoa@theobroma-systems.com>2020-05-28 13:32:51 +0200
committerErick Ochoa <erick.ochoa@theobroma-systems.com>2020-06-03 16:06:00 +0200
commitc355cf30a9400a293315617ef64a9a3e88755568 (patch)
treed1223364bd918940f6027cfec179c06282dcc14d
parentcbe56ad4aeca7eb01ae1233387def84fb74ee70a (diff)
sanity check passes
-rw-r--r--gcc/ipa-hello-world.c347
-rw-r--r--gcc/ipa-type-collector.c11
-rw-r--r--gcc/types-inlines.h11
3 files changed, 333 insertions, 36 deletions
diff --git a/gcc/ipa-hello-world.c b/gcc/ipa-hello-world.c
index 98cf274e6c6..cef1c981f31 100644
--- a/gcc/ipa-hello-world.c
+++ b/gcc/ipa-hello-world.c
@@ -100,7 +100,7 @@ update_typemap(const_tree type, ptrset_t &types, Reason reason, typemap &calc)
assert_type_is_in_ptrset(type, types);
const bool already_in_typemap = calc.find(type) != calc.end();
already_in_typemap ? calc[type] |= reason : calc[type] = reason;
- log("updating %s\n", get_type_identifier(type).c_str());
+ log("updating %s\n", type_to_string(type).c_str());
reason.print();
}
@@ -183,17 +183,9 @@ static void
update_escape_info_function(const_tree type, ptrset_t &types, Reason reason, typemap &calc)
{
assert_is_type(type, FUNCTION_TYPE);
- const_tree ret_type = TREE_TYPE(type);
- gcc_assert(ret_type);
- update_escape_info(ret_type, types, reason, calc);
-
- for (tree arg_node = TYPE_ARG_TYPES(type); NULL_TREE != arg_node; arg_node = TREE_CHAIN(arg_node))
- {
- const_tree arg_type = TREE_VALUE(arg_node);
- gcc_assert(arg_type);
- update_escape_info(arg_type, types, reason, calc);
- }
- //TODO: Add base_type for method types
+ update_typemap(type, types, reason, calc);
+ //Note, this is for function pointers, but we don't need to update the
+ //arguments because as long as the definition is not escaping, I think we are good...
}
static void
@@ -244,7 +236,7 @@ update_escape_info( const_tree type, ptrset_t &types, Reason reason, typemap &ca
break;
case FUNCTION_TYPE:
// We must not consider function pointers?
- //update_escape_info_function(type, types, reason, calc);
+ update_escape_info_function(type, types, reason, calc);
break;
case METHOD_TYPE:
default:
@@ -296,6 +288,7 @@ filter_known_function(cgraph_node *node)
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;
}
@@ -368,6 +361,159 @@ mark_escaping_function(ptrset_t &types, typemap &calc, cgraph_node *cnode)
reason2.return_is_visible = is_escaping;
mark_escaping_return_type(types, calc, cnode, reason2);
}
+static void update_escape_info_expr(ptrset_t &types, typemap &calc, const_tree expr, Reason reason);
+
+static void
+update_escape_info_leaf_expr(ptrset_t &types, typemap &calc, const_tree expr, Reason reason, const enum tree_code ex_code)
+{
+ assert_is_type(expr, ex_code);
+ const_tree type = TREE_TYPE(expr);
+ gcc_assert(type);
+ update_escape_info(type, types, reason, calc);
+}
+
+static void
+update_escape_info_ssa_name(ptrset_t &types, typemap &calc, const_tree expr, Reason reason)
+{
+ update_escape_info_leaf_expr(types, calc, expr, reason, SSA_NAME);
+}
+
+static void
+update_escape_info_integer_cst(ptrset_t &types, typemap &calc, const_tree expr, Reason reason)
+{
+ update_escape_info_leaf_expr(types, calc, expr, reason, INTEGER_CST);
+}
+
+static void
+update_escape_info_real_cst(ptrset_t &types, typemap &calc, const_tree expr, Reason reason)
+{
+ update_escape_info_leaf_expr(types, calc, expr, reason, REAL_CST);
+}
+
+static void
+update_escape_info_from_op(ptrset_t &types, typemap &calc, const_tree expr, Reason reason, unsigned n)
+{
+ gcc_assert(expr);
+ const_tree op_n = TREE_OPERAND(expr, n);
+ gcc_assert(op_n);
+ update_escape_info_expr(types, calc, op_n, reason);
+}
+
+static void
+update_escape_info_from_op0(ptrset_t &types, typemap &calc, const_tree expr, Reason reason, const enum tree_code ex_code)
+{
+ assert_is_type(expr, ex_code);
+ update_escape_info_from_op(types, calc, expr, reason, 0);
+}
+
+static void
+update_escape_info_from_op1(ptrset_t &types, typemap &calc, const_tree expr, Reason reason, const enum tree_code ex_code)
+{
+ assert_is_type(expr, ex_code);
+ update_escape_info_from_op(types, calc, expr, reason, 0);
+ update_escape_info_from_op(types, calc, expr, reason, 1);
+}
+
+static void
+update_escape_info_component_ref(ptrset_t &types, typemap &calc, const_tree expr, Reason reason)
+{
+ update_escape_info_from_op1(types, calc, expr, reason, COMPONENT_REF);
+}
+
+static void
+update_escape_info_mem_ref(ptrset_t &types, typemap &calc, const_tree expr, Reason reason)
+{
+ update_escape_info_from_op1(types, calc, expr, reason, MEM_REF);
+}
+
+static void
+update_escape_info_field_decl(ptrset_t &types, typemap &calc, const_tree expr, Reason reason)
+{
+ location_t loc = DECL_SOURCE_LOCATION(expr);
+ const bool is_builtin = BUILTINS_LOCATION == loc;
+ if (is_builtin) return;
+ update_escape_info_leaf_expr(types, calc, expr, reason, FIELD_DECL);
+}
+
+static void
+update_escape_info_var_decl(ptrset_t &types, typemap &calc, const_tree expr, Reason reason)
+{
+ location_t loc = DECL_SOURCE_LOCATION(expr);
+ const bool is_builtin = BUILTINS_LOCATION == loc;
+ if (is_builtin) return;
+ update_escape_info_leaf_expr(types, calc, expr, reason, VAR_DECL);
+}
+
+static void
+update_escape_info_array_ref(ptrset_t &types, typemap &calc, const_tree expr, Reason reason)
+{
+ update_escape_info_from_op1(types, calc, expr, reason, ARRAY_REF);
+}
+
+static void
+update_escape_info_addr_expr(ptrset_t &types, typemap &calc, const_tree expr, Reason reason)
+{
+ update_escape_info_from_op0(types, calc, expr, reason, ADDR_EXPR);
+}
+
+static void
+update_escape_info_constructor(ptrset_t &types, typemap &calc, const_tree expr, Reason reason)
+{
+ //TODO:
+}
+
+static void
+update_escape_info_expr(ptrset_t &types, typemap &calc, const_tree expr, Reason reason)
+{
+ gcc_assert(expr);
+ const_tree type = TREE_TYPE(expr);
+ gcc_assert(type);
+ const enum tree_code code = TREE_CODE(expr);
+ switch (code)
+ {
+ case SSA_NAME:
+ update_escape_info_ssa_name(types, calc, expr, reason);
+ break;
+ case INTEGER_CST:
+ update_escape_info_integer_cst(types, calc, expr, reason);
+ break;
+ case COMPONENT_REF:
+ update_escape_info_component_ref(types, calc, expr, reason);
+ break;
+ case MEM_REF:
+ update_escape_info_mem_ref(types, calc, expr, reason);
+ break;
+ case FIELD_DECL:
+ update_escape_info_field_decl(types, calc, expr, reason);
+ break;
+ case VAR_DECL:
+ update_escape_info_var_decl(types, calc, expr, reason);
+ break;
+ case ARRAY_REF:
+ update_escape_info_array_ref(types, calc, expr, reason);
+ break;
+ case ADDR_EXPR:
+ update_escape_info_addr_expr(types, calc, expr, reason);
+ break;
+ case CONSTRUCTOR:
+ update_escape_info_constructor(types, calc, expr, reason);
+ break;
+ case REAL_CST:
+ update_escape_info_real_cst(types, calc, expr, reason);
+ break;
+ case BIT_FIELD_REF:
+ case RESULT_DECL:
+ case PARM_DECL:
+ case STRING_CST:
+ case FUNCTION_DECL:
+ default:
+ {
+ log("tree_code: %s\n", get_tree_code_name(code));
+ gcc_unreachable();
+ }
+ break;
+ }
+}
static void
calculate_escaping_types_from_cast(ptrset_t &types, typemap &calc, gimple *stmt)
@@ -380,19 +526,61 @@ calculate_escaping_types_from_cast(ptrset_t &types, typemap &calc, gimple *stmt)
}
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:
@@ -414,14 +602,14 @@ calculate_escaping_types_from_call_lhs(ptrset_t &types, typemap &calc, undefset
if (!fn) return;
const bool is_undefined = undef.find(fn) != undef.end();
+#ifdef OPTIMIZED
if (!is_undefined) return;
+#endif
- const_tree lhs_type = TREE_TYPE(lhs);
- gcc_assert(lhs_type);
Reason reason {};
reason.is_escaping = is_undefined;
reason.return_is_visible = is_undefined;
- update_escape_info(lhs_type, types, reason, calc);
+ update_escape_info_expr(types, calc, lhs, reason);
}
static void
@@ -434,11 +622,12 @@ calculate_escaping_types_from_call_rhs(ptrset_t &types, typemap &calc, undefset
if (!fn) return;
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 {};
@@ -464,20 +653,50 @@ calculate_escaping_types_from_call(ptrset_t &types, typemap &calc, undefset &und
if (!fn) return;
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
@@ -549,6 +768,32 @@ calculate_escaping_types_from_cnode(ptrset_t &types, typemap &calc, cgraph_node
}
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 {};
+ reason.is_escaping = false;
+ reason.return_is_visible = false;
+ const_tree func_type = TREE_TYPE(decl);
+ assert_is_type(func_type, FUNCTION_TYPE);
+ // Only call this if it is interesting...
+ if (types.in_points_to_record(func_type)) update_typemap(func_type, types, reason, calc);
+ int i = 0;
+ tree var_decl = NULL;
+ FOR_EACH_LOCAL_DECL(func, i, var_decl)
+ {
+ gcc_assert(var_decl);
+ const_tree var_decl_type = TREE_TYPE(var_decl);
+ update_escape_info(var_decl_type, types, reason, calc);
+ }
+
+}
+
+static void
calculate_escaping_functions(ptrset_t &types, typemap &calc)
{
cgraph_node *cnode = NULL;
@@ -572,6 +817,7 @@ calculate_escaping_functions(ptrset_t &types, typemap &calc)
gcc_assert(decl);
undefined_functions.erase(decl);
mark_escaping_function(types, calc, cnode);
+ calculate_escaping_locals(types, calc, cnode);
}
FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(cnode)
@@ -629,19 +875,51 @@ sanity_check_escape_xor_not(ptrset_t &types)
const bool valid_sets = !eq_type_compare(type_esc, type_non);
if (valid_sets) continue;
log("comparing %s == %s\n", type_to_string(type_esc).c_str(), type_to_string(type_non).c_str());
+ //TODO: Remove this comment once we have restricted the "repairing" of sets a bit more.
//gcc_assert(valid_sets);
}
}
}
static void
-fix_escaping_types_in_set(ptrset_t &types)
+sanity_check_escape_union_not_equals_ptrset(ptrset_t &types)
{
- std::vector<const_tree> fixes;
+ typeset _union;
for (auto i = types.escaping.cbegin(), e = types.escaping.cend(); i != e; ++i)
{
- for (auto j = types.non_escaping.cbegin(), f = types.non_escaping.cend(); j != f; ++j)
+ const_tree type = *i;
+ _union.insert(type);
+ }
+
+ for (auto i = types.non_escaping.cbegin(), e = types.non_escaping.cend(); i != e; ++i)
+ {
+ const_tree type = *i;
+ _union.insert(type);
+ }
+
+
+ for (auto i = types.points_to_record.cbegin(), e = types.points_to_record.cend(); i != e; ++i)
+ {
+ const_tree type = *i;
+ const bool in_union = _union.find(type) != _union.end();
+ if (in_union) continue;
+ log("this type was not found in union %s\n", type_to_string(type).c_str());
+ gcc_unreachable();
+ }
+
+}
+
+static void
+fix_escaping_types_in_set(ptrset_t &types)
+{
+ bool fixed_point_reached = false;
+ do {
+ std::vector<const_tree> fixes;
+ fixed_point_reached = true;
+ for (auto i = types.escaping.cbegin(), e = types.escaping.cend(); i != e; ++i)
{
+ for (auto j = types.non_escaping.cbegin(), f = types.non_escaping.cend(); j != f; ++j)
+ {
const_tree type_esc = *i;
gcc_assert(type_esc);
const_tree type_non = *j;
@@ -655,25 +933,42 @@ fix_escaping_types_in_set(ptrset_t &types)
// By making sure that they are equal explicitly because of incompletenes...
// * type_non must be incomplete
// * type_non must be pointing to an incomplete type and match the structure of type_esc (those which can be compared)
- log("checking for incompleteness %s == %s\n", type_to_string(type_esc).c_str(), type_to_string(type_non).c_str());
- if (is_complete(type_non)) continue;
+ log("**NOT** checking for incompleteness %s == %s\n", type_to_string(type_esc).c_str(), type_to_string(type_non).c_str());
+ fixed_point_reached = false;
log("fixing %s == %s\n", type_to_string(type_esc).c_str(), type_to_string(type_non).c_str());
// Add incomplete to escaping
// delete incomplete from non_escaping
// We shouldn't do that inside our iteration loop.
fixes.push_back(type_non);
+ }
}
- }
- for (auto i = fixes.cbegin(), e = fixes.cend(); i != e; ++i)
- {
+ for (auto i = fixes.cbegin(), e = fixes.cend(); i != e; ++i)
+ {
const_tree escaping_type = *i;
types.escaping.insert(escaping_type);
types.non_escaping.erase(escaping_type);
+ }
+ } while (!fixed_point_reached);
+}
+
+static void
+print_escaping_types_in_set(ptrset_t &types)
+{
+ std::vector<const_tree> fixes;
+ for (auto i = types.non_escaping.cbegin(), e = types.non_escaping.cend(); i != e; ++i)
+ {
+ const_tree type_non = *i;
+ gcc_assert(type_non);
+
+ log("non_escaping: %s \n", type_to_string(type_non).c_str());
}
+
}
+
+
static unsigned int
iphw_execute()
{
@@ -688,6 +983,8 @@ iphw_execute()
sanity_check_escape_xor_not(types);
fix_escaping_types_in_set(types);
sanity_check_escape_xor_not(types);
+ sanity_check_escape_union_not_equals_ptrset(types);
+ print_escaping_types_in_set(types);
gcc_assert(false);
return 0;
}
diff --git a/gcc/ipa-type-collector.c b/gcc/ipa-type-collector.c
index 9b70cea5c0d..5c4b32afa47 100644
--- a/gcc/ipa-type-collector.c
+++ b/gcc/ipa-type-collector.c
@@ -74,17 +74,6 @@ static type_comparison_func_t comparisons[type_comparisons] = {
}
static void collect_types_from_expr(const_tree expr, ptrset_t &types);
-
-inline void
-is_gimple_rhs_class(gimple *stmt, const enum gimple_rhs_class ex_class)
-{
- gcc_assert(stmt);
- is_gimple_code(stmt, GIMPLE_ASSIGN);
- const enum gimple_rhs_class ob_class = gimple_assign_rhs_class(stmt);
- const bool succeeds = ex_class == ob_class;
- gcc_assert(succeeds);
-}
-
static void
collect_types_from_op(const_tree expr, ptrset_t &types, unsigned n)
{
diff --git a/gcc/types-inlines.h b/gcc/types-inlines.h
index 404176c7cea..fb42e2c9a9c 100644
--- a/gcc/types-inlines.h
+++ b/gcc/types-inlines.h
@@ -1,6 +1,7 @@
#pragma once
+
inline void
log(const char* const fmt, ...)
{
@@ -53,3 +54,13 @@ assert_is_complete_type(const_tree a, const enum tree_code expected_code)
//assert_is_complete(a);
assert_is_type(a, expected_code);
}
+
+inline void
+is_gimple_rhs_class(gimple *stmt, const enum gimple_rhs_class ex_class)
+{
+ gcc_assert(stmt);
+ is_gimple_code(stmt, GIMPLE_ASSIGN);
+ const enum gimple_rhs_class ob_class = gimple_assign_rhs_class(stmt);
+ const bool succeeds = ex_class == ob_class;
+ gcc_assert(succeeds);
+}