svf-tools 1.0.1021 → 1.0.1023

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build.sh CHANGED
@@ -250,10 +250,10 @@ BUILD_DIR="./${BUILD_TYPE}-build"
250
250
  rm -rf "${BUILD_DIR}"
251
251
  mkdir "${BUILD_DIR}"
252
252
  # If you need shared libs, turn BUILD_SHARED_LIBS on
253
- cmake -D CMAKE_BUILD_TYPE:STRING="${BUILD_TYPE}" \
254
- -DSVF_ENABLE_ASSERTIONS:BOOL=true \
255
- -DSVF_SANITIZE="${SVF_SANITIZER}" \
256
- -DBUILD_SHARED_LIBS=off \
253
+ cmake -D CMAKE_BUILD_TYPE:STRING="${BUILD_TYPE}" \
254
+ -DSVF_ENABLE_ASSERTIONS:BOOL=true \
255
+ -DSVF_SANITIZE="${SVF_SANITIZER}" \
256
+ -DBUILD_SHARED_LIBS=off \
257
257
  -S "${SVFHOME}" -B "${BUILD_DIR}"
258
258
  cmake --build "${BUILD_DIR}" -j ${jobs}
259
259
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svf-tools",
3
- "version": "1.0.1021",
3
+ "version": "1.0.1023",
4
4
  "description": "* <b>[TypeClone](https://github.com/SVF-tools/SVF/wiki/TypeClone) published in our [ECOOP paper](https://yuleisui.github.io/publications/ecoop20.pdf) is now available in SVF </b> * <b>SVF now uses a single script for its build. Just type [`source ./build.sh`](https://github.com/SVF-tools/SVF/blob/master/build.sh) in your terminal, that's it!</b> * <b>SVF now supports LLVM-10.0.0! </b> * <b>We thank [bsauce](https://github.com/bsauce) for writing a user manual of SVF ([link1](https://www.jianshu.com/p/068a08ec749c) and [link2](https://www.jianshu.com/p/777c30d4240e)) in Chinese </b> * <b>SVF now supports LLVM-9.0.0 (Thank [Byoungyoung Lee](https://github.com/SVF-tools/SVF/issues/142) for his help!). </b> * <b>SVF now supports a set of [field-sensitive pointer analyses](https://yuleisui.github.io/publications/sas2019a.pdf). </b> * <b>[Use SVF as an external lib](https://github.com/SVF-tools/SVF/wiki/Using-SVF-as-a-lib-in-your-own-tool) for your own project (Contributed by [Hongxu Chen](https://github.com/HongxuChen)). </b> * <b>SVF now supports LLVM-7.0.0. </b> * <b>SVF now supports Docker. [Try SVF in Docker](https://github.com/SVF-tools/SVF/wiki/Try-SVF-in-Docker)! </b> * <b>SVF now supports [LLVM-6.0.0](https://github.com/svf-tools/SVF/pull/38) (Contributed by [Jack Anthony](https://github.com/jackanth)). </b> * <b>SVF now supports [LLVM-4.0.0](https://github.com/svf-tools/SVF/pull/23) (Contributed by Jared Carlson. Thank [Jared](https://github.com/jcarlson23) and [Will](https://github.com/dtzWill) for their in-depth [discussions](https://github.com/svf-tools/SVF/pull/18) about updating SVF!) </b> * <b>SVF now supports analysis for C++ programs.</b> <br />",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -33,7 +33,6 @@
33
33
  #include <fstream>
34
34
  #include <iostream>
35
35
  #include <string>
36
- #include <regex>
37
36
  #include "CFL/CFGrammar.h"
38
37
  #include "Graphs/GenericGraph.h"
39
38
  #include "Graphs/ConsG.h"
@@ -32,7 +32,6 @@
32
32
  #include "Util/WorkList.h"
33
33
  #include "SVFIR/SVFValue.h"
34
34
  #include <string>
35
- #include <regex>
36
35
  #include <fstream>
37
36
  #include <sstream>
38
37
  #include <iostream>
@@ -437,13 +436,23 @@ void CFGNormalizer::ebnfSignReplace(char sign, CFGrammar *grammar)
437
436
 
438
437
  void CFGNormalizer::strTrans(std::string LHS, CFGrammar *grammar, GrammarBase::Production& normalProd)
