11 #include <unordered_set>
13 #include "gcc-plugin.h"
14 #include "plugin-version.h"
16 #include "tree-pass.h"
20 #include "tree-ssa-alias.h"
21 #include "internal-fn.h"
24 #include "basic-block.h"
25 #include "gimple-expr.h"
27 #include "gimple-pretty-print.h"
28 #include "gimple-iterator.h"
29 #include "gimple-walk.h"
31 #include "stringpool.h"
32 #include "pretty-print.h"
43 const pass_data mem_check_data =
56 struct mem_check_pass : gimple_opt_pass
58 mem_check_pass(gcc::context *ctx)
59 : gimple_opt_pass(mem_check_data, ctx)
64 virtual unsigned int execute(
function* fun)
override
68 gimple_seq gimple_body = fun->gimple_body;
76 gimple_stmt_iterator it = gsi_start_1(&gimple_body);
77 for(; !gsi_end_p(it); gsi_next(&it)) {
78 if (gsi_stmt(it)->code == GIMPLE_CALL) {
79 tree ret_tree = gimple_call_lhs(gsi_stmt(it));
80 tree fn_tree = gimple_call_fndecl(gsi_stmt(it));
81 gimple* last_stmt = gsi_stmt(it);
82 if (!strcmp(IDENTIFIER_POINTER(DECL_NAME(fn_tree)),
"get_memobj_direct")) {
85 tree fntype = build_function_type_list(void_type_node, NULL_TREE);
86 tree ldecl = build_fn_decl (
"lock_om", fntype);
87 gimple *lcall = gimple_build_call (ldecl, 0);
89 gsi_insert_before(&it, lcall, GSI_SAME_STMT);
92 std::unordered_set<tree> vars;
93 vars.insert(ret_tree);
94 gimple_stmt_iterator end_it = it;
95 for(; !gsi_end_p(end_it); gsi_next(&end_it)) {
97 if (gsi_stmt(end_it)->code == GIMPLE_ASSIGN) {
98 if (TREE_CODE(gimple_assign_lhs(gsi_stmt(end_it))) == MEM_REF) {
99 tree reffed = gimple_assign_lhs(gsi_stmt(end_it));
100 tree reffed_id = TREE_OPERAND(reffed, 0);
101 if (vars.find(reffed_id) != vars.end()) {
103 last_stmt = gsi_stmt(end_it);
106 }
else if (TREE_CODE(gimple_assign_lhs(gsi_stmt(end_it))) == SSA_NAME ||
107 TREE_CODE(gimple_assign_lhs(gsi_stmt(end_it))) == VAR_DECL) {
108 tree rhs1, rhs2, rhs3;
109 rhs1 = gimple_assign_rhs1(gsi_stmt(end_it));
110 rhs2 = gimple_assign_rhs2(gsi_stmt(end_it));
111 rhs3 = gimple_assign_rhs3(gsi_stmt(end_it));
112 if (vars.find(rhs1) != vars.end() || vars.find(rhs2) != vars.end() ||
113 vars.find(rhs3) != vars.end()) {
114 vars.insert(gimple_assign_lhs(gsi_stmt(end_it)));
117 if (gimple_assign_rhs_code(gsi_stmt(end_it)) == MEM_REF) {
118 tree reffed = TREE_OPERAND(gimple_assign_rhs1(gsi_stmt(end_it)), 0);
119 if (vars.find(reffed) != vars.end()) {
120 last_stmt = gsi_stmt(end_it);
128 tree udecl = build_fn_decl (
"unlock_om", fntype);
129 gimple *ucall = gimple_build_call (udecl, 0);
130 gsi_insert_after(&it, ucall, GSI_NEW_STMT);
141 it = gsi_start_1(&gimple_body);
142 for(; !gsi_end_p(it); gsi_next(&it)) {
144 if (gsi_stmt(it)->code == GIMPLE_ASSIGN){
145 if (TREE_CODE(gimple_assign_lhs(gsi_stmt(it))) == MEM_REF) {
146 tree lt = TREE_OPERAND(gimple_assign_lhs(gsi_stmt(it)), 0);
147 tree lty = TREE_TYPE(lt);
148 tree ltyty = TREE_TYPE(lty);
149 tree ltsiz = TYPE_SIZE(ltyty);
150 tree fntype = build_function_type_list(void_type_node, ptr_type_node, integer_type_node, NULL_TREE);
151 wfndecl = build_fn_decl (
"log_write", fntype);
152 gimple *call = gimple_build_call (
wfndecl, 2, lt, ltsiz);
155 gimple_set_location(call, gimple_location(gsi_stmt(it)));
156 gsi_insert_after(&it, call, GSI_NEW_STMT);
159 if (gimple_assign_rhs_code(gsi_stmt(it)) == MEM_REF) {
160 tree lt = TREE_OPERAND(gimple_assign_rhs1(gsi_stmt(it)),0);
161 tree lty = TREE_TYPE(lt);
162 tree ltyty = TREE_TYPE(lty);
163 tree ltsiz = TYPE_SIZE(ltyty);
166 tree fntype = build_function_type_list(void_type_node, ptr_type_node, integer_type_node, NULL_TREE);
167 rfndecl = build_fn_decl (
"log_read", fntype);
168 gimple *call = gimple_build_call (
rfndecl, 2, lt, ltsiz);
171 gimple_set_location(call, gimple_location(gsi_stmt(it)));
172 gsi_insert_after(&it, call, GSI_NEW_STMT);
188 static tree callback_op (tree *t,
int *,
void *data)
190 enum tree_code code = TREE_CODE(*t);
192 if (code == MEM_REF) {
193 *((
int*)((
struct walk_stmt_info*)data)->info) = 1;
198 virtual mem_check_pass* clone()
override
208 struct plugin_gcc_version *version)
212 if (!plugin_default_version_check (version, &gcc_version))
214 std::cerr <<
"This GCC plugin is for version " << GCCPLUGIN_VERSION_MAJOR <<
"." << GCCPLUGIN_VERSION_MINOR <<
"\n";
218 register_callback(plugin_info->base_name,
223 struct register_pass_info pass_info;
227 pass_info.pass =
new mem_check_pass(g);
228 pass_info.reference_pass_name =
"cfg";
229 pass_info.ref_pass_instance_number = 1;
230 pass_info.pos_op = PASS_POS_INSERT_BEFORE;
232 register_callback (plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP,
NULL, &pass_info);