diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AsmParser/LLLexer.cpp | 1 | ||||
-rw-r--r-- | lib/AsmParser/LLParser.cpp | 3 | ||||
-rw-r--r-- | lib/AsmParser/LLToken.h | 1 | ||||
-rw-r--r-- | lib/Bitcode/Reader/BitcodeReader.cpp | 2 | ||||
-rw-r--r-- | lib/Bitcode/Writer/BitcodeWriter.cpp | 2 | ||||
-rw-r--r-- | lib/IR/Attributes.cpp | 6 | ||||
-rw-r--r-- | lib/IR/Function.cpp | 8 | ||||
-rw-r--r-- | lib/IR/Verifier.cpp | 78 | ||||
-rw-r--r-- | lib/Target/CppBackend/CPPBackend.cpp | 1 |
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); |