/// Utility function that checks whether \p VPBlockVec has duplicate /// VPBlockBases. static bool hasDuplicates(const SmallVectorImpl<VPBlockBase *> &VPBlockVec) { SmallDenseSet<const VPBlockBase *, 8> VPBlockSet; for (const auto *Block : VPBlockVec) { if (VPBlockSet.count(Block)) return true; VPBlockSet.insert(Block); } return false; }
/// Sort local variables so that variables appearing inside of helper /// expressions come first. static SmallVector<DbgVariable *, 8> sortLocalVars(SmallVectorImpl<DbgVariable *> &Input) { SmallVector<DbgVariable *, 8> Result; SmallVector<PointerIntPair<DbgVariable *, 1>, 8> WorkList; // Map back from a DIVariable to its containing DbgVariable. SmallDenseMap<const DILocalVariable *, DbgVariable *> DbgVar; // Set of DbgVariables in Result. SmallDenseSet<DbgVariable *, 8> Visited; // For cycle detection. SmallDenseSet<DbgVariable *, 8> Visiting; // Initialize the worklist and the DIVariable lookup table. for (auto Var : reverse(Input)) { DbgVar.insert({Var->getVariable(), Var}); WorkList.push_back({Var, 0}); } // Perform a stable topological sort by doing a DFS. while (!WorkList.empty()) { auto Item = WorkList.back(); DbgVariable *Var = Item.getPointer(); bool visitedAllDependencies = Item.getInt(); WorkList.pop_back(); // Dependency is in a different lexical scope or a global. if (!Var) continue; // Already handled. if (Visited.count(Var)) continue; // Add to Result if all dependencies are visited. if (visitedAllDependencies) { Visited.insert(Var); Result.push_back(Var); continue; } // Detect cycles. auto Res = Visiting.insert(Var); if (!Res.second) { assert(false && "dependency cycle in local variables"); return Result; } // Push dependencies and this node onto the worklist, so that this node is // visited again after all of its dependencies are handled. WorkList.push_back({Var, 1}); for (auto *Dependency : dependencies(Var)) { auto Dep = dyn_cast_or_null<const DILocalVariable>(Dependency); WorkList.push_back({DbgVar[Dep], 0}); } } return Result; }