439
438
  {
440
- std::smatch matches;
441
- std::regex LHSReg("\\s*(.*)");
439
+ // Find the position of the first non-whitespace character
440
+ size_t start = LHS.find_first_not_of(" \t\n\r");
441
+ // If the string contains non-whitespace characters, remove leading spaces
442
+ if (start != std::string::npos)
443
+ {
444
+ LHS = LHS.substr(start);
445
+ }
446
+ else
447
+ {
448
+ // If the string contains only spaces, clear it
449
+ LHS.clear();
450
+ }
451
+
442
452
  std::string delimiter;
443
453
  size_t pos;
444
454
  std::string word;
445
- std::regex_search(LHS, matches, LHSReg);
446
- LHS = matches.str(1);
455
+
447
456
  delimiter = " ";
448
457
  while ((pos = LHS.find(delimiter)) != std::string::npos)
449
458
  {
@@ -454,6 +463,7 @@ void CFGNormalizer::strTrans(std::string LHS, CFGrammar *grammar, GrammarBase::P
454
463
  normalProd.push_back(grammar->strToSymbol(LHS));
455
464
  }
456
465
 
466
+
457
467
  GrammarBase::Symbol CFGNormalizer::check_head(GrammarBase::SymbolMap<GrammarBase::Symbol, GrammarBase::Productions> &grammar, GrammarBase::Production &rule)
458
468
  {
459
469
  for(auto symProdPair: grammar)
@@ -193,49 +193,79 @@ CFLGraph* CFLGraphBuilder::buildFromText(std::string fileName, GrammarBase *gram
193
193
  return cflGraph;
194
194
  }
195
195
 
196
- CFLGraph * CFLGraphBuilder::buildFromDot(std::string fileName, GrammarBase *grammar, BuildDirection direction)
196
+ CFLGraph *CFLGraphBuilder::buildFromDot(std::string fileName, GrammarBase *grammar, BuildDirection direction)
197
197
  {
198
198
  buildlabelToKindMap(grammar);
199
199
  cflGraph = new CFLGraph(grammar->getStartKind());
200
200
  std::string lineString;
201
201
  std::ifstream inputFile(fileName);
202
202
  std::cout << "Building CFL Graph from dot file: " << fileName << "..\n";
203
- std::regex reg("Node(\\w+)\\s*->\\s*Node(\\w+)\\s*\\[.*label=(.*)\\]");
204
203
  std::cout << std::boolalpha;
205
- u32_t lineNum = 0 ;
204
+
205
+ u32_t lineNum = 0;
206
206
  current = labelToKindMap.size();
207
207
 
208
208
  while (getline(inputFile, lineString))
209
209
  {
210
210
  lineNum += 1;
211
- std::smatch matches;
212
- if (std::regex_search(lineString, matches, reg))
211
+
212
+ // Find "Node" prefixes and "->"
213
+ size_t srcStart = lineString.find("Node");
214
+ if (srcStart == std::string::npos) continue;
215
+
216
+ size_t srcEnd = lineString.find(" ", srcStart);
217
+ if (srcEnd == std::string::npos) continue;
218
+
219
+ size_t arrowPos = lineString.find("->", srcEnd);
220
+ if (arrowPos == std::string::npos) continue;
221
+
222
+ size_t dstStart = lineString.find("Node", arrowPos);
223
+ if (dstStart == std::string::npos) continue;
224
+
225
+ size_t dstEnd = lineString.find(" ", dstStart);
226
+ if (dstEnd == std::string::npos) continue;
227
+
228
+ size_t labelStart = lineString.find("label=", dstEnd);
229
+ if (labelStart == std::string::npos) continue;
230
+
231
+ labelStart += 6; // Move past "label=" to the start of the label
232
+ size_t labelEnd = lineString.find_first_of("]", labelStart);
233
+ if (labelEnd == std::string::npos) continue;
234
+
235
+ // Extract the source ID, destination ID, and label
236
+ std::string srcIDStr = lineString.substr(srcStart + 4, srcEnd - (srcStart + 4));
237
+ std::string dstIDStr = lineString.substr(dstStart + 4, dstEnd - (dstStart + 4));
238
+ std::string label = lineString.substr(labelStart, labelEnd - labelStart);
239
+
240
+ // Convert source and destination IDs from hexadecimal
241
+ u32_t srcID = std::stoul(srcIDStr, nullptr, 16);
242
+ u32_t dstID = std::stoul(dstIDStr, nullptr, 16);
243
+
244
+ CFLNode *src = addGNode(srcID);
245
+ CFLNode *dst = addGNode(dstID);
246
+
247
+ if (labelToKindMap.find(label) != labelToKindMap.end())
248
+ {
249
+ cflGraph->addCFLEdge(src, dst, labelToKindMap[label]);
250
+ }
251
+ else
213
252
  {
214
- u32_t srcID = std::stoul(matches.str(1), nullptr, 16);
215
- u32_t dstID = std::stoul(matches.str(2), nullptr, 16);
216
- std::string label = matches.str(3);
217
- CFLNode *src = addGNode(srcID);
218
- CFLNode *dst = addGNode(dstID);
219
- if (labelToKindMap.find(label) != labelToKindMap.end())
253
+ if (Options::FlexSymMap() == true)
254
+ {
255
+ labelToKindMap.insert({label, current++});
220
256
  cflGraph->addCFLEdge(src, dst, labelToKindMap[label]);
257
+ }
221
258
  else
222
259
  {
223
- if(Options::FlexSymMap() == true)
224
- {
225
- labelToKindMap.insert({label, current++});
226
- cflGraph->addCFLEdge(src, dst, labelToKindMap[label]);
227
- }
228
- else
229
- {
230
- std::string msg = "In line " + std::to_string(lineNum) +
231
- " sym can not find in grammar, please correct the input dot or set --flexsymmap.";
232
- SVFUtil::errMsg(msg);
233
- std::cout << msg;
234
- abort();
235
- }
260
+ std::string msg = "In line " + std::to_string(lineNum) +
261
+ " sym cannot be found in grammar. Please correct the input dot or set --flexsymmap.";
262
+ SVFUtil::errMsg(msg);
263
+ std::cout << msg;
264
+ abort();
236
265
  }
237
266
  }
238
267
  }
268
+
239
269
  inputFile.close();
240
270
  return cflGraph;
241
271
  }
@@ -247,7 +277,6 @@ CFLGraph* CFLGraphBuilder::buildFromJson(std::string fileName, GrammarBase *gram
247
277
  return cflGraph;
248
278
  }
249
279
 
250
-
251
280
  CFLGraph* AliasCFLGraphBuilder::buildBigraph(ConstraintGraph *graph, Kind startKind, GrammarBase *grammar)
252
281
  {
253
282
  cflGraph = new CFLGraph(startKind);
@@ -543,4 +572,4 @@ CFLGraph* VFCFLGraphBuilder::buildBiPEGgraph(ConstraintGraph *graph, Kind startK
543
572
  }
544
573
 
545
574
 
546
- } // end of SVF namespace
575
+ } // end of SVF namespace
@@ -29,7 +29,6 @@
29
29
 
30
30
  #include <string>
31
31
  #include <fstream>
32
- #include <regex>
33
32
  #include <sstream>
34
33
  #include <iostream>
35
34
  #include "CFL/GrammarBuilder.h"
@@ -44,48 +43,69 @@ const inline std::string GrammarBuilder::parseProductionsString() const
44
43
  std::cerr << "Can't open CFL grammar file `" << fileName << "`" << std::endl;
45
44
  abort();
46
45
  }
46
+
47
47
  std::string lineString;
48
48
  std::string lines = "";
49
49
  std::string startString;
50
50
  std::string symbolString;
51
51
  const std::string WHITESPACE = " \n\r\t\f\v";
52
52
  int lineNum = 0;
53
+
53
54
  while (getline(textFile, lineString))
54
55
  {
55
- if(lineNum == 1)
56
+ if (lineNum == 1)
56
57
  {
57
58
  startString = stripSpace(lineString);
58
59
  }
59
- if(lineNum == 3)
60
+ else if (lineNum == 3)
61
+ {
62
+ // Trim leading and trailing whitespace
63
+ size_t start = lineString.find_first_not_of(WHITESPACE);
64
+ size_t end = lineString.find_last_not_of(WHITESPACE);
65
+ if (start != std::string::npos && end != std::string::npos)
66
+ {
67
+ symbolString = lineString.substr(start, end - start + 1);
68
+ }
69
+ }
70
+
71
+ // Append line to `lines` with whitespace trimmed
72
+ size_t start = lineString.find_first_not_of(WHITESPACE);
73
+ size_t end = lineString.find_last_not_of(WHITESPACE);
74
+ if (start != std::string::npos && end != std::string::npos)
60
75
  {
61
- symbolString = lineString.substr(lineString.find_first_not_of(WHITESPACE), lineString.find_last_not_of(WHITESPACE)+1);
76
+ lines.append(lineString.substr(start, end - start + 1));
62
77
  }
63
78
 
64
- lines.append(lineString.substr(lineString.find_first_not_of(WHITESPACE), lineString.find_last_not_of(WHITESPACE)+1));
65
79
  lineNum++;
66
80
  }
67
81
 
68
- std::regex reg("Start:([\\s\\S]*)Terminal:(.*)Productions:([\\s\\S]*)");
69
- std::smatch matches;
70
- if (std::regex_search(lines, matches, reg))
82
+ // Extract "Productions:" part from `lines` manually
83
+ size_t productionsPos = lines.find("Productions:");
84
+ if (productionsPos != std::string::npos)
71
85
  {
72
- lines = matches.str(3);
86
+ lines = lines.substr(productionsPos + std::string("Productions:").length());
73
87
  }
88
+
89
+ // Parse `symbolString` to insert symbols
74
90
  std::string sString;
75
91
  size_t pos = 0;
76
92
  while ((pos = symbolString.find(" ")) != std::string::npos)
77
93
  {
78
94
  sString = stripSpace(symbolString.substr(0, pos));
79
- symbolString.erase(0, pos + 1); //Capital is Nonterminal, Otherwise is terminal
95
+ symbolString.erase(0, pos + 1); // Remove the processed part
80
96
  grammar->insertSymbol(sString);
81
97
  }
98
+ // Insert the remaining symbol
82
99
  grammar->insertSymbol(symbolString);
100
+
101
+ // Set the start kind and add the epsilon terminal
83
102
  grammar->setStartKind(grammar->insertSymbol(startString));
84
103
  grammar->insertTerminalKind("epsilon");
85
104
 
86
105
  return lines;
87
106
  }
