summaryrefslogtreecommitdiff
path: root/gcc/ipa-prototype.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ipa-prototype.c')
-rw-r--r--gcc/ipa-prototype.c490
1 files changed, 12 insertions, 478 deletions
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);