@@ -543,6 +543,7 @@ struct NodeBox {
543543 std::monostate fillFailedNode ();
544544 std::monostate fillUnreachableNode ();
545545 std::monostate fillSnapshotNode (Snapshot_t snapshot);
546+ std::monostate fillNotToExploreNode ();
546547 bool isUnexplored () const ;
547548 std::vector<SymVal> collect_path_conds ();
548549 int min_cost_of_reaching_here ();
@@ -664,6 +665,22 @@ struct UnExploredNode : Node {
664665 }
665666};
666667
668+ struct NotToExploreNode : Node {
669+ NotToExploreNode () {}
670+ std::string to_string () override { return " NotToExploreNode" ; }
671+
672+ protected:
673+ void generate_dot (std::ostream &os, int parent_dot_id,
674+ const std::string &edge_label) override {
675+ int current_node_dot_id = current_id++;
676+ graphviz_node (os, current_node_dot_id, " NotToExplore" , " box" , " grey" );
677+
678+ if (parent_dot_id != -1 ) {
679+ graphviz_edge (os, parent_dot_id, current_node_dot_id, edge_label);
680+ }
681+ }
682+ };
683+
667684struct SnapshotNode : Node {
668685 SnapshotNode (Snapshot_t snapshot) : snapshot(snapshot) {}
669686 std::string to_string () override { return " SnapshotNode" ; }
@@ -761,6 +778,15 @@ inline std::monostate NodeBox::fillSnapshotNode(Snapshot_t snapshot) {
761778 return std::monostate ();
762779}
763780
781+ inline std::monostate NodeBox::fillNotToExploreNode () {
782+ if (this ->isUnexplored ()) {
783+ node = std::make_unique<NotToExploreNode>();
784+ } else {
785+ assert (dynamic_cast <NotToExploreNode *>(node.get ()) != nullptr );
786+ }
787+ return std::monostate ();
788+ }
789+
764790inline std::monostate NodeBox::fillFinishedNode () {
765791 if (this ->isUnexplored ()) {
766792 node = std::make_unique<Finished>();
@@ -896,6 +922,10 @@ class ExploreTree_t {
896922 return std::monostate ();
897923 }
898924
925+ std::monostate fillNotToExploredNode () {
926+ return cursor->fillNotToExploreNode ();
927+ }
928+
899929 bool worth_to_create_snapshot () {
900930 if (!ENABLE_COST_MODEL) {
901931 return REUSE_SNAPSHOT;
@@ -911,8 +941,8 @@ class ExploreTree_t {
911941 auto parent_cost =
912942 cursor->parent ? cursor->parent ->min_cost_of_reaching_here () : 0 ;
913943 auto exec_from_parent_cost = reach_parent_cost + cursor->instr_cost ;
914- GENSYM_INFO (" The score of snapshot tendency: " + std::to_string (exec_from_parent_cost -
915- snapshot_cost));
944+ GENSYM_INFO (" The score of snapshot tendency: " +
945+ std::to_string (exec_from_parent_cost - snapshot_cost));
916946 return snapshot_cost <= exec_from_parent_cost;
917947 }
918948
@@ -924,6 +954,7 @@ class ExploreTree_t {
924954 if_else_node != nullptr &&
925955 " Can't move cursor when the branch node is not initialized correctly!" );
926956 int cost_from_parent = CostManager.dump_instr_cost ();
957+ cursor->instr_cost = cost_from_parent;
927958 if (branch) {
928959 true_branch_cov_map[if_else_node->id ] = true ;
929960 if (worth_to_create_snapshot ()) {
@@ -947,6 +978,26 @@ class ExploreTree_t {
947978 return std::monostate ();
948979 }
949980
981+ std::monostate moveCursorNoControl (bool branch) {
982+ Profile.step (StepProfileKind::CURSOR_MOVE);
983+ assert (cursor != nullptr );
984+ auto if_else_node = dynamic_cast <IfElseNode *>(cursor->node .get ());
985+ assert (
986+ if_else_node != nullptr &&
987+ " Can't move cursor when the branch node is not initialized correctly!" );
988+ int cost_from_parent = CostManager.dump_instr_cost ();
989+ cursor->instr_cost = cost_from_parent;
990+ if (branch) {
991+ true_branch_cov_map[if_else_node->id ] = true ;
992+ if_else_node->false_branch ->fillNotToExploreNode ();
993+ cursor = if_else_node->true_branch .get ();
994+ } else {
995+ assert (false &&
996+ " moveCursorNoControl should not be used for false branch" );
997+ }
998+ return std::monostate ();
999+ }
1000+
9501001 std::monostate print () {
9511002 std::cout << root->node ->to_string () << std::endl;
9521003 return std::monostate ();
@@ -966,6 +1017,45 @@ class ExploreTree_t {
9661017 return std::monostate ();
9671018 }
9681019
1020+ std::monostate print_overall_result () {
1021+ // Print how many paths have been explored, how many paths are unreachable,
1022+ // how many paths are failed, how many paths are finished successfully
1023+ int unexplored_count = 0 ;
1024+ int finished_count = 0 ;
1025+ int failed_count = 0 ;
1026+ int not_to_explore_count = 0 ;
1027+ int unreachable_count = 0 ;
1028+ std::function<void (NodeBox *)> dfs = [&](NodeBox *node) {
1029+ if (auto if_else_node = dynamic_cast <IfElseNode *>(node->node .get ())) {
1030+ dfs (if_else_node->true_branch .get ());
1031+ dfs (if_else_node->false_branch .get ());
1032+ } else if (dynamic_cast <UnExploredNode *>(node->node .get ())) {
1033+ unexplored_count += 1 ;
1034+ } else if (dynamic_cast <Finished *>(node->node .get ())) {
1035+ finished_count += 1 ;
1036+ } else if (dynamic_cast <Failed *>(node->node .get ())) {
1037+ failed_count += 1 ;
1038+ } else if (dynamic_cast <Unreachable *>(node->node .get ())) {
1039+ unreachable_count += 1 ;
1040+ } else if (dynamic_cast <SnapshotNode *>(node->node .get ())) {
1041+ // Snapshot node is considered unexplored
1042+ unexplored_count += 1 ;
1043+ } else if (dynamic_cast <NotToExploreNode *>(node->node .get ())) {
1044+ not_to_explore_count += 1 ;
1045+ } else {
1046+ throw std::runtime_error (" Unknown node type in explore tree" );
1047+ }
1048+ };
1049+ dfs (root.get ());
1050+ std::cout << " Explore Tree Overall Result:" << std::endl;
1051+ std::cout << " Unexplored paths: " << unexplored_count << std::endl;
1052+ std::cout << " Finished paths: " << finished_count << std::endl;
1053+ std::cout << " Failed paths: " << failed_count << std::endl;
1054+ std::cout << " Unreachable paths: " << unreachable_count << std::endl;
1055+ std::cout << " NotToExplore paths: " << not_to_explore_count << std::endl;
1056+ return std::monostate ();
1057+ }
1058+
9691059 NodeBox *pick_unexplored () {
9701060 // Pick an unexplored node from the tree
9711061 // For now, we just iterate through the tree and return the first unexplored
0 commit comments