88
107
 
108
+
89
109
  const inline std::vector<std::string> GrammarBuilder::loadWordProductions() const
90
110
  {
91
111
  size_t pos = 0;
@@ -104,17 +124,21 @@ const inline std::vector<std::string> GrammarBuilder::loadWordProductions() cons
104
124
 
105
125
  const inline std::string GrammarBuilder::stripSpace(std::string s) const
106
126
  {
107
- std::smatch matches;
108
- std::regex stripReg("\\s*(\\S*)\\s*");
109
- std::regex_search(s, matches, stripReg);
110
- return matches.str(1);
111
- }
127
+ // Remove leading spaces
128
+ size_t start = s.find_first_not_of(" ");
129
+ if (start == std::string::npos)
130
+ {
131
+ return ""; // Return an empty string if no non-space character is found
132
+ }
112
133
 
134
+ // Remove trailing spaces
135
+ size_t end = s.find_last_not_of(" ");
136
+ return s.substr(start, end - start + 1);
137
+ }
113
138
 
114
- /// build grammarbase from textfile
139
+ /// Build grammarbase from textfile
115
140
  GrammarBase* GrammarBuilder::build() const
116
141
  {
117
- std::smatch matches;
118
142
  std::string delimiter = " ";
119
143
  std::string delimiter1 = "->";
120
144
  std::string word = "";
@@ -124,29 +148,50 @@ GrammarBase* GrammarBuilder::build() const
124
148
 
125
149
  for (auto wordProd : wordProdVec)
126
150
  {
151
+ // Find the position of the '->' delimiter
127
152
  if ((pos = wordProd.find(delimiter1)) != std::string::npos)
128
153
  {
154
+ // Extract and strip RHS (right-hand side) and LHS (left-hand side)
129
155
  std::string RHS = stripSpace(wordProd.substr(0, pos));
130
- std::string LHS = wordProd.substr(pos + delimiter1.size(), wordProd.size() - 1);
156
+ std::string LHS = stripSpace(wordProd.substr(pos + delimiter1.size()));
157
+
158
+ // Insert RHS symbol into grammar
131
159
  GrammarBase::Symbol RHSSymbol = grammar->insertSymbol(RHS);
132
160
  prod.push_back(RHSSymbol);
133
- if (grammar->getRawProductions().find(RHSSymbol) == grammar->getRawProductions().end()) grammar->getRawProductions().insert({RHSSymbol, {}});
134
- std::regex LHSRegEx("\\s*(.*)");
135
- std::regex_search(LHS, matches, LHSRegEx);
136
- LHS = matches.str(1);
161
+
162
+ // Ensure RHS symbol exists in raw productions
163
+ if (grammar->getRawProductions().find(RHSSymbol) == grammar->getRawProductions().end())
164
+ {
165
+ grammar->getRawProductions().insert({RHSSymbol, {}});
166
+ }
167
+
168
+ // Parse LHS string into symbols
137
169
  while ((pos = LHS.find(delimiter)) != std::string::npos)
138
170
  {
139
- word = LHS.substr(0, pos);
140
- LHS.erase(0, pos + delimiter.length()); //Capital is Nonterminal, Otherwise is terminal
171
+ // Extract each word before the space
172
+ word = stripSpace(LHS.substr(0, pos));
173
+ LHS.erase(0, pos + delimiter.length());
174
+
175
+ // Insert symbol into production
141
176
  prod.push_back(grammar->insertSymbol(word));
142
177
  }
143
- prod.push_back(grammar->insertSymbol(LHS));
178
+
179
+ // Insert the remaining word (if any) into the production
180
+ if (!LHS.empty())
181
+ {
182
+ prod.push_back(grammar->insertSymbol(stripSpace(LHS)));
183
+ }
184
+
185
+ // Add the production to raw productions
144
186
  grammar->getRawProductions().at(RHSSymbol).insert(prod);
187
+
188
+ // Clear the production for the next iteration
145
189
  prod = {};
146
190
  }
147
191
  }
148
192
 
149
193
  return grammar;
150
- };
151
-
152
194
  }
