From ee7970e77ea2553aa5cd1a26f40296f1b7cf4305 Mon Sep 17 00:00:00 2001 From: Vaivaswatha Nagaraj Date: Wed, 16 Dec 2015 16:16:19 +0000 Subject: [PATCH] Add InaccessibleMemOnly and inaccessibleMemOrArgMemOnly attributes Summary: This patch introduces two new function attributes InaccessibleMemOnly: This attribute indicates that the function may only access memory that is not accessible by the program/IR being compiled. This is a weaker form of ReadNone. inaccessibleMemOrArgMemOnly: This attribute indicates that the function may only access memory that is either not accessible by the program/IR being compiled, or is pointed to by its pointer arguments. This is a weaker form of ArgMemOnly Test cases have been updated. This revision uses this (https://github.com/llvm-mirror/llvm/commit/d001932f3a8aa1ebd1555162fdce365f011bc292) as reference. Reviewers: jmolloy, hfinkel Subscribers: reames, joker.eph, llvm-commits Differential Revision: http://reviews.llvm.org/D15499 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@255778 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LangRef.rst | 8 ++++++++ include/llvm/Bitcode/LLVMBitCodes.h | 4 +++- include/llvm/IR/Attributes.td | 7 +++++++ include/llvm/IR/Function.h | 20 ++++++++++++++++++++ lib/AsmParser/LLLexer.cpp | 2 ++ lib/AsmParser/LLParser.cpp | 4 ++++ lib/AsmParser/LLToken.h | 2 ++ lib/Bitcode/Reader/BitcodeReader.cpp | 4 ++++ lib/Bitcode/Writer/BitcodeWriter.cpp | 4 ++++ lib/IR/Attributes.cpp | 6 ++++++ lib/IR/Verifier.cpp | 16 +++++++++++++++- test/Bindings/llvm-c/Inputs/invalid.ll.bc | Bin 624 -> 688 bytes test/Bindings/llvm-c/invalid-bitcode.test | 2 +- test/Bitcode/attributes.ll | 16 ++++++++++++++-- test/Bitcode/compatibility.ll | 20 +++++++++++++------- test/Bitcode/invalid.ll | 2 +- test/Bitcode/invalid.ll.bc | Bin 624 -> 688 bytes test/LTO/X86/Inputs/invalid.ll.bc | Bin 624 -> 688 bytes test/LTO/X86/invalid.ll | 2 +- 19 files changed, 105 insertions(+), 14 deletions(-) diff --git a/docs/LangRef.rst b/docs/LangRef.rst index f8d87da7061..c968818acf2 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -1243,6 +1243,14 @@ example: thread execution pattern under certain parallel execution models. Transformations that are execution model agnostic may not make the execution of a convergent operation control dependent on any additional values. +``inaccessiblememonly`` + This attribute indicates that the function may only access memory that + is not accessible by the module being compiled. This is a weaker form + of ``readnone``. +``inaccessiblemem_or_argmemonly`` + This attribute indicates that the function may only access memory that is + either not accessible by the module being compiled, or is pointed to + by its pointer arguments. This is a weaker form of ``argmemonly`` ``inlinehint`` This attribute indicates that the source code contained a hint that inlining this function is desirable (such as the "inline" keyword in diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index 6780c8e6a97..bcc84bedbed 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -483,7 +483,9 @@ enum { BITCODE_CURRENT_EPOCH = 0 }; ATTR_KIND_ARGMEMONLY = 45, ATTR_KIND_SWIFT_SELF = 46, ATTR_KIND_SWIFT_ERROR = 47, - ATTR_KIND_NO_RECURSE = 48 + ATTR_KIND_NO_RECURSE = 48, + ATTR_KIND_INACCESSIBLEMEM_ONLY = 49, + ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEMONLY = 50 }; enum ComdatSelectionKindCodes { diff --git a/include/llvm/IR/Attributes.td b/include/llvm/IR/Attributes.td index 3f4be671251..0660ed15476 100644 --- a/include/llvm/IR/Attributes.td +++ b/include/llvm/IR/Attributes.td @@ -41,6 +41,13 @@ def Dereferenceable : EnumAttr<"dereferenceable">; /// Pointer is either null or dereferenceable. def DereferenceableOrNull : EnumAttr<"dereferenceable_or_null">; +/// Function may only access memory that is inaccessible from IR. +def InaccessibleMemOnly : EnumAttr<"inaccessiblememonly">; + +/// Function may only access memory that is either inaccessible from the IR, +/// or pointed to by its pointer arguments. +def InaccessibleMemOrArgMemOnly : EnumAttr<"inaccessiblemem_or_argmemonly">; + /// Pass structure in an alloca. def InAlloca : EnumAttr<"inalloca">; diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index a55ff5cb6e2..2843cf2cce3 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -293,6 +293,26 @@ public: } void setOnlyAccessesArgMemory() { addFnAttr(Attribute::ArgMemOnly); } + /// @brief Determine if the function may only access memory that is + /// inaccessible from the IR. + bool onlyAccessesInaccessibleMemory() const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, + Attribute::InaccessibleMemOnly); + } + void setOnlyAccessesInaccessibleMemory() { + addFnAttr(Attribute::InaccessibleMemOnly); + } + + /// @brief Determine if the function may only access memory that is + // either inaccessible from the IR or pointed to by its arguments. + bool onlyAccessesInaccessibleMemOrArgMem() const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, + Attribute::InaccessibleMemOrArgMemOnly); + } + void setOnlyAccessesInaccessibleMemOrArgMem() { + addFnAttr(Attribute::InaccessibleMemOrArgMemOnly); + } + /// @brief Determine if the function cannot return. bool doesNotReturn() const { return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index aef0585f87b..b1bc5682193 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -609,6 +609,8 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(convergent); KEYWORD(dereferenceable); KEYWORD(dereferenceable_or_null); + KEYWORD(inaccessiblememonly); + KEYWORD(inaccessiblemem_or_argmemonly); KEYWORD(inlinehint); KEYWORD(inreg); KEYWORD(jumptable); diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 0b2880949f6..d0bd31c4217 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -995,6 +995,10 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B, case lltok::kw_builtin: B.addAttribute(Attribute::Builtin); break; case lltok::kw_cold: B.addAttribute(Attribute::Cold); break; case lltok::kw_convergent: B.addAttribute(Attribute::Convergent); break; + case lltok::kw_inaccessiblememonly: + B.addAttribute(Attribute::InaccessibleMemOnly); break; + case lltok::kw_inaccessiblemem_or_argmemonly: + B.addAttribute(Attribute::InaccessibleMemOrArgMemOnly); break; case lltok::kw_inlinehint: B.addAttribute(Attribute::InlineHint); break; case lltok::kw_jumptable: B.addAttribute(Attribute::JumpTable); break; case lltok::kw_minsize: B.addAttribute(Attribute::MinSize); break; diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index d86001a9dc9..a6632e4f29c 100644 --- a/lib/AsmParser/LLToken.h +++ b/lib/AsmParser/LLToken.h @@ -115,6 +115,8 @@ namespace lltok { kw_convergent, kw_dereferenceable, kw_dereferenceable_or_null, + kw_inaccessiblememonly, + kw_inaccessiblemem_or_argmemonly, kw_inlinehint, kw_inreg, kw_jumptable, diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index d80e70d3515..0905b5fb6d2 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1230,6 +1230,10 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) { return Attribute::Cold; case bitc::ATTR_KIND_CONVERGENT: return Attribute::Convergent; + case bitc::ATTR_KIND_INACCESSIBLEMEM_ONLY: + return Attribute::InaccessibleMemOnly; + case bitc::ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEMONLY: + return Attribute::InaccessibleMemOrArgMemOnly; case bitc::ATTR_KIND_INLINE_HINT: return Attribute::InlineHint; case bitc::ATTR_KIND_IN_REG: diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index e34ce5ac430..a1f87863757 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -178,6 +178,10 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { return bitc::ATTR_KIND_IN_ALLOCA; case Attribute::Cold: return bitc::ATTR_KIND_COLD; + case Attribute::InaccessibleMemOnly: + return bitc::ATTR_KIND_INACCESSIBLEMEM_ONLY; + case Attribute::InaccessibleMemOrArgMemOnly: + return bitc::ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEMONLY; case Attribute::InlineHint: return bitc::ATTR_KIND_INLINE_HINT; case Attribute::InReg: diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp index 4d8ca08fabc..2b8f67f24df 100644 --- a/lib/IR/Attributes.cpp +++ b/lib/IR/Attributes.cpp @@ -198,6 +198,10 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return "byval"; if (hasAttribute(Attribute::Convergent)) return "convergent"; + if (hasAttribute(Attribute::InaccessibleMemOnly)) + return "inaccessiblememonly"; + if (hasAttribute(Attribute::InaccessibleMemOrArgMemOnly)) + return "inaccessiblemem_or_argmemonly"; if (hasAttribute(Attribute::InAlloca)) return "inalloca"; if (hasAttribute(Attribute::InlineHint)) @@ -445,6 +449,8 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) { case Attribute::Convergent: return 1ULL << 46; case Attribute::SafeStack: return 1ULL << 47; case Attribute::NoRecurse: return 1ULL << 48; + case Attribute::InaccessibleMemOnly: return 1ULL << 49; + case Attribute::InaccessibleMemOrArgMemOnly: return 1ULL << 50; case Attribute::Dereferenceable: llvm_unreachable("dereferenceable attribute not supported in raw format"); break; diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 53d00377469..a70de2c7b93 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -1251,7 +1251,9 @@ void Verifier::VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx, I->getKindAsEnum() == Attribute::JumpTable || I->getKindAsEnum() == Attribute::Convergent || I->getKindAsEnum() == Attribute::ArgMemOnly || - I->getKindAsEnum() == Attribute::NoRecurse) { + I->getKindAsEnum() == Attribute::NoRecurse || + I->getKindAsEnum() == Attribute::InaccessibleMemOnly || + I->getKindAsEnum() == Attribute::InaccessibleMemOrArgMemOnly) { if (!isFunction) { CheckFailed("Attribute '" + I->getAsString() + "' only applies to functions!", V); @@ -1421,6 +1423,18 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly)), "Attributes 'readnone and readonly' are incompatible!", V); + Assert( + !(Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone) && + Attrs.hasAttribute(AttributeSet::FunctionIndex, + Attribute::InaccessibleMemOrArgMemOnly)), + "Attributes 'readnone and inaccessiblemem_or_argmemonly' are incompatible!", V); + + Assert( + !(Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone) && + Attrs.hasAttribute(AttributeSet::FunctionIndex, + Attribute::InaccessibleMemOnly)), + "Attributes 'readnone and inaccessiblememonly' are incompatible!", V); + Assert( !(Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::NoInline) && Attrs.hasAttribute(AttributeSet::FunctionIndex, diff --git a/test/Bindings/llvm-c/Inputs/invalid.ll.bc b/test/Bindings/llvm-c/Inputs/invalid.ll.bc index 8f7474b9e468a12c9a0719386bf9e9eda12cdd85..60c7afffbc2308e4ceb58663b5e84d21fba6e1c1 100644 GIT binary patch delta 118 zcmeysvVm3A$@#!NQxOIRRt5%!Bpw45pU8dB-hQ^z4eb?RJpmL~;Fb delta 55 zcmdnM`hkVh$@#!NMIHu*nG;pB867504CFH75ShZlz;NO)!^RIWjFWSi%z1U#1b7-u H7$5)u*qshF diff --git a/test/Bindings/llvm-c/invalid-bitcode.test b/test/Bindings/llvm-c/invalid-bitcode.test index 9219f36eb24..f8835b9b8bd 100644 --- a/test/Bindings/llvm-c/invalid-bitcode.test +++ b/test/Bindings/llvm-c/invalid-bitcode.test @@ -1,3 +1,3 @@ ; RUN: not llvm-c-test --module-dump < %S/Inputs/invalid.ll.bc 2>&1 | FileCheck %s -CHECK: Error parsing bitcode: Unknown attribute kind (50) +CHECK: Error parsing bitcode: Unknown attribute kind (52) diff --git a/test/Bitcode/attributes.ll b/test/Bitcode/attributes.ll index e3eda4887b3..1b3526f1fa0 100644 --- a/test/Bitcode/attributes.ll +++ b/test/Bitcode/attributes.ll @@ -204,7 +204,7 @@ define void @f34() ; CHECK: define void @f34() { call void @nobuiltin() nobuiltin -; CHECK: call void @nobuiltin() #28 +; CHECK: call void @nobuiltin() #30 ret void; } @@ -277,6 +277,16 @@ define void @f47() norecurse { ret void } +; CHECK: define void @f48() #28 +define void @f48() inaccessiblememonly { + ret void +} + +; CHECK: define void @f49() #29 +define void @f49() inaccessiblemem_or_argmemonly { + ret void +} + ; CHECK: attributes #0 = { noreturn } ; CHECK: attributes #1 = { nounwind } ; CHECK: attributes #2 = { readnone } @@ -305,4 +315,6 @@ define void @f47() norecurse { ; CHECK: attributes #25 = { convergent } ; CHECK: attributes #26 = { argmemonly } ; CHECK: attributes #27 = { norecurse } -; CHECK: attributes #28 = { nobuiltin } +; CHECK: attributes #28 = { inaccessiblememonly } +; CHECK: attributes #29 = { inaccessiblemem_or_argmemonly } +; CHECK: attributes #30 = { nobuiltin } diff --git a/test/Bitcode/compatibility.ll b/test/Bitcode/compatibility.ll index 465facc2a88..31e501de0a1 100644 --- a/test/Bitcode/compatibility.ll +++ b/test/Bitcode/compatibility.ll @@ -503,6 +503,10 @@ declare void @f.kvpair() "cpu"="cortex-a8" ; CHECK:declare void @f.kvpair() #31 declare void @f.norecurse() norecurse ; CHECK: declare void @f.norecurse() #32 +declare void @f.inaccessiblememonly() inaccessiblememonly +; CHECK: declare void @f.inaccessiblememonly() #33 +declare void @f.inaccessiblemem_or_argmemonly() inaccessiblemem_or_argmemonly +; CHECK: declare void @f.inaccessiblemem_or_argmemonly() #34 ; Functions -- section declare void @f.section() section "80" @@ -561,7 +565,7 @@ declare void @f.prologuearray() prologue [4 x i32] [i32 0, i32 1, i32 2, i32 3] ; Functions -- Personality constant declare void @llvm.donothing() nounwind readnone -; CHECK: declare void @llvm.donothing() #33 +; CHECK: declare void @llvm.donothing() #35 define void @f.no_personality() personality i8 3 { ; CHECK: define void @f.no_personality() personality i8 3 invoke void @llvm.donothing() to label %normal unwind label %exception @@ -1136,7 +1140,7 @@ exit: ; CHECK: select <2 x i1> , <2 x i8> , <2 x i8> call void @f.nobuiltin() builtin - ; CHECK: call void @f.nobuiltin() #37 + ; CHECK: call void @f.nobuiltin() #39 call fastcc noalias i32* @f.noalias() noinline ; CHECK: call fastcc noalias i32* @f.noalias() #12 @@ -1516,11 +1520,13 @@ normal: ; CHECK: attributes #30 = { uwtable } ; CHECK: attributes #31 = { "cpu"="cortex-a8" } ; CHECK: attributes #32 = { norecurse } -; CHECK: attributes #33 = { nounwind readnone } -; CHECK: attributes #34 = { argmemonly nounwind readonly } -; CHECK: attributes #35 = { argmemonly nounwind } -; CHECK: attributes #36 = { nounwind readonly } -; CHECK: attributes #37 = { builtin } +; CHECK: attributes #33 = { inaccessiblememonly } +; CHECK: attributes #34 = { inaccessiblemem_or_argmemonly } +; CHECK: attributes #35 = { nounwind readnone } +; CHECK: attributes #36 = { argmemonly nounwind readonly } +; CHECK: attributes #37 = { argmemonly nounwind } +; CHECK: attributes #38 = { nounwind readonly } +; CHECK: attributes #39 = { builtin } ;; Metadata diff --git a/test/Bitcode/invalid.ll b/test/Bitcode/invalid.ll index 2f2eca94321..c56f0ffefa9 100644 --- a/test/Bitcode/invalid.ll +++ b/test/Bitcode/invalid.ll @@ -1,6 +1,6 @@ ; RUN: not llvm-dis < %s.bc 2>&1 | FileCheck %s -; CHECK: llvm-dis{{(\.EXE|\.exe)?}}: error: Unknown attribute kind (50) +; CHECK: llvm-dis{{(\.EXE|\.exe)?}}: error: Unknown attribute kind (52) ; invalid.ll.bc has an invalid attribute number. ; The test checks that LLVM reports the error and doesn't access freed memory diff --git a/test/Bitcode/invalid.ll.bc b/test/Bitcode/invalid.ll.bc index 8f7474b9e468a12c9a0719386bf9e9eda12cdd85..60c7afffbc2308e4ceb58663b5e84d21fba6e1c1 100644 GIT binary patch delta 118 zcmeysvVm3A$@#!NQxOIRRt5%!Bpw45pU8dB-hQ^z4eb?RJpmL~;Fb delta 55 zcmdnM`hkVh$@#!NMIHu*nG;pB867504CFH75ShZlz;NO)!^RIWjFWSi%z1U#1b7-u H7$5)u*qshF diff --git a/test/LTO/X86/Inputs/invalid.ll.bc b/test/LTO/X86/Inputs/invalid.ll.bc index 8f7474b9e468a12c9a0719386bf9e9eda12cdd85..60c7afffbc2308e4ceb58663b5e84d21fba6e1c1 100644 GIT binary patch delta 118 zcmeysvVm3A$@#!NQxOIRRt5%!Bpw45pU8dB-hQ^z4eb?RJpmL~;Fb delta 55 zcmdnM`hkVh$@#!NMIHu*nG;pB867504CFH75ShZlz;NO)!^RIWjFWSi%z1U#1b7-u H7$5)u*qshF diff --git a/test/LTO/X86/invalid.ll b/test/LTO/X86/invalid.ll index 3de11112c71..b9d0bca091d 100644 --- a/test/LTO/X86/invalid.ll +++ b/test/LTO/X86/invalid.ll @@ -1,4 +1,4 @@ ; RUN: not llvm-lto %S/Inputs/invalid.ll.bc 2>&1 | FileCheck %s -; CHECK: llvm-lto{{.*}}: error loading file '{{.*}}/Inputs/invalid.ll.bc': Unknown attribute kind (50) +; CHECK: llvm-lto{{.*}}: error loading file '{{.*}}/Inputs/invalid.ll.bc': Unknown attribute kind (52) -- 2.34.1