2bdd946d40c6975fc9ad14900180335839039723
[c11tester.git] / funcnode.cc
1 #include "funcnode.h"
2
3 FuncNode::FuncNode() :
4         predicate_tree_initialized(false),
5         predicate_tree_entry(new Predicate(NULL, true)),
6         func_inst_map(),
7         inst_list(),
8         entry_insts(),
9         thrd_read_map()
10 {}
11
12 /* Check whether FuncInst with the same type, position, and location
13  * as act has been added to func_inst_map or not. If not, add it.
14  *
15  * Note: currently, actions with the same position are filtered out by process_action,
16  * so the collision list of FuncInst is not used. May remove it later. 
17  */
18 void FuncNode::add_inst(ModelAction *act)
19 {
20         ASSERT(act);
21         const char * position = act->get_position();
22
23         /* THREAD* actions, ATOMIC_LOCK, ATOMIC_TRYLOCK, and ATOMIC_UNLOCK
24          * actions are not tagged with their source line numbers
25          */
26         if (position == NULL)
27                 return;
28
29         if ( func_inst_map.contains(position) ) {
30                 FuncInst * inst = func_inst_map.get(position);
31
32                 ASSERT(inst->get_type() == act->get_type());
33                 if (inst->get_location() != act->get_location())
34                         inst->not_single_location();
35
36                 return;
37         }
38
39         FuncInst * func_inst = new FuncInst(act, this);
40
41         func_inst_map.put(position, func_inst);
42         inst_list.push_back(func_inst);
43 }
44
45 /* Get the FuncInst with the same type, position, and location
46  * as act
47  *
48  * @return FuncInst with the same type, position, and location as act */
49 FuncInst * FuncNode::get_inst(ModelAction *act)
50 {
51         ASSERT(act);
52         const char * position = act->get_position();
53
54         /* THREAD* actions, ATOMIC_LOCK, ATOMIC_TRYLOCK, and ATOMIC_UNLOCK
55          * actions are not tagged with their source line numbers
56          */
57         if (position == NULL)
58                 return NULL;
59
60         FuncInst * inst = func_inst_map.get(position);
61         if (inst == NULL)
62                 return NULL;
63
64         action_type inst_type = inst->get_type();
65         action_type act_type = act->get_type();
66
67         // else if branch: an RMWRCAS action is converted to a RMW or READ action
68         if (inst_type == act_type)
69                 return inst;
70         else if (inst_type == ATOMIC_RMWRCAS &&
71                         (act_type == ATOMIC_RMW || act_type == ATOMIC_READ))
72                 return inst;
73
74         return NULL;
75 }
76
77
78 void FuncNode::add_entry_inst(FuncInst * inst)
79 {
80         if (inst == NULL)
81                 return;
82
83         mllnode<FuncInst *> * it;
84         for (it = entry_insts.begin(); it != NULL; it = it->getNext()) {
85                 if (inst == it->getVal())
86                         return;
87         }
88
89         entry_insts.push_back(inst);
90 }
91
92 /**
93  * @brief Convert ModelAdtion list to FuncInst list 
94  * @param act_list A list of ModelActions
95  */
96 void FuncNode::update_tree(action_list_t * act_list)
97 {
98         if (act_list == NULL)
99                 return;
100         else if (act_list->size() == 0)
101                 return;
102
103         /* build inst_list from act_list for later processing */
104         func_inst_list_t inst_list;
105         action_list_t read_act_list;
106
107         for (sllnode<ModelAction *> * it = act_list->begin(); it != NULL; it = it->getNext()) {
108                 ModelAction * act = it->getVal();
109                 FuncInst * func_inst = get_inst(act);
110
111                 if (func_inst == NULL)
112                         continue;
113
114                 inst_list.push_back(func_inst);
115
116 //              model_print("position: %s ", act->get_position());
117 //              act->print();
118
119                 if (func_inst->is_read())
120                         read_act_list.push_back(act);
121         }
122
123         model_print("function %s\n", func_name);
124         update_inst_tree(&inst_list);
125         update_predicate_tree(&read_act_list);
126         deep_update(predicate_tree_entry);
127
128         print_predicate_tree();
129 }
130
131 /** 
132  * @brief Link FuncInsts in inst_list  - add one FuncInst to another's predecessors and successors
133  * @param inst_list A list of FuncInsts
134  */
135 void FuncNode::update_inst_tree(func_inst_list_t * inst_list)
136 {
137         if (inst_list == NULL)
138                 return;
139         else if (inst_list->size() == 0)
140                 return;
141
142         /* start linking */
143         sllnode<FuncInst *>* it = inst_list->begin();
144         sllnode<FuncInst *>* prev;
145
146         /* add the first instruction to the list of entry insts */
147         FuncInst * entry_inst = it->getVal();
148         add_entry_inst(entry_inst);
149
150         it = it->getNext();
151         while (it != NULL) {
152                 prev = it->getPrev();
153
154                 FuncInst * prev_inst = prev->getVal();
155                 FuncInst * curr_inst = it->getVal();
156
157                 prev_inst->add_succ(curr_inst);
158                 curr_inst->add_pred(prev_inst);
159
160                 it = it->getNext();
161         }
162 }
163
164 /* @param tid thread id
165  * Store the values read by atomic read actions into thrd_read_map */
166 void FuncNode::store_read(ModelAction * act, uint32_t tid)
167 {
168         ASSERT(act);
169
170         void * location = act->get_location();
171         uint64_t read_from_val = act->get_reads_from_value();
172
173         /* resize and initialize */
174         uint32_t old_size = thrd_read_map.size();
175         if (old_size <= tid) {
176                 thrd_read_map.resize(tid + 1);
177                 for (uint32_t i = old_size; i < tid + 1;i++)
178                         thrd_read_map[i] = new read_map_t();
179         }
180
181         read_map_t * read_map = thrd_read_map[tid];
182         read_map->put(location, read_from_val);
183
184         /* Store the memory locations where atomic reads happen */
185         // read_locations.add(location);
186 }
187
188 uint64_t FuncNode::query_last_read(void * location, uint32_t tid)
189 {
190         if (thrd_read_map.size() <= tid)
191                 return VALUE_NONE;
192
193         read_map_t * read_map = thrd_read_map[tid];
194
195         /* last read value not found */
196         if ( !read_map->contains(location) )
197                 return VALUE_NONE;
198
199         uint64_t read_val = read_map->get(location);
200         return read_val;
201 }
202
203 /* @param tid thread id
204  * Reset read map for a thread. This function shall only be called
205  * when a thread exits a function
206  */
207 void FuncNode::clear_read_map(uint32_t tid)
208 {
209         if (thrd_read_map.size() <= tid)
210                 return;
211
212         thrd_read_map[tid]->reset();
213 }
214
215 void FuncNode::update_predicate_tree(action_list_t * act_list)
216 {
217         if (act_list == NULL || act_list->size() == 0)
218                 return;
219 /*
220         if (predicate_tree_initialized) {
221                 return;
222         }
223         predicate_tree_initialized = true;
224 */
225         /* map a FuncInst to the parent of its predicate */
226         HashTable<FuncInst *, Predicate *, uintptr_t, 0> inst_pred_map(128);
227         HashTable<void *, ModelAction *, uintptr_t, 0> loc_act_map(128);
228         HashTable<FuncInst *, ModelAction *, uintptr_t, 0> inst_act_map(128);
229
230         sllnode<ModelAction *> *it = act_list->begin();
231         Predicate * curr_pred = predicate_tree_entry;
232
233         while (it != NULL) {
234                 ModelAction * next_act = it->getVal();
235                 FuncInst * next_inst = get_inst(next_act);
236                 Predicate * old_pred = curr_pred;
237
238                 bool branch_found = follow_branch(&curr_pred, next_inst, next_act, &inst_act_map);
239
240                 // check back edges
241                 if (!branch_found) {
242                         Predicate * back_pred = curr_pred->get_backedge();
243                         if (back_pred != NULL) {
244                                 curr_pred = back_pred;
245                                 continue;
246                         }
247
248                         if (inst_pred_map.contains(next_inst)) {
249                                 back_pred = inst_pred_map.get(next_inst);
250                                 curr_pred->set_backedge(back_pred);
251                                 curr_pred = back_pred;
252                                 continue;
253                         }
254                 }
255
256                 if (!inst_pred_map.contains(next_inst))
257                         inst_pred_map.put(next_inst, old_pred);
258
259                 if (!branch_found) {
260                         if ( loc_act_map.contains(next_act->get_location()) ) {
261                                 ModelAction * last_act = loc_act_map.get(next_act->get_location());
262                                 FuncInst * last_inst = get_inst(last_act);
263
264                                 Predicate * new_pred1 = new Predicate(next_inst);
265                                 new_pred1->add_predicate_expr(EQUALITY, last_inst, true);
266
267                                 Predicate * new_pred2 = new Predicate(next_inst);
268                                 new_pred2->add_predicate_expr(EQUALITY, last_inst, false);
269
270                                 curr_pred->add_child(new_pred1);
271                                 curr_pred->add_child(new_pred2);
272                                 new_pred1->set_parent(curr_pred);
273                                 new_pred2->set_parent(curr_pred);
274
275                                 uint64_t last_read = last_act->get_reads_from_value();
276                                 uint64_t next_read = next_act->get_reads_from_value();
277
278                                 if ( last_read == next_read )
279                                         curr_pred = new_pred1;
280                                 else
281                                         curr_pred = new_pred2;
282                         } else {
283                                 Predicate * new_pred = new Predicate(next_inst);
284                                 curr_pred->add_child(new_pred);
285                                 new_pred->set_parent(curr_pred);
286
287                                 curr_pred = new_pred;
288                         }
289                 }
290
291                 loc_act_map.put(next_act->get_location(), next_act);
292                 inst_act_map.put(next_inst, next_act);
293                 it = it->getNext();
294         }
295 }
296
297 void FuncNode::deep_update(Predicate * curr_pred)
298 {
299         FuncInst * func_inst = curr_pred->get_func_inst();
300         if (func_inst != NULL && !func_inst->is_single_location()) {
301                 bool has_null_pred = false;
302                 PredExprSet * pred_expressions = curr_pred->get_pred_expressions();
303                 PredExprSetIter * pred_expr_it = pred_expressions->iterator();
304                 while (pred_expr_it->hasNext()) {
305                         pred_expr * pred_expression = pred_expr_it->next();
306                         if (pred_expression->token == NULLITY) {
307                                 has_null_pred = true;
308                                 break;
309                         }
310                 }
311
312                 if (!has_null_pred) {
313 //                      func_inst->print();
314                         Predicate * another_branch = new Predicate(func_inst);
315                         another_branch->copy_predicate_expr(curr_pred);
316                         another_branch->add_predicate_expr(NULLITY, NULL, 1);
317                         curr_pred->add_predicate_expr(NULLITY, NULL, 0);
318
319                         Predicate * parent = curr_pred->get_parent();
320                         parent->add_child(another_branch);
321 //                      another_branch.add_children(i);
322                 }
323         }
324
325         ModelVector<Predicate *> * branches = curr_pred->get_children();
326         for (uint i = 0; i < branches->size(); i++) {
327                 Predicate * branch = (*branches)[i];
328                 deep_update(branch);
329         }
330 }
331
332 /* Given curr_pred and next_inst, find the branch following curr_pred that
333  * contains next_inst and the correct predicate. 
334  * @return true if branch found, false otherwise.
335  */
336 bool FuncNode::follow_branch(Predicate ** curr_pred, FuncInst * next_inst, ModelAction * next_act,
337         HashTable<FuncInst *, ModelAction *, uintptr_t, 0> * inst_act_map)
338 {
339         /* check if a branch with func_inst and corresponding predicate exists */
340         bool branch_found = false;
341         ModelVector<Predicate *> * branches = (*curr_pred)->get_children();
342         for (uint i = 0; i < branches->size(); i++) {
343                 Predicate * branch = (*branches)[i];
344                 if (branch->get_func_inst() != next_inst)
345                         continue;
346
347                 PredExprSet * pred_expressions = branch->get_pred_expressions();
348
349                 /* no predicate, follow the only branch */
350                 if (pred_expressions->getSize() == 0) {
351                         *curr_pred = branch;
352                         branch_found = true;
353                         break;
354                 }
355
356                 PredExprSetIter * pred_expr_it = pred_expressions->iterator();
357                 while (pred_expr_it->hasNext()) {
358                         pred_expr * pred_expression = pred_expr_it->next();
359                         uint64_t last_read, next_read;
360                         bool equality;
361
362                         switch(pred_expression->token) {
363                                 case EQUALITY:
364                                         FuncInst * to_be_compared;
365                                         ModelAction * last_act;
366
367                                         to_be_compared = pred_expression->func_inst;
368                                         last_act = inst_act_map->get(to_be_compared);
369
370                                         last_read = last_act->get_reads_from_value();
371                                         next_read = next_act->get_reads_from_value();
372
373                                         equality = (last_read == next_read);
374                                         if (equality == pred_expression->value) {
375                                                 *curr_pred = branch;
376 //                                              model_print("predicate: token: %d, location: %p, value: %d - ", pred_expression->token, pred_expression->location, pred_expression->value); next_inst->print();
377                                                 branch_found = true;
378                                         }
379                                         break;
380                                 case NULLITY:
381                                         next_read = next_act->get_reads_from_value();
382                                         equality = ((void*)next_read == NULL);
383                                         //model_print("%s ", next_act->get_position()); next_act->print();
384                                         if (equality == pred_expression->value) {
385                                                 *curr_pred = branch;
386                                                 branch_found = true;
387                                         }
388                                         break;
389                                 default:
390                                         model_print("unkown predicate token\n");
391                                         break;
392                         }
393                 }
394
395         }
396
397         return branch_found;
398 }
399
400 void FuncNode::print_predicate_tree()
401 {
402         model_print("digraph function_%s {\n", func_name);
403         predicate_tree_entry->print_pred_subtree();
404         model_print("}\n");     // end of graph
405 }
406
407 /* @param tid thread id
408  * Print the values read by the last read actions for each memory location
409  */
410 /*
411 void FuncNode::print_last_read(uint32_t tid)
412 {
413         ASSERT(thrd_read_map.size() > tid);
414         read_map_t * read_map = thrd_read_map[tid];
415
416         mllnode<void *> * it;
417         for (it = read_locations.begin();it != NULL;it=it->getNext()) {
418                 if ( !read_map->contains(it->getVal()) )
419                         break;
420
421                 uint64_t read_val = read_map->get(it->getVal());
422                 model_print("last read of thread %d at %p: 0x%x\n", tid, it->getVal(), read_val);
423         }
424 }
425 */