1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#include "gimple-caster.hpp"
#include "gimple-pretty-print.h"
#include "type-incomplete-equality.hpp"
#include "type-stringifier.hpp"
void
GimpleCaster::_walk_pre(gassign *s)
{
const enum gimple_rhs_class code = gimple_assign_rhs_class(s);
const bool valid_input = GIMPLE_SINGLE_RHS == code;
if (!valid_input) return;
// I originally was using gimple_assign_cast_p
// but that proved to be insufficient...
// So we have to use our equality comparison...
TypeIncompleteEquality equality;
const_tree lhs = gimple_assign_lhs(s);
const_tree rhs = gimple_assign_rhs1(s);
gcc_assert(lhs && rhs);
Reason reason {};
const_tree t_lhs = TREE_TYPE(lhs);
const_tree t_rhs = TREE_TYPE(rhs);
gcc_assert(t_lhs && t_rhs);
bool is_cast = !equality.equal(t_lhs, t_rhs);
TypeStringifier stringifier;
const std::string name_l = stringifier.stringify(t_lhs);
const std::string name_r = stringifier.stringify(t_rhs);
// If it is cast, we might need to look at the definition of rhs
// If the definition comes from a known function... then we are good...
bool is_ssa = TREE_CODE(rhs) == SSA_NAME;
while (is_ssa) {
gimple *def_for_rhs = SSA_NAME_DEF_STMT(rhs);
gcall *is_call = dyn_cast<gcall*>(def_for_rhs);
// poor man's goto
if (!is_call) break;
const_tree fn = gimple_call_fndecl(is_call);
// poor man's goto
if (!fn) break;
bool known_function = GimpleEscaper::filter_known_function(fn);
is_cast = !known_function;
is_ssa = false;
}
reason.type_is_casted = is_cast;
exprEscaper.update(lhs, reason);
exprEscaper.update(rhs, reason);
// TODO:
// I think this will re-do the work... But it might be necessary?
GimpleEscaper::_walk_pre(s);
}
void
GimpleCaster::_walk_pre(gcall *s)
{
GimpleEscaper::_walk_pre(s);
const_tree fn = gimple_call_fndecl(s);
// If there's no function declaration, how do we
// know the argument types?
if (!fn) return;
cgraph_node *node = cgraph_node::get(fn);
const bool known_function = GimpleEscaper::filter_known_function(node) || GimpleEscaper::filter_known_function(fn);
if (known_function) return;
const_tree f_t = TREE_TYPE(fn);
TypeIncompleteEquality equality;
TypeStringifier stringifier;
unsigned i = 0;
unsigned n = gimple_call_num_args(s);
for (tree a = TYPE_ARG_TYPES(f_t); NULL_TREE != a; a = TREE_CHAIN(a))
{
const_tree formal_t = TREE_VALUE(a);
// There seems to be a final VOID_TYPE at the end of some functions?
const enum tree_code code = TREE_CODE(formal_t);
const bool is_void = VOID_TYPE == code;
if (is_void) continue;
const_tree real = gimple_call_arg(s, i);
const_tree real_t = TREE_TYPE(real);
const bool is_casted = !equality.equal(formal_t, real_t);
const std::string name_r = stringifier.stringify(real_t);
const std::string name_f = stringifier.stringify(formal_t);
Reason arg_reason;
arg_reason.type_is_casted = is_casted;
exprEscaper.update(real, arg_reason);
i++;
}
/*
unsigned n = gimple_call_num_args(s);
for (unsigned i = 0; i < n; i++)
{
const_tree a = gimple_call_arg(s, i);
gcc_assert(a);
exprEscaper.update(a, reason);
}
*/
const_tree lhs = gimple_call_lhs(s);
if (!lhs) return;
const_tree r_t = TREE_TYPE(f_t);
const_tree l_t TREE_TYPE(lhs);
const bool is_casted = !equality.equal(r_t, l_t);
const std::string name_r_t = stringifier.stringify(r_t);
const std::string name_l_t = stringifier.stringify(r_t);
Reason ret_reason;
ret_reason.type_is_casted = is_casted;
exprEscaper.update(lhs, ret_reason);
}
|