summaryrefslogtreecommitdiff
path: root/lib/IR/Verifier.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/IR/Verifier.cpp')
-rw-r--r--lib/IR/Verifier.cpp349
1 files changed, 205 insertions, 144 deletions
diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp
index 534104686d81..e5231bb78a36 100644
--- a/lib/IR/Verifier.cpp
+++ b/lib/IR/Verifier.cpp
@@ -55,6 +55,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
@@ -206,7 +207,7 @@ private:
template <typename... Ts> void WriteTs() {}
public:
- /// \brief A check failed, so printout out the condition and the message.
+ /// A check failed, so printout out the condition and the message.
///
/// This provides a nice place to put a breakpoint if you want to see why
/// something is not correct.
@@ -216,7 +217,7 @@ public:
Broken = true;
}
- /// \brief A check failed (with values to print).
+ /// A check failed (with values to print).
///
/// This calls the Message-only version so that the above is easier to set a
/// breakpoint on.
@@ -254,14 +255,14 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
DominatorTree DT;
- /// \brief When verifying a basic block, keep track of all of the
+ /// When verifying a basic block, keep track of all of the
/// instructions we have seen so far.
///
/// This allows us to do efficient dominance checks for the case when an
/// instruction has an operand that is an instruction in the same block.
SmallPtrSet<Instruction *, 16> InstsInThisBlock;
- /// \brief Keep track of the metadata nodes that have been checked already.
+ /// Keep track of the metadata nodes that have been checked already.
SmallPtrSet<const Metadata *, 32> MDNodes;
/// Keep track which DISubprogram is attached to which function.
@@ -270,10 +271,10 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
/// Track all DICompileUnits visited.
SmallPtrSet<const Metadata *, 2> CUVisited;
- /// \brief The result type for a landingpad.
+ /// The result type for a landingpad.
Type *LandingPadResultTy;
- /// \brief Whether we've seen a call to @llvm.localescape in this function
+ /// Whether we've seen a call to @llvm.localescape in this function
/// already.
bool SawFrameEscape;
@@ -408,6 +409,7 @@ private:
void visitModuleFlag(const MDNode *Op,
DenseMap<const MDString *, const MDNode *> &SeenIDs,
SmallVectorImpl<const MDNode *> &Requirements);
+ void visitModuleFlagCGProfileEntry(const MDOperand &MDO);
void visitFunction(const Function &F);
void visitBasicBlock(BasicBlock &BB);
void visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty);
@@ -466,6 +468,7 @@ private:
void visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS);
void visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI);
void visitDbgIntrinsic(StringRef Kind, DbgInfoIntrinsic &DII);
+ void visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI);
void visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI);
void visitAtomicRMWInst(AtomicRMWInst &RMWI);
void visitFenceInst(FenceInst &FI);
@@ -565,10 +568,24 @@ void Verifier::visitGlobalValue(const GlobalValue &GV) {
if (GV.isDeclarationForLinker())
Assert(!GV.hasComdat(), "Declaration may not be in a Comdat!", &GV);
- if (GV.hasDLLImportStorageClass())
+ if (GV.hasDLLImportStorageClass()) {
Assert(!GV.isDSOLocal(),
"GlobalValue with DLLImport Storage is dso_local!", &GV);
+ Assert((GV.isDeclaration() && GV.hasExternalLinkage()) ||
+ GV.hasAvailableExternallyLinkage(),
+ "Global is marked as dllimport, but not external", &GV);
+ }
+
+ if (GV.hasLocalLinkage())
+ Assert(GV.isDSOLocal(),
+ "GlobalValue with private or internal linkage must be dso_local!",
+ &GV);
+
+ if (!GV.hasDefaultVisibility() && !GV.hasExternalWeakLinkage())
+ Assert(GV.isDSOLocal(),
+ "GlobalValue with non default visibility must be dso_local!", &GV);
+
forEachUser(&GV, GlobalValueVisited, [&](const Value *V) -> bool {
if (const Instruction *I = dyn_cast<Instruction>(V)) {
if (!I->getParent() || !I->getParent()->getParent())
@@ -655,11 +672,6 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
}
}
- Assert(!GV.hasDLLImportStorageClass() ||
- (GV.isDeclaration() && GV.hasExternalLinkage()) ||
- GV.hasAvailableExternallyLinkage(),
- "Global is marked as dllimport, but not external", &GV);
-
// Visit any debug info attachments.
SmallVector<MDNode *, 1> MDs;
GV.getMetadata(LLVMContext::MD_dbg, MDs);
@@ -858,7 +870,12 @@ void Verifier::visitDIScope(const DIScope &N) {
void Verifier::visitDISubrange(const DISubrange &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_subrange_type, "invalid tag", &N);
- AssertDI(N.getCount() >= -1, "invalid subrange count", &N);
+ auto Count = N.getCount();
+ AssertDI(Count, "Count must either be a signed constant or a DIVariable",
+ &N);
+ AssertDI(!Count.is<ConstantInt*>() ||
+ Count.get<ConstantInt*>()->getSExtValue() >= -1,
+ "invalid subrange count", &N);
}
void Verifier::visitDIEnumerator(const DIEnumerator &N) {
@@ -905,9 +922,12 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) {
}
}
+/// Detect mutually exclusive flags.
static bool hasConflictingReferenceFlags(unsigned Flags) {
- return (Flags & DINode::FlagLValueReference) &&
- (Flags & DINode::FlagRValueReference);
+ return ((Flags & DINode::FlagLValueReference) &&
+ (Flags & DINode::FlagRValueReference)) ||
+ ((Flags & DINode::FlagTypePassByValue) &&
+ (Flags & DINode::FlagTypePassByReference));
}
void Verifier::visitTemplateParams(const MDNode &N, const Metadata &RawParams) {
@@ -927,7 +947,8 @@ void Verifier::visitDICompositeType(const DICompositeType &N) {
N.getTag() == dwarf::DW_TAG_structure_type ||
N.getTag() == dwarf::DW_TAG_union_type ||
N.getTag() == dwarf::DW_TAG_enumeration_type ||
- N.getTag() == dwarf::DW_TAG_class_type,
+ N.getTag() == dwarf::DW_TAG_class_type ||
+ N.getTag() == dwarf::DW_TAG_variant_part,
"invalid tag", &N);
AssertDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope());
@@ -940,6 +961,14 @@ void Verifier::visitDICompositeType(const DICompositeType &N) {
N.getRawVTableHolder());
AssertDI(!hasConflictingReferenceFlags(N.getFlags()),
"invalid reference flags", &N);
+
+ if (N.isVector()) {
+ const DINodeArray Elements = N.getElements();
+ AssertDI(Elements.size() == 1 &&
+ Elements[0]->getTag() == dwarf::DW_TAG_subrange_type,
+ "invalid vector, expected one element of type subrange", &N);
+ }
+
if (auto *Params = N.getRawTemplateParams())
visitTemplateParams(N, *Params);
@@ -948,6 +977,11 @@ void Verifier::visitDICompositeType(const DICompositeType &N) {
AssertDI(N.getFile() && !N.getFile()->getFilename().empty(),
"class/union requires a filename", &N, N.getFile());
}
+
+ if (auto *D = N.getRawDiscriminator()) {
+ AssertDI(isa<DIDerivedType>(D) && N.getTag() == dwarf::DW_TAG_variant_part,
+ "discriminator can only appear on variant part");
+ }
}
void Verifier::visitDISubroutineType(const DISubroutineType &N) {
@@ -964,8 +998,23 @@ void Verifier::visitDISubroutineType(const DISubroutineType &N) {
void Verifier::visitDIFile(const DIFile &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_file_type, "invalid tag", &N);
- AssertDI((N.getChecksumKind() != DIFile::CSK_None ||
- N.getChecksum().empty()), "invalid checksum kind", &N);
+ Optional<DIFile::ChecksumInfo<StringRef>> Checksum = N.getChecksum();
+ if (Checksum) {
+ AssertDI(Checksum->Kind <= DIFile::ChecksumKind::CSK_Last,
+ "invalid checksum kind", &N);
+ size_t Size;
+ switch (Checksum->Kind) {
+ case DIFile::CSK_MD5:
+ Size = 32;
+ break;
+ case DIFile::CSK_SHA1:
+ Size = 40;
+ break;
+ }
+ AssertDI(Checksum->Value.size() == Size, "invalid checksum length", &N);
+ AssertDI(Checksum->Value.find_if_not(llvm::isHexDigit) == StringRef::npos,
+ "invalid checksum", &N);
+ }
}
void Verifier::visitDICompileUnit(const DICompileUnit &N) {
@@ -1038,12 +1087,13 @@ void Verifier::visitDISubprogram(const DISubprogram &N) {
if (auto *S = N.getRawDeclaration())
AssertDI(isa<DISubprogram>(S) && !cast<DISubprogram>(S)->isDefinition(),
"invalid subprogram declaration", &N, S);
- if (auto *RawVars = N.getRawVariables()) {
- auto *Vars = dyn_cast<MDTuple>(RawVars);
- AssertDI(Vars, "invalid variable list", &N, RawVars);
- for (Metadata *Op : Vars->operands()) {
- AssertDI(Op && isa<DILocalVariable>(Op), "invalid local variable", &N,
- Vars, Op);
+ if (auto *RawNode = N.getRawRetainedNodes()) {
+ auto *Node = dyn_cast<MDTuple>(RawNode);
+ AssertDI(Node, "invalid retained nodes list", &N, RawNode);
+ for (Metadata *Op : Node->operands()) {
+ AssertDI(Op && (isa<DILocalVariable>(Op) || isa<DILabel>(Op)),
+ "invalid retained nodes, expected DILocalVariable or DILabel",
+ &N, Node, Op);
}
}
AssertDI(!hasConflictingReferenceFlags(N.getFlags()),
@@ -1175,6 +1225,17 @@ void Verifier::visitDILocalVariable(const DILocalVariable &N) {
"local variable requires a valid scope", &N, N.getRawScope());
}
+void Verifier::visitDILabel(const DILabel &N) {
+ if (auto *S = N.getRawScope())
+ AssertDI(isa<DIScope>(S), "invalid scope", &N, S);
+ if (auto *F = N.getRawFile())
+ AssertDI(isa<DIFile>(F), "invalid file", &N, F);
+
+ AssertDI(N.getTag() == dwarf::DW_TAG_label, "invalid tag", &N);
+ AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),
+ "label requires a valid scope", &N, N.getRawScope());
+}
+
void Verifier::visitDIExpression(const DIExpression &N) {
AssertDI(N.isValid(), "invalid expression", &N);
}
@@ -1351,12 +1412,35 @@ Verifier::visitModuleFlag(const MDNode *Op,
Assert(M.getNamedMetadata("llvm.linker.options"),
"'Linker Options' named metadata no longer supported");
}
+
+ if (ID->getString() == "CG Profile") {
+ for (const MDOperand &MDO : cast<MDNode>(Op->getOperand(2))->operands())
+ visitModuleFlagCGProfileEntry(MDO);
+ }
+}
+
+void Verifier::visitModuleFlagCGProfileEntry(const MDOperand &MDO) {
+ auto CheckFunction = [&](const MDOperand &FuncMDO) {
+ if (!FuncMDO)
+ return;
+ auto F = dyn_cast<ValueAsMetadata>(FuncMDO);
+ Assert(F && isa<Function>(F->getValue()), "expected a Function or null",
+ FuncMDO);
+ };
+ auto Node = dyn_cast_or_null<MDNode>(MDO);
+ Assert(Node && Node->getNumOperands() == 3, "expected a MDNode triple", MDO);
+ CheckFunction(Node->getOperand(0));
+ CheckFunction(Node->getOperand(1));
+ auto Count = dyn_cast_or_null<ConstantAsMetadata>(Node->getOperand(2));
+ Assert(Count && Count->getType()->isIntegerTy(),
+ "expected an integer constant", Node->getOperand(2));
}
/// Return true if this attribute kind only applies to functions.
static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
switch (Kind) {
case Attribute::NoReturn:
+ case Attribute::NoCfCheck:
case Attribute::NoUnwind:
case Attribute::NoInline:
case Attribute::AlwaysInline:
@@ -1365,6 +1449,7 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
case Attribute::StackProtectReq:
case Attribute::StackProtectStrong:
case Attribute::SafeStack:
+ case Attribute::ShadowCallStack:
case Attribute::NoRedZone:
case Attribute::NoImplicitFloat:
case Attribute::Naked:
@@ -1382,6 +1467,7 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
case Attribute::Builtin:
case Attribute::NoBuiltin:
case Attribute::Cold:
+ case Attribute::OptForFuzzing:
case Attribute::OptimizeNone:
case Attribute::JumpTable:
case Attribute::Convergent:
@@ -1692,8 +1778,11 @@ void Verifier::verifyFunctionMetadata(
"expected string with name of the !prof annotation", MD);
MDString *MDS = cast<MDString>(MD->getOperand(0));
StringRef ProfName = MDS->getString();
- Assert(ProfName.equals("function_entry_count"),
- "first operand should be 'function_entry_count'", MD);
+ Assert(ProfName.equals("function_entry_count") ||
+ ProfName.equals("synthetic_function_entry_count"),
+ "first operand should be 'function_entry_count'"
+ " or 'synthetic_function_entry_count'",
+ MD);
// Check second operand.
Assert(MD->getOperand(1) != nullptr, "second operand should not be null",
@@ -2151,11 +2240,6 @@ void Verifier::visitFunction(const Function &F) {
Assert(false, "Invalid user of intrinsic instruction!", U);
}
- Assert(!F.hasDLLImportStorageClass() ||
- (F.isDeclaration() && F.hasExternalLinkage()) ||
- F.hasAvailableExternallyLinkage(),
- "Function is marked as dllimport, but not external.", &F);
-
auto *N = F.getSubprogram();
HasDebugInfo = (N != nullptr);
if (!HasDebugInfo)
@@ -2209,26 +2293,25 @@ void Verifier::visitBasicBlock(BasicBlock &BB) {
if (isa<PHINode>(BB.front())) {
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) {
+ llvm::sort(Preds.begin(), Preds.end());
+ 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)));
- std::sort(Values.begin(), Values.end());
+ 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)));
+ llvm::sort(Values.begin(), Values.end());
for (unsigned i = 0, e = Values.size(); i != e; ++i) {
// Check to make sure that if there is more than one entry for a
@@ -2239,12 +2322,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]);
}
}
@@ -2820,17 +2903,20 @@ void Verifier::verifyMustTailCall(CallInst &CI) {
Function *F = CI.getParent()->getParent();
FunctionType *CallerTy = F->getFunctionType();
FunctionType *CalleeTy = CI.getFunctionType();
- Assert(CallerTy->getNumParams() == CalleeTy->getNumParams(),
- "cannot guarantee tail call due to mismatched parameter counts", &CI);
+ if (!CI.getCalledFunction() || !CI.getCalledFunction()->isIntrinsic()) {
+ Assert(CallerTy->getNumParams() == CalleeTy->getNumParams(),
+ "cannot guarantee tail call due to mismatched parameter counts",
+ &CI);
+ for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) {
+ Assert(
+ isTypeCongruent(CallerTy->getParamType(I), CalleeTy->getParamType(I)),
+ "cannot guarantee tail call due to mismatched parameter types", &CI);
+ }
+ }
Assert(CallerTy->isVarArg() == CalleeTy->isVarArg(),
"cannot guarantee tail call due to mismatched varargs", &CI);
Assert(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) {
- Assert(
- 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.
Assert(F->getCallingConv() == CI.getCallingConv(),
@@ -2866,7 +2952,7 @@ void Verifier::verifyMustTailCall(CallInst &CI) {
// Check the return.
ReturnInst *Ret = dyn_cast_or_null<ReturnInst>(Next);
- Assert(Ret, "musttail call must be precede a ret with an optional bitcast",
+ Assert(Ret, "musttail call must precede a ret with an optional bitcast",
&CI);
Assert(!Ret->getReturnValue() || Ret->getReturnValue() == RetVal,
"musttail call result must be returned", Ret);
@@ -3120,8 +3206,7 @@ void Verifier::visitLoadInst(LoadInst &LI) {
"Load cannot have Release ordering", &LI);
Assert(LI.getAlignment() != 0,
"Atomic load must specify explicit alignment", &LI);
- Assert(ElTy->isIntegerTy() || ElTy->isPointerTy() ||
- ElTy->isFloatingPointTy(),
+ Assert(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy(),
"atomic load operand must have integer, pointer, or floating point "
"type!",
ElTy, &LI);
@@ -3149,8 +3234,7 @@ void Verifier::visitStoreInst(StoreInst &SI) {
"Store cannot have Acquire ordering", &SI);
Assert(SI.getAlignment() != 0,
"Atomic store must specify explicit alignment", &SI);
- Assert(ElTy->isIntegerTy() || ElTy->isPointerTy() ||
- ElTy->isFloatingPointTy(),
+ Assert(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy(),
"atomic store operand must have integer, pointer, or floating point "
"type!",
ElTy, &SI);
@@ -3241,9 +3325,8 @@ void Verifier::visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI) {
PointerType *PTy = dyn_cast<PointerType>(CXI.getOperand(0)->getType());
Assert(PTy, "First cmpxchg operand must be a pointer.", &CXI);
Type *ElTy = PTy->getElementType();
- Assert(ElTy->isIntegerTy() || ElTy->isPointerTy(),
- "cmpxchg operand must have integer or pointer type",
- ElTy, &CXI);
+ Assert(ElTy->isIntOrPtrTy(),
+ "cmpxchg operand must have integer or pointer type", ElTy, &CXI);
checkAtomicMemAccessSize(ElTy, &CXI);
Assert(ElTy == CXI.getOperand(1)->getType(),
"Expected value type does not match pointer operand type!", &CXI,
@@ -4015,96 +4098,36 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
case Intrinsic::dbg_value: // llvm.dbg.value
visitDbgIntrinsic("value", cast<DbgInfoIntrinsic>(*CS.getInstruction()));
break;
+ case Intrinsic::dbg_label: // llvm.dbg.label
+ visitDbgLabelIntrinsic("label", cast<DbgLabelInst>(*CS.getInstruction()));
+ break;
case Intrinsic::memcpy:
case Intrinsic::memmove:
case Intrinsic::memset: {
- ConstantInt *AlignCI = dyn_cast<ConstantInt>(CS.getArgOperand(3));
- Assert(AlignCI,
- "alignment argument of memory intrinsics must be a constant int",
- CS);
- const APInt &AlignVal = AlignCI->getValue();
- Assert(AlignCI->isZero() || AlignVal.isPowerOf2(),
- "alignment argument of memory intrinsics must be a power of 2", CS);
- Assert(isa<ConstantInt>(CS.getArgOperand(4)),
- "isvolatile argument of memory intrinsics must be a constant int",
- CS);
- break;
- }
- case Intrinsic::memcpy_element_unordered_atomic: {
- const AtomicMemCpyInst *MI = cast<AtomicMemCpyInst>(CS.getInstruction());
-
- ConstantInt *ElementSizeCI =
- dyn_cast<ConstantInt>(MI->getRawElementSizeInBytes());
- Assert(ElementSizeCI,
- "element size of the element-wise unordered atomic memory "
- "intrinsic must be a constant int",
- CS);
- const APInt &ElementSizeVal = ElementSizeCI->getValue();
- Assert(ElementSizeVal.isPowerOf2(),
- "element size of the element-wise atomic memory intrinsic "
- "must be a power of 2",
- CS);
-
- if (auto *LengthCI = dyn_cast<ConstantInt>(MI->getLength())) {
- uint64_t Length = LengthCI->getZExtValue();
- uint64_t ElementSize = MI->getElementSizeInBytes();
- Assert((Length % ElementSize) == 0,
- "constant length must be a multiple of the element size in the "
- "element-wise atomic memory intrinsic",
- CS);
- }
-
- auto IsValidAlignment = [&](uint64_t Alignment) {
- return isPowerOf2_64(Alignment) && ElementSizeVal.ule(Alignment);
+ const auto *MI = cast<MemIntrinsic>(CS.getInstruction());
+ auto IsValidAlignment = [&](unsigned Alignment) -> bool {
+ return Alignment == 0 || isPowerOf2_32(Alignment);
};
- uint64_t DstAlignment = CS.getParamAlignment(0),
- SrcAlignment = CS.getParamAlignment(1);
- Assert(IsValidAlignment(DstAlignment),
- "incorrect alignment of the destination argument", CS);
- Assert(IsValidAlignment(SrcAlignment),
- "incorrect alignment of the source argument", CS);
- break;
- }
- case Intrinsic::memmove_element_unordered_atomic: {
- auto *MI = cast<AtomicMemMoveInst>(CS.getInstruction());
-
- ConstantInt *ElementSizeCI =
- dyn_cast<ConstantInt>(MI->getRawElementSizeInBytes());
- Assert(ElementSizeCI,
- "element size of the element-wise unordered atomic memory "
- "intrinsic must be a constant int",
- CS);
- const APInt &ElementSizeVal = ElementSizeCI->getValue();
- Assert(ElementSizeVal.isPowerOf2(),
- "element size of the element-wise atomic memory intrinsic "
- "must be a power of 2",
+ Assert(IsValidAlignment(MI->getDestAlignment()),
+ "alignment of arg 0 of memory intrinsic must be 0 or a power of 2",
CS);
-
- if (auto *LengthCI = dyn_cast<ConstantInt>(MI->getLength())) {
- uint64_t Length = LengthCI->getZExtValue();
- uint64_t ElementSize = MI->getElementSizeInBytes();
- Assert((Length % ElementSize) == 0,
- "constant length must be a multiple of the element size in the "
- "element-wise atomic memory intrinsic",
+ if (const auto *MTI = dyn_cast<MemTransferInst>(MI)) {
+ Assert(IsValidAlignment(MTI->getSourceAlignment()),
+ "alignment of arg 1 of memory intrinsic must be 0 or a power of 2",
CS);
}
-
- auto IsValidAlignment = [&](uint64_t Alignment) {
- return isPowerOf2_64(Alignment) && ElementSizeVal.ule(Alignment);
- };
- uint64_t DstAlignment = CS.getParamAlignment(0),
- SrcAlignment = CS.getParamAlignment(1);
- Assert(IsValidAlignment(DstAlignment),
- "incorrect alignment of the destination argument", CS);
- Assert(IsValidAlignment(SrcAlignment),
- "incorrect alignment of the source argument", CS);
+ Assert(isa<ConstantInt>(CS.getArgOperand(3)),
+ "isvolatile argument of memory intrinsics must be a constant int",
+ CS);
break;
}
+ case Intrinsic::memcpy_element_unordered_atomic:
+ case Intrinsic::memmove_element_unordered_atomic:
case Intrinsic::memset_element_unordered_atomic: {
- auto *MI = cast<AtomicMemSetInst>(CS.getInstruction());
+ const auto *AMI = cast<AtomicMemIntrinsic>(CS.getInstruction());
ConstantInt *ElementSizeCI =
- dyn_cast<ConstantInt>(MI->getRawElementSizeInBytes());
+ dyn_cast<ConstantInt>(AMI->getRawElementSizeInBytes());
Assert(ElementSizeCI,
"element size of the element-wise unordered atomic memory "
"intrinsic must be a constant int",
@@ -4115,9 +4138,9 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
"must be a power of 2",
CS);
- if (auto *LengthCI = dyn_cast<ConstantInt>(MI->getLength())) {
+ if (auto *LengthCI = dyn_cast<ConstantInt>(AMI->getLength())) {
uint64_t Length = LengthCI->getZExtValue();
- uint64_t ElementSize = MI->getElementSizeInBytes();
+ uint64_t ElementSize = AMI->getElementSizeInBytes();
Assert((Length % ElementSize) == 0,
"constant length must be a multiple of the element size in the "
"element-wise atomic memory intrinsic",
@@ -4127,9 +4150,14 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
auto IsValidAlignment = [&](uint64_t Alignment) {
return isPowerOf2_64(Alignment) && ElementSizeVal.ule(Alignment);
};
- uint64_t DstAlignment = CS.getParamAlignment(0);
+ uint64_t DstAlignment = AMI->getDestAlignment();
Assert(IsValidAlignment(DstAlignment),
"incorrect alignment of the destination argument", CS);
+ if (const auto *AMT = dyn_cast<AtomicMemTransferInst>(AMI)) {
+ uint64_t SrcAlignment = AMT->getSourceAlignment();
+ Assert(IsValidAlignment(SrcAlignment),
+ "incorrect alignment of the source argument", CS);
+ }
break;
}
case Intrinsic::gcroot:
@@ -4429,7 +4457,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
};
}
-/// \brief Carefully grab the subprogram from a local scope.
+/// Carefully grab the subprogram from a local scope.
///
/// This carefully grabs the subprogram from a local scope, avoiding the
/// built-in assertions that would typically fire.
@@ -4486,8 +4514,8 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgInfoIntrinsic &DII) {
// The scopes for variables and !dbg attachments must agree.
DILocalVariable *Var = DII.getVariable();
DILocation *Loc = DII.getDebugLoc();
- Assert(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment",
- &DII, BB, F);
+ AssertDI(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment",
+ &DII, BB, F);
DISubprogram *VarSP = getSubprogram(Var->getRawScope());
DISubprogram *LocSP = getSubprogram(Loc->getRawScope());
@@ -4502,7 +4530,40 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgInfoIntrinsic &DII) {
verifyFnArgs(DII);
}
+void Verifier::visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI) {
+ AssertDI(isa<DILabel>(DLI.getRawVariable()),
+ "invalid llvm.dbg." + Kind + " intrinsic variable", &DLI,
+ DLI.getRawVariable());
+
+ // Ignore broken !dbg attachments; they're checked elsewhere.
+ if (MDNode *N = DLI.getDebugLoc().getAsMDNode())
+ if (!isa<DILocation>(N))
+ return;
+
+ BasicBlock *BB = DLI.getParent();
+ Function *F = BB ? BB->getParent() : nullptr;
+
+ // The scopes for variables and !dbg attachments must agree.
+ DILabel *Label = DLI.getLabel();
+ DILocation *Loc = DLI.getDebugLoc();
+ Assert(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment",
+ &DLI, BB, F);
+
+ DISubprogram *LabelSP = getSubprogram(Label->getRawScope());
+ DISubprogram *LocSP = getSubprogram(Loc->getRawScope());
+ if (!LabelSP || !LocSP)
+ return;
+
+ AssertDI(LabelSP == LocSP, "mismatched subprogram between llvm.dbg." + Kind +
+ " label and !dbg attachment",
+ &DLI, BB, F, Label, Label->getScope()->getSubprogram(), Loc,
+ Loc->getScope()->getSubprogram());
+}
+
void Verifier::verifyFragmentExpression(const DbgInfoIntrinsic &I) {
+ if (dyn_cast<DbgLabelInst>(&I))
+ return;
+
DILocalVariable *V = dyn_cast_or_null<DILocalVariable>(I.getRawVariable());
DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression());