summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AsmParser/LLLexer.cpp1
-rw-r--r--lib/AsmParser/LLParser.cpp3
-rw-r--r--lib/AsmParser/LLToken.h1
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp2
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp2
-rw-r--r--lib/IR/Attributes.cpp6
-rw-r--r--lib/IR/Function.cpp8
-rw-r--r--lib/IR/Verifier.cpp78
-rw-r--r--lib/Target/CppBackend/CPPBackend.cpp1
9 files changed, 76 insertions, 26 deletions
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp
index 3c384f5fcc..1b32047e4b 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/lib/AsmParser/LLLexer.cpp
@@ -572,6 +572,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(alwaysinline);
KEYWORD(builtin);
KEYWORD(byval);
+ KEYWORD(inalloca);
KEYWORD(cold);
KEYWORD(inlinehint);
KEYWORD(inreg);
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index 3b903cdb09..a5b2aa586e 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -944,6 +944,7 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B,
"invalid use of attribute on a function");
break;
case lltok::kw_byval:
+ case lltok::kw_inalloca:
case lltok::kw_nest:
case lltok::kw_noalias:
case lltok::kw_nocapture:
@@ -1156,6 +1157,7 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) {
continue;
}
case lltok::kw_byval: B.addAttribute(Attribute::ByVal); break;
+ case lltok::kw_inalloca: B.addAttribute(Attribute::InAlloca); break;
case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break;
case lltok::kw_nest: B.addAttribute(Attribute::Nest); break;
case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break;
@@ -1218,6 +1220,7 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) {
// Error handling.
case lltok::kw_align:
case lltok::kw_byval:
+ case lltok::kw_inalloca:
case lltok::kw_nest:
case lltok::kw_nocapture:
case lltok::kw_returned:
diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h
index 786d84d766..5a6866dd14 100644
--- a/lib/AsmParser/LLToken.h
+++ b/lib/AsmParser/LLToken.h
@@ -99,6 +99,7 @@ namespace lltok {
kw_sanitize_address,
kw_builtin,
kw_byval,
+ kw_inalloca,
kw_cold,
kw_inlinehint,
kw_inreg,
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index ce3b7d163e..37515eb6f2 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -522,6 +522,8 @@ static Attribute::AttrKind GetAttrFromCode(uint64_t Code) {
return Attribute::Builtin;
case bitc::ATTR_KIND_BY_VAL:
return Attribute::ByVal;
+ case bitc::ATTR_KIND_IN_ALLOCA:
+ return Attribute::InAlloca;
case bitc::ATTR_KIND_COLD:
return Attribute::Cold;
case bitc::ATTR_KIND_INLINE_HINT:
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index caa9e56263..be19b781d4 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -169,6 +169,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
return bitc::ATTR_KIND_BUILTIN;
case Attribute::ByVal:
return bitc::ATTR_KIND_BY_VAL;
+ case Attribute::InAlloca:
+ return bitc::ATTR_KIND_IN_ALLOCA;
case Attribute::Cold:
return bitc::ATTR_KIND_COLD;
case Attribute::InlineHint:
diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp
index 0f2b7a0ebb..9d9d948527 100644
--- a/lib/IR/Attributes.cpp
+++ b/lib/IR/Attributes.cpp
@@ -166,6 +166,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "builtin";
if (hasAttribute(Attribute::ByVal))
return "byval";
+ if (hasAttribute(Attribute::InAlloca))
+ return "inalloca";
if (hasAttribute(Attribute::InlineHint))
return "inlinehint";
if (hasAttribute(Attribute::InReg))
@@ -388,6 +390,7 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {
case Attribute::Cold: return 1ULL << 40;
case Attribute::Builtin: return 1ULL << 41;
case Attribute::OptimizeNone: return 1ULL << 42;
+ case Attribute::InAlloca: return 1ULL << 43;
}
llvm_unreachable("Unsupported attribute type");
}
@@ -1174,7 +1177,8 @@ AttributeSet AttributeFuncs::typeIncompatible(Type *Ty, uint64_t Index) {
.addAttribute(Attribute::NoCapture)
.addAttribute(Attribute::ReadNone)
.addAttribute(Attribute::ReadOnly)
- .addAttribute(Attribute::StructRet);
+ .addAttribute(Attribute::StructRet)
+ .addAttribute(Attribute::InAlloca);
return AttributeSet::get(Ty->getContext(), Index, Incompatible);
}
diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp
index e8a2402b3d..970bbaeed8 100644
--- a/lib/IR/Function.cpp
+++ b/lib/IR/Function.cpp
@@ -84,6 +84,14 @@ bool Argument::hasByValAttr() const {
hasAttribute(getArgNo()+1, Attribute::ByVal);
}
+/// \brief Return true if this argument has the inalloca attribute on it in
+/// its containing function.
+bool Argument::hasInAllocaAttr() const {
+ if (!getType()->isPointerTy()) return false;
+ return getParent()->getAttributes().
+ hasAttribute(getArgNo()+1, Attribute::InAlloca);
+}
+
unsigned Argument::getParamAlignment() const {
assert(getType()->isPointerTy() && "Only pointers have alignments");
return getParent()->getParamAlignment(getArgNo()+1);
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);
}
diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp
index 07a9db35a1..c290f70e9e 100644
--- a/lib/Target/CppBackend/CPPBackend.cpp
+++ b/lib/Target/CppBackend/CPPBackend.cpp
@@ -491,6 +491,7 @@ void CppWriter::printAttributes(const AttributeSet &PAL,
HANDLE_ATTR(NoUnwind);
HANDLE_ATTR(NoAlias);
HANDLE_ATTR(ByVal);
+ HANDLE_ATTR(InAlloca);
HANDLE_ATTR(Nest);
HANDLE_ATTR(ReadNone);
HANDLE_ATTR(ReadOnly);