Skip to content

Commit

Permalink
[Attr] Add "willreturn" function attribute
Browse files Browse the repository at this point in the history
This patch introduces a new function attribute, willreturn, to indicate
that a call of this function will either exhibit undefined behavior or
comes back and continues execution at a point in the existing call stack
that includes the current invocation.

This attribute guarantees that the function does not have any endless
loops, endless recursion, or terminating functions like abort or exit.

Patch by Hideto Ueno (@uenoku)

Reviewers: jdoerfert

Subscribers: mehdi_amini, hiraditya, steven_wu, dexonsmith, lebedev.ri, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D62801

llvm-svn: 364555
  • Loading branch information
Johannes Doerfert committed Jun 27, 2019
1 parent 7d8274d commit 3b77583
Show file tree
Hide file tree
Showing 13 changed files with 503 additions and 3 deletions.
7 changes: 7 additions & 0 deletions llvm/docs/LangRef.rst
Expand Up @@ -1475,6 +1475,13 @@ example:
This function attribute indicates that the function does not call itself
either directly or indirectly down any possible call path. This produces
undefined behavior at runtime if the function ever does recurse.
``willreturn``
This function attribute indicates that a call of this function will
either exhibit undefined behavior or comes back and continues execution
at a point in the existing call stack that includes the current invocation.
Annotated functions may still raise an exception, i.a., ``nounwind`` is not implied.
If an invocation of an annotated function does not return control back
to a point in the call stack, the behavior is undefined.
``nounwind``
This function attribute indicates that the function never raises an
exception. If the function does raise an exception, its runtime
Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/Bitcode/LLVMBitCodes.h
Expand Up @@ -606,7 +606,8 @@ enum AttributeKindCodes {
ATTR_KIND_OPT_FOR_FUZZING = 57,
ATTR_KIND_SHADOWCALLSTACK = 58,
ATTR_KIND_SPECULATIVE_LOAD_HARDENING = 59,
ATTR_KIND_IMMARG = 60
ATTR_KIND_IMMARG = 60,
ATTR_KIND_WILLRETURN = 61,
};

enum ComdatSelectionKindCodes {
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/IR/Attributes.td
Expand Up @@ -196,6 +196,9 @@ def SwiftSelf : EnumAttr<"swiftself">;
/// Function must be in a unwind table.
def UWTable : EnumAttr<"uwtable">;

/// Function always comes back to callsite.
def WillReturn : EnumAttr<"willreturn">;

/// Function only writes to memory.
def WriteOnly : EnumAttr<"writeonly">;

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/AsmParser/LLLexer.cpp
Expand Up @@ -683,6 +683,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(swifterror);
KEYWORD(swiftself);
KEYWORD(uwtable);
KEYWORD(willreturn);
KEYWORD(writeonly);
KEYWORD(zeroext);
KEYWORD(immarg);
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/AsmParser/LLParser.cpp
Expand Up @@ -1315,6 +1315,7 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B,
break;
case lltok::kw_strictfp: B.addAttribute(Attribute::StrictFP); break;
case lltok::kw_uwtable: B.addAttribute(Attribute::UWTable); break;
case lltok::kw_willreturn: B.addAttribute(Attribute::WillReturn); break;
case lltok::kw_writeonly: B.addAttribute(Attribute::WriteOnly); break;

// Error handling.
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/AsmParser/LLToken.h
Expand Up @@ -225,6 +225,7 @@ enum Kind {
kw_swifterror,
kw_swiftself,
kw_uwtable,
kw_willreturn,
kw_writeonly,
kw_zeroext,
kw_immarg,
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Bitcode/Reader/BitcodeReader.cpp
Expand Up @@ -1272,6 +1272,8 @@ static uint64_t getRawAttributeMask(Attribute::AttrKind Val) {
return 1ULL << 60;
case Attribute::ImmArg:
return 1ULL << 61;
case Attribute::WillReturn:
return 1ULL << 62;
case Attribute::Dereferenceable:
llvm_unreachable("dereferenceable attribute not supported in raw format");
break;
Expand Down Expand Up @@ -1510,6 +1512,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
return Attribute::SwiftSelf;
case bitc::ATTR_KIND_UW_TABLE:
return Attribute::UWTable;
case bitc::ATTR_KIND_WILLRETURN:
return Attribute::WillReturn;
case bitc::ATTR_KIND_WRITEONLY:
return Attribute::WriteOnly;
case bitc::ATTR_KIND_Z_EXT:
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
Expand Up @@ -710,6 +710,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
return bitc::ATTR_KIND_SWIFT_SELF;
case Attribute::UWTable:
return bitc::ATTR_KIND_UW_TABLE;
case Attribute::WillReturn:
return bitc::ATTR_KIND_WILLRETURN;
case Attribute::WriteOnly:
return bitc::ATTR_KIND_WRITEONLY;
case Attribute::ZExt:
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/IR/Attributes.cpp
Expand Up @@ -333,6 +333,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "noredzone";
if (hasAttribute(Attribute::NoReturn))
return "noreturn";
if (hasAttribute(Attribute::WillReturn))
return "willreturn";
if (hasAttribute(Attribute::NoCfCheck))
return "nocf_check";
if (hasAttribute(Attribute::NoRecurse))
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/IR/Verifier.cpp
Expand Up @@ -1486,6 +1486,7 @@ void Verifier::visitModuleFlagCGProfileEntry(const MDOperand &MDO) {
static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
switch (Kind) {
case Attribute::NoReturn:
case Attribute::WillReturn:
case Attribute::NoCfCheck:
case Attribute::NoUnwind:
case Attribute::NoInline:
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Transforms/Utils/CodeExtractor.cpp
Expand Up @@ -801,6 +801,7 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs,
case Attribute::StructRet:
case Attribute::SwiftError:
case Attribute::SwiftSelf:
case Attribute::WillReturn:
case Attribute::WriteOnly:
case Attribute::ZExt:
case Attribute::ImmArg:
Expand Down
11 changes: 9 additions & 2 deletions llvm/test/Bitcode/attributes.ll
Expand Up @@ -204,7 +204,7 @@ define void @f34()
; CHECK: define void @f34()
{
call void @nobuiltin() nobuiltin
; CHECK: call void @nobuiltin() #36
; CHECK: call void @nobuiltin() #37
ret void;
}

Expand Down Expand Up @@ -351,6 +351,12 @@ define void @f59() shadowcallstack
ret void
}

; CHECK: define void @f60() #36
define void @f60() willreturn
{
ret void
}

; CHECK: attributes #0 = { noreturn }
; CHECK: attributes #1 = { nounwind }
; CHECK: attributes #2 = { readnone }
Expand Down Expand Up @@ -387,4 +393,5 @@ define void @f59() shadowcallstack
; CHECK: attributes #33 = { speculatable }
; CHECK: attributes #34 = { sanitize_hwaddress }
; CHECK: attributes #35 = { shadowcallstack }
; CHECK: attributes #36 = { nobuiltin }
; CHECK: attributes #36 = { willreturn }
; CHECK: attributes #37 = { nobuiltin }

0 comments on commit 3b77583

Please sign in to comment.