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.cpp78
1 files changed, 53 insertions, 25 deletions
diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp
index febd29f072..35b786ecf2 100644
--- a/lib/IR/Verifier.cpp
+++ b/lib/IR/Verifier.cpp
@@ -813,26 +813,25 @@ void Verifier::VerifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty,
!Attrs.hasAttribute(Idx, Attribute::Nest) &&
!Attrs.hasAttribute(Idx, Attribute::StructRet) &&
!Attrs.hasAttribute(Idx, Attribute::NoCapture) &&
- !Attrs.hasAttribute(Idx, Attribute::Returned),
- "Attribute 'byval', 'nest', 'sret', 'nocapture', and 'returned' "
- "do not apply to return values!", V);
-
- // Check for mutually incompatible attributes.
- Assert1(!((Attrs.hasAttribute(Idx, Attribute::ByVal) &&
- Attrs.hasAttribute(Idx, Attribute::Nest)) ||
- (Attrs.hasAttribute(Idx, Attribute::ByVal) &&
- Attrs.hasAttribute(Idx, Attribute::StructRet)) ||
- (Attrs.hasAttribute(Idx, Attribute::Nest) &&
- Attrs.hasAttribute(Idx, Attribute::StructRet))), "Attributes "
- "'byval, nest, and sret' are incompatible!", V);
-
- Assert1(!((Attrs.hasAttribute(Idx, Attribute::ByVal) &&
- Attrs.hasAttribute(Idx, Attribute::Nest)) ||
- (Attrs.hasAttribute(Idx, Attribute::ByVal) &&
- Attrs.hasAttribute(Idx, Attribute::InReg)) ||
- (Attrs.hasAttribute(Idx, Attribute::Nest) &&
- Attrs.hasAttribute(Idx, Attribute::InReg))), "Attributes "
- "'byval, nest, and inreg' are incompatible!", V);
+ !Attrs.hasAttribute(Idx, Attribute::Returned) &&
+ !Attrs.hasAttribute(Idx, Attribute::InAlloca),
+ "Attributes 'byval', 'inalloca', 'nest', 'sret', 'nocapture', and "
+ "'returned' do not apply to return values!", 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);
+ Assert1(AttrCount <= 1, "Attributes 'byval', 'inalloca', 'inreg', 'nest', "
+ "and 'sret' are incompatible!", V);
+
+ Assert1(!(Attrs.hasAttribute(Idx, Attribute::InAlloca) &&
+ Attrs.hasAttribute(Idx, Attribute::ReadOnly)), "Attributes "
+ "'inalloca and readonly' are incompatible!", V);
Assert1(!(Attrs.hasAttribute(Idx, Attribute::StructRet) &&
Attrs.hasAttribute(Idx, Attribute::Returned)), "Attributes "
@@ -855,14 +854,18 @@ void Verifier::VerifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty,
"Wrong types for attribute: " +
AttributeFuncs::typeIncompatible(Ty, Idx).getAsString(Idx), V);
- if (PointerType *PTy = dyn_cast<PointerType>(Ty))
- Assert1(!Attrs.hasAttribute(Idx, Attribute::ByVal) ||
- PTy->getElementType()->isSized(),
- "Attribute 'byval' does not support unsized types!", V);
- else
+ if (PointerType *PTy = dyn_cast<PointerType>(Ty)) {
+ if (!PTy->getElementType()->isSized()) {
+ Assert1(!Attrs.hasAttribute(Idx, Attribute::ByVal) &&
+ !Attrs.hasAttribute(Idx, Attribute::InAlloca),
+ "Attributes 'byval' and 'inalloca' do not support unsized types!",
+ V);
+ }
+ } else {
Assert1(!Attrs.hasAttribute(Idx, Attribute::ByVal),
"Attribute 'byval' only applies to parameters with pointer type!",
V);
+ }
}
// VerifyFunctionAttrs - Check parameter attributes against a function type.
@@ -1533,6 +1536,15 @@ void Verifier::VerifyCallSite(CallSite CS) {
// Verify call attributes.
VerifyFunctionAttrs(FTy, Attrs, I);
+ // Verify that values used for inalloca parameters are in fact allocas.
+ for (unsigned i = 0, e = CS.arg_size(); i != e; ++i) {
+ if (!Attrs.hasAttribute(1 + i, Attribute::InAlloca))
+ continue;
+ Value *Arg = CS.getArgument(i);
+ Assert2(isa<AllocaInst>(Arg), "Inalloca argument is not an alloca!", I,
+ Arg);
+ }
+
if (FTy->isVarArg()) {
// FIXME? is 'nest' even legal here?
bool SawNest = false;
@@ -1870,6 +1882,22 @@ void Verifier::visitAllocaInst(AllocaInst &AI) {
&AI);
Assert1(AI.getArraySize()->getType()->isIntegerTy(),
"Alloca array size must have integer type", &AI);
+
+ // Verify that an alloca instruction is not used with inalloca more than once.
+ unsigned InAllocaUses = 0;
+ for (User::use_iterator UI = AI.use_begin(), UE = AI.use_end(); UI != UE;
+ ++UI) {
+ CallSite CS(*UI);
+ if (!CS)
+ continue;
+ unsigned ArgNo = CS.getArgumentNo(UI);
+ if (CS.isInAllocaArgument(ArgNo)) {
+ InAllocaUses++;
+ Assert1(InAllocaUses <= 1,
+ "Allocas can be used at most once with inalloca!", &AI);
+ }
+ }
+
visitInstruction(AI);
}