55 stat = std::make_unique<MTAStat>();
81 tcg =
tct->getThreadCallGraph();
87 stat->performThreadCallGraphStat(
tcg);
88 stat->performTCTStat(
tct.get());
128 return mhp.release();
140 if (addrStmt !=
nullptr)
144 if (globalVar !=
nullptr)
151 return globalObjVars;
165 std::deque<NodeID> worklist;
168 worklist.push_back(pt);
171 while (!worklist.empty())
173 NodeID obj = worklist.front();
174 worklist.pop_front();
177 if (!ptsClosure.
test(target))
179 ptsClosure.
set(target);
180 worklist.push_back(target);
185 if (!ptsClosure.
test(field))
187 ptsClosure.
set(field);
188 worklist.push_back(field);
200 if (first.
tid != second.
tid)
203 return mhp->getTCT()->getTCTNode(first.
tid)->isMultiforked();
211 out.emplace(first.
stmt, second.
stmt);
233 std::vector<RaceOccurrence>& occurrences,
236 for (
const auto&
item : *callGraph)
241 for (
auto bbIt : *fun)
242 for (
const ICFGNode* node : bbIt.second->getICFGNodeList())
245 mhp->getThreadSummary(node);
246 if (threadSummary ==
nullptr)
254 accessedPtr = load->getRHSVarID();
260 accessedPtr = store->getLHSVarID();
267 objects &= escapedObjects;
273 const size_t firstNewOccurrence = occurrences.size();
274 for (
const auto& tidAndInterleaving :
276 occurrences.push_back(
278 stmt, node, isStore, tidAndInterleaving.first,
279 &tidAndInterleaving.second, locked});
280 for (
NodeID object : objects)
281 for (
size_t index = firstNewOccurrence;
283 objectToOccurrences[
object].push_back(
index);
290 const std::vector<RaceOccurrence>& occurrences,
291 const std::vector<size_t>& occurrenceIndices)
293 std::vector<RaceClass> classes;
295 for (
size_t occurrenceIndex : occurrenceIndices)
303 const auto found = keyToClass.find(key);
304 if (found == keyToClass.end())
306 keyToClass[key] = classes.size();
313 classes[found->second].members.push_back(occurrenceIndex);
320 const std::vector<RaceOccurrence>& occurrences,
321 const std::vector<RaceClass>& classes,
322 std::set<RacePair>& outRacePairs)
324 for (
size_t firstIndex = 0; firstIndex < classes.size(); ++firstIndex)
325 for (
size_t secondIndex = firstIndex;
326 secondIndex < classes.size(); ++secondIndex)
328 const RaceClass& firstClass = classes[firstIndex];
329 const RaceClass& secondClass = classes[secondIndex];
338 mhp, firstRepresentative, secondRepresentative))
341 if (firstIndex != secondIndex)
345 firstRepresentative.
node, secondRepresentative.
node))
347 for (
size_t memberIndex : firstClass.
members)
348 for (
size_t otherIndex : secondClass.
members)
350 occurrences[otherIndex]);
354 const std::vector<size_t>& members = firstClass.
members;
357 firstRepresentative.
node, firstRepresentative.
node))
359 for (
size_t firstPosition = 0;
360 firstPosition < members.size(); ++firstPosition)
361 for (
size_t secondPosition = firstPosition;
362 secondPosition < members.size(); ++secondPosition)
364 outRacePairs, occurrences[members[firstPosition]],
365 occurrences[members[secondPosition]]);
375 std::set<RacePair>& outRacePairs)
378 outRacePairs.clear();
379 std::set<const SVFStmt*> bugStmts;
388 for (
auto it =
tcg->forksitesBegin(), eit =
tcg->forksitesEnd(); it != eit; ++it)
391 seed |= pta->
getPts(actual->getId());
395 std::vector<RaceOccurrence> occurrences;
398 svfir, pta,
mhp, lockAnalysis, callGraph, escSet,
399 occurrences, objectToOccurrences);
404 for (
const auto& objectAndOccs : objectToOccurrences)
406 const std::vector<RaceClass> classes =
409 mhp, lockAnalysis, occurrences, classes, outRacePairs);
412 for (
const RacePair& pair : outRacePairs)
414 bugStmts.insert(pair.stmt1);
415 bugStmts.insert(pair.stmt2);
430 std::set<RacePair> racePairs;
433 for (
const RacePair& rp : racePairs)
447 size_t icfgNodeCount = 0;
451 size_t functionCount = 0;
452 for (
auto it =
svfir->getCallGraph()->begin(), eit =
svfir->getCallGraph()->end(); it != eit; ++it)
455 size_t pagStmtCount = 0;
457 eit =
svfir->getICFG()->end(); it != eit; ++it)
460 if (
svfir->hasSVFStmtList(node))
461 pagStmtCount +=
svfir->getSVFStmtList(node).size();
467 SVFUtil::outs() <<
" PAG statements: " << pagStmtCount <<
"\n";
473 std::set<const ICFGNode*>
nodes;
474 for (
NodeID id : svfgNodeIds)
480 if (stmtNode->getICFGNode() !=
nullptr)
481 nodes.insert(stmtNode->getICFGNode());
487 const std::set<const ICFGNode*>& icfgNodes)
489 std::set<const FunObjVar*> functions;
490 std::set<const SVFStmt*> statements;
491 for (
const ICFGNode* node : icfgNodes)
493 if (node->getFun() !=
nullptr)
494 functions.insert(node->getFun());
495 statements.insert(node->getSVFStmts().begin(), node->getSVFStmts().end());
499 SVFUtil::outs() <<
" ICFG nodes: " << icfgNodes.size() <<
"\n";
500 SVFUtil::outs() <<
" Functions: " << functions.size() <<
"\n";
501 SVFUtil::outs() <<
" PAG statements: " << statements.size() <<
"\n";
508 const FunObjVar* function = node ==
nullptr ? nullptr : node->
getFun();
512 const std::string fields[] =
515 function ==
nullptr ? std::string() : function->
getName(),
516 block ==
nullptr ? std::string() : block->
getName(),
518 value ==
nullptr ? std::string() : value->
getName(),
519 value ==
nullptr ? std::string() : value->
getSourceLoc(),
523 for (
const std::string& field : fields)
525 key += std::to_string(field.size());
534 for (
unsigned char byte : value)
536 digest ^=
static_cast<u64_t>(byte);
537 digest *= 1099511628211ULL;
540 digest *= 1099511628211ULL;
544 const std::set<RacePair>& pairs)
547 std::set<std::string> statementKeys;
550 statementToKey.emplace(pair.stmt1, std::string());
551 statementToKey.emplace(pair.stmt2, std::string());
553 for (
auto& statementAndKey : statementToKey)
556 statementKeys.insert(statementAndKey.second);
559 RaceDigests digests{1469598103934665603ULL, 1469598103934665603ULL};
560 for (
const std::string& key : statementKeys)
563 std::set<std::pair<std::string, std::string>> pairKeys;
566 std::string first = statementToKey.at(pair.stmt1);
567 std::string second = statementToKey.at(pair.stmt2);
569 std::swap(first, second);
570 pairKeys.emplace(std::move(first), std::move(second));
573 for (
const auto& pair : pairKeys)
596 std::set<const SVFStmt*> vulnerableStatements;
599 vulnerableStatements.insert(pair.stmt1);
600 vulnerableStatements.insert(pair.stmt2);
602 return vulnerableStatements;
626 <<
" nodes; [Pre-TVF] "
628 <<
" interference edges\n";
653 tct->dump(
"original_tct");
659 std::unique_ptr<TCT> deepTct =
665 for (
const auto& deepPair : *deepTct)
666 if (
const ICFGNode* forkSite = deepPair.second->getCxtThread().getThread())
668 ++forkSiteInstances[forkSite];
669 if (deepPair.second->isMultiforked())
670 forkSiteInstances[forkSite] = 2;
673 for (
const auto& prePair : *
tct)
675 const ICFGNode* forkSite = prePair.second->getCxtThread().getThread();
676 if (forkSite ==
nullptr)
679 if (fIt != forkSiteInstances.end() && fIt->second > 1)
680 prePair.second->setMultiforked(
true);
716 std::set<const SVFStmt*> vulnerableStatements;
724 SVFUtil::outs() <<
"Found " << vulnerableStatements.size() <<
" vulnerable statements\n";
732 SVFUtil::outs() <<
"[SKIP] No race candidates; VFG_pre is unnecessary\n";
744 SVFUtil::outs() <<
"[SKIP] No race pairs found in pre-analysis\n";
753 std::set<const ICFGNode*> mtaSlicedNodes;
760 SVFUtil::outs() <<
"[Slicing Mode] Single unified slice (V_Single) for ILA + FSPTA\n";
773 SVFUtil::outs() <<
"Unified sliced to " << mtaSlicedNodes.size()
778 SVFUtil::outs() <<
"[Slicing Mode] Differential slices (separate ILA + FSPTA)\n";
786 std::set<const ICFGNode*> threadVFSources;
801 SVFUtil::errs() <<
"[ERROR] Failed to execution-close VFG'_pre\n";
806 <<
"[VFG'_pre] " << preCandidate.
svfgNodes.size()
807 <<
" dependency nodes, "
809 <<
" execution-closure nodes\n";
820 edge.first->getId(), edge.second->getId());
823 threadVFSources.insert(edge.first->getICFGNode());
824 threadVFSources.insert(edge.second->getICFGNode());
825 threadVFSources.insert(entry.second.begin(), entry.second.end());
838 mtaSlicedNodes =
multiStageSlicer->runILASlicing(vulnerableStatements, threadVFSources);
906 SVFUtil::outs() <<
"\n=== PTA Slicing and Sliced Pointer Analysis ===\n";
910 SVFUtil::outs() <<
"[SKIP] No thread functions found in pre-analysis, skipping PTA slicing\n";
915 SVFUtil::outs() <<
"[SKIP] No race pairs found in pre-analysis, skipping PTA slicing\n";
923 std::set<const ICFGNode*> ptaSlicedNodes;
929 SVFUtil::outs() <<
"[Main FSMPTA] Base SVFG or sliced ILA unavailable\n";
937 SVFUtil::outs() <<
"[Slicing Mode] Reusing unified slice (V_Single) for FSPTA\n";
944 SVFUtil::errs() <<
"[ERROR] Single-slice FSMPTA execution closure failed\n";
950 << ptaSlicedNodes.size() <<
" ICFG nodes, "
951 << finalSVFGNodeIds.
count()
952 <<
" execution-closure SVFG nodes\n";
967 SVFUtil::outs() <<
"Using " << vulnerableStatements.size() <<
" vulnerable statements from pre-analysis\n";
974 SVFUtil::errs() <<
"[ERROR] Differential PTA slicing requires the ILA slicer\n";
982 SVFUtil::errs() <<
"[ERROR] Execution-closed VFG'_pre is unavailable\n";
1001 <<
" interference edges over VFG'_pre\n";
1009 finalSVFGNodeIds = finalSlice.
nodeIds();
1011 NodeBS outsideCandidate = finalSVFGNodeIds;
1013 if (!outsideCandidate.
empty())
1015 SVFUtil::errs() <<
"[ERROR] Initial FSPTA slice escapes VFG'_pre by "
1016 << outsideCandidate.
count() <<
" SVFG nodes\n";
1027 outsideCandidate = finalSVFGNodeIds;
1029 if (!outsideCandidate.
empty())
1031 SVFUtil::errs() <<
"[ERROR] FSMPTA execution closure escapes VFG'_pre by "
1032 << outsideCandidate.
count() <<
" SVFG nodes\n";
1043 <<
" / " << preCandidate.
svfgNodes.size() <<
" / "
1044 << preCandidateIds.
count()
1045 <<
" SVFG nodes (final / pre-candidate / execution-closed), "
1046 << finalSVFGNodeIds.
count()
1047 <<
" execution-closure solve nodes\n";
1048 SVFUtil::outs() <<
"PTA sliced to " << ptaSlicedNodes.size()
1062 SVFUtil::outs() <<
"[Main FSMPTA] Reusing BaseSVFG; Main-TVF comes from the sliced main ILA\n";
1065 SVFUtil::errs() <<
"[ERROR] Unsupported FSMPTA mapping/clustering configuration\n";
1072 auto solver = std::make_unique<FSMPTA<const SlicedSVFGView*>>(
1077 solver->getSVFG()->dump(
"mta_svfg");
1106 <<
" alarm-digest=" << digests.
alarm
1107 <<
" pair-digest=" << digests.
pair <<
"\n";
1109 SVFUtil::outs() <<
"\nNo race pairs detected in sliced graph.\n";
1114 SVFUtil::errs() <<
"[ERROR] MTA sliced view not available\n";
1119 SVFUtil::errs() <<
"[ERROR] Sliced MHP or LockAnalysis not available\n";
1124 SVFUtil::errs() <<
"[ERROR] Main flow-sensitive pointer analysis not available\n";
1128 std::set<RacePair> detectedPairs;
1139 std::set<const SVFStmt*> racyStmts;
1140 for (
const RacePair& pair : detectedPairs)
1142 racyStmts.insert(pair.stmt1);
1143 racyStmts.insert(pair.stmt2);
1148 SVFUtil::outs() <<
"Race pairs (sliced graph): " << detectedPairs.size() <<
"\n";
1149 SVFUtil::outs() <<
"Race statements (sliced graph): " << racyStmts.size() <<
"\n";
1155 SVFUtil::outs() <<
"[MSLI-RQ] mode=MSli alarms=" << racyStmts.size()
1156 <<
" pairs=" << detectedPairs.size()
1157 <<
" alarm-digest=" << digests.
alarm
1158 <<
" pair-digest=" << digests.
pair <<
"\n";
1161 if (!detectedPairs.empty())
1164 SVFUtil::outs() <<
"Found " << detectedPairs.size() <<
" race pair(s) in sliced graph\n";
1168 SVFUtil::outs() <<
"\nNo race pairs detected in sliced graph.\n";
1179 SVFUtil::outs() <<
"\n=== Whole-program FSAM Race Detection (no slicing) ===\n";
1182 SVFUtil::outs() <<
"[SKIP] No thread functions / race pairs in pre-analysis\n";
1191 std::set<const ICFGNode*> allNodes;
1193 eit =
svfir->getICFG()->end(); it != eit; ++it)
1194 allNodes.insert(it->second);
1209 "Whole-program ILA: construct MHP/ForkJoin");
1221 std::make_unique<LockAnalysis>(
slicedTCT.get());
1229 ScopedPhaseTimer timer(
"Whole-program Replace Pre-TVF with Main-TVF overlay");
1236 <<
" interference edges over the whole BaseSVFG\n";
1240 auto solver = std::make_unique<FSMPTA<SVFG*>>(
1246 std::set<RacePair> detectedPairs;
1254 std::set<const SVFStmt*> racyStmts;
1255 for (
const RacePair& pair : detectedPairs)
1257 racyStmts.insert(pair.stmt1);
1258 racyStmts.insert(pair.stmt2);
1263 SVFUtil::outs() <<
"Race pairs (whole program): " << detectedPairs.size() <<
"\n";
1264 SVFUtil::outs() <<
"Race statements (whole program): " << racyStmts.size() <<
"\n";
1268 SVFUtil::outs() <<
"[MSLI-RQ] mode=FSAM alarms=" << racyStmts.size()
1269 <<
" pairs=" << detectedPairs.size()
1270 <<
" alarm-digest=" << digests.
alarm
1271 <<
" pair-digest=" << digests.
pair <<
"\n";
1278 if (
svfir !=
nullptr || pag ==
nullptr || preAnalysis.
getPAG() != pag)
1280 SVFUtil::errs() <<
"[ERROR] SlicedMTA is single-use and requires a "
1281 <<
"matching SVFIR and Andersen pre-analysis\n";
1335 edge->getDstNode()->getFunction() !=
nullptr)
1346 const std::set<RacePair>& preAnalysisRacePairs,
1352 std::set<RacePair> filteredRacePairs;
1357 for (
const RacePair& pair : preAnalysisRacePairs)
1359 const ICFGNode* node1 = pair.stmt1->getICFGNode();
1360 const ICFGNode* node2 = pair.stmt2->getICFGNode();
1362 if (!
slicedMHP->mayHappenInParallelCache(node1, node2))
1372 pts1 = slicedPTA->
getPts(ldStmt1->getRHSVarID());
1377 pts1 = slicedPTA->
getPts(stStmt1->getLHSVarID());
1387 pts2 = slicedPTA->
getPts(ldStmt2->getRHSVarID());
1392 pts2 = slicedPTA->
getPts(stStmt2->getLHSVarID());
1401 filteredRacePairs.insert(pair);
1404 return filteredRacePairs;
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
const ValVar * getLHSVar() const
static AndersenWaveDiff * createAndersenWaveDiff(SVFIR *_pag)
Create an singleton instance directly instead of invoking llvm pass manager.
NodeID getRHSVarID() const
const PointsTo & getPts(NodeID id) override
void dump(const std::string &filename)
Dump the graph.
static NodeBS buildExecutionDependencyClosure(SVFG *graph, AndersenBase *preAnalysis, NodeBS dependencyNodes)
static bool supportsCurrentConfiguration()
bool hasBasicBlock() const
GEdgeKind getEdgeKind() const
iterator begin()
Iterators.
IDToNodeMapTy::iterator iterator
const GEdgeSetTy & getOutEdges() const
virtual const FunObjVar * getFun() const
Return the function of this ICFGNode.
const SVFStmtList & getSVFStmts() const
ICFGNodeIDToNodeMapTy::iterator iterator
void updateCallGraph(CallGraph *callgraph)
update ICFG for indirect calls
GlobalICFGNode * getGlobalICFGNode() const
bool isProtectedByCommonLock(const ICFGNode *i1, const ICFGNode *i2)
static std::unique_ptr< MHP > create(TCT *t, ICFGGraph icfg, CGGraph cg, StateRepresentation representation=StateRepresentation::MaterializedContexts)
Construct MHP and initialize its graph-dependent ForkJoinAnalysis.
static ThreadVFBuildConfig wholeProgram()
static ThreadVFBuildConfig mainPhase(const SlicedSVFGView &scope, const ThreadVFCandidateList *candidates=nullptr)
std::pair< const StmtSVFGNode *, const StmtSVFGNode * > ThreadVFEdge
@ SlicingOnly
Build unlabelled connectivity for VFG_pre slicing.
static void emitRacePairs(MHP *mhp, LockAnalysis *lockAnalysis, const std::vector< RaceOccurrence > &occurrences, const std::vector< RaceClass > &classes, std::set< RacePair > &outRacePairs)
virtual LockAnalysis * computeLocksets(TCT *tct)
Compute locksets.
static std::vector< RaceClass > buildRaceClasses(const std::vector< RaceOccurrence > &occurrences, const std::vector< size_t > &occurrenceIndices)
Map< NodeID, std::vector< size_t > > ObjectToRaceOccurrences
std::unique_ptr< TCT > tct
static bool occurrencesRace(MHP *mhp, const RaceOccurrence &first, const RaceOccurrence &second)
virtual ~MTA()
Destructor.
static PointsTo getGlobalObjectVariables(SVFIR *svfir)
Escape/points-to helpers for the shared detector.
virtual MHP * computeMHP(TCT *tct)
Compute MHP.
static void commitRacePair(std::set< RacePair > &out, const RaceOccurrence &first, const RaceOccurrence &second)
static void collectRaceOccurrences(SVFIR *svfir, AndersenBase *pta, MHP *mhp, LockAnalysis *lockAnalysis, CallGraph *callGraph, const PointsTo &escapedObjects, std::vector< RaceOccurrence > &occurrences, ObjectToRaceOccurrences &objectToOccurrences)
Helpers for the equivalence-class race detector.
std::unique_ptr< MTAStat > stat
static std::set< const SVFStmt * > detectRace(SVFIR *svfir, AndersenBase *pta, MHP *mhp, LockAnalysis *lockAnalysis, CallGraph *callGraph, std::set< RacePair > &outRacePairs)
static bool hasThreadFunctions(CallGraph *callGraph)
virtual bool runOnModule(SVFIR *module)
We start the pass here.
virtual void reportRaces()
Run the shared detector and print a race report.
static PointsTo getPointsToClosure(AndersenBase *pta, const PointsTo &pts)
Carries around command line options.
static const Option< bool > MTAEnableSlicing
MTA slicing: slice before the FSAM main analysis (false = whole-program baseline),...
static const Option< bool > DumpMTAGraphs
MTA: dump the pointer-analysis and thread call graphs (ptacg/tcg.dot), Default: false.
static const Option< bool > MTASingleStageSlicing
MTA slicing: one unified slice for ILA + FSPTA (single-pass baseline), Default: false.
bool printStat()
Whether print statistics.
NodeID getBaseObjVarID(NodeID id)
CallGraph * getCallGraph() const
Return call graph.
virtual const NodeBS & getAllFieldsObjVars(NodeID id)
bool empty() const
Returns true if set is empty.
void set(u32_t n)
Inserts n in the set.
bool intersects(const PointsTo &rhs) const
Returns true if this set and rhs share any elements.
bool test(u32_t n) const
Returns true if n is in this set.
bool hasSVFGNode(NodeID id) const
Whether has the SVFGNode.
SVFGNode * getSVFGNode(NodeID id) const
Get a SVFG node.
SVFStmtList & getSVFStmtList(const ICFGNode *inst)
Given an instruction, get all its PAGEdges.
const BaseObjVar * getBaseObject(NodeID id) const
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
ICFGNode * getICFGNode() const
const SVFVar * getValue() const
const SVFBasicBlock * getBB() const
NodeID getId() const
Get ID.
virtual const std::string getSourceLoc() const
virtual const std::string & getName() const
const bool hasLLVMValue() const
const std::string valueOnlyToString() const
void dump(const std::string &filename) const
Dump sliced ICFG to dot file.
NodeBS preCandidateSolveNodeIds
bool runWholeProgramDetection()
static RaceDigests computeRaceDigests(const std::set< RacePair > &pairs)
std::unique_ptr< LockAnalysis > lockAnalysis
std::set< RacePair > racePairs
AndersenWaveDiff * preAndersen
MTA::RacePair RacePair
The shared race detector lives in MTA; reuse its race-pair type.
std::unique_ptr< MTASVFGBuilder > preSVFGBuilder
static std::string raceStatementKey(const SVFStmt *statement)
bool runPTASlicingAndAnalysis()
MTASVFGBuilder::ThreadVFCandidateList selectedThreadVFCandidates
bool runFinalRaceDetection()
std::set< const SVFStmt * > getVulnerableStmts() const
Union of both statements of every candidate race pair (the slice targets).
ThreadCallGraph * threadCallGraph
std::unique_ptr< LockAnalysis > slicedLockAnalysis
std::unique_ptr< SlicedSVFIRView > mtaSlicedView
std::set< RacePair > detectRacePairsOnSlicedGraph(const std::set< RacePair > &preAnalysisRacePairs, BVDataPTAImpl *slicedPTA, MHP *slicedMHP, LockAnalysis *slicedLockAnalysis)
Refine the pre-analysis candidate pairs with main-phase ILA and FSAM.
bool runMTASlicingAndAnalysis()
std::unique_ptr< MultiStageSlicer > multiStageSlicer
static std::set< const ICFGNode * > collectICFGNodes(SVFG *svfg, const NodeBS &svfgNodeIds)
static void updateDigest(u64_t &digest, const std::string &value)
std::set< const ICFGNode * > singleSlicedNodes
std::unique_ptr< SingleSlicer > singleSlicer
void buildPreAnalysisSVFG()
static void reportPTASliceStatistics(const std::set< const ICFGNode * > &icfgNodes)
NodeBS singleSlicedSVFGNodeIds
bool runOnModule(SVFIR *pag, AndersenWaveDiff &preAnalysis)
Run the slicing pipeline with its prepared Andersen pre-analysis.
std::unique_ptr< SlicedSVFIRView > ptaSlicedView
std::unique_ptr< TCT > tct
std::unique_ptr< SlicedSVFGView > slicedSVFGView
std::unique_ptr< SlicedTCT > slicedTCT
std::unique_ptr< MHP > mhp
std::unique_ptr< MHP > slicedMHP
static void reportOriginalStatistics(SVFIR *svfir)
Pipeline utilities shared by the sliced and whole-program paths.
BVDataPTAImpl * getMainPTA() const
std::unique_ptr< FlowSensitive > mainFSMPTA
void dump(const std::string &filename) const
Dump the sliced PAG to a dot file.
const SlicedThreadCallGraphView * getThreadCallGraph() const
Get SlicedThreadCallGraphView.
const SlicedICFGView * getICFG() const
Get SlicedICFGView.
const SlicedPAGView * getPAG() const
Get SlicedPAGView.
static std::unique_ptr< SlicedTCT > create(PointerAnalysis &pointerAnalysis, const SlicedSVFIRView &slicedView, u32_t contextLimit)
void dump(const std::string &filename) const
Dump sliced ThreadCallGraph to dot file.
bool test(unsigned Idx) const
bool intersectWithComplement(const SparseBitVector &RHS)
static std::unique_ptr< TCT > create(PointerAnalysis *p)
Construct and build a TCT with the command-line context bound.
const ValVar * getActualParmAtForkSite(const CallICFGNode *inst) const
std::string bugMsg1(const std::string &msg)
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
bool cmpNodeBS(const NodeBS &lpts, const NodeBS &rpts)
std::ostream & errs()
Overwrite llvm::errs().
std::ostream & outs()
Overwrite llvm::outs().
LLVM_NODISCARD std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast(const Y &Val)
std::map< Key, Value, Compare, Allocator > OrderedMap
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
iter_range< typename GenericGraphTraits< GraphType >::nodes_iterator > nodes(const GraphType &G)
Map< NodeID, NodeBS > interleavingByTid
bool operator<(const RaceClassKey &other) const
const NodeBS * interleaving
std::vector< size_t > members
One occurrence of a memory access under one thread instance.
const NodeBS * interleaving
A race pair: two statements that may race.
OrderedSet< const SVFGNode * > svfgNodes
OrderedSet< const ICFGNode * > icfgNodes