summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/IR/Verifier.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/IR/Verifier.cpp')
-rw-r--r--contrib/llvm/lib/IR/Verifier.cpp767
1 files changed, 475 insertions, 292 deletions
diff --git a/contrib/llvm/lib/IR/Verifier.cpp b/contrib/llvm/lib/IR/Verifier.cpp
index 5855059..454a56a 100644
--- a/contrib/llvm/lib/IR/Verifier.cpp
+++ b/contrib/llvm/lib/IR/Verifier.cpp
@@ -49,7 +49,6 @@
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/ilist.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
@@ -59,6 +58,8 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/ilist.h"
+#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
@@ -81,10 +82,10 @@
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
-#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
@@ -102,7 +103,6 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
@@ -267,6 +267,9 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
/// \brief 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.
+ DenseMap<const DISubprogram *, const Function *> DISubprogramAttachments;
+
/// Track all DICompileUnits visited.
SmallPtrSet<const Metadata *, 2> CUVisited;
@@ -277,6 +280,9 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
/// already.
bool SawFrameEscape;
+ /// Whether the current function has a DISubprogram attached to it.
+ bool HasDebugInfo = false;
+
/// Stores the count of how many objects were passed to llvm.localescape for a
/// given function and the largest index passed to llvm.localrecover.
DenseMap<Function *, std::pair<unsigned, unsigned>> FrameEscapeInfo;
@@ -297,6 +303,9 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
// constant expressions, we can arrive at a particular user many times.
SmallPtrSet<const Value *, 32> GlobalValueVisited;
+ // Keeps track of duplicate function argument debug info.
+ SmallVector<const DILocalVariable *, 16> DebugFnArgs;
+
TBAAVerifier TBAAVerifyHelper;
void checkAtomicMemAccessSize(Type *Ty, const Instruction *I);
@@ -342,6 +351,7 @@ public:
visit(const_cast<Function &>(F));
verifySiblingFuncletUnwinds();
InstsInThisBlock.clear();
+ DebugFnArgs.clear();
LandingPadResultTy = nullptr;
SawFrameEscape = false;
SiblingFuncletInfo.clear();
@@ -379,7 +389,7 @@ public:
verifyCompileUnits();
verifyDeoptimizeCallingConvs();
-
+ DISubprogramAttachments.clear();
return !Broken;
}
@@ -457,6 +467,7 @@ private:
void visitUserOp1(Instruction &I);
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 visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI);
@@ -481,12 +492,11 @@ private:
void verifyMustTailCall(CallInst &CI);
bool performTypeCheck(Intrinsic::ID ID, Function *F, Type *Ty, int VT,
unsigned ArgNo, std::string &Suffix);
- bool verifyAttributeCount(AttributeSet Attrs, unsigned Params);
- void verifyAttributeTypes(AttributeSet Attrs, unsigned Idx, bool isFunction,
+ bool verifyAttributeCount(AttributeList Attrs, unsigned Params);
+ void verifyAttributeTypes(AttributeSet Attrs, bool IsFunction,
const Value *V);
- void verifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty,
- bool isReturnValue, const Value *V);
- void verifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs,
+ void verifyParameterAttrs(AttributeSet Attrs, Type *Ty, const Value *V);
+ void verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs,
const Value *V);
void verifyFunctionMetadata(ArrayRef<std::pair<unsigned, MDNode *>> MDs);
@@ -497,6 +507,7 @@ private:
void verifySiblingFuncletUnwinds();
void verifyFragmentExpression(const DbgInfoIntrinsic &I);
+ void verifyFnArgs(const DbgInfoIntrinsic &I);
/// Module-level debug info verification...
void verifyCompileUnits();
@@ -652,7 +663,8 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
if (auto *GVE = dyn_cast<DIGlobalVariableExpression>(MD))
visitDIGlobalVariableExpression(*GVE);
else
- AssertDI(false, "!dbg attachment of global variable must be a DIGlobalVariableExpression");
+ AssertDI(false, "!dbg attachment of global variable must be a "
+ "DIGlobalVariableExpression");
}
if (!GV.hasInitializer()) {
@@ -822,28 +834,6 @@ static bool isType(const Metadata *MD) { return !MD || isa<DIType>(MD); }
static bool isScope(const Metadata *MD) { return !MD || isa<DIScope>(MD); }
static bool isDINode(const Metadata *MD) { return !MD || isa<DINode>(MD); }
-template <class Ty>
-static bool isValidMetadataArrayImpl(const MDTuple &N, bool AllowNull) {
- for (Metadata *MD : N.operands()) {
- if (MD) {
- if (!isa<Ty>(MD))
- return false;
- } else {
- if (!AllowNull)
- return false;
- }
- }
- return true;
-}
-
-template <class Ty> static bool isValidMetadataArray(const MDTuple &N) {
- return isValidMetadataArrayImpl<Ty>(N, /* AllowNull */ false);
-}
-
-template <class Ty> static bool isValidMetadataNullArray(const MDTuple &N) {
- return isValidMetadataArrayImpl<Ty>(N, /* AllowNull */ true);
-}
-
void Verifier::visitDILocation(const DILocation &N) {
AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),
"location requires a valid scope", &N, N.getRawScope());
@@ -900,6 +890,13 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) {
AssertDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope());
AssertDI(isType(N.getRawBaseType()), "invalid base type", &N,
N.getRawBaseType());
+
+ if (N.getDWARFAddressSpace()) {
+ AssertDI(N.getTag() == dwarf::DW_TAG_pointer_type ||
+ N.getTag() == dwarf::DW_TAG_reference_type,
+ "DWARF address space only applies to pointer or reference types",
+ &N);
+ }
}
static bool hasConflictingReferenceFlags(unsigned Flags) {
@@ -1024,6 +1021,8 @@ void Verifier::visitDISubprogram(const DISubprogram &N) {
AssertDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope());
if (auto *F = N.getRawFile())
AssertDI(isa<DIFile>(F), "invalid file", &N, F);
+ else
+ AssertDI(N.getLine() == 0, "line specified with no file", &N, N.getLine());
if (auto *T = N.getRawType())
AssertDI(isa<DISubroutineType>(T), "invalid subroutine type", &N, T);
AssertDI(isType(N.getRawContainingType()), "invalid containing type", &N,
@@ -1054,6 +1053,14 @@ void Verifier::visitDISubprogram(const DISubprogram &N) {
// Subprogram declarations (part of the type hierarchy).
AssertDI(!Unit, "subprogram declarations must not have a compile unit", &N);
}
+
+ if (auto *RawThrownTypes = N.getRawThrownTypes()) {
+ auto *ThrownTypes = dyn_cast<MDTuple>(RawThrownTypes);
+ AssertDI(ThrownTypes, "invalid thrown types list", &N, RawThrownTypes);
+ for (Metadata *Op : ThrownTypes->operands())
+ AssertDI(Op && isa<DIType>(Op), "invalid thrown type", &N, ThrownTypes,
+ Op);
+ }
}
void Verifier::visitDILexicalBlockBase(const DILexicalBlockBase &N) {
@@ -1199,9 +1206,9 @@ void Verifier::visitComdat(const Comdat &C) {
void Verifier::visitModuleIdents(const Module &M) {
const NamedMDNode *Idents = M.getNamedMetadata("llvm.ident");
- if (!Idents)
+ if (!Idents)
return;
-
+
// llvm.ident takes a list of metadata entry. Each entry has only one string.
// Scan each llvm.ident entry and make sure that this requirement is met.
for (const MDNode *N : Idents->operands()) {
@@ -1211,7 +1218,7 @@ void Verifier::visitModuleIdents(const Module &M) {
("invalid value for llvm.ident metadata entry operand"
"(the operand should be a string)"),
N->getOperand(0));
- }
+ }
}
void Verifier::visitModuleFlags(const Module &M) {
@@ -1275,6 +1282,13 @@ Verifier::visitModuleFlag(const MDNode *Op,
// These behavior types accept any value.
break;
+ case Module::Max: {
+ Assert(mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2)),
+ "invalid value for 'max' module flag (expected constant integer)",
+ Op->getOperand(2));
+ break;
+ }
+
case Module::Require: {
// The value should itself be an MDNode with two operands, a flag ID (an
// MDString), and a value.
@@ -1310,73 +1324,90 @@ Verifier::visitModuleFlag(const MDNode *Op,
Assert(Inserted,
"module flag identifiers must be unique (or of 'require' type)", ID);
}
-}
-void Verifier::verifyAttributeTypes(AttributeSet Attrs, unsigned Idx,
- bool isFunction, const Value *V) {
- unsigned Slot = ~0U;
- for (unsigned I = 0, E = Attrs.getNumSlots(); I != E; ++I)
- if (Attrs.getSlotIndex(I) == Idx) {
- Slot = I;
- break;
- }
+ if (ID->getString() == "wchar_size") {
+ ConstantInt *Value
+ = mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2));
+ Assert(Value, "wchar_size metadata requires constant integer argument");
+ }
+
+ if (ID->getString() == "Linker Options") {
+ // If the llvm.linker.options named metadata exists, we assume that the
+ // bitcode reader has upgraded the module flag. Otherwise the flag might
+ // have been created by a client directly.
+ Assert(M.getNamedMetadata("llvm.linker.options"),
+ "'Linker Options' named metadata no longer supported");
+ }
+}
+
+/// Return true if this attribute kind only applies to functions.
+static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
+ switch (Kind) {
+ case Attribute::NoReturn:
+ case Attribute::NoUnwind:
+ case Attribute::NoInline:
+ case Attribute::AlwaysInline:
+ case Attribute::OptimizeForSize:
+ case Attribute::StackProtect:
+ case Attribute::StackProtectReq:
+ case Attribute::StackProtectStrong:
+ case Attribute::SafeStack:
+ case Attribute::NoRedZone:
+ case Attribute::NoImplicitFloat:
+ case Attribute::Naked:
+ case Attribute::InlineHint:
+ case Attribute::StackAlignment:
+ case Attribute::UWTable:
+ case Attribute::NonLazyBind:
+ case Attribute::ReturnsTwice:
+ case Attribute::SanitizeAddress:
+ case Attribute::SanitizeThread:
+ case Attribute::SanitizeMemory:
+ case Attribute::MinSize:
+ case Attribute::NoDuplicate:
+ case Attribute::Builtin:
+ case Attribute::NoBuiltin:
+ case Attribute::Cold:
+ case Attribute::OptimizeNone:
+ case Attribute::JumpTable:
+ case Attribute::Convergent:
+ case Attribute::ArgMemOnly:
+ case Attribute::NoRecurse:
+ case Attribute::InaccessibleMemOnly:
+ case Attribute::InaccessibleMemOrArgMemOnly:
+ case Attribute::AllocSize:
+ case Attribute::Speculatable:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
- assert(Slot != ~0U && "Attribute set inconsistency!");
+/// Return true if this is a function attribute that can also appear on
+/// arguments.
+static bool isFuncOrArgAttr(Attribute::AttrKind Kind) {
+ return Kind == Attribute::ReadOnly || Kind == Attribute::WriteOnly ||
+ Kind == Attribute::ReadNone;
+}
- for (AttributeSet::iterator I = Attrs.begin(Slot), E = Attrs.end(Slot);
- I != E; ++I) {
- if (I->isStringAttribute())
+void Verifier::verifyAttributeTypes(AttributeSet Attrs, bool IsFunction,
+ const Value *V) {
+ for (Attribute A : Attrs) {
+ if (A.isStringAttribute())
continue;
- if (I->getKindAsEnum() == Attribute::NoReturn ||
- I->getKindAsEnum() == Attribute::NoUnwind ||
- I->getKindAsEnum() == Attribute::NoInline ||
- I->getKindAsEnum() == Attribute::AlwaysInline ||
- I->getKindAsEnum() == Attribute::OptimizeForSize ||
- I->getKindAsEnum() == Attribute::StackProtect ||
- I->getKindAsEnum() == Attribute::StackProtectReq ||
- I->getKindAsEnum() == Attribute::StackProtectStrong ||
- I->getKindAsEnum() == Attribute::SafeStack ||
- I->getKindAsEnum() == Attribute::NoRedZone ||
- I->getKindAsEnum() == Attribute::NoImplicitFloat ||
- I->getKindAsEnum() == Attribute::Naked ||
- I->getKindAsEnum() == Attribute::InlineHint ||
- I->getKindAsEnum() == Attribute::StackAlignment ||
- I->getKindAsEnum() == Attribute::UWTable ||
- I->getKindAsEnum() == Attribute::NonLazyBind ||
- I->getKindAsEnum() == Attribute::ReturnsTwice ||
- I->getKindAsEnum() == Attribute::SanitizeAddress ||
- I->getKindAsEnum() == Attribute::SanitizeThread ||
- I->getKindAsEnum() == Attribute::SanitizeMemory ||
- I->getKindAsEnum() == Attribute::MinSize ||
- I->getKindAsEnum() == Attribute::NoDuplicate ||
- I->getKindAsEnum() == Attribute::Builtin ||
- I->getKindAsEnum() == Attribute::NoBuiltin ||
- I->getKindAsEnum() == Attribute::Cold ||
- I->getKindAsEnum() == Attribute::OptimizeNone ||
- I->getKindAsEnum() == Attribute::JumpTable ||
- I->getKindAsEnum() == Attribute::Convergent ||
- I->getKindAsEnum() == Attribute::ArgMemOnly ||
- I->getKindAsEnum() == Attribute::NoRecurse ||
- I->getKindAsEnum() == Attribute::InaccessibleMemOnly ||
- I->getKindAsEnum() == Attribute::InaccessibleMemOrArgMemOnly ||
- I->getKindAsEnum() == Attribute::AllocSize) {
- if (!isFunction) {
- CheckFailed("Attribute '" + I->getAsString() +
- "' only applies to functions!", V);
- return;
- }
- } else if (I->getKindAsEnum() == Attribute::ReadOnly ||
- I->getKindAsEnum() == Attribute::WriteOnly ||
- I->getKindAsEnum() == Attribute::ReadNone) {
- if (Idx == 0) {
- CheckFailed("Attribute '" + I->getAsString() +
- "' does not apply to function returns");
+ if (isFuncOnlyAttr(A.getKindAsEnum())) {
+ if (!IsFunction) {
+ CheckFailed("Attribute '" + A.getAsString() +
+ "' only applies to functions!",
+ V);
return;
}
- } else if (isFunction) {
- CheckFailed("Attribute '" + I->getAsString() +
- "' does not apply to functions!", V);
+ } else if (IsFunction && !isFuncOrArgAttr(A.getKindAsEnum())) {
+ CheckFailed("Attribute '" + A.getAsString() +
+ "' does not apply to functions!",
+ V);
return;
}
}
@@ -1384,106 +1415,91 @@ void Verifier::verifyAttributeTypes(AttributeSet Attrs, unsigned Idx,
// VerifyParameterAttrs - Check the given attributes for an argument or return
// value of the specified type. The value V is printed in error messages.
-void Verifier::verifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty,
- bool isReturnValue, const Value *V) {
- if (!Attrs.hasAttributes(Idx))
+void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty,
+ const Value *V) {
+ if (!Attrs.hasAttributes())
return;
- verifyAttributeTypes(Attrs, Idx, false, V);
-
- if (isReturnValue)
- Assert(!Attrs.hasAttribute(Idx, Attribute::ByVal) &&
- !Attrs.hasAttribute(Idx, Attribute::Nest) &&
- !Attrs.hasAttribute(Idx, Attribute::StructRet) &&
- !Attrs.hasAttribute(Idx, Attribute::NoCapture) &&
- !Attrs.hasAttribute(Idx, Attribute::Returned) &&
- !Attrs.hasAttribute(Idx, Attribute::InAlloca) &&
- !Attrs.hasAttribute(Idx, Attribute::SwiftSelf) &&
- !Attrs.hasAttribute(Idx, Attribute::SwiftError),
- "Attributes 'byval', 'inalloca', 'nest', 'sret', 'nocapture', "
- "'returned', 'swiftself', and 'swifterror' do not apply to return "
- "values!",
- V);
+ verifyAttributeTypes(Attrs, /*IsFunction=*/false, V);
// Check for mutually incompatible attributes. Only inreg is compatible with
// sret.
unsigned AttrCount = 0;
- AttrCount += Attrs.hasAttribute(Idx, Attribute::ByVal);
- AttrCount += Attrs.hasAttribute(Idx, Attribute::InAlloca);
- AttrCount += Attrs.hasAttribute(Idx, Attribute::StructRet) ||
- Attrs.hasAttribute(Idx, Attribute::InReg);
- AttrCount += Attrs.hasAttribute(Idx, Attribute::Nest);
+ AttrCount += Attrs.hasAttribute(Attribute::ByVal);
+ AttrCount += Attrs.hasAttribute(Attribute::InAlloca);
+ AttrCount += Attrs.hasAttribute(Attribute::StructRet) ||
+ Attrs.hasAttribute(Attribute::InReg);
+ AttrCount += Attrs.hasAttribute(Attribute::Nest);
Assert(AttrCount <= 1, "Attributes 'byval', 'inalloca', 'inreg', 'nest', "
"and 'sret' are incompatible!",
V);
- Assert(!(Attrs.hasAttribute(Idx, Attribute::InAlloca) &&
- Attrs.hasAttribute(Idx, Attribute::ReadOnly)),
+ Assert(!(Attrs.hasAttribute(Attribute::InAlloca) &&
+ Attrs.hasAttribute(Attribute::ReadOnly)),
"Attributes "
"'inalloca and readonly' are incompatible!",
V);
- Assert(!(Attrs.hasAttribute(Idx, Attribute::StructRet) &&
- Attrs.hasAttribute(Idx, Attribute::Returned)),
+ Assert(!(Attrs.hasAttribute(Attribute::StructRet) &&
+ Attrs.hasAttribute(Attribute::Returned)),
"Attributes "
"'sret and returned' are incompatible!",
V);
- Assert(!(Attrs.hasAttribute(Idx, Attribute::ZExt) &&
- Attrs.hasAttribute(Idx, Attribute::SExt)),
+ Assert(!(Attrs.hasAttribute(Attribute::ZExt) &&
+ Attrs.hasAttribute(Attribute::SExt)),
"Attributes "
"'zeroext and signext' are incompatible!",
V);
- Assert(!(Attrs.hasAttribute(Idx, Attribute::ReadNone) &&
- Attrs.hasAttribute(Idx, Attribute::ReadOnly)),
+ Assert(!(Attrs.hasAttribute(Attribute::ReadNone) &&
+ Attrs.hasAttribute(Attribute::ReadOnly)),
"Attributes "
"'readnone and readonly' are incompatible!",
V);
- Assert(!(Attrs.hasAttribute(Idx, Attribute::ReadNone) &&
- Attrs.hasAttribute(Idx, Attribute::WriteOnly)),
+ Assert(!(Attrs.hasAttribute(Attribute::ReadNone) &&
+ Attrs.hasAttribute(Attribute::WriteOnly)),
"Attributes "
"'readnone and writeonly' are incompatible!",
V);
- Assert(!(Attrs.hasAttribute(Idx, Attribute::ReadOnly) &&
- Attrs.hasAttribute(Idx, Attribute::WriteOnly)),
+ Assert(!(Attrs.hasAttribute(Attribute::ReadOnly) &&
+ Attrs.hasAttribute(Attribute::WriteOnly)),
"Attributes "
"'readonly and writeonly' are incompatible!",
V);
- Assert(!(Attrs.hasAttribute(Idx, Attribute::NoInline) &&
- Attrs.hasAttribute(Idx, Attribute::AlwaysInline)),
+ Assert(!(Attrs.hasAttribute(Attribute::NoInline) &&
+ Attrs.hasAttribute(Attribute::AlwaysInline)),
"Attributes "
"'noinline and alwaysinline' are incompatible!",
V);
- Assert(
- !AttrBuilder(Attrs, Idx).overlaps(AttributeFuncs::typeIncompatible(Ty)),
- "Wrong types for attribute: " +
- AttributeSet::get(Context, Idx, AttributeFuncs::typeIncompatible(Ty))
- .getAsString(Idx),
- V);
+ AttrBuilder IncompatibleAttrs = AttributeFuncs::typeIncompatible(Ty);
+ Assert(!AttrBuilder(Attrs).overlaps(IncompatibleAttrs),
+ "Wrong types for attribute: " +
+ AttributeSet::get(Context, IncompatibleAttrs).getAsString(),
+ V);
if (PointerType *PTy = dyn_cast<PointerType>(Ty)) {
SmallPtrSet<Type*, 4> Visited;
if (!PTy->getElementType()->isSized(&Visited)) {
- Assert(!Attrs.hasAttribute(Idx, Attribute::ByVal) &&
- !Attrs.hasAttribute(Idx, Attribute::InAlloca),
+ Assert(!Attrs.hasAttribute(Attribute::ByVal) &&
+ !Attrs.hasAttribute(Attribute::InAlloca),
"Attributes 'byval' and 'inalloca' do not support unsized types!",
V);
}
if (!isa<PointerType>(PTy->getElementType()))
- Assert(!Attrs.hasAttribute(Idx, Attribute::SwiftError),
+ Assert(!Attrs.hasAttribute(Attribute::SwiftError),
"Attribute 'swifterror' only applies to parameters "
"with pointer to pointer type!",
V);
} else {
- Assert(!Attrs.hasAttribute(Idx, Attribute::ByVal),
+ Assert(!Attrs.hasAttribute(Attribute::ByVal),
"Attribute 'byval' only applies to parameters with pointer type!",
V);
- Assert(!Attrs.hasAttribute(Idx, Attribute::SwiftError),
+ Assert(!Attrs.hasAttribute(Attribute::SwiftError),
"Attribute 'swifterror' only applies to parameters "
"with pointer type!",
V);
@@ -1492,7 +1508,7 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty,
// Check parameter attributes against a function type.
// The value V is printed in error messages.
-void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs,
+void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs,
const Value *V) {
if (Attrs.isEmpty())
return;
@@ -1503,122 +1519,124 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs,
bool SawSwiftSelf = false;
bool SawSwiftError = false;
- for (unsigned i = 0, e = Attrs.getNumSlots(); i != e; ++i) {
- unsigned Idx = Attrs.getSlotIndex(i);
-
- Type *Ty;
- if (Idx == 0)
- Ty = FT->getReturnType();
- else if (Idx-1 < FT->getNumParams())
- Ty = FT->getParamType(Idx-1);
- else
- break; // VarArgs attributes, verified elsewhere.
+ // Verify return value attributes.
+ AttributeSet RetAttrs = Attrs.getRetAttributes();
+ Assert((!RetAttrs.hasAttribute(Attribute::ByVal) &&
+ !RetAttrs.hasAttribute(Attribute::Nest) &&
+ !RetAttrs.hasAttribute(Attribute::StructRet) &&
+ !RetAttrs.hasAttribute(Attribute::NoCapture) &&
+ !RetAttrs.hasAttribute(Attribute::Returned) &&
+ !RetAttrs.hasAttribute(Attribute::InAlloca) &&
+ !RetAttrs.hasAttribute(Attribute::SwiftSelf) &&
+ !RetAttrs.hasAttribute(Attribute::SwiftError)),
+ "Attributes 'byval', 'inalloca', 'nest', 'sret', 'nocapture', "
+ "'returned', 'swiftself', and 'swifterror' do not apply to return "
+ "values!",
+ V);
+ Assert((!RetAttrs.hasAttribute(Attribute::ReadOnly) &&
+ !RetAttrs.hasAttribute(Attribute::WriteOnly) &&
+ !RetAttrs.hasAttribute(Attribute::ReadNone)),
+ "Attribute '" + RetAttrs.getAsString() +
+ "' does not apply to function returns",
+ V);
+ verifyParameterAttrs(RetAttrs, FT->getReturnType(), V);
- verifyParameterAttrs(Attrs, Idx, Ty, Idx == 0, V);
+ // Verify parameter attributes.
+ for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
+ Type *Ty = FT->getParamType(i);
+ AttributeSet ArgAttrs = Attrs.getParamAttributes(i);
- if (Idx == 0)
- continue;
+ verifyParameterAttrs(ArgAttrs, Ty, V);
- if (Attrs.hasAttribute(Idx, Attribute::Nest)) {
+ if (ArgAttrs.hasAttribute(Attribute::Nest)) {
Assert(!SawNest, "More than one parameter has attribute nest!", V);
SawNest = true;
}
- if (Attrs.hasAttribute(Idx, Attribute::Returned)) {
+ if (ArgAttrs.hasAttribute(Attribute::Returned)) {
Assert(!SawReturned, "More than one parameter has attribute returned!",
V);
Assert(Ty->canLosslesslyBitCastTo(FT->getReturnType()),
- "Incompatible "
- "argument and return types for 'returned' attribute",
+ "Incompatible argument and return types for 'returned' attribute",
V);
SawReturned = true;
}
- if (Attrs.hasAttribute(Idx, Attribute::StructRet)) {
+ if (ArgAttrs.hasAttribute(Attribute::StructRet)) {
Assert(!SawSRet, "Cannot have multiple 'sret' parameters!", V);
- Assert(Idx == 1 || Idx == 2,
+ Assert(i == 0 || i == 1,
"Attribute 'sret' is not on first or second parameter!", V);
SawSRet = true;
}
- if (Attrs.hasAttribute(Idx, Attribute::SwiftSelf)) {
+ if (ArgAttrs.hasAttribute(Attribute::SwiftSelf)) {
Assert(!SawSwiftSelf, "Cannot have multiple 'swiftself' parameters!", V);
SawSwiftSelf = true;
}
- if (Attrs.hasAttribute(Idx, Attribute::SwiftError)) {
+ if (ArgAttrs.hasAttribute(Attribute::SwiftError)) {
Assert(!SawSwiftError, "Cannot have multiple 'swifterror' parameters!",
V);
SawSwiftError = true;
}
- if (Attrs.hasAttribute(Idx, Attribute::InAlloca)) {
- Assert(Idx == FT->getNumParams(), "inalloca isn't on the last parameter!",
- V);
+ if (ArgAttrs.hasAttribute(Attribute::InAlloca)) {
+ Assert(i == FT->getNumParams() - 1,
+ "inalloca isn't on the last parameter!", V);
}
}
- if (!Attrs.hasAttributes(AttributeSet::FunctionIndex))
+ if (!Attrs.hasAttributes(AttributeList::FunctionIndex))
return;
- verifyAttributeTypes(Attrs, AttributeSet::FunctionIndex, true, V);
+ verifyAttributeTypes(Attrs.getFnAttributes(), /*IsFunction=*/true, V);
- Assert(
- !(Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone) &&
- Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly)),
- "Attributes 'readnone and readonly' are incompatible!", V);
+ Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) &&
+ Attrs.hasFnAttribute(Attribute::ReadOnly)),
+ "Attributes 'readnone and readonly' are incompatible!", V);
- Assert(
- !(Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone) &&
- Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::WriteOnly)),
- "Attributes 'readnone and writeonly' are incompatible!", V);
+ Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) &&
+ Attrs.hasFnAttribute(Attribute::WriteOnly)),
+ "Attributes 'readnone and writeonly' are incompatible!", V);
- Assert(
- !(Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly) &&
- Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::WriteOnly)),
- "Attributes 'readonly and writeonly' are incompatible!", V);
+ Assert(!(Attrs.hasFnAttribute(Attribute::ReadOnly) &&
+ Attrs.hasFnAttribute(Attribute::WriteOnly)),
+ "Attributes 'readonly and writeonly' are incompatible!", V);
- Assert(
- !(Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone) &&
- Attrs.hasAttribute(AttributeSet::FunctionIndex,
- Attribute::InaccessibleMemOrArgMemOnly)),
- "Attributes 'readnone and inaccessiblemem_or_argmemonly' are incompatible!", V);
+ Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) &&
+ Attrs.hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly)),
+ "Attributes 'readnone and inaccessiblemem_or_argmemonly' are "
+ "incompatible!",
+ V);
- Assert(
- !(Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone) &&
- Attrs.hasAttribute(AttributeSet::FunctionIndex,
- Attribute::InaccessibleMemOnly)),
- "Attributes 'readnone and inaccessiblememonly' are incompatible!", V);
+ Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) &&
+ Attrs.hasFnAttribute(Attribute::InaccessibleMemOnly)),
+ "Attributes 'readnone and inaccessiblememonly' are incompatible!", V);
- Assert(
- !(Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::NoInline) &&
- Attrs.hasAttribute(AttributeSet::FunctionIndex,
- Attribute::AlwaysInline)),
- "Attributes 'noinline and alwaysinline' are incompatible!", V);
-
- if (Attrs.hasAttribute(AttributeSet::FunctionIndex,
- Attribute::OptimizeNone)) {
- Assert(Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::NoInline),
+ Assert(!(Attrs.hasFnAttribute(Attribute::NoInline) &&
+ Attrs.hasFnAttribute(Attribute::AlwaysInline)),
+ "Attributes 'noinline and alwaysinline' are incompatible!", V);
+
+ if (Attrs.hasFnAttribute(Attribute::OptimizeNone)) {
+ Assert(Attrs.hasFnAttribute(Attribute::NoInline),
"Attribute 'optnone' requires 'noinline'!", V);
- Assert(!Attrs.hasAttribute(AttributeSet::FunctionIndex,
- Attribute::OptimizeForSize),
+ Assert(!Attrs.hasFnAttribute(Attribute::OptimizeForSize),
"Attributes 'optsize and optnone' are incompatible!", V);
- Assert(!Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::MinSize),
+ Assert(!Attrs.hasFnAttribute(Attribute::MinSize),
"Attributes 'minsize and optnone' are incompatible!", V);
}
- if (Attrs.hasAttribute(AttributeSet::FunctionIndex,
- Attribute::JumpTable)) {
+ if (Attrs.hasFnAttribute(Attribute::JumpTable)) {
const GlobalValue *GV = cast<GlobalValue>(V);
Assert(GV->hasGlobalUnnamedAddr(),
"Attribute 'jumptable' requires 'unnamed_addr'", V);
}
- if (Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::AllocSize)) {
+ if (Attrs.hasFnAttribute(Attribute::AllocSize)) {
std::pair<unsigned, Optional<unsigned>> Args =
- Attrs.getAllocSizeArgs(AttributeSet::FunctionIndex);
+ Attrs.getAllocSizeArgs(AttributeList::FunctionIndex);
auto CheckParam = [&](StringRef Name, unsigned ParamNo) {
if (ParamNo >= FT->getNumParams()) {
@@ -1649,8 +1667,8 @@ void Verifier::verifyFunctionMetadata(
for (const auto &Pair : MDs) {
if (Pair.first == LLVMContext::MD_prof) {
MDNode *MD = Pair.second;
- Assert(MD->getNumOperands() == 2,
- "!prof annotations should have exactly 2 operands", MD);
+ Assert(MD->getNumOperands() >= 2,
+ "!prof annotations should have no less than 2 operands", MD);
// Check first operand.
Assert(MD->getOperand(0) != nullptr, "first operand should not be null",
@@ -1725,18 +1743,10 @@ void Verifier::visitConstantExpr(const ConstantExpr *CE) {
}
}
-bool Verifier::verifyAttributeCount(AttributeSet Attrs, unsigned Params) {
- if (Attrs.getNumSlots() == 0)
- return true;
-
- unsigned LastSlot = Attrs.getNumSlots() - 1;
- unsigned LastIndex = Attrs.getSlotIndex(LastSlot);
- if (LastIndex <= Params
- || (LastIndex == AttributeSet::FunctionIndex
- && (LastSlot == 0 || Attrs.getSlotIndex(LastSlot - 1) <= Params)))
- return true;
-
- return false;
+bool Verifier::verifyAttributeCount(AttributeList Attrs, unsigned Params) {
+ // There shouldn't be more attribute sets than there are parameters plus the
+ // function and return value.
+ return Attrs.getNumAttrSets() <= Params + 2;
}
/// Verify that statepoint intrinsic is well formed.
@@ -1844,7 +1854,7 @@ void Verifier::verifyStatepoint(ImmutableCallSite CS) {
Assert(ExpectedNumArgs <= (int)CS.arg_size(),
"gc.statepoint too few arguments according to length fields", &CI);
- // Check that the only uses of this gc.statepoint are gc.result or
+ // Check that the only uses of this gc.statepoint are gc.result or
// gc.relocate calls which are tied to this statepoint and thus part
// of the same statepoint sequence
for (const User *U : CI.users()) {
@@ -1963,7 +1973,7 @@ void Verifier::visitFunction(const Function &F) {
Assert(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy(),
"Invalid struct return type!", &F);
- AttributeSet Attrs = F.getAttributes();
+ AttributeList Attrs = F.getAttributes();
Assert(verifyAttributeCount(Attrs, FT->getNumParams()),
"Attribute after last parameter!", &F);
@@ -1974,7 +1984,7 @@ void Verifier::visitFunction(const Function &F) {
// On function declarations/definitions, we do not support the builtin
// attribute. We do not check this in VerifyFunctionAttrs since that is
// checking for Attributes that can/can not ever be on functions.
- Assert(!Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::Builtin),
+ Assert(!Attrs.hasFnAttribute(Attribute::Builtin),
"Attribute 'builtin' can only be applied to a callsite.", &F);
// Check that this function meets the restrictions on this calling convention.
@@ -1984,6 +1994,19 @@ void Verifier::visitFunction(const Function &F) {
default:
case CallingConv::C:
break;
+ case CallingConv::AMDGPU_KERNEL:
+ case CallingConv::SPIR_KERNEL:
+ Assert(F.getReturnType()->isVoidTy(),
+ "Calling convention requires void return type", &F);
+ LLVM_FALLTHROUGH;
+ case CallingConv::AMDGPU_VS:
+ case CallingConv::AMDGPU_HS:
+ case CallingConv::AMDGPU_GS:
+ case CallingConv::AMDGPU_PS:
+ case CallingConv::AMDGPU_CS:
+ Assert(!F.hasStructRetAttr(),
+ "Calling convention does not allow sret", &F);
+ LLVM_FALLTHROUGH;
case CallingConv::Fast:
case CallingConv::Cold:
case CallingConv::Intel_OCL_BI:
@@ -2014,7 +2037,7 @@ void Verifier::visitFunction(const Function &F) {
}
// Check that swifterror argument is only used by loads and stores.
- if (Attrs.hasAttribute(i+1, Attribute::SwiftError)) {
+ if (Attrs.hasParamAttribute(i, Attribute::SwiftError)) {
verifySwiftErrorValue(&Arg);
}
++i;
@@ -2078,13 +2101,19 @@ void Verifier::visitFunction(const Function &F) {
switch (I.first) {
default:
break;
- case LLVMContext::MD_dbg:
+ case LLVMContext::MD_dbg: {
++NumDebugAttachments;
AssertDI(NumDebugAttachments == 1,
"function must have a single !dbg attachment", &F, I.second);
AssertDI(isa<DISubprogram>(I.second),
"function !dbg attachment must be a subprogram", &F, I.second);
+ auto *SP = cast<DISubprogram>(I.second);
+ const Function *&AttachedTo = DISubprogramAttachments[SP];
+ AssertDI(!AttachedTo || AttachedTo == &F,
+ "DISubprogram attached to more than one function", SP, &F);
+ AttachedTo = &F;
break;
+ }
case LLVMContext::MD_prof:
++NumProfAttachments;
Assert(NumProfAttachments == 1,
@@ -2113,11 +2142,10 @@ void Verifier::visitFunction(const Function &F) {
"Function is marked as dllimport, but not external.", &F);
auto *N = F.getSubprogram();
- if (!N)
+ HasDebugInfo = (N != nullptr);
+ if (!HasDebugInfo)
return;
- visitDISubprogram(*N);
-
// Check that all !dbg attachments lead to back to N (or, at least, another
// subprogram that describes the same function).
//
@@ -2476,15 +2504,13 @@ void Verifier::visitPtrToIntInst(PtrToIntInst &I) {
Type *SrcTy = I.getOperand(0)->getType();
Type *DestTy = I.getType();
- Assert(SrcTy->getScalarType()->isPointerTy(),
- "PtrToInt source must be pointer", &I);
+ Assert(SrcTy->isPtrOrPtrVectorTy(), "PtrToInt source must be pointer", &I);
if (auto *PTy = dyn_cast<PointerType>(SrcTy->getScalarType()))
Assert(!DL.isNonIntegralPointerType(PTy),
"ptrtoint not supported for non-integral pointers");
- Assert(DestTy->getScalarType()->isIntegerTy(),
- "PtrToInt result must be integral", &I);
+ Assert(DestTy->isIntOrIntVectorTy(), "PtrToInt result must be integral", &I);
Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), "PtrToInt type mismatch",
&I);
@@ -2503,10 +2529,9 @@ void Verifier::visitIntToPtrInst(IntToPtrInst &I) {
Type *SrcTy = I.getOperand(0)->getType();
Type *DestTy = I.getType();
- Assert(SrcTy->getScalarType()->isIntegerTy(),
+ Assert(SrcTy->isIntOrIntVectorTy(),
"IntToPtr source must be an integral", &I);
- Assert(DestTy->getScalarType()->isPointerTy(),
- "IntToPtr result must be a pointer", &I);
+ Assert(DestTy->isPtrOrPtrVectorTy(), "IntToPtr result must be a pointer", &I);
if (auto *PTy = dyn_cast<PointerType>(DestTy->getScalarType()))
Assert(!DL.isNonIntegralPointerType(PTy),
@@ -2601,11 +2626,20 @@ void Verifier::verifyCallSite(CallSite CS) {
"Call parameter type does not match function signature!",
CS.getArgument(i), FTy->getParamType(i), I);
- AttributeSet Attrs = CS.getAttributes();
+ AttributeList Attrs = CS.getAttributes();
Assert(verifyAttributeCount(Attrs, CS.arg_size()),
"Attribute after last parameter!", I);
+ if (Attrs.hasAttribute(AttributeList::FunctionIndex, Attribute::Speculatable)) {
+ // Don't allow speculatable on call sites, unless the underlying function
+ // declaration is also speculatable.
+ Function *Callee
+ = dyn_cast<Function>(CS.getCalledValue()->stripPointerCasts());
+ Assert(Callee && Callee->isSpeculatable(),
+ "speculatable attribute may not apply to call sites", I);
+ }
+
// Verify call attributes.
verifyFunctionAttrs(FTy, Attrs, I);
@@ -2623,7 +2657,7 @@ void Verifier::verifyCallSite(CallSite CS) {
// make sure the underlying alloca/parameter it comes from has a swifterror as
// well.
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
- if (CS.paramHasAttr(i+1, Attribute::SwiftError)) {
+ if (CS.paramHasAttr(i, Attribute::SwiftError)) {
Value *SwiftErrorArg = CS.getArgument(i);
if (auto AI = dyn_cast<AllocaInst>(SwiftErrorArg->stripInBoundsOffsets())) {
Assert(AI->isSwiftError(),
@@ -2641,24 +2675,25 @@ void Verifier::verifyCallSite(CallSite CS) {
bool SawNest = false;
bool SawReturned = false;
- for (unsigned Idx = 1; Idx < 1 + FTy->getNumParams(); ++Idx) {
- if (Attrs.hasAttribute(Idx, Attribute::Nest))
+ for (unsigned Idx = 0; Idx < FTy->getNumParams(); ++Idx) {
+ if (Attrs.hasParamAttribute(Idx, Attribute::Nest))
SawNest = true;
- if (Attrs.hasAttribute(Idx, Attribute::Returned))
+ if (Attrs.hasParamAttribute(Idx, Attribute::Returned))
SawReturned = true;
}
// Check attributes on the varargs part.
- for (unsigned Idx = 1 + FTy->getNumParams(); Idx <= CS.arg_size(); ++Idx) {
- Type *Ty = CS.getArgument(Idx-1)->getType();
- verifyParameterAttrs(Attrs, Idx, Ty, false, I);
+ for (unsigned Idx = FTy->getNumParams(); Idx < CS.arg_size(); ++Idx) {
+ Type *Ty = CS.getArgument(Idx)->getType();
+ AttributeSet ArgAttrs = Attrs.getParamAttributes(Idx);
+ verifyParameterAttrs(ArgAttrs, Ty, I);
- if (Attrs.hasAttribute(Idx, Attribute::Nest)) {
+ if (ArgAttrs.hasAttribute(Attribute::Nest)) {
Assert(!SawNest, "More than one parameter has attribute nest!", I);
SawNest = true;
}
- if (Attrs.hasAttribute(Idx, Attribute::Returned)) {
+ if (ArgAttrs.hasAttribute(Attribute::Returned)) {
Assert(!SawReturned, "More than one parameter has attribute returned!",
I);
Assert(Ty->canLosslesslyBitCastTo(FTy->getReturnType()),
@@ -2668,11 +2703,12 @@ void Verifier::verifyCallSite(CallSite CS) {
SawReturned = true;
}
- Assert(!Attrs.hasAttribute(Idx, Attribute::StructRet),
+ Assert(!ArgAttrs.hasAttribute(Attribute::StructRet),
"Attribute 'sret' cannot be used for vararg call arguments!", I);
- if (Attrs.hasAttribute(Idx, Attribute::InAlloca))
- Assert(Idx == CS.arg_size(), "inalloca isn't on the last argument!", I);
+ if (ArgAttrs.hasAttribute(Attribute::InAlloca))
+ Assert(Idx == CS.arg_size() - 1, "inalloca isn't on the last argument!",
+ I);
}
}
@@ -2726,9 +2762,9 @@ void Verifier::verifyCallSite(CallSite CS) {
// do so causes assertion failures when the inliner sets up inline scope info.
if (I->getFunction()->getSubprogram() && CS.getCalledFunction() &&
CS.getCalledFunction()->getSubprogram())
- Assert(I->getDebugLoc(), "inlinable function call in a function with debug "
- "info must have a !dbg location",
- I);
+ AssertDI(I->getDebugLoc(), "inlinable function call in a function with "
+ "debug info must have a !dbg location",
+ I);
visitInstruction(*I);
}
@@ -2745,18 +2781,18 @@ static bool isTypeCongruent(Type *L, Type *R) {
return PL->getAddressSpace() == PR->getAddressSpace();
}
-static AttrBuilder getParameterABIAttributes(int I, AttributeSet Attrs) {
+static AttrBuilder getParameterABIAttributes(int I, AttributeList Attrs) {
static const Attribute::AttrKind ABIAttrs[] = {
Attribute::StructRet, Attribute::ByVal, Attribute::InAlloca,
Attribute::InReg, Attribute::Returned, Attribute::SwiftSelf,
Attribute::SwiftError};
AttrBuilder Copy;
for (auto AK : ABIAttrs) {
- if (Attrs.hasAttribute(I + 1, AK))
+ if (Attrs.hasParamAttribute(I, AK))
Copy.addAttribute(AK);
}
- if (Attrs.hasAttribute(I + 1, Attribute::Alignment))
- Copy.addAlignmentAttr(Attrs.getParamAlignment(I + 1));
+ if (Attrs.hasParamAttribute(I, Attribute::Alignment))
+ Copy.addAlignmentAttr(Attrs.getParamAlignment(I));
return Copy;
}
@@ -2787,8 +2823,8 @@ void Verifier::verifyMustTailCall(CallInst &CI) {
// - All ABI-impacting function attributes, such as sret, byval, inreg,
// returned, and inalloca, must match.
- AttributeSet CallerAttrs = F->getAttributes();
- AttributeSet CalleeAttrs = CI.getAttributes();
+ AttributeList CallerAttrs = F->getAttributes();
+ AttributeList CalleeAttrs = CI.getAttributes();
for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) {
AttrBuilder CallerABIAttrs = getParameterABIAttributes(I, CallerAttrs);
AttrBuilder CalleeABIAttrs = getParameterABIAttributes(I, CalleeAttrs);
@@ -2913,11 +2949,10 @@ void Verifier::visitICmpInst(ICmpInst &IC) {
Assert(Op0Ty == Op1Ty,
"Both operands to ICmp instruction are not of the same type!", &IC);
// Check that the operands are the right type
- Assert(Op0Ty->isIntOrIntVectorTy() || Op0Ty->getScalarType()->isPointerTy(),
+ Assert(Op0Ty->isIntOrIntVectorTy() || Op0Ty->isPtrOrPtrVectorTy(),
"Invalid operand types for ICmp instruction", &IC);
// Check that the predicate is valid.
- Assert(IC.getPredicate() >= CmpInst::FIRST_ICMP_PREDICATE &&
- IC.getPredicate() <= CmpInst::LAST_ICMP_PREDICATE,
+ Assert(IC.isIntPredicate(),
"Invalid predicate in ICmp instruction!", &IC);
visitInstruction(IC);
@@ -2933,8 +2968,7 @@ void Verifier::visitFCmpInst(FCmpInst &FC) {
Assert(Op0Ty->isFPOrFPVectorTy(),
"Invalid operand types for FCmp instruction", &FC);
// Check that the predicate is valid.
- Assert(FC.getPredicate() >= CmpInst::FIRST_FCMP_PREDICATE &&
- FC.getPredicate() <= CmpInst::LAST_FCMP_PREDICATE,
+ Assert(FC.isFPPredicate(),
"Invalid predicate in FCmp instruction!", &FC);
visitInstruction(FC);
@@ -2972,7 +3006,7 @@ void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) {
GetElementPtrInst::getIndexedType(GEP.getSourceElementType(), Idxs);
Assert(ElTy, "Invalid indices for GEP pointer type!", &GEP);
- Assert(GEP.getType()->getScalarType()->isPointerTy() &&
+ Assert(GEP.getType()->isPtrOrPtrVectorTy() &&
GEP.getResultElementType() == ElTy,
"GEP is not of right type for indices!", &GEP, ElTy);
@@ -2988,7 +3022,7 @@ void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) {
unsigned IndexWidth = IndexTy->getVectorNumElements();
Assert(IndexWidth == GEPWidth, "Invalid GEP index vector width", &GEP);
}
- Assert(IndexTy->getScalarType()->isIntegerTy(),
+ Assert(IndexTy->isIntOrIntVectorTy(),
"All GEP indices should be of integer type");
}
}
@@ -3074,7 +3108,7 @@ void Verifier::visitLoadInst(LoadInst &LI) {
ElTy, &LI);
checkAtomicMemAccessSize(ElTy, &LI);
} else {
- Assert(LI.getSynchScope() == CrossThread,
+ Assert(LI.getSyncScopeID() == SyncScope::System,
"Non-atomic load cannot have SynchronizationScope specified", &LI);
}
@@ -3103,7 +3137,7 @@ void Verifier::visitStoreInst(StoreInst &SI) {
ElTy, &SI);
checkAtomicMemAccessSize(ElTy, &SI);
} else {
- Assert(SI.getSynchScope() == CrossThread,
+ Assert(SI.getSyncScopeID() == SyncScope::System,
"Non-atomic store cannot have SynchronizationScope specified", &SI);
}
visitInstruction(SI);
@@ -3116,7 +3150,7 @@ void Verifier::verifySwiftErrorCallSite(CallSite CS,
for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
I != E; ++I, ++Idx) {
if (*I == SwiftErrorVal) {
- Assert(CS.paramHasAttr(Idx+1, Attribute::SwiftError),
+ Assert(CS.paramHasAttr(Idx, Attribute::SwiftError),
"swifterror value when used in a callsite should be marked "
"with swifterror attribute",
SwiftErrorVal, CS);
@@ -3148,8 +3182,9 @@ void Verifier::verifySwiftErrorValue(const Value *SwiftErrorVal) {
void Verifier::visitAllocaInst(AllocaInst &AI) {
SmallPtrSet<Type*, 4> Visited;
PointerType *PTy = AI.getType();
- Assert(PTy->getAddressSpace() == 0,
- "Allocation instruction pointer not in the generic address space!",
+ // TODO: Relax this restriction?
+ Assert(PTy->getAddressSpace() == DL.getAllocaAddrSpace(),
+ "Allocation instruction pointer not in the stack address space!",
&AI);
Assert(AI.getAllocatedType()->isSized(&Visited),
"Cannot allocate unsized type", &AI);
@@ -3901,7 +3936,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
// If the intrinsic takes MDNode arguments, verify that they are either global
// or are local to *this* function.
- for (Value *V : CS.args())
+ for (Value *V : CS.args())
if (auto *MD = dyn_cast<MetadataAsValue>(V))
visitMetadataAsValue(*MD, CS.getCaller());
@@ -3929,6 +3964,26 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
"constant int",
CS);
break;
+ case Intrinsic::experimental_constrained_fadd:
+ case Intrinsic::experimental_constrained_fsub:
+ case Intrinsic::experimental_constrained_fmul:
+ case Intrinsic::experimental_constrained_fdiv:
+ case Intrinsic::experimental_constrained_frem:
+ case Intrinsic::experimental_constrained_sqrt:
+ case Intrinsic::experimental_constrained_pow:
+ case Intrinsic::experimental_constrained_powi:
+ case Intrinsic::experimental_constrained_sin:
+ case Intrinsic::experimental_constrained_cos:
+ case Intrinsic::experimental_constrained_exp:
+ case Intrinsic::experimental_constrained_exp2:
+ case Intrinsic::experimental_constrained_log:
+ case Intrinsic::experimental_constrained_log10:
+ case Intrinsic::experimental_constrained_log2:
+ case Intrinsic::experimental_constrained_rint:
+ case Intrinsic::experimental_constrained_nearbyint:
+ visitConstrainedFPIntrinsic(
+ cast<ConstrainedFPIntrinsic>(*CS.getInstruction()));
+ break;
case Intrinsic::dbg_declare: // llvm.dbg.declare
Assert(isa<MetadataAsValue>(CS.getArgOperand(0)),
"invalid llvm.dbg.declare intrinsic call 1", CS);
@@ -3952,10 +4007,16 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
CS);
break;
}
- case Intrinsic::memcpy_element_atomic: {
- ConstantInt *ElementSizeCI = dyn_cast<ConstantInt>(CS.getArgOperand(3));
- Assert(ElementSizeCI, "element size of the element-wise atomic memory "
- "intrinsic must be a constant int",
+ case Intrinsic::memcpy_element_unordered_atomic: {
+ const ElementUnorderedAtomicMemCpyInst *MI =
+ cast<ElementUnorderedAtomicMemCpyInst>(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(),
@@ -3963,19 +4024,91 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
"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);
};
-
- uint64_t DstAlignment = CS.getParamAlignment(1),
- SrcAlignment = CS.getParamAlignment(2);
-
+ uint64_t DstAlignment = CS.getParamAlignment(0),
+ SrcAlignment = CS.getParamAlignment(1);
Assert(IsValidAlignment(DstAlignment),
- "incorrect alignment of the destination argument",
+ "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<ElementUnorderedAtomicMemMoveInst>(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);
+ };
+ 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",
+ "incorrect alignment of the source argument", CS);
+ break;
+ }
+ case Intrinsic::memset_element_unordered_atomic: {
+ auto *MI = cast<ElementUnorderedAtomicMemSetInst>(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);
+ };
+ uint64_t DstAlignment = CS.getParamAlignment(0);
+ Assert(IsValidAlignment(DstAlignment),
+ "incorrect alignment of the destination argument", CS);
break;
}
case Intrinsic::gcroot:
@@ -4182,7 +4315,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
// relocated pointer. It can be casted to the correct type later if it's
// desired. However, they must have the same address space and 'vectorness'
GCRelocateInst &Relocate = cast<GCRelocateInst>(*CS.getInstruction());
- Assert(Relocate.getDerivedPtr()->getType()->getScalarType()->isPointerTy(),
+ Assert(Relocate.getDerivedPtr()->getType()->isPtrOrPtrVectorTy(),
"gc.relocate: relocated value must be a gc pointer", CS);
auto ResultType = CS.getType();
@@ -4205,7 +4338,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
}
case Intrinsic::masked_load: {
Assert(CS.getType()->isVectorTy(), "masked_load: must return a vector", CS);
-
+
Value *Ptr = CS.getArgOperand(0);
//Value *Alignment = CS.getArgOperand(1);
Value *Mask = CS.getArgOperand(2);
@@ -4215,12 +4348,12 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
// DataTy is the overloaded type
Type *DataTy = cast<PointerType>(Ptr->getType())->getElementType();
- Assert(DataTy == CS.getType(),
+ Assert(DataTy == CS.getType(),
"masked_load: return must match pointer type", CS);
Assert(PassThru->getType() == DataTy,
"masked_load: pass through and data type must match", CS);
Assert(Mask->getType()->getVectorNumElements() ==
- DataTy->getVectorNumElements(),
+ DataTy->getVectorNumElements(),
"masked_load: vector mask must be same length as data", CS);
break;
}
@@ -4234,10 +4367,10 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
// DataTy is the overloaded type
Type *DataTy = cast<PointerType>(Ptr->getType())->getElementType();
- Assert(DataTy == Val->getType(),
+ Assert(DataTy == Val->getType(),
"masked_store: storee must match pointer type", CS);
Assert(Mask->getType()->getVectorNumElements() ==
- DataTy->getVectorNumElements(),
+ DataTy->getVectorNumElements(),
"masked_store: vector mask must be same length as data", CS);
break;
}
@@ -4294,6 +4427,20 @@ static DISubprogram *getSubprogram(Metadata *LocalScope) {
return nullptr;
}
+void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) {
+ unsigned NumOperands = FPI.getNumArgOperands();
+ Assert(((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)),
+ "invalid rounding mode argument", &FPI);
+ Assert(FPI.getRoundingMode() != ConstrainedFPIntrinsic::rmInvalid,
+ "invalid rounding mode argument", &FPI);
+ Assert(FPI.getExceptionBehavior() != ConstrainedFPIntrinsic::ebInvalid,
+ "invalid exception behavior argument", &FPI);
+}
+
template <class DbgIntrinsicTy>
void Verifier::visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII) {
auto *MD = cast<MetadataAsValue>(DII.getArgOperand(0))->getMetadata();
@@ -4330,6 +4477,8 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII) {
" variable and !dbg attachment",
&DII, BB, F, Var, Var->getScope()->getSubprogram(), Loc,
Loc->getScope()->getSubprogram());
+
+ verifyFnArgs(DII);
}
static uint64_t getVariableSize(const DILocalVariable &V) {
@@ -4398,15 +4547,49 @@ void Verifier::verifyFragmentExpression(const DbgInfoIntrinsic &I) {
AssertDI(FragSize != VarSize, "fragment covers entire variable", &I, V, E);
}
+void Verifier::verifyFnArgs(const DbgInfoIntrinsic &I) {
+ // This function does not take the scope of noninlined function arguments into
+ // account. Don't run it if current function is nodebug, because it may
+ // contain inlined debug intrinsics.
+ 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();
+ }
+ AssertDI(Var, "dbg intrinsic without variable");
+
+ unsigned ArgNo = Var->getArg();
+ if (!ArgNo)
+ return;
+
+ // Verify there are no duplicate function argument debug info entries.
+ // These will cause hard-to-debug assertions in the DWARF backend.
+ if (DebugFnArgs.size() < ArgNo)
+ DebugFnArgs.resize(ArgNo, nullptr);
+
+ auto *Prev = DebugFnArgs[ArgNo - 1];
+ DebugFnArgs[ArgNo - 1] = Var;
+ AssertDI(!Prev || (Prev == Var), "conflicting debug info for argument", &I,
+ Prev, Var);
+}
+
void Verifier::verifyCompileUnits() {
auto *CUs = M.getNamedMetadata("llvm.dbg.cu");
SmallPtrSet<const Metadata *, 2> Listed;
if (CUs)
Listed.insert(CUs->op_begin(), CUs->op_end());
- AssertDI(
- all_of(CUVisited,
- [&Listed](const Metadata *CU) { return Listed.count(CU); }),
- "All DICompileUnits must be listed in llvm.dbg.cu");
+ for (auto *CU : CUVisited)
+ AssertDI(Listed.count(CU), "DICompileUnit not listed in llvm.dbg.cu", CU);
CUVisited.clear();
}
OpenPOWER on IntegriCloud