diff options
author | Erick Ochoa <erick.ochoa@theobroma-systems.com> | 2020-05-28 13:32:51 +0200 |
---|---|---|
committer | Erick Ochoa <erick.ochoa@theobroma-systems.com> | 2020-06-03 16:06:00 +0200 |
commit | c355cf30a9400a293315617ef64a9a3e88755568 (patch) | |
tree | d1223364bd918940f6027cfec179c06282dcc14d | |
parent | cbe56ad4aeca7eb01ae1233387def84fb74ee70a (diff) |
sanity check passes
-rw-r--r-- | gcc/ipa-hello-world.c | 347 | ||||
-rw-r--r-- | gcc/ipa-type-collector.c | 11 | ||||
-rw-r--r-- | gcc/types-inlines.h | 11 |
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); +} |