Add InaccessibleMemOnly and inaccessibleMemOrArgMemOnly attributes
authorVaivaswatha Nagaraj <vn@compilertree.com>
Wed, 16 Dec 2015 16:16:19 +0000 (16:16 +0000)
committerVaivaswatha Nagaraj <vn@compilertree.com>
Wed, 16 Dec 2015 16:16:19 +0000 (16:16 +0000)
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

19 files changed:
docs/LangRef.rst
include/llvm/Bitcode/LLVMBitCodes.h
include/llvm/IR/Attributes.td
include/llvm/IR/Function.h
lib/AsmParser/LLLexer.cpp
lib/AsmParser/LLParser.cpp
lib/AsmParser/LLToken.h
lib/Bitcode/Reader/BitcodeReader.cpp
lib/Bitcode/Writer/BitcodeWriter.cpp
lib/IR/Attributes.cpp
lib/IR/Verifier.cpp
test/Bindings/llvm-c/Inputs/invalid.ll.bc
test/Bindings/llvm-c/invalid-bitcode.test
test/Bitcode/attributes.ll
test/Bitcode/compatibility.ll
test/Bitcode/invalid.ll
test/Bitcode/invalid.ll.bc
test/LTO/X86/Inputs/invalid.ll.bc
test/LTO/X86/invalid.ll

index f8d87da7061b21e72d6d606404cca98872ee45a6..c968818acf253f2b65104ce5ee9acff2d389bac3 100644 (file)
@@ -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
index 6780c8e6a977e07b02984a1b5670333fc1691a5f..bcc84bedbed04d79285d9f65621285af5fe3cf74 100644 (file)
@@ -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 {
index 3f4be671251e79fe06cb6453ee8933fe16d2f0ea..0660ed15476ae1639e5cf2f9b933eac892d5d123 100644 (file)
@@ -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">;
 
index a55ff5cb6e2b4f7690c7705620d7c7507402f5a1..2843cf2cce35255f878ebca038c87c1d33bfbba0 100644 (file)
@@ -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,
index aef0585f87b5be99c7d1f1ca07b3e0366ecbb800..b1bc56821930cc27d9461aea969a60de48efd2f1 100644 (file)
@@ -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);
index 0b2880949f673b0bfaafa259e210877f2eaf6b2a..d0bd31c42179f1fda8547083c0688390e49645c1 100644 (file)
@@ -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;
index d86001a9dc9334917455a7025ac833fcfeb8c502..a6632e4f29c83fed70602c447813f8f863d84b78 100644 (file)
@@ -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,
index d80e70d3515abdd31526cbbf57231d17f1a1a202..0905b5fb6d296b1ca181acb1a6860ba95dfd0847 100644 (file)
@@ -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:
index e34ce5ac430c0ea36a05b5573ddf39dcc34dd975..a1f87863757bb777b2e516f4e33a3b5292e83dcf 100644 (file)
@@ -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:
index 4d8ca08fabccb71fb7414b6743ca72aec86b9458..2b8f67f24dfde56df0ee1ae02dff6567d431c80e 100644 (file)
@@ -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;
index 53d00377469e34506cd8ac1363ae052114ad5b0a..a70de2c7b93a79244a9a58ea2e23e31ef763d551 100644 (file)
@@ -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,
index 8f7474b9e468a12c9a0719386bf9e9eda12cdd85..60c7afffbc2308e4ceb58663b5e84d21fba6e1c1 100644 (file)
Binary files a/test/Bindings/llvm-c/Inputs/invalid.ll.bc and b/test/Bindings/llvm-c/Inputs/invalid.ll.bc differ
index 9219f36eb2428dc3007ca3d8d7b300dfcc378859..f8835b9b8bd0243603dd6ad927cc440dd4db5582 100644 (file)
@@ -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)
index e3eda4887b36171fa17de9e5cae943b2e1f99180..1b3526f1fa0de4287bc0090d2c0c3b626ecca813 100644 (file)
@@ -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 }
index 465facc2a88fa694e6e2440314db4497f02b4f73..31e501de0a11f30bf773103230a7bf92d9556dbc 100644 (file)
@@ -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> <i1 true, i1 false>, <2 x i8> <i8 2, i8 3>, <2 x i8> <i8 3, i8 2>
 
   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
 
index 2f2eca94321e5336fe2647ae2fcf5659b1083e6f..c56f0ffefa9e61270a84e26e1e46524df793da55 100644 (file)
@@ -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
index 8f7474b9e468a12c9a0719386bf9e9eda12cdd85..60c7afffbc2308e4ceb58663b5e84d21fba6e1c1 100644 (file)
Binary files a/test/Bitcode/invalid.ll.bc and b/test/Bitcode/invalid.ll.bc differ
index 8f7474b9e468a12c9a0719386bf9e9eda12cdd85..60c7afffbc2308e4ceb58663b5e84d21fba6e1c1 100644 (file)
Binary files a/test/LTO/X86/Inputs/invalid.ll.bc and b/test/LTO/X86/Inputs/invalid.ll.bc differ
index 3de11112c71d6e706f3d487dc086915a5e73027e..b9d0bca091d0060904ed6aa359ac9eeaf38b5cb5 100644 (file)
@@ -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)