klee
PTree.cpp
Go to the documentation of this file.
1//===-- PTree.cpp ---------------------------------------------------------===//
2//
3// The KLEE Symbolic Virtual Machine
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "PTree.h"
11
12#include "ExecutionState.h"
13
14#include "klee/Expr/Expr.h"
17
18#include <bitset>
19#include <vector>
20
21using namespace klee;
22using namespace llvm;
23
24namespace {
25
26cl::opt<bool>
27 CompressProcessTree("compress-process-tree",
28 cl::desc("Remove intermediate nodes in the process "
29 "tree whenever possible (default=false)"),
30 cl::init(false), cl::cat(MiscCat));
31
32} // namespace
33
34PTree::PTree(ExecutionState *initialState)
35 : root(PTreeNodePtr(new PTreeNode(nullptr, initialState))) {
36 initialState->ptreeNode = root.getPointer();
37}
38
39void PTree::attach(PTreeNode *node, ExecutionState *leftState,
40 ExecutionState *rightState, BranchType reason) {
41 assert(node && !node->left.getPointer() && !node->right.getPointer());
42 assert(node == rightState->ptreeNode &&
43 "Attach assumes the right state is the current state");
44 node->state = nullptr;
45 node->left = PTreeNodePtr(new PTreeNode(node, leftState));
46 // The current node inherits the tag
47 uint8_t currentNodeTag = root.getInt();
48 if (node->parent)
49 currentNodeTag = node->parent->left.getPointer() == node
50 ? node->parent->left.getInt()
51 : node->parent->right.getInt();
52 node->right = PTreeNodePtr(new PTreeNode(node, rightState), currentNodeTag);
53}
54
56 assert(!n->left.getPointer() && !n->right.getPointer());
57 do {
58 PTreeNode *p = n->parent;
59 if (p) {
60 if (n == p->left.getPointer()) {
61 p->left = PTreeNodePtr(nullptr);
62 } else {
63 assert(n == p->right.getPointer());
64 p->right = PTreeNodePtr(nullptr);
65 }
66 }
67 delete n;
68 n = p;
69 } while (n && !n->left.getPointer() && !n->right.getPointer());
70
71 if (n && CompressProcessTree) {
72 // We're now at a node that has exactly one child; we've just deleted the
73 // other one. Eliminate the node and connect its child to the parent
74 // directly (if it's not the root).
75 PTreeNodePtr child = n->left.getPointer() ? n->left : n->right;
76 PTreeNode *parent = n->parent;
77
78 child.getPointer()->parent = parent;
79 if (!parent) {
80 // We're at the root.
81 root = child;
82 } else {
83 if (n == parent->left.getPointer()) {
84 parent->left = child;
85 } else {
86 assert(n == parent->right.getPointer());
87 parent->right = child;
88 }
89 }
90
91 delete n;
92 }
93}
94
95void PTree::dump(llvm::raw_ostream &os) {
97 pp->setNewline("\\l");
98 os << "digraph G {\n";
99 os << "\tsize=\"10,7.5\";\n";
100 os << "\tratio=fill;\n";
101 os << "\trotate=90;\n";
102 os << "\tcenter = \"true\";\n";
103 os << "\tnode [style=\"filled\",width=.1,height=.1,fontname=\"Terminus\"]\n";
104 os << "\tedge [arrowsize=.3]\n";
105 std::vector<const PTreeNode*> stack;
106 stack.push_back(root.getPointer());
107 while (!stack.empty()) {
108 const PTreeNode *n = stack.back();
109 stack.pop_back();
110 os << "\tn" << n << " [shape=diamond";
111 if (n->state)
112 os << ",fillcolor=green";
113 os << "];\n";
114 if (n->left.getPointer()) {
115 os << "\tn" << n << " -> n" << n->left.getPointer();
116 os << " [label=0b"
117 << std::bitset<PtrBitCount>(n->left.getInt()).to_string() << "];\n";
118 stack.push_back(n->left.getPointer());
119 }
120 if (n->right.getPointer()) {
121 os << "\tn" << n << " -> n" << n->right.getPointer();
122 os << " [label=0b"
123 << std::bitset<PtrBitCount>(n->right.getInt()).to_string() << "];\n";
124 stack.push_back(n->right.getPointer());
125 }
126 }
127 os << "}\n";
128 delete pp;
129}
130
131PTreeNode::PTreeNode(PTreeNode *parent, ExecutionState *state) : parent{parent}, state{state} {
132 state->ptreeNode = this;
133 left = PTreeNodePtr(nullptr);
134 right = PTreeNodePtr(nullptr);
135}
BranchType
Reason an ExecutionState forked.
Definition: BranchTypes.h:48
ExecutionState representing a path under exploration.
PTreeNode * ptreeNode
Pointer to the process tree of the current state Copies of ExecutionState should not copy ptreeNode.
static ExprPPrinter * create(llvm::raw_ostream &os)
virtual void setNewline(const std::string &newline)=0
ExecutionState * state
Definition: PTree.h:35
PTreeNode(const PTreeNode &)=delete
PTreeNode * parent
Definition: PTree.h:31
PTreeNodePtr right
Definition: PTree.h:34
PTreeNodePtr left
Definition: PTree.h:33
void attach(PTreeNode *node, ExecutionState *leftState, ExecutionState *rightState, BranchType reason)
Definition: PTree.cpp:39
PTreeNodePtr root
Definition: PTree.h:47
void dump(llvm::raw_ostream &os)
Definition: PTree.cpp:95
void remove(PTreeNode *node)
Definition: PTree.cpp:55
Definition: main.cpp:291
llvm::PointerIntPair< PTreeNode *, PtrBitCount, uint8_t > PTreeNodePtr
Definition: PTree.h:27
llvm::cl::OptionCategory MiscCat