195
+
196
+
197
+ }
@@ -75,7 +75,7 @@ private:
75
75
  ///@{
76
76
  void processFunEntry(const Function* fun, WorkList& worklist);
77
77
 
78
- void processNoPrecessorBasicBlocks(const Function* fun, WorkList& worklist);
78
+ void processUnreachableFromEntry(const Function* fun, WorkList& worklist);
79
79
 
80
80
  void processFunBody(WorkList& worklist);
81
81
 
@@ -109,6 +109,8 @@ private:
109
109
  FunToFunExitNodeMapTy FunToFunExitNodeMap; ///< map a function to its FunEntryICFGNode
110
110
  CallGraph* callgraph;
111
111
 
112
+ Map<const Function*, DominatorTree> FunToDominatorTree;
113
+
112
114
  /// Constructor
113
115
  LLVMModuleSet();
114
116
 
@@ -397,6 +399,8 @@ public:
397
399
  return icfg;
398
400
  }
399
401
 
402
+ DominatorTree& getDomTree(const Function* fun);
403
+
400
404
  private:
401
405
  /// Create SVFTypes
402
406
  SVFType* addSVFTypeInfo(const Type* t);
@@ -70,7 +70,7 @@ ICFG* ICFGBuilder::build()
70
70
  continue;
71
71
  WorkList worklist;
