1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

Simplify some Verifier attribute checks with AttributeSet

Now that we have a type that can represent the attributes on a single
return, function, or parameter, we can pass it around directly rather
than passing around AttributeList and Idx. Removes some more one-based
argument attribute index counting.

NFC

llvm-svn: 300285
This commit is contained in:
Reid Kleckner 2017-04-14 00:06:06 +00:00
parent 2271480dbe
commit e796a4cc81
2 changed files with 176 additions and 189 deletions

View File

@ -242,7 +242,7 @@ public:
uint64_t getDereferenceableBytes() const;
uint64_t getDereferenceableOrNullBytes() const;
std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
std::string getAsString(bool InAttrGrp) const;
std::string getAsString(bool InAttrGrp = false) const;
typedef const Attribute *iterator;
iterator begin() const;

View File

@ -490,10 +490,9 @@ private:
bool performTypeCheck(Intrinsic::ID ID, Function *F, Type *Ty, int VT,
unsigned ArgNo, std::string &Suffix);
bool verifyAttributeCount(AttributeList Attrs, unsigned Params);
void verifyAttributeTypes(AttributeList Attrs, unsigned Idx, bool isFunction,
void verifyAttributeTypes(AttributeSet Attrs, bool IsFunction,
const Value *V);
void verifyParameterAttrs(AttributeList Attrs, unsigned Idx, Type *Ty,
bool isReturnValue, const Value *V);
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);
@ -1309,71 +1308,73 @@ Verifier::visitModuleFlag(const MDNode *Op,
}
}
void Verifier::verifyAttributeTypes(AttributeList 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;
}
/// 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:
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 (AttributeList::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);
if (isFuncOnlyAttr(A.getKindAsEnum())) {
if (!IsFunction) {
CheckFailed("Attribute '" + A.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");
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;
}
}
@ -1381,106 +1382,91 @@ void Verifier::verifyAttributeTypes(AttributeList 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(AttributeList 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: " +
AttributeList::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);
@ -1500,123 +1486,122 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs,
bool SawSwiftSelf = false;
bool SawSwiftError = false;
for (unsigned i = 0, e = Attrs.getNumSlots(); i != e; ++i) {
unsigned Idx = Attrs.getSlotIndex(i);
// 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);
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 parameter attributes.
for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
Type *Ty = FT->getParamType(i);
AttributeSet ArgAttrs = Attrs.getParamAttributes(i);
verifyParameterAttrs(Attrs, Idx, Ty, Idx == 0, V);
verifyParameterAttrs(ArgAttrs, Ty, V);
if (Idx == 0)
continue;
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(AttributeList::FunctionIndex))
return;
verifyAttributeTypes(Attrs, AttributeList::FunctionIndex, true, V);
verifyAttributeTypes(Attrs.getFnAttributes(), /*IsFunction=*/true, V);
Assert(
!(Attrs.hasAttribute(AttributeList::FunctionIndex, Attribute::ReadNone) &&
Attrs.hasAttribute(AttributeList::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(AttributeList::FunctionIndex, Attribute::ReadNone) &&
Attrs.hasAttribute(AttributeList::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(AttributeList::FunctionIndex, Attribute::ReadOnly) &&
Attrs.hasAttribute(AttributeList::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(AttributeList::FunctionIndex, Attribute::ReadNone) &&
Attrs.hasAttribute(AttributeList::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(AttributeList::FunctionIndex, Attribute::ReadNone) &&
Attrs.hasAttribute(AttributeList::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(AttributeList::FunctionIndex, Attribute::NoInline) &&
Attrs.hasAttribute(AttributeList::FunctionIndex,
Attribute::AlwaysInline)),
"Attributes 'noinline and alwaysinline' are incompatible!", V);
Assert(!(Attrs.hasFnAttribute(Attribute::NoInline) &&
Attrs.hasFnAttribute(Attribute::AlwaysInline)),
"Attributes 'noinline and alwaysinline' are incompatible!", V);
if (Attrs.hasAttribute(AttributeList::FunctionIndex,
Attribute::OptimizeNone)) {
Assert(
Attrs.hasAttribute(AttributeList::FunctionIndex, Attribute::NoInline),
"Attribute 'optnone' requires 'noinline'!", V);
if (Attrs.hasFnAttribute(Attribute::OptimizeNone)) {
Assert(Attrs.hasFnAttribute(Attribute::NoInline),
"Attribute 'optnone' requires 'noinline'!", V);
Assert(!Attrs.hasAttribute(AttributeList::FunctionIndex,
Attribute::OptimizeForSize),
Assert(!Attrs.hasFnAttribute(Attribute::OptimizeForSize),
"Attributes 'optsize and optnone' are incompatible!", V);
Assert(
!Attrs.hasAttribute(AttributeList::FunctionIndex, Attribute::MinSize),
"Attributes 'minsize and optnone' are incompatible!", V);
Assert(!Attrs.hasFnAttribute(Attribute::MinSize),
"Attributes 'minsize and optnone' are incompatible!", V);
}
if (Attrs.hasAttribute(AttributeList::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(AttributeList::FunctionIndex, Attribute::AllocSize)) {
if (Attrs.hasFnAttribute(Attribute::AllocSize)) {
std::pair<unsigned, Optional<unsigned>> Args =
Attrs.getAllocSizeArgs(AttributeList::FunctionIndex);
@ -1974,7 +1959,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(AttributeList::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.
@ -2652,24 +2637,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()),
@ -2679,11 +2665,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);
}
}