This patch addresses two cleanup issues:

1. Verify::VerifyParameterAttrs in "lib/IR/Verifier.cpp" and
   AttrBuilder::removeFunctionOnlyAttrs in "lib/IR/Attributes.cpp" (only called
   by Verify::VerifyFunctionAttrs) separately maintained a list of function-only
   attribute types. I've consolidated the logic into a new function used for
   both cases in "lib/IR/Verifier.cpp", so this logic is in one place (other
   than the AsmParser front-end)

2. Various functions in "lib/IR/Verifier.cpp" passed AttributeSet around by
   reference needlessly, as it's just a handle to an immutable pimpl body.

Patch by Stephen Lin!


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179790 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bill Wendling 2013-04-18 20:15:25 +00:00
parent 4b15d6ae49
commit bb1b63c483
3 changed files with 71 additions and 111 deletions

View File

@ -474,9 +474,6 @@ public:
bool td_empty() const { return TargetDepAttrs.empty(); }
/// \brief Remove attributes that are used on functions only.
void removeFunctionOnlyAttrs();
bool operator==(const AttrBuilder &B);
bool operator!=(const AttrBuilder &B) {
return !(*this == B);

View File

@ -1115,33 +1115,6 @@ bool AttrBuilder::operator==(const AttrBuilder &B) {
return Alignment == B.Alignment && StackAlignment == B.StackAlignment;
}
void AttrBuilder::removeFunctionOnlyAttrs() {
removeAttribute(Attribute::NoReturn)
.removeAttribute(Attribute::NoUnwind)
.removeAttribute(Attribute::ReadNone)
.removeAttribute(Attribute::ReadOnly)
.removeAttribute(Attribute::NoInline)
.removeAttribute(Attribute::AlwaysInline)
.removeAttribute(Attribute::OptimizeForSize)
.removeAttribute(Attribute::StackProtect)
.removeAttribute(Attribute::StackProtectReq)
.removeAttribute(Attribute::StackProtectStrong)
.removeAttribute(Attribute::NoRedZone)
.removeAttribute(Attribute::NoImplicitFloat)
.removeAttribute(Attribute::Naked)
.removeAttribute(Attribute::InlineHint)
.removeAttribute(Attribute::StackAlignment)
.removeAttribute(Attribute::UWTable)
.removeAttribute(Attribute::NonLazyBind)
.removeAttribute(Attribute::ReturnsTwice)
.removeAttribute(Attribute::SanitizeAddress)
.removeAttribute(Attribute::SanitizeThread)
.removeAttribute(Attribute::SanitizeMemory)
.removeAttribute(Attribute::MinSize)
.removeAttribute(Attribute::NoDuplicate)
.removeAttribute(Attribute::NoBuiltin);
}
AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) {
// FIXME: Remove this in 4.0.
if (!Val) return *this;

View File

@ -301,9 +301,12 @@ namespace {
bool VerifyIntrinsicType(Type *Ty,
ArrayRef<Intrinsic::IITDescriptor> &Infos,
SmallVectorImpl<Type*> &ArgTys);
void VerifyParameterAttrs(AttributeSet Attrs, uint64_t Idx, Type *Ty,
bool VerifyAttributeCount(AttributeSet Attrs, unsigned Params);
void VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx,
bool isFunction, const Value *V);
void VerifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty,
bool isReturnValue, const Value *V);
void VerifyFunctionAttrs(FunctionType *FT, const AttributeSet &Attrs,
void VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs,
const Value *V);
void WriteValue(const Value *V) {
@ -626,37 +629,66 @@ void Verifier::visitModuleFlag(MDNode *Op, DenseMap<MDString*, MDNode*>&SeenIDs,
}
}
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;
}
assert(Slot != ~0U && "Attribute set inconsistency!");
for (AttributeSet::iterator I = Attrs.begin(Slot), E = Attrs.end(Slot);
I != E; ++I) {
if (I->isStringAttribute())
continue;
if (I->getKindAsEnum() == Attribute::NoReturn ||
I->getKindAsEnum() == Attribute::NoUnwind ||
I->getKindAsEnum() == Attribute::ReadNone ||
I->getKindAsEnum() == Attribute::ReadOnly ||
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::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::NoBuiltin) {
if (!isFunction)
CheckFailed("Attribute '" + I->getKindAsString() +
"' only applies to functions!", V);
return;
} else if (isFunction) {
CheckFailed("Attribute '" + I->getKindAsString() +
"' does not apply to functions!", V);
return;
}
}
}
// 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, uint64_t Idx, Type *Ty,
void Verifier::VerifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty,
bool isReturnValue, const Value *V) {
if (!Attrs.hasAttributes(Idx))
return;
Assert1(!Attrs.hasAttribute(Idx, Attribute::NoReturn) &&
!Attrs.hasAttribute(Idx, Attribute::NoUnwind) &&
!Attrs.hasAttribute(Idx, Attribute::ReadNone) &&
!Attrs.hasAttribute(Idx, Attribute::ReadOnly) &&
!Attrs.hasAttribute(Idx, Attribute::NoInline) &&
!Attrs.hasAttribute(Idx, Attribute::AlwaysInline) &&
!Attrs.hasAttribute(Idx, Attribute::OptimizeForSize) &&
!Attrs.hasAttribute(Idx, Attribute::StackProtect) &&
!Attrs.hasAttribute(Idx, Attribute::StackProtectReq) &&
!Attrs.hasAttribute(Idx, Attribute::NoRedZone) &&
!Attrs.hasAttribute(Idx, Attribute::NoImplicitFloat) &&
!Attrs.hasAttribute(Idx, Attribute::Naked) &&
!Attrs.hasAttribute(Idx, Attribute::InlineHint) &&
!Attrs.hasAttribute(Idx, Attribute::StackAlignment) &&
!Attrs.hasAttribute(Idx, Attribute::UWTable) &&
!Attrs.hasAttribute(Idx, Attribute::NonLazyBind) &&
!Attrs.hasAttribute(Idx, Attribute::ReturnsTwice) &&
!Attrs.hasAttribute(Idx, Attribute::SanitizeAddress) &&
!Attrs.hasAttribute(Idx, Attribute::SanitizeThread) &&
!Attrs.hasAttribute(Idx, Attribute::SanitizeMemory) &&
!Attrs.hasAttribute(Idx, Attribute::MinSize) &&
!Attrs.hasAttribute(Idx, Attribute::NoBuiltin),
"Some attributes in '" + Attrs.getAsString(Idx) +
"' only apply to functions!", V);
VerifyAttributeTypes(Attrs, Idx, false, V);
if (isReturnValue)
Assert1(!Attrs.hasAttribute(Idx, Attribute::ByVal) &&
@ -712,8 +744,7 @@ void Verifier::VerifyParameterAttrs(AttributeSet Attrs, uint64_t Idx, Type *Ty,
// VerifyFunctionAttrs - Check parameter attributes against a function type.
// The value V is printed in error messages.
void Verifier::VerifyFunctionAttrs(FunctionType *FT,
const AttributeSet &Attrs,
void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs,
const Value *V) {
if (Attrs.isEmpty())
return;
@ -721,72 +752,31 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT,
bool SawNest = false;
for (unsigned i = 0, e = Attrs.getNumSlots(); i != e; ++i) {
unsigned Index = Attrs.getSlotIndex(i);
unsigned Idx = Attrs.getSlotIndex(i);
Type *Ty;
if (Index == 0)
if (Idx == 0)
Ty = FT->getReturnType();
else if (Index-1 < FT->getNumParams())
Ty = FT->getParamType(Index-1);
else if (Idx-1 < FT->getNumParams())
Ty = FT->getParamType(Idx-1);
else
break; // VarArgs attributes, verified elsewhere.
VerifyParameterAttrs(Attrs, Index, Ty, Index == 0, V);
VerifyParameterAttrs(Attrs, Idx, Ty, Idx == 0, V);
if (Attrs.hasAttribute(i, Attribute::Nest)) {
Assert1(!SawNest, "More than one parameter has attribute nest!", V);
SawNest = true;
}
if (Attrs.hasAttribute(Index, Attribute::StructRet))
Assert1(Index == 1, "Attribute sret is not on first parameter!", V);
if (Attrs.hasAttribute(Idx, Attribute::StructRet))
Assert1(Idx == 1, "Attribute sret is not on first parameter!", V);
}
if (!Attrs.hasAttributes(AttributeSet::FunctionIndex))
return;
AttrBuilder NotFn(Attrs, AttributeSet::FunctionIndex);
NotFn.removeFunctionOnlyAttrs();
Assert1(NotFn.empty(), "Attributes '" +
AttributeSet::get(V->getContext(),
AttributeSet::FunctionIndex,
NotFn).getAsString(AttributeSet::FunctionIndex) +
"' do not apply to the function!", V);
// Check for mutually incompatible attributes.
Assert1(!((Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::ByVal) &&
Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::Nest)) ||
(Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::ByVal) &&
Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::StructRet)) ||
(Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::Nest) &&
Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::StructRet))),
"Attributes 'byval, nest, and sret' are incompatible!", V);
Assert1(!((Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::ByVal) &&
Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::Nest)) ||
(Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::ByVal) &&
Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::InReg)) ||
(Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::Nest) &&
Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::InReg))),
"Attributes 'byval, nest, and inreg' are incompatible!", V);
Assert1(!(Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::ZExt) &&
Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::SExt)),
"Attributes 'zeroext and signext' are incompatible!", V);
VerifyAttributeTypes(Attrs, AttributeSet::FunctionIndex, true, V);
Assert1(!(Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::ReadNone) &&
@ -801,7 +791,7 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT,
"Attributes 'noinline and alwaysinline' are incompatible!", V);
}
static bool VerifyAttributeCount(const AttributeSet &Attrs, unsigned Params) {
bool Verifier::VerifyAttributeCount(AttributeSet Attrs, unsigned Params) {
if (Attrs.getNumSlots() == 0)
return true;
@ -837,7 +827,7 @@ void Verifier::visitFunction(Function &F) {
Assert1(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy(),
"Invalid struct return type!", &F);
const AttributeSet &Attrs = F.getAttributes();
AttributeSet Attrs = F.getAttributes();
Assert1(VerifyAttributeCount(Attrs, FT->getNumParams()),
"Attribute after last parameter!", &F);
@ -1350,7 +1340,7 @@ void Verifier::VerifyCallSite(CallSite CS) {
"Call parameter type does not match function signature!",
CS.getArgument(i), FTy->getParamType(i), I);
const AttributeSet &Attrs = CS.getAttributes();
AttributeSet Attrs = CS.getAttributes();
Assert1(VerifyAttributeCount(Attrs, CS.arg_size()),
"Attribute after last parameter!", I);