72
72
  processFunEntry(fun,worklist);
73
- processNoPrecessorBasicBlocks(fun, worklist);
73
+ processUnreachableFromEntry(fun, worklist);
74
74
  processFunBody(worklist);
75
75
  processFunExit(fun);
76
76
 
@@ -122,21 +122,20 @@ void ICFGBuilder::processFunEntry(const Function* fun, WorkList& worklist)
122
122
  }
123
123
 
124
124
  /*!
125
- * bbs with no predecessors
125
+ * bbs unreachable from function entry
126
126
  */
127
- void ICFGBuilder::processNoPrecessorBasicBlocks(const Function* fun, WorkList& worklist)
127
+ void ICFGBuilder::processUnreachableFromEntry(const Function* fun, WorkList& worklist)
128
128
  {
129
- for (const auto& bb: *fun)
129
+ SVFLoopAndDomInfo* pInfo =
130
+ llvmModuleSet()->getSVFFunction(fun)->getLoopAndDomInfo();
131
+ for (const auto& bb : *fun)
130
132
  {
131
- for (const auto& inst: bb)
133
+ if (pInfo->isUnreachable(llvmModuleSet()->getSVFBasicBlock(&bb)) &&
134
+ !visited.count(&bb.front()))
132
135
  {
133
- if (LLVMUtil::isNoPrecessorBasicBlock(inst.getParent()) &&
134
- !visited.count(&inst))
135
- {
136
- visited.insert(&inst);
137
- (void)addBlockICFGNode(&inst);
138
- worklist.push(&inst);
139
- }
136
+ visited.insert(&bb.front());
137
+ (void)addBlockICFGNode(&bb.front());
138
+ worklist.push(&bb.front());
140
139
  }
141
140
  }
142
141
  }
