diff options
author | Sanjoy Das <sanjoy@playingwithpointers.com> | 2015-04-16 20:29:50 +0000 |
---|---|---|
committer | Sanjoy Das <sanjoy@playingwithpointers.com> | 2015-04-16 20:29:50 +0000 |
commit | 31ea6d1590ce79845504b8d928f07cb71bd4be80 (patch) | |
tree | f253459b724d977c2b1ff6a0cdbcc620a8e89f9d /llvm/lib/AsmParser | |
parent | 90356501f54dd6eebcb053a3206d5a4afc3bebb9 (diff) | |
download | bcm5719-llvm-31ea6d1590ce79845504b8d928f07cb71bd4be80.tar.gz bcm5719-llvm-31ea6d1590ce79845504b8d928f07cb71bd4be80.zip |
[IR] Introduce a dereferenceable_or_null(N) attribute.
Summary:
If a pointer is marked as dereferenceable_or_null(N), LLVM assumes it
is either `null` or `dereferenceable(N)` or both. This change only
introduces the attribute and adds a token test case for the `llvm-as`
/ `llvm-dis`. It does not hook up other parts of the optimizer to
actually exploit the attribute -- those changes will come later.
For pointers in address space 0, `dereferenceable(N)` is now exactly
equivalent to `dereferenceable_or_null(N)` && `nonnull`. For other
address spaces, `dereferenceable(N)` is potentially weaker than
`dereferenceable_or_null(N)` && `nonnull` (since we could have a null
`dereferenceable(N)` pointer).
The motivating case for this change is Java (and other managed
languages), where pointers are either `null` or dereferenceable up to
some usually known-at-compile-time constant offset.
Reviewers: rafael, hfinkel
Reviewed By: hfinkel
Subscribers: nicholas, llvm-commits
Differential Revision: http://reviews.llvm.org/D8650
llvm-svn: 235132
Diffstat (limited to 'llvm/lib/AsmParser')
-rw-r--r-- | llvm/lib/AsmParser/LLLexer.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLParser.cpp | 34 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLParser.h | 2 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLToken.h | 1 |
4 files changed, 31 insertions, 7 deletions
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 3bf090a4b33..a72f713c490 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -598,6 +598,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(inalloca); KEYWORD(cold); KEYWORD(dereferenceable); + KEYWORD(dereferenceable_or_null); KEYWORD(inlinehint); KEYWORD(inreg); KEYWORD(jumptable); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 64ed2a2b7e3..2b306dbd642 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -976,6 +976,7 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B, break; case lltok::kw_byval: case lltok::kw_dereferenceable: + case lltok::kw_dereferenceable_or_null: case lltok::kw_inalloca: case lltok::kw_nest: case lltok::kw_noalias: @@ -1220,11 +1221,18 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) { case lltok::kw_byval: B.addAttribute(Attribute::ByVal); break; case lltok::kw_dereferenceable: { uint64_t Bytes; - if (ParseOptionalDereferenceableBytes(Bytes)) + if (ParseOptionalDerefAttrBytes(lltok::kw_dereferenceable, Bytes)) return true; B.addDereferenceableAttr(Bytes); continue; } + case lltok::kw_dereferenceable_or_null: { + uint64_t Bytes; + if (ParseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, Bytes)) + return true; + B.addDereferenceableOrNullAttr(Bytes); + continue; + } 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; @@ -1284,11 +1292,18 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) { return HaveError; case lltok::kw_dereferenceable: { uint64_t Bytes; - if (ParseOptionalDereferenceableBytes(Bytes)) + if (ParseOptionalDerefAttrBytes(lltok::kw_dereferenceable, Bytes)) return true; B.addDereferenceableAttr(Bytes); continue; } + case lltok::kw_dereferenceable_or_null: { + uint64_t Bytes; + if (ParseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, Bytes)) + return true; + B.addDereferenceableOrNullAttr(Bytes); + continue; + } case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break; case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break; case lltok::kw_nonnull: B.addAttribute(Attribute::NonNull); break; @@ -1516,12 +1531,19 @@ bool LLParser::ParseOptionalAlignment(unsigned &Alignment) { return false; } -/// ParseOptionalDereferenceableBytes +/// ParseOptionalDerefAttrBytes /// ::= /* empty */ -/// ::= 'dereferenceable' '(' 4 ')' -bool LLParser::ParseOptionalDereferenceableBytes(uint64_t &Bytes) { +/// ::= AttrKind '(' 4 ')' +/// +/// where AttrKind is either 'dereferenceable' or 'dereferenceable_or_null'. +bool LLParser::ParseOptionalDerefAttrBytes(lltok::Kind AttrKind, + uint64_t &Bytes) { + assert((AttrKind == lltok::kw_dereferenceable || + AttrKind == lltok::kw_dereferenceable_or_null) && + "contract!"); + Bytes = 0; - if (!EatIfPresent(lltok::kw_dereferenceable)) + if (!EatIfPresent(AttrKind)) return false; LocTy ParenLoc = Lex.getLoc(); if (!EatIfPresent(lltok::lparen)) diff --git a/llvm/lib/AsmParser/LLParser.h b/llvm/lib/AsmParser/LLParser.h index 5e92e570e72..117cdcba255 100644 --- a/llvm/lib/AsmParser/LLParser.h +++ b/llvm/lib/AsmParser/LLParser.h @@ -223,7 +223,7 @@ namespace llvm { bool ParseOptionalDLLStorageClass(unsigned &DLLStorageClass); bool ParseOptionalCallingConv(unsigned &CC); bool ParseOptionalAlignment(unsigned &Alignment); - bool ParseOptionalDereferenceableBytes(uint64_t &Bytes); + bool ParseOptionalDerefAttrBytes(lltok::Kind AttrKind, uint64_t &Bytes); bool ParseScopeAndOrdering(bool isAtomic, SynchronizationScope &Scope, AtomicOrdering &Ordering); bool ParseOrdering(AtomicOrdering &Ordering); diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h index a7aa17c37cc..2bdc53b3e2e 100644 --- a/llvm/lib/AsmParser/LLToken.h +++ b/llvm/lib/AsmParser/LLToken.h @@ -106,6 +106,7 @@ namespace lltok { kw_inalloca, kw_cold, kw_dereferenceable, + kw_dereferenceable_or_null, kw_inlinehint, kw_inreg, kw_jumptable, |