+ void * loc = next_act->get_location();
+
+ if (next_inst->is_read()) {
+ /* read + rmw */
+ if ( loc_act_map->contains(loc) ) {
+ ModelAction * last_act = loc_act_map->get(loc);
+ FuncInst * last_inst = get_inst(last_act);
+ struct half_pred_expr * expression = new half_pred_expr(EQUALITY, last_inst);
+ half_pred_expressions->push_back(expression);
+ } else if ( next_inst->is_single_location() ){
+ loc_set_t * loc_may_equal = loc_may_equal_map->get(loc);
+
+ if (loc_may_equal != NULL) {
+ loc_set_iter * loc_it = loc_may_equal->iterator();
+ while (loc_it->hasNext()) {
+ void * neighbor = loc_it->next();
+ if (loc_act_map->contains(neighbor)) {
+ ModelAction * last_act = loc_act_map->get(neighbor);
+ FuncInst * last_inst = get_inst(last_act);
+
+ struct half_pred_expr * expression = new half_pred_expr(EQUALITY, last_inst);
+ half_pred_expressions->push_back(expression);
+ }
+ }
+ }
+ } else {
+ // next_inst is not single location
+ uint64_t read_val = next_act->get_reads_from_value();
+
+ // only infer NULLITY predicate when it is actually NULL.
+ if ( (void*)read_val == NULL) {
+ struct half_pred_expr * expression = new half_pred_expr(NULLITY, NULL);
+ half_pred_expressions->push_back(expression);
+ }
+ }
+ } else {
+ /* Pure writes */
+ // TODO: do anything here?
+ }
+}
+
+/* Able to generate complex predicates when there are multiple predciate expressions */
+void FuncNode::generate_predicates(Predicate ** curr_pred, FuncInst * next_inst,
+ SnapVector<struct half_pred_expr *> * half_pred_expressions)
+{
+ if (half_pred_expressions->size() == 0) {
+ Predicate * new_pred = new Predicate(next_inst);
+ (*curr_pred)->add_child(new_pred);
+ new_pred->set_parent(*curr_pred);
+
+ /* entry predicates and predicates containing pure write actions
+ * have no predicate expressions */
+ if ( (*curr_pred)->is_entry_predicate() )
+ new_pred->add_predicate_expr(NOPREDICATE, NULL, true);
+ else if (next_inst->is_write()) {
+ /* next_inst->is_write() <==> pure writes */
+ new_pred->add_predicate_expr(NOPREDICATE, NULL, true);
+ }
+
+ return;
+ }
+
+ SnapVector<Predicate *> predicates;
+
+ struct half_pred_expr * half_expr = (*half_pred_expressions)[0];
+ predicates.push_back(new Predicate(next_inst));
+ predicates.push_back(new Predicate(next_inst));
+
+ predicates[0]->add_predicate_expr(half_expr->token, half_expr->func_inst, true);
+ predicates[1]->add_predicate_expr(half_expr->token, half_expr->func_inst, false);
+
+ for (uint i = 1; i < half_pred_expressions->size(); i++) {
+ half_expr = (*half_pred_expressions)[i];
+
+ uint old_size = predicates.size();
+ for (uint j = 0; j < old_size; j++) {
+ Predicate * pred = predicates[j];
+ Predicate * new_pred = new Predicate(next_inst);
+ new_pred->copy_predicate_expr(pred);
+
+ pred->add_predicate_expr(half_expr->token, half_expr->func_inst, true);
+ new_pred->add_predicate_expr(half_expr->token, half_expr->func_inst, false);
+
+ predicates.push_back(new_pred);
+ }
+ }
+
+ for (uint i = 0; i < predicates.size(); i++) {
+ Predicate * pred= predicates[i];
+ (*curr_pred)->add_child(pred);
+ pred->set_parent(*curr_pred);
+ }
+
+ /* Free memories allocated by infer_predicate */
+ for (uint i = 0; i < half_pred_expressions->size(); i++) {
+ struct half_pred_expr * tmp = (*half_pred_expressions)[i];
+ snapshot_free(tmp);
+ }
+}
+
+/* Amend predicates that contain no predicate expressions. Currenlty only amend with NULLITY predicates */
+bool FuncNode::amend_predicate_expr(Predicate ** curr_pred, FuncInst * next_inst, ModelAction * next_act)
+{
+ // there should only be only child
+ Predicate * unset_pred = (*curr_pred)->get_children()->back();
+ uint64_t read_val = next_act->get_reads_from_value();
+
+ // only generate NULLITY predicate when it is actually NULL.
+ if ( !next_inst->is_single_location() && (void*)read_val == NULL ) {
+ Predicate * new_pred = new Predicate(next_inst);
+
+ (*curr_pred)->add_child(new_pred);
+ new_pred->set_parent(*curr_pred);
+
+ unset_pred->add_predicate_expr(NULLITY, NULL, false);
+ new_pred->add_predicate_expr(NULLITY, NULL, true);
+
+ return true;
+ }
+
+ return false;
+}
+
+void FuncNode::add_to_val_loc_map(uint64_t val, void * loc)
+{
+ loc_set_t * locations = val_loc_map->get(val);
+
+ if (locations == NULL) {
+ locations = new loc_set_t();
+ val_loc_map->put(val, locations);
+ }
+
+ update_loc_may_equal_map(loc, locations);
+ locations->add(loc);
+ // values_may_read_from->add(val);
+}
+
+void FuncNode::add_to_val_loc_map(value_set_t * values, void * loc)
+{
+ if (values == NULL)
+ return;
+
+ value_set_iter * it = values->iterator();
+ while (it->hasNext()) {
+ uint64_t val = it->next();
+ add_to_val_loc_map(val, loc);
+ }
+}
+
+void FuncNode::update_loc_may_equal_map(void * new_loc, loc_set_t * old_locations)
+{
+ if ( old_locations->contains(new_loc) )
+ return;
+
+ loc_set_t * neighbors = loc_may_equal_map->get(new_loc);
+
+ if (neighbors == NULL) {
+ neighbors = new loc_set_t();
+ loc_may_equal_map->put(new_loc, neighbors);
+ }
+
+ loc_set_iter * loc_it = old_locations->iterator();
+ while (loc_it->hasNext()) {
+ // new_loc: { old_locations, ... }
+ void * member = loc_it->next();
+ neighbors->add(member);
+
+ // for each i in old_locations, i : { new_loc, ... }
+ loc_set_t * _neighbors = loc_may_equal_map->get(member);
+ if (_neighbors == NULL) {
+ _neighbors = new loc_set_t();
+ loc_may_equal_map->put(member, _neighbors);
+ }
+ _neighbors->add(new_loc);
+ }
+}
+
+/* Every time a thread enters a function, set its position to the predicate tree entry */
+void FuncNode::init_predicate_tree_position(thread_id_t tid)
+{
+ int thread_id = id_to_int(tid);
+ if (predicate_tree_position.size() <= (uint) thread_id)
+ predicate_tree_position.resize(thread_id + 1);
+
+ predicate_tree_position[thread_id] = predicate_tree_entry;
+}
+
+void FuncNode::set_predicate_tree_position(thread_id_t tid, Predicate * pred)
+{
+ int thread_id = id_to_int(tid);
+ predicate_tree_position[thread_id] = pred;
+}
+
+/* @return The position of a thread in a predicate tree */
+Predicate * FuncNode::get_predicate_tree_position(thread_id_t tid)
+{
+ int thread_id = id_to_int(tid);
+ return predicate_tree_position[thread_id];