From dce4a407a24b04eebc6a376f8e62b41aaa7b071f Mon Sep 17 00:00:00 2001 From: Stephen Hines Date: Thu, 29 May 2014 02:49:00 -0700 Subject: Update LLVM for 3.5 rebase (r209712). Change-Id: I149556c940fb7dc92d075273c87ff584f400941f --- lib/IR/Verifier.cpp | 442 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 298 insertions(+), 144 deletions(-) (limited to 'lib/IR/Verifier.cpp') diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 089ad1c..bcc38c1 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -61,6 +61,7 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/InlineAsm.h" +#include "llvm/IR/InstIterator.h" #include "llvm/IR/InstVisitor.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" @@ -76,15 +77,71 @@ #include using namespace llvm; -static cl::opt DisableDebugInfoVerifier("disable-debug-info-verifier", - cl::init(true)); +static cl::opt VerifyDebugInfo("verify-debug-info", cl::init(false)); namespace { -class Verifier : public InstVisitor { - friend class InstVisitor; - +struct VerifierSupport { raw_ostream &OS; const Module *M; + + /// \brief Track the brokenness of the module while recursively visiting. + bool Broken; + + explicit VerifierSupport(raw_ostream &OS) + : OS(OS), M(nullptr), Broken(false) {} + + void WriteValue(const Value *V) { + if (!V) + return; + if (isa(V)) { + OS << *V << '\n'; + } else { + V->printAsOperand(OS, true, M); + OS << '\n'; + } + } + + void WriteType(Type *T) { + if (!T) + return; + OS << ' ' << *T; + } + + // CheckFailed - A check failed, so print out the condition and the message + // that failed. This provides a nice place to put a breakpoint if you want + // to see why something is not correct. + void CheckFailed(const Twine &Message, const Value *V1 = nullptr, + const Value *V2 = nullptr, const Value *V3 = nullptr, + const Value *V4 = nullptr) { + OS << Message.str() << "\n"; + WriteValue(V1); + WriteValue(V2); + WriteValue(V3); + WriteValue(V4); + Broken = true; + } + + void CheckFailed(const Twine &Message, const Value *V1, Type *T2, + const Value *V3 = nullptr) { + OS << Message.str() << "\n"; + WriteValue(V1); + WriteType(T2); + WriteValue(V3); + Broken = true; + } + + void CheckFailed(const Twine &Message, Type *T1, Type *T2 = nullptr, + Type *T3 = nullptr) { + OS << Message.str() << "\n"; + WriteType(T1); + WriteType(T2); + WriteType(T3); + Broken = true; + } +}; +class Verifier : public InstVisitor, VerifierSupport { + friend class InstVisitor; + LLVMContext *Context; const DataLayout *DL; DominatorTree DT; @@ -104,15 +161,10 @@ class Verifier : public InstVisitor { /// personality function. const Value *PersonalityFn; - /// \brief Finder keeps track of all debug info MDNodes in a Module. - DebugInfoFinder Finder; - - /// \brief Track the brokenness of the module while recursively visiting. - bool Broken; - public: explicit Verifier(raw_ostream &OS = dbgs()) - : OS(OS), M(0), Context(0), DL(0), PersonalityFn(0), Broken(false) {} + : VerifierSupport(OS), Context(nullptr), DL(nullptr), + PersonalityFn(nullptr) {} bool verify(const Function &F) { M = F.getParent(); @@ -142,16 +194,11 @@ public: // FIXME: It's really gross that we have to cast away constness here. DT.recalculate(const_cast(F)); - Finder.reset(); Broken = false; // FIXME: We strip const here because the inst visitor strips const. visit(const_cast(F)); InstsInThisBlock.clear(); - PersonalityFn = 0; - - if (!DisableDebugInfoVerifier) - // Verify Debug Info. - verifyDebugInfo(); + PersonalityFn = nullptr; return !Broken; } @@ -159,7 +206,6 @@ public: bool verify(const Module &M) { this->M = &M; Context = &M.getContext(); - Finder.reset(); Broken = false; // Scan through, checking all of the external function's linkage now... @@ -187,13 +233,6 @@ public: visitModuleFlags(M); visitModuleIdents(M); - if (!DisableDebugInfoVerifier) { - Finder.reset(); - Finder.processModule(M); - // Verify Debug Info. - verifyDebugInfo(); - } - return !Broken; } @@ -262,6 +301,7 @@ private: void visitLandingPadInst(LandingPadInst &LPI); void VerifyCallSite(CallSite CS); + void verifyMustTailCall(CallInst &CI); bool PerformTypeCheck(Intrinsic::ID ID, Function *F, Type *Ty, int VT, unsigned ArgNo, std::string &Suffix); bool VerifyIntrinsicType(Type *Ty, ArrayRef &Infos, @@ -278,56 +318,21 @@ private: void VerifyBitcastType(const Value *V, Type *DestTy, Type *SrcTy); void VerifyConstantExprBitcastType(const ConstantExpr *CE); +}; +class DebugInfoVerifier : public VerifierSupport { +public: + explicit DebugInfoVerifier(raw_ostream &OS = dbgs()) : VerifierSupport(OS) {} - void verifyDebugInfo(); - - void WriteValue(const Value *V) { - if (!V) - return; - if (isa(V)) { - OS << *V << '\n'; - } else { - V->printAsOperand(OS, true, M); - OS << '\n'; - } - } - - void WriteType(Type *T) { - if (!T) - return; - OS << ' ' << *T; - } - - // CheckFailed - A check failed, so print out the condition and the message - // that failed. This provides a nice place to put a breakpoint if you want - // to see why something is not correct. - void CheckFailed(const Twine &Message, const Value *V1 = 0, - const Value *V2 = 0, const Value *V3 = 0, - const Value *V4 = 0) { - OS << Message.str() << "\n"; - WriteValue(V1); - WriteValue(V2); - WriteValue(V3); - WriteValue(V4); - Broken = true; - } - - void CheckFailed(const Twine &Message, const Value *V1, Type *T2, - const Value *V3 = 0) { - OS << Message.str() << "\n"; - WriteValue(V1); - WriteType(T2); - WriteValue(V3); - Broken = true; + bool verify(const Module &M) { + this->M = &M; + verifyDebugInfo(); + return !Broken; } - void CheckFailed(const Twine &Message, Type *T1, Type *T2 = 0, Type *T3 = 0) { - OS << Message.str() << "\n"; - WriteType(T1); - WriteType(T2); - WriteType(T3); - Broken = true; - } +private: + void verifyDebugInfo(); + void processInstructions(DebugInfoFinder &Finder); + void processCallInst(DebugInfoFinder &Finder, const CallInst &CI); }; } // End anonymous namespace @@ -345,18 +350,14 @@ private: void Verifier::visit(Instruction &I) { for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) - Assert1(I.getOperand(i) != 0, "Operand is null", &I); + Assert1(I.getOperand(i) != nullptr, "Operand is null", &I); InstVisitor::visit(I); } void Verifier::visitGlobalValue(const GlobalValue &GV) { - Assert1(!GV.isDeclaration() || - GV.isMaterializable() || - GV.hasExternalLinkage() || - GV.hasExternalWeakLinkage() || - (isa(GV) && - (GV.hasLocalLinkage() || GV.hasWeakLinkage())), + Assert1(!GV.isDeclaration() || GV.isMaterializable() || + GV.hasExternalLinkage() || GV.hasExternalWeakLinkage(), "Global is external, but doesn't have external or weak linkage!", &GV); @@ -395,14 +396,22 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) { "invalid linkage for intrinsic global variable", &GV); // Don't worry about emitting an error for it not being an array, // visitGlobalValue will complain on appending non-array. - if (ArrayType *ATy = dyn_cast(GV.getType())) { + if (ArrayType *ATy = dyn_cast(GV.getType()->getElementType())) { StructType *STy = dyn_cast(ATy->getElementType()); PointerType *FuncPtrTy = FunctionType::get(Type::getVoidTy(*Context), false)->getPointerTo(); - Assert1(STy && STy->getNumElements() == 2 && + // FIXME: Reject the 2-field form in LLVM 4.0. + Assert1(STy && (STy->getNumElements() == 2 || + STy->getNumElements() == 3) && STy->getTypeAtIndex(0u)->isIntegerTy(32) && STy->getTypeAtIndex(1) == FuncPtrTy, "wrong type for intrinsic global variable", &GV); + if (STy->getNumElements() == 3) { + Type *ETy = STy->getTypeAtIndex(2); + Assert1(ETy->isPointerTy() && + cast(ETy)->getElementType()->isIntegerTy(8), + "wrong type for intrinsic global variable", &GV); + } } } @@ -472,11 +481,7 @@ void Verifier::visitGlobalAlias(const GlobalAlias &GA) { "Alias should have external or external weak linkage!", &GA); Assert1(GA.getAliasee(), "Aliasee cannot be NULL!", &GA); - Assert1(GA.getType() == GA.getAliasee()->getType(), - "Alias and aliasee types should match!", &GA); Assert1(!GA.hasUnnamedAddr(), "Alias cannot have unnamed_addr!", &GA); - Assert1(!GA.hasSection(), "Alias cannot have a section!", &GA); - Assert1(!GA.getAlignment(), "Alias connot have an alignment", &GA); const Constant *Aliasee = GA.getAliasee(); const GlobalValue *GV = dyn_cast(Aliasee); @@ -492,14 +497,7 @@ void Verifier::visitGlobalAlias(const GlobalAlias &GA) { "addrspacecast of GlobalValue", &GA); - if (CE->getOpcode() == Instruction::BitCast) { - unsigned SrcAS = GV->getType()->getPointerAddressSpace(); - unsigned DstAS = CE->getType()->getPointerAddressSpace(); - - Assert1(SrcAS == DstAS, - "Alias bitcasts cannot be between different address spaces", - &GA); - } + VerifyConstantExprBitcastType(CE); } Assert1(!GV->isDeclaration(), "Alias must point to a definition", &GA); if (const GlobalAlias *GAAliasee = dyn_cast(GV)) { @@ -507,10 +505,6 @@ void Verifier::visitGlobalAlias(const GlobalAlias &GA) { &GA); } - const GlobalValue *AG = GA.getAliasedGlobal(); - Assert1(AG, "Aliasing chain should end with function or global variable", - &GA); - visitGlobalValue(GA); } @@ -522,7 +516,7 @@ void Verifier::visitNamedMDNode(const NamedMDNode &NMD) { Assert1(!MD->isFunctionLocal(), "Named metadata operand cannot be function local!", MD); - visitMDNode(*MD, 0); + visitMDNode(*MD, nullptr); } } @@ -548,7 +542,7 @@ void Verifier::visitMDNode(MDNode &MD, Function *F) { // If this was an instruction, bb, or argument, verify that it is in the // function that we expect. - Function *ActualF = 0; + Function *ActualF = nullptr; if (Instruction *I = dyn_cast(Op)) ActualF = I->getParent()->getParent(); else if (BasicBlock *BB = dyn_cast(Op)) @@ -821,6 +815,7 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, bool SawNest = false; bool SawReturned = false; + bool SawSRet = false; for (unsigned i = 0, e = Attrs.getNumSlots(); i != e; ++i) { unsigned Idx = Attrs.getSlotIndex(i); @@ -851,8 +846,12 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, SawReturned = true; } - if (Attrs.hasAttribute(Idx, Attribute::StructRet)) - Assert1(Idx == 1, "Attribute sret is not on first parameter!", V); + if (Attrs.hasAttribute(Idx, Attribute::StructRet)) { + Assert1(!SawSRet, "Cannot have multiple 'sret' parameters!", V); + Assert1(Idx == 1 || Idx == 2, + "Attribute 'sret' is not on first or second parameter!", V); + SawSRet = true; + } if (Attrs.hasAttribute(Idx, Attribute::InAlloca)) { Assert1(Idx == FT->getNumParams(), @@ -1489,6 +1488,16 @@ void Verifier::VerifyCallSite(CallSite CS) { // Verify call attributes. VerifyFunctionAttrs(FTy, Attrs, I); + // Conservatively check the inalloca argument. + // We have a bug if we can find that there is an underlying alloca without + // inalloca. + if (CS.hasInAllocaArgument()) { + Value *InAllocaArg = CS.getArgument(FTy->getNumParams() - 1); + if (auto AI = dyn_cast(InAllocaArg->stripInBoundsOffsets())) + Assert2(AI->isUsedWithInAlloca(), + "inalloca argument for call has mismatched alloca", AI, I); + } + if (FTy->isVarArg()) { // FIXME? is 'nest' even legal here? bool SawNest = false; @@ -1530,7 +1539,7 @@ void Verifier::VerifyCallSite(CallSite CS) { } // Verify that there's no metadata unless it's a direct call to an intrinsic. - if (CS.getCalledFunction() == 0 || + if (CS.getCalledFunction() == nullptr || !CS.getCalledFunction()->getName().startswith("llvm.")) { for (FunctionType::param_iterator PI = FTy->param_begin(), PE = FTy->param_end(); PI != PE; ++PI) @@ -1541,9 +1550,102 @@ void Verifier::VerifyCallSite(CallSite CS) { visitInstruction(*I); } +/// Two types are "congruent" if they are identical, or if they are both pointer +/// types with different pointee types and the same address space. +static bool isTypeCongruent(Type *L, Type *R) { + if (L == R) + return true; + PointerType *PL = dyn_cast(L); + PointerType *PR = dyn_cast(R); + if (!PL || !PR) + return false; + return PL->getAddressSpace() == PR->getAddressSpace(); +} + +static AttrBuilder getParameterABIAttributes(int I, AttributeSet Attrs) { + static const Attribute::AttrKind ABIAttrs[] = { + Attribute::StructRet, Attribute::ByVal, Attribute::InAlloca, + Attribute::InReg, Attribute::Returned}; + AttrBuilder Copy; + for (auto AK : ABIAttrs) { + if (Attrs.hasAttribute(I + 1, AK)) + Copy.addAttribute(AK); + } + if (Attrs.hasAttribute(I + 1, Attribute::Alignment)) + Copy.addAlignmentAttr(Attrs.getParamAlignment(I + 1)); + return Copy; +} + +void Verifier::verifyMustTailCall(CallInst &CI) { + Assert1(!CI.isInlineAsm(), "cannot use musttail call with inline asm", &CI); + + // - The caller and callee prototypes must match. Pointer types of + // parameters or return types may differ in pointee type, but not + // address space. + Function *F = CI.getParent()->getParent(); + auto GetFnTy = [](Value *V) { + return cast( + cast(V->getType())->getElementType()); + }; + FunctionType *CallerTy = GetFnTy(F); + FunctionType *CalleeTy = GetFnTy(CI.getCalledValue()); + Assert1(CallerTy->getNumParams() == CalleeTy->getNumParams(), + "cannot guarantee tail call due to mismatched parameter counts", &CI); + Assert1(CallerTy->isVarArg() == CalleeTy->isVarArg(), + "cannot guarantee tail call due to mismatched varargs", &CI); + Assert1(isTypeCongruent(CallerTy->getReturnType(), CalleeTy->getReturnType()), + "cannot guarantee tail call due to mismatched return types", &CI); + for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) { + Assert1( + isTypeCongruent(CallerTy->getParamType(I), CalleeTy->getParamType(I)), + "cannot guarantee tail call due to mismatched parameter types", &CI); + } + + // - The calling conventions of the caller and callee must match. + Assert1(F->getCallingConv() == CI.getCallingConv(), + "cannot guarantee tail call due to mismatched calling conv", &CI); + + // - All ABI-impacting function attributes, such as sret, byval, inreg, + // returned, and inalloca, must match. + AttributeSet CallerAttrs = F->getAttributes(); + AttributeSet CalleeAttrs = CI.getAttributes(); + for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) { + AttrBuilder CallerABIAttrs = getParameterABIAttributes(I, CallerAttrs); + AttrBuilder CalleeABIAttrs = getParameterABIAttributes(I, CalleeAttrs); + Assert2(CallerABIAttrs == CalleeABIAttrs, + "cannot guarantee tail call due to mismatched ABI impacting " + "function attributes", &CI, CI.getOperand(I)); + } + + // - The call must immediately precede a :ref:`ret ` instruction, + // or a pointer bitcast followed by a ret instruction. + // - The ret instruction must return the (possibly bitcasted) value + // produced by the call or void. + Value *RetVal = &CI; + Instruction *Next = CI.getNextNode(); + + // Handle the optional bitcast. + if (BitCastInst *BI = dyn_cast_or_null(Next)) { + Assert1(BI->getOperand(0) == RetVal, + "bitcast following musttail call must use the call", BI); + RetVal = BI; + Next = BI->getNextNode(); + } + + // Check the return. + ReturnInst *Ret = dyn_cast_or_null(Next); + Assert1(Ret, "musttail call must be precede a ret with an optional bitcast", + &CI); + Assert1(!Ret->getReturnValue() || Ret->getReturnValue() == RetVal, + "musttail call result must be returned", Ret); +} + void Verifier::visitCallInst(CallInst &CI) { VerifyCallSite(&CI); + if (CI.isMustTailCall()) + verifyMustTailCall(CI); + if (Function *F = CI.getCalledFunction()) if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) visitIntrinsicFunctionCall(ID, CI); @@ -1731,11 +1833,11 @@ void Verifier::visitLoadInst(LoadInst &LI) { "Atomic load must specify explicit alignment", &LI); if (!ElTy->isPointerTy()) { Assert2(ElTy->isIntegerTy(), - "atomic store operand must have integer type!", + "atomic load operand must have integer type!", &LI, ElTy); unsigned Size = ElTy->getPrimitiveSizeInBits(); Assert2(Size >= 8 && !(Size & (Size - 1)), - "atomic store operand must be power-of-two byte-sized integer", + "atomic load operand must be power-of-two byte-sized integer", &LI, ElTy); } } else { @@ -2020,8 +2122,8 @@ void Verifier::visitInstruction(Instruction &I) { // instruction, it is an error! for (Use &U : I.uses()) { if (Instruction *Used = dyn_cast(U.getUser())) - Assert2(Used->getParent() != 0, "Instruction referencing instruction not" - " embedded in a basic block!", &I, Used); + Assert2(Used->getParent() != nullptr, "Instruction referencing" + " instruction not embedded in a basic block!", &I, Used); else { CheckFailed("Use of instruction is not an instruction!", U); return; @@ -2029,7 +2131,7 @@ void Verifier::visitInstruction(Instruction &I) { } for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { - Assert1(I.getOperand(i) != 0, "Instruction has null operand!", &I); + Assert1(I.getOperand(i) != nullptr, "Instruction has null operand!", &I); // Check to make sure that only first-class-values are operands to // instructions. @@ -2103,11 +2205,6 @@ void Verifier::visitInstruction(Instruction &I) { MDNode *MD = I.getMetadata(LLVMContext::MD_range); Assert1(!MD || isa(I), "Ranges are only for loads!", &I); - if (!DisableDebugInfoVerifier) { - MD = I.getMetadata(LLVMContext::MD_dbg); - Finder.processLocation(*M, DILocation(MD)); - } - InstsInThisBlock.insert(&I); } @@ -2137,18 +2234,18 @@ bool Verifier::VerifyIntrinsicType(Type *Ty, case IITDescriptor::Integer: return !Ty->isIntegerTy(D.Integer_Width); case IITDescriptor::Vector: { VectorType *VT = dyn_cast(Ty); - return VT == 0 || VT->getNumElements() != D.Vector_Width || + return !VT || VT->getNumElements() != D.Vector_Width || VerifyIntrinsicType(VT->getElementType(), Infos, ArgTys); } case IITDescriptor::Pointer: { PointerType *PT = dyn_cast(Ty); - return PT == 0 || PT->getAddressSpace() != D.Pointer_AddressSpace || + return !PT || PT->getAddressSpace() != D.Pointer_AddressSpace || VerifyIntrinsicType(PT->getElementType(), Infos, ArgTys); } case IITDescriptor::Struct: { StructType *ST = dyn_cast(Ty); - if (ST == 0 || ST->getNumElements() != D.Struct_NumElements) + if (!ST || ST->getNumElements() != D.Struct_NumElements) return true; for (unsigned i = 0, e = D.Struct_NumElements; i != e; ++i) @@ -2307,17 +2404,7 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { MDNode *MD = cast(CI.getArgOperand(0)); Assert1(MD->getNumOperands() == 1, "invalid llvm.dbg.declare intrinsic call 2", &CI); - if (!DisableDebugInfoVerifier) - Finder.processDeclare(*M, cast(&CI)); } break; - case Intrinsic::dbg_value: { //llvm.dbg.value - if (!DisableDebugInfoVerifier) { - Assert1(CI.getArgOperand(0) && isa(CI.getArgOperand(0)), - "invalid llvm.dbg.value intrinsic call 1", &CI); - Finder.processValue(*M, cast(&CI)); - } - break; - } case Intrinsic::memcpy: case Intrinsic::memmove: case Intrinsic::memset: @@ -2379,25 +2466,58 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { } } -void Verifier::verifyDebugInfo() { +void DebugInfoVerifier::verifyDebugInfo() { + if (!VerifyDebugInfo) + return; + + DebugInfoFinder Finder; + Finder.processModule(*M); + processInstructions(Finder); + // Verify Debug Info. - if (!DisableDebugInfoVerifier) { - for (DICompileUnit CU : Finder.compile_units()) { - Assert1(CU.Verify(), "DICompileUnit does not Verify!", CU); - } - for (DISubprogram S : Finder.subprograms()) { - Assert1(S.Verify(), "DISubprogram does not Verify!", S); - } - for (DIGlobalVariable GV : Finder.global_variables()) { - Assert1(GV.Verify(), "DIGlobalVariable does not Verify!", GV); - } - for (DIType T : Finder.types()) { - Assert1(T.Verify(), "DIType does not Verify!", T); - } - for (DIScope S : Finder.scopes()) { - Assert1(S.Verify(), "DIScope does not Verify!", S); - } + // + // NOTE: The loud braces are necessary for MSVC compatibility. + for (DICompileUnit CU : Finder.compile_units()) { + Assert1(CU.Verify(), "DICompileUnit does not Verify!", CU); } + for (DISubprogram S : Finder.subprograms()) { + Assert1(S.Verify(), "DISubprogram does not Verify!", S); + } + for (DIGlobalVariable GV : Finder.global_variables()) { + Assert1(GV.Verify(), "DIGlobalVariable does not Verify!", GV); + } + for (DIType T : Finder.types()) { + Assert1(T.Verify(), "DIType does not Verify!", T); + } + for (DIScope S : Finder.scopes()) { + Assert1(S.Verify(), "DIScope does not Verify!", S); + } +} + +void DebugInfoVerifier::processInstructions(DebugInfoFinder &Finder) { + for (const Function &F : *M) + for (auto I = inst_begin(&F), E = inst_end(&F); I != E; ++I) { + if (MDNode *MD = I->getMetadata(LLVMContext::MD_dbg)) + Finder.processLocation(*M, DILocation(MD)); + if (const CallInst *CI = dyn_cast(&*I)) + processCallInst(Finder, *CI); + } +} + +void DebugInfoVerifier::processCallInst(DebugInfoFinder &Finder, + const CallInst &CI) { + if (Function *F = CI.getCalledFunction()) + if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) + switch (ID) { + case Intrinsic::dbg_declare: + Finder.processDeclare(*M, cast(&CI)); + break; + case Intrinsic::dbg_value: + Finder.processValue(*M, cast(&CI)); + break; + default: + break; + } } //===----------------------------------------------------------------------===// @@ -2427,7 +2547,8 @@ bool llvm::verifyModule(const Module &M, raw_ostream *OS) { // Note that this function's return value is inverted from what you would // expect of a function called "verify". - return !V.verify(M) || Broken; + DebugInfoVerifier DIV(OS ? *OS : NullStr); + return !V.verify(M) || !DIV.verify(M) || Broken; } namespace { @@ -2463,15 +2584,48 @@ struct VerifierLegacyPass : public FunctionPass { AU.setPreservesAll(); } }; +struct DebugInfoVerifierLegacyPass : public ModulePass { + static char ID; + + DebugInfoVerifier V; + bool FatalErrors; + + DebugInfoVerifierLegacyPass() : ModulePass(ID), FatalErrors(true) { + initializeDebugInfoVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); + } + explicit DebugInfoVerifierLegacyPass(bool FatalErrors) + : ModulePass(ID), V(dbgs()), FatalErrors(FatalErrors) { + initializeDebugInfoVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); + } + + bool runOnModule(Module &M) override { + if (!V.verify(M) && FatalErrors) + report_fatal_error("Broken debug info found, compilation aborted!"); + + return false; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } +}; } char VerifierLegacyPass::ID = 0; INITIALIZE_PASS(VerifierLegacyPass, "verify", "Module Verifier", false, false) +char DebugInfoVerifierLegacyPass::ID = 0; +INITIALIZE_PASS(DebugInfoVerifierLegacyPass, "verify-di", "Debug Info Verifier", + false, false) + FunctionPass *llvm::createVerifierPass(bool FatalErrors) { return new VerifierLegacyPass(FatalErrors); } +ModulePass *llvm::createDebugInfoVerifierPass(bool FatalErrors) { + return new DebugInfoVerifierLegacyPass(FatalErrors); +} + PreservedAnalyses VerifierPass::run(Module *M) { if (verifyModule(*M, &dbgs()) && FatalErrors) report_fatal_error("Broken module found, compilation aborted!"); -- cgit v1.1