NVMLib  very early alpha
A library to optimally use a Hybrid RAM setup.
mem_track.cc
Go to the documentation of this file.
1 
10 #include <iostream>
11 #include <unordered_set>
12 // This is the first gcc header to be included
13 #include "gcc-plugin.h"
14 #include "plugin-version.h"
15 
16 #include "tree-pass.h"
17 #include "context.h"
18 #include "function.h"
19 #include "tree.h"
20 #include "tree-ssa-alias.h"
21 #include "internal-fn.h"
22 #include "is-a.h"
23 #include "predict.h"
24 #include "basic-block.h"
25 #include "gimple-expr.h"
26 #include "gimple.h"
27 #include "gimple-pretty-print.h"
28 #include "gimple-iterator.h"
29 #include "gimple-walk.h"
30 #include "attribs.h"
31 #include "stringpool.h"
32 #include "pretty-print.h"
33 #include <string.h>
34 
36 
37 static struct plugin_info my_gcc_plugin_info = { "1.0", "Memory Reference Tracker" };
38 tree rfndecl;
39 tree wfndecl;
40 
41 namespace
42 {
43  const pass_data mem_check_data =
44  {
45  GIMPLE_PASS,
46  "mem_check", /* name */
47  OPTGROUP_NONE, /* optinfo_flags */
48  TV_NONE, /* tv_id */
49  PROP_gimple_any, /* properties_required */
50  0, /* properties_provided */
51  0, /* properties_destroyed */
52  0, /* todo_flags_start */
53  0 /* todo_flags_finish */
54  };
55 
56  struct mem_check_pass : gimple_opt_pass
57  {
58  mem_check_pass(gcc::context *ctx)
59  : gimple_opt_pass(mem_check_data, ctx)
60  {
61 
62  }
63 
64  virtual unsigned int execute(function* fun) override
65  {
66  // fun is the current function being called
67 
68  gimple_seq gimple_body = fun->gimple_body;
69 
70  //std::cerr << "FUNCTION '" << function_name(fun)
71  // << "' at " << LOCATION_FILE(fun->function_start_locus) << ":" << LOCATION_LINE(fun->function_start_locus) << "\n";
72  //std::cerr << "*******************\n";
73 
74  // Dump its body
75  //print_gimple_seq(stderr, gimple_body, 0, 0);
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")) {
83  //printf("GV_________________\n");
84 
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);
88  gsi_prev(&it);
89  gsi_insert_before(&it, lcall, GSI_SAME_STMT);
90  gsi_next(&it);
91 
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)) {
96  // debug_gimple_stmt(gsi_stmt(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()) {
102  //printf("unlock here\n");
103  last_stmt = gsi_stmt(end_it);
104  break;
105  }
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)));
115  }
116  }
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);
121  //printf("Could end here.\n");
122  }
123  }
124  }
125  }
126  //end_it.ptr = last_stmt;
127  it.ptr = last_stmt;
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);
131  }
132  }
133  }
134  /*printf("______________________________\n");
135  gimple_stmt_iterator it1 = gsi_start_1(&gimple_body);
136  for(; !gsi_end_p(it1); gsi_next(&it1)) {
137  debug_gimple_stmt(gsi_stmt(it1));
138  }
139  printf("\n======================\nInjected mutexes.\n======================\n\n");*/
140 
141  it = gsi_start_1(&gimple_body);
142  for(; !gsi_end_p(it); gsi_next(&it)) {
143  // debug_gimple_stmt(gsi_stmt(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);
153 
154  //dump_function_header(stderr, rfndecl,0);
155  gimple_set_location(call, gimple_location(gsi_stmt(it)));
156  gsi_insert_after(&it, call, GSI_NEW_STMT);
157 
158  }
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);
164  //printf("debug lt %s\n", );
165 
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);
169 
170  //dump_function_header(stderr, rfndecl,0);
171  gimple_set_location(call, gimple_location(gsi_stmt(it)));
172  gsi_insert_after(&it, call, GSI_NEW_STMT);
173  }
174  }
175  }
176  /*printf("______________________________\n");
177  it1 = gsi_start_1(&gimple_body);
178  for(; !gsi_end_p(it1); gsi_next(&it1)) {
179  print_gimple_stmt(stderr, gsi_stmt(it1), 100, 100);
180  debug_gimple_stmt(gsi_stmt(it1));
181  printf ("\n\n");
182  }
183  std::cout << "*******************\n\n";*/
184 
185  return 0;
186  }
187 
188  static tree callback_op (tree *t, int *, void *data)
189  {
190  enum tree_code code = TREE_CODE(*t);
191 
192  if (code == MEM_REF) {
193  *((int*)((struct walk_stmt_info*)data)->info) = 1;
194  }
195  return NULL;
196  }
197 
198  virtual mem_check_pass* clone() override
199  {
200  // We do not clone ourselves
201  return this;
202  }
203  };
204 }
205 
206 
207 int plugin_init (struct plugin_name_args *plugin_info,
208  struct plugin_gcc_version *version)
209 {
210  // We check the current gcc loading this plugin against the gcc we used to
211  // created this plugin
212  if (!plugin_default_version_check (version, &gcc_version))
213  {
214  std::cerr << "This GCC plugin is for version " << GCCPLUGIN_VERSION_MAJOR << "." << GCCPLUGIN_VERSION_MINOR << "\n";
215  return 1;
216  }
217 
218  register_callback(plugin_info->base_name,
219  /* event */ PLUGIN_INFO,
220  /* callback */ NULL, /* user_data */ &my_gcc_plugin_info);
221 
222  // Register the phase right after omplower
223  struct register_pass_info pass_info;
224 
225  // Note that after the cfg is built, fun->gimple_body is not accessible
226  // anymore so we run this pass just before it
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;
231 
232  register_callback (plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info);
233 
234  return 0;
235 }
plugin_init
int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
Definition: mem_track.cc:207
wfndecl
tree wfndecl
Definition: mem_track.cc:39
my_gcc_plugin_info
static struct plugin_info my_gcc_plugin_info
Definition: mem_track.cc:37
rfndecl
tree rfndecl
Definition: mem_track.cc:38
NULL
#define NULL
Definition: list.h:13
plugin_is_GPL_compatible
int plugin_is_GPL_compatible
Definition: mem_track.cc:35