diff options
Diffstat (limited to 'gnu/llvm/lib/IR/Verifier.cpp')
| -rw-r--r-- | gnu/llvm/lib/IR/Verifier.cpp | 329 |
1 files changed, 189 insertions, 140 deletions
diff --git a/gnu/llvm/lib/IR/Verifier.cpp b/gnu/llvm/lib/IR/Verifier.cpp index 454a56a7692..1754f7d4501 100644 --- a/gnu/llvm/lib/IR/Verifier.cpp +++ b/gnu/llvm/lib/IR/Verifier.cpp @@ -75,7 +75,6 @@ #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalAlias.h" @@ -115,8 +114,6 @@ using namespace llvm; -static cl::opt<bool> VerifyDebugInfo("verify-debug-info", cl::init(true)); - namespace llvm { struct VerifierSupport { @@ -468,8 +465,7 @@ private: void visitUserOp2(Instruction &I) { visitUserOp1(I); } void visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS); void visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI); - template <class DbgIntrinsicTy> - void visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII); + void visitDbgIntrinsic(StringRef Kind, DbgInfoIntrinsic &DII); void visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI); void visitAtomicRMWInst(AtomicRMWInst &RMWI); void visitFenceInst(FenceInst &FI); @@ -507,6 +503,10 @@ private: void verifySiblingFuncletUnwinds(); void verifyFragmentExpression(const DbgInfoIntrinsic &I); + template <typename ValueOrMetadata> + void verifyFragmentExpression(const DIVariable &V, + DIExpression::FragmentInfo Fragment, + ValueOrMetadata *Desc); void verifyFnArgs(const DbgInfoIntrinsic &I); /// Module-level debug info verification... @@ -565,6 +565,10 @@ void Verifier::visitGlobalValue(const GlobalValue &GV) { if (GV.isDeclarationForLinker()) Assert(!GV.hasComdat(), "Declaration may not be in a Comdat!", &GV); + if (GV.hasDLLImportStorageClass()) + Assert(!GV.isDSOLocal(), + "GlobalValue with DLLImport Storage is dso_local!", &GV); + forEachUser(&GV, GlobalValueVisited, [&](const Value *V) -> bool { if (const Instruction *I = dyn_cast<Instruction>(V)) { if (!I->getParent() || !I->getParent()->getParent()) @@ -839,6 +843,8 @@ void Verifier::visitDILocation(const DILocation &N) { "location requires a valid scope", &N, N.getRawScope()); if (auto *IA = N.getRawInlinedAt()) AssertDI(isa<DILocation>(IA), "inlined-at should be a location", &N, IA); + if (auto *SP = dyn_cast<DISubprogram>(N.getRawScope())) + AssertDI(SP->isDefinition(), "scope points into the type hierarchy", &N); } void Verifier::visitGenericDINode(const GenericDINode &N) { @@ -1067,6 +1073,8 @@ void Verifier::visitDILexicalBlockBase(const DILexicalBlockBase &N) { AssertDI(N.getTag() == dwarf::DW_TAG_lexical_block, "invalid tag", &N); AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()), "invalid local scope", &N, N.getRawScope()); + if (auto *SP = dyn_cast<DISubprogram>(N.getRawScope())) + AssertDI(SP->isDefinition(), "scope points into the type hierarchy", &N); } void Verifier::visitDILexicalBlock(const DILexicalBlock &N) { @@ -1139,7 +1147,6 @@ void Verifier::visitDITemplateValueParameter( void Verifier::visitDIVariable(const DIVariable &N) { if (auto *S = N.getRawScope()) AssertDI(isa<DIScope>(S), "invalid scope", &N, S); - AssertDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType()); if (auto *F = N.getRawFile()) AssertDI(isa<DIFile>(F), "invalid file", &N, F); } @@ -1150,6 +1157,8 @@ void Verifier::visitDIGlobalVariable(const DIGlobalVariable &N) { AssertDI(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N); AssertDI(!N.getName().empty(), "missing global variable name", &N); + AssertDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType()); + AssertDI(N.getType(), "missing global variable type", &N); if (auto *Member = N.getRawStaticDataMemberDeclaration()) { AssertDI(isa<DIDerivedType>(Member), "invalid static data member declaration", &N, Member); @@ -1160,6 +1169,7 @@ void Verifier::visitDILocalVariable(const DILocalVariable &N) { // Checks common to all variables. visitDIVariable(N); + AssertDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType()); AssertDI(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N); AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()), "local variable requires a valid scope", &N, N.getRawScope()); @@ -1174,8 +1184,11 @@ void Verifier::visitDIGlobalVariableExpression( AssertDI(GVE.getVariable(), "missing variable"); if (auto *Var = GVE.getVariable()) visitDIGlobalVariable(*Var); - if (auto *Expr = GVE.getExpression()) + if (auto *Expr = GVE.getExpression()) { visitDIExpression(*Expr); + if (auto Fragment = Expr->getFragmentInfo()) + verifyFragmentExpression(*GVE.getVariable(), *Fragment, &GVE); + } } void Verifier::visitDIObjCProperty(const DIObjCProperty &N) { @@ -1361,6 +1374,7 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) { case Attribute::NonLazyBind: case Attribute::ReturnsTwice: case Attribute::SanitizeAddress: + case Attribute::SanitizeHWAddress: case Attribute::SanitizeThread: case Attribute::SanitizeMemory: case Attribute::MinSize: @@ -1377,6 +1391,7 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) { case Attribute::InaccessibleMemOrArgMemOnly: case Attribute::AllocSize: case Attribute::Speculatable: + case Attribute::StrictFP: return true; default: break; @@ -2195,24 +2210,23 @@ void Verifier::visitBasicBlock(BasicBlock &BB) { SmallVector<BasicBlock*, 8> Preds(pred_begin(&BB), pred_end(&BB)); SmallVector<std::pair<BasicBlock*, Value*>, 8> Values; std::sort(Preds.begin(), Preds.end()); - PHINode *PN; - for (BasicBlock::iterator I = BB.begin(); (PN = dyn_cast<PHINode>(I));++I) { + for (const PHINode &PN : BB.phis()) { // Ensure that PHI nodes have at least one entry! - Assert(PN->getNumIncomingValues() != 0, + Assert(PN.getNumIncomingValues() != 0, "PHI nodes must have at least one entry. If the block is dead, " "the PHI should be removed!", - PN); - Assert(PN->getNumIncomingValues() == Preds.size(), + &PN); + Assert(PN.getNumIncomingValues() == Preds.size(), "PHINode should have one entry for each predecessor of its " "parent basic block!", - PN); + &PN); // Get and sort all incoming values in the PHI node... Values.clear(); - Values.reserve(PN->getNumIncomingValues()); - for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) - Values.push_back(std::make_pair(PN->getIncomingBlock(i), - PN->getIncomingValue(i))); + Values.reserve(PN.getNumIncomingValues()); + for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) + Values.push_back( + std::make_pair(PN.getIncomingBlock(i), PN.getIncomingValue(i))); std::sort(Values.begin(), Values.end()); for (unsigned i = 0, e = Values.size(); i != e; ++i) { @@ -2224,12 +2238,12 @@ void Verifier::visitBasicBlock(BasicBlock &BB) { Values[i].second == Values[i - 1].second, "PHI node has multiple entries for the same basic block with " "different incoming values!", - PN, Values[i].first, Values[i].second, Values[i - 1].second); + &PN, Values[i].first, Values[i].second, Values[i - 1].second); // Check to make sure that the predecessors and PHI node entries are // matched up. Assert(Values[i].first == Preds[i], - "PHI node entries do not match predecessors!", PN, + "PHI node entries do not match predecessors!", &PN, Values[i].first, Preds[i]); } } @@ -3001,7 +3015,11 @@ void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { Assert(isa<PointerType>(TargetTy), "GEP base pointer is not a vector or a vector of pointers", &GEP); Assert(GEP.getSourceElementType()->isSized(), "GEP into unsized type!", &GEP); + SmallVector<Value*, 16> Idxs(GEP.idx_begin(), GEP.idx_end()); + Assert(all_of( + Idxs, [](Value* V) { return V->getType()->isIntOrIntVectorTy(); }), + "GEP indexes must be integers", &GEP); Type *ElTy = GetElementPtrInst::getIndexedType(GEP.getSourceElementType(), Idxs); Assert(ElTy, "Invalid indices for GEP pointer type!", &GEP); @@ -3969,6 +3987,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) { case Intrinsic::experimental_constrained_fmul: case Intrinsic::experimental_constrained_fdiv: case Intrinsic::experimental_constrained_frem: + case Intrinsic::experimental_constrained_fma: case Intrinsic::experimental_constrained_sqrt: case Intrinsic::experimental_constrained_pow: case Intrinsic::experimental_constrained_powi: @@ -3987,10 +4006,13 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) { case Intrinsic::dbg_declare: // llvm.dbg.declare Assert(isa<MetadataAsValue>(CS.getArgOperand(0)), "invalid llvm.dbg.declare intrinsic call 1", CS); - visitDbgIntrinsic("declare", cast<DbgDeclareInst>(*CS.getInstruction())); + visitDbgIntrinsic("declare", cast<DbgInfoIntrinsic>(*CS.getInstruction())); + break; + case Intrinsic::dbg_addr: // llvm.dbg.addr + visitDbgIntrinsic("addr", cast<DbgInfoIntrinsic>(*CS.getInstruction())); break; case Intrinsic::dbg_value: // llvm.dbg.value - visitDbgIntrinsic("value", cast<DbgValueInst>(*CS.getInstruction())); + visitDbgIntrinsic("value", cast<DbgInfoIntrinsic>(*CS.getInstruction())); break; case Intrinsic::memcpy: case Intrinsic::memmove: @@ -4008,9 +4030,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) { break; } case Intrinsic::memcpy_element_unordered_atomic: { - const ElementUnorderedAtomicMemCpyInst *MI = - cast<ElementUnorderedAtomicMemCpyInst>(CS.getInstruction()); - ; + const AtomicMemCpyInst *MI = cast<AtomicMemCpyInst>(CS.getInstruction()); ConstantInt *ElementSizeCI = dyn_cast<ConstantInt>(MI->getRawElementSizeInBytes()); @@ -4045,7 +4065,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) { break; } case Intrinsic::memmove_element_unordered_atomic: { - auto *MI = cast<ElementUnorderedAtomicMemMoveInst>(CS.getInstruction()); + auto *MI = cast<AtomicMemMoveInst>(CS.getInstruction()); ConstantInt *ElementSizeCI = dyn_cast<ConstantInt>(MI->getRawElementSizeInBytes()); @@ -4080,7 +4100,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) { break; } case Intrinsic::memset_element_unordered_atomic: { - auto *MI = cast<ElementUnorderedAtomicMemSetInst>(CS.getInstruction()); + auto *MI = cast<AtomicMemSetInst>(CS.getInstruction()); ConstantInt *ElementSizeCI = dyn_cast<ConstantInt>(MI->getRawElementSizeInBytes()); @@ -4429,8 +4449,9 @@ static DISubprogram *getSubprogram(Metadata *LocalScope) { void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) { unsigned NumOperands = FPI.getNumArgOperands(); - Assert(((NumOperands == 3 && FPI.isUnaryOp()) || (NumOperands == 4)), - "invalid arguments for constrained FP intrinsic", &FPI); + Assert(((NumOperands == 5 && FPI.isTernaryOp()) || + (NumOperands == 3 && FPI.isUnaryOp()) || (NumOperands == 4)), + "invalid arguments for constrained FP intrinsic", &FPI); Assert(isa<MetadataAsValue>(FPI.getArgOperand(NumOperands-1)), "invalid exception behavior argument", &FPI); Assert(isa<MetadataAsValue>(FPI.getArgOperand(NumOperands-2)), @@ -4441,8 +4462,7 @@ void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) { "invalid exception behavior argument", &FPI); } -template <class DbgIntrinsicTy> -void Verifier::visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII) { +void Verifier::visitDbgIntrinsic(StringRef Kind, DbgInfoIntrinsic &DII) { auto *MD = cast<MetadataAsValue>(DII.getArgOperand(0))->getMetadata(); AssertDI(isa<ValueAsMetadata>(MD) || (isa<MDNode>(MD) && !cast<MDNode>(MD)->getNumOperands()), @@ -4481,46 +4501,15 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII) { verifyFnArgs(DII); } -static uint64_t getVariableSize(const DILocalVariable &V) { - // Be careful of broken types (checked elsewhere). - const Metadata *RawType = V.getRawType(); - while (RawType) { - // Try to get the size directly. - if (auto *T = dyn_cast<DIType>(RawType)) - if (uint64_t Size = T->getSizeInBits()) - return Size; - - if (auto *DT = dyn_cast<DIDerivedType>(RawType)) { - // Look at the base type. - RawType = DT->getRawBaseType(); - continue; - } - - // Missing type or size. - break; - } - - // Fail gracefully. - return 0; -} - void Verifier::verifyFragmentExpression(const DbgInfoIntrinsic &I) { - DILocalVariable *V; - DIExpression *E; - if (auto *DVI = dyn_cast<DbgValueInst>(&I)) { - V = dyn_cast_or_null<DILocalVariable>(DVI->getRawVariable()); - E = dyn_cast_or_null<DIExpression>(DVI->getRawExpression()); - } else { - auto *DDI = cast<DbgDeclareInst>(&I); - V = dyn_cast_or_null<DILocalVariable>(DDI->getRawVariable()); - E = dyn_cast_or_null<DIExpression>(DDI->getRawExpression()); - } + DILocalVariable *V = dyn_cast_or_null<DILocalVariable>(I.getRawVariable()); + DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression()); // We don't know whether this intrinsic verified correctly. if (!V || !E || !E->isValid()) return; - // Nothing to do if this isn't a bit piece expression. + // Nothing to do if this isn't a DW_OP_LLVM_fragment expression. auto Fragment = E->getFragmentInfo(); if (!Fragment) return; @@ -4534,17 +4523,24 @@ void Verifier::verifyFragmentExpression(const DbgInfoIntrinsic &I) { if (V->isArtificial()) return; + verifyFragmentExpression(*V, *Fragment, &I); +} + +template <typename ValueOrMetadata> +void Verifier::verifyFragmentExpression(const DIVariable &V, + DIExpression::FragmentInfo Fragment, + ValueOrMetadata *Desc) { // If there's no size, the type is broken, but that should be checked // elsewhere. - uint64_t VarSize = getVariableSize(*V); + auto VarSize = V.getSizeInBits(); if (!VarSize) return; - unsigned FragSize = Fragment->SizeInBits; - unsigned FragOffset = Fragment->OffsetInBits; - AssertDI(FragSize + FragOffset <= VarSize, - "fragment is larger than or outside of variable", &I, V, E); - AssertDI(FragSize != VarSize, "fragment covers entire variable", &I, V, E); + unsigned FragSize = Fragment.SizeInBits; + unsigned FragOffset = Fragment.OffsetInBits; + AssertDI(FragSize + FragOffset <= *VarSize, + "fragment is larger than or outside of variable", Desc, &V); + AssertDI(FragSize != *VarSize, "fragment covers entire variable", Desc, &V); } void Verifier::verifyFnArgs(const DbgInfoIntrinsic &I) { @@ -4554,18 +4550,11 @@ void Verifier::verifyFnArgs(const DbgInfoIntrinsic &I) { if (!HasDebugInfo) return; - DILocalVariable *Var; - if (auto *DV = dyn_cast<DbgValueInst>(&I)) { - // For performance reasons only check non-inlined ones. - if (DV->getDebugLoc()->getInlinedAt()) - return; - Var = DV->getVariable(); - } else { - auto *DD = cast<DbgDeclareInst>(&I); - if (DD->getDebugLoc()->getInlinedAt()) - return; - Var = DD->getVariable(); - } + // For performance reasons only check non-inlined ones. + if (I.getDebugLoc()->getInlinedAt()) + return; + + DILocalVariable *Var = I.getVariable(); AssertDI(Var, "dbg intrinsic without variable"); unsigned ArgNo = Var->getArg(); @@ -4584,6 +4573,11 @@ void Verifier::verifyFnArgs(const DbgInfoIntrinsic &I) { } void Verifier::verifyCompileUnits() { + // When more than one Module is imported into the same context, such as during + // an LTO build before linking the modules, ODR type uniquing may cause types + // to point to a different CU. This check does not make sense in this case. + if (M.getContext().isODRUniquingDebugTypes()) + return; auto *CUs = M.getNamedMetadata("llvm.dbg.cu"); SmallPtrSet<const Metadata *, 2> Listed; if (CUs) @@ -4675,19 +4669,8 @@ struct VerifierLegacyPass : public FunctionPass { HasErrors |= !V->verify(F); HasErrors |= !V->verify(); - if (FatalErrors) { - if (HasErrors) - report_fatal_error("Broken module found, compilation aborted!"); - assert(!V->hasBrokenDebugInfo() && "Module contains invalid debug info"); - } - - // Strip broken debug info. - if (V->hasBrokenDebugInfo()) { - DiagnosticInfoIgnoringInvalidDebugMetadata DiagInvalid(M); - M.getContext().diagnose(DiagInvalid); - if (!StripDebugInfo(M)) - report_fatal_error("Failed to strip malformed debug info"); - } + if (FatalErrors && (HasErrors || V->hasBrokenDebugInfo())) + report_fatal_error("Broken module found, compilation aborted!"); return false; } @@ -4716,7 +4699,8 @@ template <typename... Tys> void TBAAVerifier::CheckFailed(Tys &&... Args) { /// TBAA scheme. This means \p BaseNode is either a scalar node, or a /// struct-type node describing an aggregate data structure (like a struct). TBAAVerifier::TBAABaseNodeSummary -TBAAVerifier::verifyTBAABaseNode(Instruction &I, const MDNode *BaseNode) { +TBAAVerifier::verifyTBAABaseNode(Instruction &I, const MDNode *BaseNode, + bool IsNewFormat) { if (BaseNode->getNumOperands() < 2) { CheckFailed("Base nodes must have at least two operands", &I, BaseNode); return {true, ~0u}; @@ -4726,7 +4710,7 @@ TBAAVerifier::verifyTBAABaseNode(Instruction &I, const MDNode *BaseNode) { if (Itr != TBAABaseNodes.end()) return Itr->second; - auto Result = verifyTBAABaseNodeImpl(I, BaseNode); + auto Result = verifyTBAABaseNodeImpl(I, BaseNode, IsNewFormat); auto InsertResult = TBAABaseNodes.insert({BaseNode, Result}); (void)InsertResult; assert(InsertResult.second && "We just checked!"); @@ -4734,7 +4718,8 @@ TBAAVerifier::verifyTBAABaseNode(Instruction &I, const MDNode *BaseNode) { } TBAAVerifier::TBAABaseNodeSummary -TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode) { +TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode, + bool IsNewFormat) { const TBAAVerifier::TBAABaseNodeSummary InvalidNode = {true, ~0u}; if (BaseNode->getNumOperands() == 2) { @@ -4744,13 +4729,32 @@ TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode) { : InvalidNode; } - if (BaseNode->getNumOperands() % 2 != 1) { - CheckFailed("Struct tag nodes must have an odd number of operands!", - BaseNode); - return InvalidNode; + if (IsNewFormat) { + if (BaseNode->getNumOperands() % 3 != 0) { + CheckFailed("Access tag nodes must have the number of operands that is a " + "multiple of 3!", BaseNode); + return InvalidNode; + } + } else { + if (BaseNode->getNumOperands() % 2 != 1) { + CheckFailed("Struct tag nodes must have an odd number of operands!", + BaseNode); + return InvalidNode; + } } - if (!isa<MDString>(BaseNode->getOperand(0))) { + // Check the type size field. + if (IsNewFormat) { + auto *TypeSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( + BaseNode->getOperand(1)); + if (!TypeSizeNode) { + CheckFailed("Type size nodes must be constants!", &I, BaseNode); + return InvalidNode; + } + } + + // Check the type name field. In the new format it can be anything. + if (!IsNewFormat && !isa<MDString>(BaseNode->getOperand(0))) { CheckFailed("Struct tag nodes have a string as their first operand", BaseNode); return InvalidNode; @@ -4763,7 +4767,10 @@ TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode) { // We've already checked that BaseNode is not a degenerate root node with one // operand in \c verifyTBAABaseNode, so this loop should run at least once. - for (unsigned Idx = 1; Idx < BaseNode->getNumOperands(); Idx += 2) { + unsigned FirstFieldOpNo = IsNewFormat ? 3 : 1; + unsigned NumOpsPerField = IsNewFormat ? 3 : 2; + for (unsigned Idx = FirstFieldOpNo; Idx < BaseNode->getNumOperands(); + Idx += NumOpsPerField) { const MDOperand &FieldTy = BaseNode->getOperand(Idx); const MDOperand &FieldOffset = BaseNode->getOperand(Idx + 1); if (!isa<MDNode>(FieldTy)) { @@ -4805,6 +4812,16 @@ TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode) { } PrevOffset = OffsetEntryCI->getValue(); + + if (IsNewFormat) { + auto *MemberSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( + BaseNode->getOperand(Idx + 2)); + if (!MemberSizeNode) { + CheckFailed("Member size entries must be constants!", &I, BaseNode); + Failed = true; + continue; + } + } } return Failed ? InvalidNode @@ -4854,7 +4871,8 @@ bool TBAAVerifier::isValidScalarTBAANode(const MDNode *MD) { /// We assume we've okayed \p BaseNode via \c verifyTBAABaseNode. MDNode *TBAAVerifier::getFieldNodeFromTBAABaseNode(Instruction &I, const MDNode *BaseNode, - APInt &Offset) { + APInt &Offset, + bool IsNewFormat) { assert(BaseNode->getNumOperands() >= 2 && "Invalid base node!"); // Scalar nodes have only one possible "field" -- their parent in the access @@ -4863,35 +4881,52 @@ MDNode *TBAAVerifier::getFieldNodeFromTBAABaseNode(Instruction &I, if (BaseNode->getNumOperands() == 2) return cast<MDNode>(BaseNode->getOperand(1)); - for (unsigned Idx = 1; Idx < BaseNode->getNumOperands(); Idx += 2) { + unsigned FirstFieldOpNo = IsNewFormat ? 3 : 1; + unsigned NumOpsPerField = IsNewFormat ? 3 : 2; + for (unsigned Idx = FirstFieldOpNo; Idx < BaseNode->getNumOperands(); + Idx += NumOpsPerField) { auto *OffsetEntryCI = mdconst::extract<ConstantInt>(BaseNode->getOperand(Idx + 1)); if (OffsetEntryCI->getValue().ugt(Offset)) { - if (Idx == 1) { + if (Idx == FirstFieldOpNo) { CheckFailed("Could not find TBAA parent in struct type node", &I, BaseNode, &Offset); return nullptr; } + unsigned PrevIdx = Idx - NumOpsPerField; auto *PrevOffsetEntryCI = - mdconst::extract<ConstantInt>(BaseNode->getOperand(Idx - 1)); + mdconst::extract<ConstantInt>(BaseNode->getOperand(PrevIdx + 1)); Offset -= PrevOffsetEntryCI->getValue(); - return cast<MDNode>(BaseNode->getOperand(Idx - 2)); + return cast<MDNode>(BaseNode->getOperand(PrevIdx)); } } + unsigned LastIdx = BaseNode->getNumOperands() - NumOpsPerField; auto *LastOffsetEntryCI = mdconst::extract<ConstantInt>( - BaseNode->getOperand(BaseNode->getNumOperands() - 1)); - + BaseNode->getOperand(LastIdx + 1)); Offset -= LastOffsetEntryCI->getValue(); - return cast<MDNode>(BaseNode->getOperand(BaseNode->getNumOperands() - 2)); + return cast<MDNode>(BaseNode->getOperand(LastIdx)); +} + +static bool isNewFormatTBAATypeNode(llvm::MDNode *Type) { + if (!Type || Type->getNumOperands() < 3) + return false; + + // In the new format type nodes shall have a reference to the parent type as + // its first operand. + MDNode *Parent = dyn_cast_or_null<MDNode>(Type->getOperand(0)); + if (!Parent) + return false; + + return true; } bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) { AssertTBAA(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) || isa<VAArgInst>(I) || isa<AtomicRMWInst>(I) || isa<AtomicCmpXchgInst>(I), - "TBAA is only for loads, stores and calls!", &I); + "This instruction shall not have a TBAA access tag!", &I); bool IsStructPathTBAA = isa<MDNode>(MD->getOperand(0)) && MD->getNumOperands() >= 3; @@ -4900,18 +4935,34 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) { IsStructPathTBAA, "Old-style TBAA is no longer allowed, use struct-path TBAA instead", &I); - AssertTBAA(MD->getNumOperands() < 5, - "Struct tag metadata must have either 3 or 4 operands", &I, MD); - MDNode *BaseNode = dyn_cast_or_null<MDNode>(MD->getOperand(0)); MDNode *AccessType = dyn_cast_or_null<MDNode>(MD->getOperand(1)); - if (MD->getNumOperands() == 4) { - auto *IsImmutableCI = - mdconst::dyn_extract_or_null<ConstantInt>(MD->getOperand(3)); + bool IsNewFormat = isNewFormatTBAATypeNode(AccessType); + + if (IsNewFormat) { + AssertTBAA(MD->getNumOperands() == 4 || MD->getNumOperands() == 5, + "Access tag metadata must have either 4 or 5 operands", &I, MD); + } else { + AssertTBAA(MD->getNumOperands() < 5, + "Struct tag metadata must have either 3 or 4 operands", &I, MD); + } + + // Check the access size field. + if (IsNewFormat) { + auto *AccessSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( + MD->getOperand(3)); + AssertTBAA(AccessSizeNode, "Access size field must be a constant", &I, MD); + } + + // Check the immutability flag. + unsigned ImmutabilityFlagOpNo = IsNewFormat ? 4 : 3; + if (MD->getNumOperands() == ImmutabilityFlagOpNo + 1) { + auto *IsImmutableCI = mdconst::dyn_extract_or_null<ConstantInt>( + MD->getOperand(ImmutabilityFlagOpNo)); AssertTBAA(IsImmutableCI, - "Immutability tag on struct tag metadata must be a constant", &I, - MD); + "Immutability tag on struct tag metadata must be a constant", + &I, MD); AssertTBAA( IsImmutableCI->isZero() || IsImmutableCI->isOne(), "Immutability part of the struct tag metadata must be either 0 or 1", @@ -4919,13 +4970,15 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) { } AssertTBAA(BaseNode && AccessType, - "Malformed struct tag metadata: base and access-type " + "Malformed struct tag metadata: base and access-type " "should be non-null and point to Metadata nodes", &I, MD, BaseNode, AccessType); - AssertTBAA(isValidScalarTBAANode(AccessType), - "Access type node must be a valid scalar type", &I, MD, - AccessType); + if (!IsNewFormat) { + AssertTBAA(isValidScalarTBAANode(AccessType), + "Access type node must be a valid scalar type", &I, MD, + AccessType); + } auto *OffsetCI = mdconst::dyn_extract_or_null<ConstantInt>(MD->getOperand(2)); AssertTBAA(OffsetCI, "Offset must be constant integer", &I, MD); @@ -4936,7 +4989,8 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) { SmallPtrSet<MDNode *, 4> StructPath; for (/* empty */; BaseNode && !IsRootTBAANode(BaseNode); - BaseNode = getFieldNodeFromTBAABaseNode(I, BaseNode, Offset)) { + BaseNode = getFieldNodeFromTBAABaseNode(I, BaseNode, Offset, + IsNewFormat)) { if (!StructPath.insert(BaseNode).second) { CheckFailed("Cycle detected in struct path", &I, MD); return false; @@ -4944,7 +4998,8 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) { bool Invalid; unsigned BaseNodeBitWidth; - std::tie(Invalid, BaseNodeBitWidth) = verifyTBAABaseNode(I, BaseNode); + std::tie(Invalid, BaseNodeBitWidth) = verifyTBAABaseNode(I, BaseNode, + IsNewFormat); // If the base node is invalid in itself, then we've already printed all the // errors we wanted to print. @@ -4958,9 +5013,13 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) { &I, MD, &Offset); AssertTBAA(BaseNodeBitWidth == Offset.getBitWidth() || - (BaseNodeBitWidth == 0 && Offset == 0), + (BaseNodeBitWidth == 0 && Offset == 0) || + (IsNewFormat && BaseNodeBitWidth == ~0u), "Access bit-width not the same as description bit-width", &I, MD, BaseNodeBitWidth, Offset.getBitWidth()); + + if (IsNewFormat && SeenAccessTypeInPath) + break; } AssertTBAA(SeenAccessTypeInPath, "Did not see access type in access path!", @@ -4990,19 +5049,9 @@ VerifierAnalysis::Result VerifierAnalysis::run(Function &F, PreservedAnalyses VerifierPass::run(Module &M, ModuleAnalysisManager &AM) { auto Res = AM.getResult<VerifierAnalysis>(M); - if (FatalErrors) { - if (Res.IRBroken) - report_fatal_error("Broken module found, compilation aborted!"); - assert(!Res.DebugInfoBroken && "Module contains invalid debug info"); - } + if (FatalErrors && (Res.IRBroken || Res.DebugInfoBroken)) + report_fatal_error("Broken module found, compilation aborted!"); - // Strip broken debug info. - if (Res.DebugInfoBroken) { - DiagnosticInfoIgnoringInvalidDebugMetadata DiagInvalid(M); - M.getContext().diagnose(DiagInvalid); - if (!StripDebugInfo(M)) - report_fatal_error("Failed to strip malformed debug info"); - } return PreservedAnalyses::all(); } |