@@ -48,7 +48,6 @@ using namespace SVFUtil;
48
48
  */
49
49
  void LLVMLoopAnalysis::buildLLVMLoops(SVFModule *mod, ICFG* icfg)
50
50
  {
51
- llvm::DominatorTree DT = llvm::DominatorTree();
52
51
  std::vector<const Loop *> loop_stack;
53
52
  for (Module& M : LLVMModuleSet::getLLVMModuleSet()->getLLVMModules())
54
53
  {
@@ -59,7 +58,7 @@ void LLVMLoopAnalysis::buildLLVMLoops(SVFModule *mod, ICFG* icfg)
59
58
  if (func->isDeclaration()) continue;
60
59
  // do not analyze external call
61
60
  if (SVFUtil::isExtCall(svffun)) continue;
62
- DT.recalculate(const_cast<Function&>(*func));
61
+ llvm::DominatorTree& DT = LLVMModuleSet::getLLVMModuleSet()->getDomTree(func);
63
62
  llvm::LoopInfoBase<llvm::BasicBlock, llvm::Loop> loopInfo;
64
63
  std::vector<const Loop*> llvmLoops;
65
64
  loopInfo.analyze(DT);
@@ -99,6 +99,15 @@ ObjTypeInference* LLVMModuleSet::getTypeInference()
99
99
  return typeInference;
100
100
  }
101
101
 
102
+ DominatorTree& LLVMModuleSet::getDomTree(const SVF::Function* fun)
103
+ {
104
+ auto it = FunToDominatorTree.find(fun);
105
+ if(it != FunToDominatorTree.end()) return it->second;
106
+ DominatorTree& dt = FunToDominatorTree[fun];
107
+ dt.recalculate(const_cast<Function&>(*fun));
108
+ return dt;
109
+ }
110
+
102
111
  SVFModule* LLVMModuleSet::buildSVFModule(Module &mod)
103
112
  {
104
113
  LLVMModuleSet* mset = getLLVMModuleSet();
@@ -407,9 +416,8 @@ void LLVMModuleSet::initDomTree(SVFFunction* svffun, const Function* fun)
407
416
  if (fun->isDeclaration())
408
417
  return;
409
418
  //process and stored dt & df
410
- DominatorTree dt;
411
419
  DominanceFrontier df;
412
- dt.recalculate(const_cast<Function&>(*fun));
420
+ DominatorTree& dt = getDomTree(fun);
413
421
  df.analyze(dt);
414
422
  LoopInfo loopInfo = LoopInfo(dt);
415
423
  PostDominatorTree pdt = PostDominatorTree(const_cast<Function&>(*fun));
@@ -75,8 +75,7 @@ void LLVMUtil::getFunReachableBBs (const Function* fun, std::vector<const SVFBas
75
75
  {
76
76
  assert(!SVFUtil::isExtCall(LLVMModuleSet::getLLVMModuleSet()->getSVFFunction(fun)) && "The calling function cannot be an external function.");
77
77
  //initial DominatorTree
78
- DominatorTree dt;
79
- dt.recalculate(const_cast<Function&>(*fun));
78
+ DominatorTree& dt = LLVMModuleSet::getLLVMModuleSet()->getDomTree(fun);
80
79
 
81
80
  Set<const BasicBlock*> visited;
82
81
  std::vector<const BasicBlock*> bbVec;