void DependencyGraphImpl::markTransitive(SmallVectorImpl<const void *> &visited, const void *node, MarkTracerImpl *tracer) { assert(Provides.count(node) && "node is not in the graph"); llvm::SpecificBumpPtrAllocator<MarkTracerImpl::Entry> scratchAlloc; struct WorklistEntry { ArrayRef<MarkTracerImpl::Entry> Reason; const void *Node; bool IsCascading; }; SmallVector<WorklistEntry, 16> worklist; SmallPtrSet<const void *, 16> visitedSet; auto addDependentsToWorklist = [&](const void *next, ArrayRef<MarkTracerImpl::Entry> reason) { auto allProvided = Provides.find(next); if (allProvided == Provides.end()) return; for (const auto &provided : allProvided->second) { auto allDependents = Dependencies.find(provided.name); if (allDependents == Dependencies.end()) continue; if (allDependents->second.second.contains(provided.kindMask)) continue; // Record that we've traversed this dependency. allDependents->second.second |= provided.kindMask; for (const auto &dependent : allDependents->second.first) { if (dependent.node == next) continue; auto intersectingKinds = provided.kindMask & dependent.kindMask; if (!intersectingKinds) continue; if (isMarked(dependent.node)) continue; bool isCascading{dependent.flags & DependencyFlags::IsCascading}; MutableArrayRef<MarkTracerImpl::Entry> newReason; if (tracer) { tracer->countStatsForNodeMarking(intersectingKinds, isCascading); newReason = {scratchAlloc.Allocate(reason.size()+1), reason.size()+1}; std::uninitialized_copy(reason.begin(), reason.end(), newReason.begin()); new (&newReason.back()) MarkTracerImpl::Entry({next, provided.name, intersectingKinds}); } worklist.push_back({ newReason, dependent.node, isCascading }); } } }; auto record = [&](WorklistEntry next) { if (!visitedSet.insert(next.Node).second) return; visited.push_back(next.Node); if (tracer) { auto &savedReason = tracer->Table[next.Node]; savedReason.clear(); savedReason.append(next.Reason.begin(), next.Reason.end()); } }; // Always mark through the starting node, even if it's already marked. markIntransitive(node); addDependentsToWorklist(node, {}); while (!worklist.empty()) { auto next = worklist.pop_back_val(); // Is this a non-cascading dependency? if (!next.IsCascading) { if (!isMarked(next.Node)) record(next); continue; } addDependentsToWorklist(next.Node, next.Reason); if (!markIntransitive(next.Node)) continue; record(next); } }
static void sortSections(MutableArrayRef<InputSection *> Vec, SortSectionPolicy K) { if (K != SortSectionPolicy::Default && K != SortSectionPolicy::None) std::stable_sort(Vec.begin(), Vec.end(), getComparator(K)); }
/// \brief Invert the 1-[0/1] mapping of diags to group into a one to many /// mapping of groups to diags in the group. static void groupDiagnostics(const std::vector<Record*> &Diags, const std::vector<Record*> &DiagGroups, std::map<std::string, GroupInfo> &DiagsInGroup) { for (unsigned i = 0, e = Diags.size(); i != e; ++i) { const Record *R = Diags[i]; DefInit *DI = dyn_cast<DefInit>(R->getValueInit("Group")); if (!DI) continue; assert(R->getValueAsDef("Class")->getName() != "CLASS_NOTE" && "Note can't be in a DiagGroup"); std::string GroupName = DI->getDef()->getValueAsString("GroupName"); DiagsInGroup[GroupName].DiagsInGroup.push_back(R); } typedef SmallPtrSet<GroupInfo *, 16> GroupSetTy; GroupSetTy ImplicitGroups; // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty // groups (these are warnings that GCC supports that clang never produces). for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) { Record *Group = DiagGroups[i]; GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")]; if (Group->isAnonymous()) { if (GI.DiagsInGroup.size() > 1) ImplicitGroups.insert(&GI); } else { if (GI.ExplicitDef) assert(GI.ExplicitDef == Group); else GI.ExplicitDef = Group; } std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups"); for (unsigned j = 0, e = SubGroups.size(); j != e; ++j) GI.SubGroups.push_back(SubGroups[j]->getValueAsString("GroupName")); } // Assign unique ID numbers to the groups. unsigned IDNo = 0; for (std::map<std::string, GroupInfo>::iterator I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo) I->second.IDNo = IDNo; // Sort the implicit groups, so we can warn about them deterministically. SmallVector<GroupInfo *, 16> SortedGroups(ImplicitGroups.begin(), ImplicitGroups.end()); for (SmallVectorImpl<GroupInfo *>::iterator I = SortedGroups.begin(), E = SortedGroups.end(); I != E; ++I) { MutableArrayRef<const Record *> GroupDiags = (*I)->DiagsInGroup; std::sort(GroupDiags.begin(), GroupDiags.end(), beforeThanCompare); } std::sort(SortedGroups.begin(), SortedGroups.end(), beforeThanCompareGroups); // Warn about the same group being used anonymously in multiple places. for (SmallVectorImpl<GroupInfo *>::const_iterator I = SortedGroups.begin(), E = SortedGroups.end(); I != E; ++I) { ArrayRef<const Record *> GroupDiags = (*I)->DiagsInGroup; if ((*I)->ExplicitDef) { std::string Name = (*I)->ExplicitDef->getValueAsString("GroupName"); for (ArrayRef<const Record *>::const_iterator DI = GroupDiags.begin(), DE = GroupDiags.end(); DI != DE; ++DI) { const DefInit *GroupInit = cast<DefInit>((*DI)->getValueInit("Group")); const Record *NextDiagGroup = GroupInit->getDef(); if (NextDiagGroup == (*I)->ExplicitDef) continue; SMRange InGroupRange = findSuperClassRange(*DI, "InGroup"); SmallString<64> Replacement; if (InGroupRange.isValid()) { Replacement += "InGroup<"; Replacement += (*I)->ExplicitDef->getName(); Replacement += ">"; } SMFixIt FixIt(InGroupRange, Replacement.str()); SrcMgr.PrintMessage(NextDiagGroup->getLoc().front(), SourceMgr::DK_Error, Twine("group '") + Name + "' is referred to anonymously", None, InGroupRange.isValid() ? FixIt : ArrayRef<SMFixIt>()); SrcMgr.PrintMessage((*I)->ExplicitDef->getLoc().front(), SourceMgr::DK_Note, "group defined here"); } } else { // If there's no existing named group, we should just warn once and use // notes to list all the other cases. ArrayRef<const Record *>::const_iterator DI = GroupDiags.begin(), DE = GroupDiags.end(); assert(DI != DE && "We only care about groups with multiple uses!"); const DefInit *GroupInit = cast<DefInit>((*DI)->getValueInit("Group")); const Record *NextDiagGroup = GroupInit->getDef(); std::string Name = NextDiagGroup->getValueAsString("GroupName"); SMRange InGroupRange = findSuperClassRange(*DI, "InGroup"); SrcMgr.PrintMessage(NextDiagGroup->getLoc().front(), SourceMgr::DK_Error, Twine("group '") + Name + "' is referred to anonymously", InGroupRange); for (++DI; DI != DE; ++DI) { GroupInit = cast<DefInit>((*DI)->getValueInit("Group")); InGroupRange = findSuperClassRange(*DI, "InGroup"); SrcMgr.PrintMessage(GroupInit->getDef()->getLoc().front(), SourceMgr::DK_Note, "also referenced here", InGroupRange); } } } }