Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -73,6 +73,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include "LLVMContextImpl.h" #include #include using namespace llvm; @@ -193,6 +194,11 @@ /// \brief Track unresolved string-based type references. SmallDenseMap UnresolvedTypeRefs; + /// \brief Cache the inverse FunctionData map, to avoid having to reconstruct + /// it from the forward map every time it's needed. + typedef DenseMap InverseFunctionDataMapTy; + InverseFunctionDataMapTy InverseFunctionDataMap; + /// \brief The result type for a landingpad. Type *LandingPadResultTy; @@ -241,6 +247,7 @@ // FIXME: We strip const here because the inst visitor strips const. visit(const_cast(F)); InstsInThisBlock.clear(); + InverseFunctionDataMap.clear(); LandingPadResultTy = nullptr; SawFrameEscape = false; @@ -287,6 +294,8 @@ // Verify type referneces last. verifyTypeRefs(); + InverseFunctionDataMap.clear(); + return !Broken; } @@ -443,6 +452,16 @@ InstVisitor::visit(I); } +template < typename CB > static void ForEachInstructionUser(const Use &TheUse, SmallPtrSet &Visited, CB &&callback) +{ + if (!Visited.insert(TheUse.getUser()).second) + return; + if (Instruction *I = dyn_cast(TheUse.getUser())) + callback(I); + else + for (const Use &TheNextUse : TheUse.getUser()->uses()) + ForEachInstructionUser(TheNextUse,Visited,callback); +} void Verifier::visitGlobalValue(const GlobalValue &GV) { Assert(!GV.isDeclaration() || GV.hasExternalLinkage() || @@ -462,6 +481,43 @@ if (GV.isDeclarationForLinker()) Assert(!GV.hasComdat(), "Declaration may not be in a Comdat!", &GV); + + // Verify that this GlobalValue is only used in this module. + // This map is used to avoid visiting uses twice. We can arrive at a user + // twice, if they have multiple operands. In particular for very large + // constant expressions, we can arrive at a particular user many times. + SmallPtrSet Visited; + for (const Use &TheUse : GV.uses()) + ForEachInstructionUser(TheUse,Visited,[&](Instruction *I){ + if (isa(I) && !I->getParent()) { + // This could be one of the ReturnInsts used to track prefix/prologue + // data. However, to be able to tell we need to construct the inverse + // mapping. Since it is expensive to construct, we cache it in the + // Verifier. + if (InverseFunctionDataMap.empty()) { + for (auto &F : M->functions()) { + if (F.hasPrefixData()) + InverseFunctionDataMap[&*F.getContext().pImpl->PrefixDataMap[&F]] = &F; + if (F.hasPrologueData()) + InverseFunctionDataMap[&*F.getContext().pImpl->PrologueDataMap[&F]] = &F; + } + } + const Function *F = InverseFunctionDataMap[cast(I)]; + if (F) { + Assert(F->getParent() == GV.getParent(), + "Global is referenced in function data of function in a different module", + &GV, GV.getParent(), F, F->getParent()); + return; + } + } + Assert(I->getParent() && I->getParent()->getParent(), + "Global is referenced by parentless instruction!", + &GV, GV.getParent(), I); + Assert(I->getParent()->getParent()->getParent() == GV.getParent(), + "Global is referenced in a different module!", + &GV, GV.getParent(), I, I->getParent()->getParent(), + I->getParent()->getParent()->getParent()); + }); } void Verifier::visitGlobalVariable(const GlobalVariable &GV) { Index: unittests/IR/VerifierTest.cpp =================================================================== --- unittests/IR/VerifierTest.cpp +++ unittests/IR/VerifierTest.cpp @@ -86,7 +86,10 @@ std::string Error; raw_string_ostream ErrorOS(Error); - EXPECT_FALSE(verifyModule(M2, &ErrorOS)); + EXPECT_TRUE(verifyModule(M2, &ErrorOS)); + EXPECT_TRUE(StringRef(ErrorOS.str()).startswith("Global is referenced in a different module!\n")); + + Error.clear(); EXPECT_TRUE(verifyModule(M1, &ErrorOS)); EXPECT_TRUE(StringRef(ErrorOS.str()).equals( "Referencing function in another module!\n"