mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
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 (d001932f3a
) as reference.
Reviewers: jmolloy, hfinkel
Subscribers: reames, joker.eph, llvm-commits
Differential Revision: http://reviews.llvm.org/D15499
llvm-svn: 255778
This commit is contained in:
parent
cefbfa53f9
commit
a478a7d3d6
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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">;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
Binary file not shown.
@ -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)
|
||||
|
@ -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 }
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
Binary file not shown.
Binary file not shown.
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user