toward building a naive predicate tree
[c11tester.git] / funcnode.cc
1 #include "funcnode.h"
2
3 FuncNode::FuncNode() :
4         predicate_tree_initialized(false),
5         func_inst_map(),
6         inst_list(),
7         entry_insts(),
8         thrd_read_map(),
9         predicate_tree_entry()
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 so, return it;
14  * if not, add it and return it.
15  *
16  * @return FuncInst with the same type, position, and location as act */
17 FuncInst * FuncNode::get_or_add_inst(ModelAction *act)
18 {
19         ASSERT(act);
20         const char * position = act->get_position();
21
22         /* THREAD* actions, ATOMIC_LOCK, ATOMIC_TRYLOCK, and ATOMIC_UNLOCK
23          * actions are not tagged with their source line numbers
24          */
25         if (position == NULL)
26                 return NULL;
27
28         if ( func_inst_map.contains(position) ) {
29                 FuncInst * inst = func_inst_map.get(position);
30
31                 if (inst->get_type() != act->get_type() ) {
32                         // model_print("action with a different type occurs at line number %s\n", position);
33                         FuncInst * func_inst = inst->search_in_collision(act);
34
35                         if (func_inst != NULL) {
36                                 // return the FuncInst found in the collision list
37                                 return func_inst;
38                         }
39
40                         func_inst = new FuncInst(act, this);
41                         inst->get_collisions()->push_back(func_inst);
42                         inst_list.push_back(func_inst); // delete?
43
44                         return func_inst;
45                 }
46
47                 return inst;
48         }
49
50         FuncInst * func_inst = new FuncInst(act, this);
51
52         func_inst_map.put(position, func_inst);
53         inst_list.push_back(func_inst);
54
55         return func_inst;
56 }
57
58 void FuncNode::add_entry_inst(FuncInst * inst)
59 {
60         if (inst == NULL)
61                 return;
62
63         mllnode<FuncInst *> * it;
64         for (it = entry_insts.begin(); it != NULL; it = it->getNext()) {
65                 if (inst == it->getVal())
66                         return;
67         }
68
69         entry_insts.push_back(inst);
70 }
71
72 /**
73  * @brief Convert ModelAdtion list to FuncInst list 
74  * @param act_list A list of ModelActions
75  */
76 void FuncNode::update_tree(action_list_t * act_list)
77 {
78         if (act_list == NULL)
79                 return;
80         else if (act_list->size() == 0)
81                 return;
82
83         /* build inst_list from act_list for later processing */
84         func_inst_list_t inst_list;
85         func_inst_list_t read_inst_list;
86         HashTable<FuncInst *, uint64_t, uintptr_t, 4> read_val_map;
87
88         for (sllnode<ModelAction *> * it = act_list->begin(); it != NULL; it = it->getNext()) {
89                 ModelAction * act = it->getVal();
90                 FuncInst * func_inst = get_or_add_inst(act);
91
92                 if (func_inst == NULL)
93                         continue;
94
95                 inst_list.push_back(func_inst);
96
97                 if (!predicate_tree_initialized) {
98                         model_print("position: %s ", act->get_position());
99                         act->print();
100                 }
101
102                 if (func_inst->is_read()) {
103                         read_inst_list.push_back(func_inst);
104                         read_val_map.put(func_inst, act->get_reads_from_value());
105                 }
106         }
107
108         update_inst_tree(&inst_list);
109         model_print("line break\n");
110         init_predicate_tree(&read_inst_list, &read_val_map);
111 }
112
113 /** 
114  * @brief Link FuncInsts in inst_list  - add one FuncInst to another's predecessors and successors
115  * @param inst_list A list of FuncInsts
116  */
117 void FuncNode::update_inst_tree(func_inst_list_t * inst_list)
118 {
119         if (inst_list == NULL)
120                 return;
121         else if (inst_list->size() == 0)
122                 return;
123
124         /* start linking */
125         sllnode<FuncInst *>* it = inst_list->begin();
126         sllnode<FuncInst *>* prev;
127
128         /* add the first instruction to the list of entry insts */
129         FuncInst * entry_inst = it->getVal();
130         add_entry_inst(entry_inst);
131
132         it = it->getNext();
133         while (it != NULL) {
134                 prev = it->getPrev();
135
136                 FuncInst * prev_inst = prev->getVal();
137                 FuncInst * curr_inst = it->getVal();
138
139                 prev_inst->add_succ(curr_inst);
140                 curr_inst->add_pred(prev_inst);
141
142                 it = it->getNext();
143         }
144 }
145
146 /* @param tid thread id
147  * Store the values read by atomic read actions into thrd_read_map */
148 void FuncNode::store_read(ModelAction * act, uint32_t tid)
149 {
150         ASSERT(act);
151
152         void * location = act->get_location();
153         uint64_t read_from_val = act->get_reads_from_value();
154
155         /* resize and initialize */
156         uint32_t old_size = thrd_read_map.size();
157         if (old_size <= tid) {
158                 thrd_read_map.resize(tid + 1);
159                 for (uint32_t i = old_size; i < tid + 1;i++)
160                         thrd_read_map[i] = new read_map_t();
161         }
162
163         read_map_t * read_map = thrd_read_map[tid];
164         read_map->put(location, read_from_val);
165
166         /* Store the memory locations where atomic reads happen */
167         // read_locations.add(location);
168 }
169
170 uint64_t FuncNode::query_last_read(void * location, uint32_t tid)
171 {
172         if (thrd_read_map.size() <= tid)
173                 return 0xdeadbeef;
174
175         read_map_t * read_map = thrd_read_map[tid];
176
177         /* last read value not found */
178         if ( !read_map->contains(location) )
179                 return 0xdeadbeef;
180
181         uint64_t read_val = read_map->get(location);
182         return read_val;
183 }
184
185 /* @param tid thread id
186  * Reset read map for a thread. This function shall only be called
187  * when a thread exits a function
188  */
189 void FuncNode::clear_read_map(uint32_t tid)
190 {
191         if (thrd_read_map.size() <= tid)
192                 return;
193
194         thrd_read_map[tid]->reset();
195 }
196
197 void FuncNode::init_predicate_tree(func_inst_list_t * inst_list, HashTable<FuncInst *, uint64_t, uintptr_t, 4> * read_val_map)
198 {
199         if (inst_list == NULL || inst_list->size() == 0)
200                 return;
201
202         if (predicate_tree_initialized) {
203                 model_print("function %s\n", func_name);
204                 print_predicate_tree();
205                 return;
206         }
207
208         predicate_tree_initialized = true;
209
210         // maybe restrict the size of hashtable to save calloc time
211         HashTable<void *, FuncInst *, uintptr_t, 4> loc_inst_map;
212
213         sllnode<FuncInst *> *it = inst_list->begin();
214         sllnode<FuncInst *> *prev;
215
216         FuncInst * entry_inst = it->getVal();
217
218         /* entry instruction has no predicate expression */
219         Predicate * curr_pred = new Predicate(entry_inst);
220         predicate_tree_entry.add(curr_pred);
221         loc_inst_map.put(entry_inst->get_location(), entry_inst);
222
223         it = it->getNext();
224         while (it != NULL) {
225                 prev = it->getPrev();
226
227                 FuncInst * curr_inst = it->getVal();
228                 FuncInst * prev_inst = prev->getVal();
229
230                 if ( loc_inst_map.contains(curr_inst->get_location()) ) {
231 //                      model_print("new predicate created at location: %p\n", curr_inst->get_location());
232                         Predicate * new_pred1 = new Predicate(curr_inst);
233                         new_pred1->add_predicate(EQUALITY, curr_inst->get_location(), true);
234
235                         Predicate * new_pred2 = new Predicate(curr_inst);
236                         new_pred2->add_predicate(EQUALITY, curr_inst->get_location(), false);
237
238                         curr_pred->add_child(new_pred1);
239                         curr_pred->add_child(new_pred2);
240
241                         uint64_t last_read = read_val_map->get(prev_inst);
242                         if ( last_read == read_val_map->get(curr_inst) )
243                                 curr_pred = new_pred1;
244                         else
245                                 curr_pred = new_pred2;
246                 } else {
247                         Predicate * new_pred = new Predicate(curr_inst);
248                         curr_pred->add_child(new_pred);
249                         curr_pred = new_pred;
250                 }
251
252                 loc_inst_map.put(curr_inst->get_location(), curr_inst);
253
254                 it = it->getNext();
255         }
256 }
257
258
259 void FuncNode::print_predicate_tree()
260 {
261         HSIterator<Predicate *, uintptr_t, 0, model_malloc, model_calloc, model_free> * it;
262         it = predicate_tree_entry.iterator();
263
264         while (it->hasNext()) {
265                 Predicate * p = it->next();
266                 p->print_pred_subtree();
267         }
268 }
269
270 /* @param tid thread id
271  * Print the values read by the last read actions for each memory location
272  */
273 /*
274 void FuncNode::print_last_read(uint32_t tid)
275 {
276         ASSERT(thrd_read_map.size() > tid);
277         read_map_t * read_map = thrd_read_map[tid];
278
279         mllnode<void *> * it;
280         for (it = read_locations.begin();it != NULL;it=it->getNext()) {
281                 if ( !read_map->contains(it->getVal()) )
282                         break;
283
284                 uint64_t read_val = read_map->get(it->getVal());
285                 model_print("last read of thread %d at %p: 0x%x\n", tid, it->getVal(), read_val);
286         }
287 }
288 */