mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 12:12:47 +01:00
[IR] Adds mustprogress as a LLVM IR attribute
This adds the LLVM IR attribute `mustprogress` as defined in LangRef through D86233. This attribute will be applied to functions with in languages like C++ where forward progress is guaranteed. Functions without this attribute are not required to make progress. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D85393
This commit is contained in:
parent
dd535e35aa
commit
770f362410
@ -650,6 +650,7 @@ enum AttributeKindCodes {
|
||||
ATTR_KIND_NULL_POINTER_IS_VALID = 67,
|
||||
ATTR_KIND_NOUNDEF = 68,
|
||||
ATTR_KIND_BYREF = 69,
|
||||
ATTR_KIND_MUSTPROGRESS = 70,
|
||||
};
|
||||
|
||||
enum ComdatSelectionKindCodes {
|
||||
|
@ -235,6 +235,9 @@ def WriteOnly : EnumAttr<"writeonly">;
|
||||
/// Zero extended before/after call.
|
||||
def ZExt : EnumAttr<"zeroext">;
|
||||
|
||||
/// Function is required to make Forward Progress.
|
||||
def MustProgress : TypeAttr<"mustprogress">;
|
||||
|
||||
/// Target-independent string attributes.
|
||||
def LessPreciseFPMAD : StrBoolAttr<"less-precise-fpmad">;
|
||||
def NoInfsFPMath : StrBoolAttr<"no-infs-fp-math">;
|
||||
|
@ -622,6 +622,13 @@ public:
|
||||
addFnAttr(Attribute::NoRecurse);
|
||||
}
|
||||
|
||||
/// Determine if the function is required to make forward progress.
|
||||
bool mustProgress() const {
|
||||
return hasFnAttribute(Attribute::MustProgress) ||
|
||||
hasFnAttribute(Attribute::WillReturn);
|
||||
}
|
||||
void setMustProgress() { addFnAttr(Attribute::MustProgress); }
|
||||
|
||||
/// True if the ABI mandates (or the user requested) that this
|
||||
/// function be in a unwind table.
|
||||
bool hasUWTable() const {
|
||||
|
@ -698,6 +698,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
KEYWORD(zeroext);
|
||||
KEYWORD(immarg);
|
||||
KEYWORD(byref);
|
||||
KEYWORD(mustprogress);
|
||||
|
||||
KEYWORD(type);
|
||||
KEYWORD(opaque);
|
||||
|
@ -1309,6 +1309,9 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B,
|
||||
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;
|
||||
case lltok::kw_mustprogress:
|
||||
B.addAttribute(Attribute::MustProgress);
|
||||
break;
|
||||
case lltok::kw_naked: B.addAttribute(Attribute::Naked); break;
|
||||
case lltok::kw_nobuiltin: B.addAttribute(Attribute::NoBuiltin); break;
|
||||
case lltok::kw_noduplicate: B.addAttribute(Attribute::NoDuplicate); break;
|
||||
@ -1724,6 +1727,7 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) {
|
||||
case lltok::kw_inlinehint:
|
||||
case lltok::kw_jumptable:
|
||||
case lltok::kw_minsize:
|
||||
case lltok::kw_mustprogress:
|
||||
case lltok::kw_naked:
|
||||
case lltok::kw_nobuiltin:
|
||||
case lltok::kw_noduplicate:
|
||||
@ -1828,6 +1832,7 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) {
|
||||
case lltok::kw_inlinehint:
|
||||
case lltok::kw_jumptable:
|
||||
case lltok::kw_minsize:
|
||||
case lltok::kw_mustprogress:
|
||||
case lltok::kw_naked:
|
||||
case lltok::kw_nobuiltin:
|
||||
case lltok::kw_noduplicate:
|
||||
|
@ -241,6 +241,7 @@ enum Kind {
|
||||
kw_zeroext,
|
||||
kw_immarg,
|
||||
kw_byref,
|
||||
kw_mustprogress,
|
||||
|
||||
kw_type,
|
||||
kw_opaque,
|
||||
|
@ -1535,6 +1535,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
|
||||
return Attribute::NoUndef;
|
||||
case bitc::ATTR_KIND_BYREF:
|
||||
return Attribute::ByRef;
|
||||
case bitc::ATTR_KIND_MUSTPROGRESS:
|
||||
return Attribute::MustProgress;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -743,6 +743,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
|
||||
return bitc::ATTR_KIND_NOUNDEF;
|
||||
case Attribute::ByRef:
|
||||
return bitc::ATTR_KIND_BYREF;
|
||||
case Attribute::MustProgress:
|
||||
return bitc::ATTR_KIND_MUSTPROGRESS;
|
||||
case Attribute::EndAttrKinds:
|
||||
llvm_unreachable("Can not encode end-attribute kinds marker.");
|
||||
case Attribute::None:
|
||||
|
@ -451,6 +451,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
|
||||
return "immarg";
|
||||
if (hasAttribute(Attribute::NoUndef))
|
||||
return "noundef";
|
||||
if (hasAttribute(Attribute::MustProgress))
|
||||
return "mustprogress";
|
||||
|
||||
const bool IsByVal = hasAttribute(Attribute::ByVal);
|
||||
if (IsByVal || hasAttribute(Attribute::StructRet)) {
|
||||
|
@ -1613,6 +1613,7 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
|
||||
case Attribute::Speculatable:
|
||||
case Attribute::StrictFP:
|
||||
case Attribute::NullPointerIsValid:
|
||||
case Attribute::MustProgress:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
|
@ -931,6 +931,7 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs,
|
||||
case Attribute::StrictFP:
|
||||
case Attribute::UWTable:
|
||||
case Attribute::NoCfCheck:
|
||||
case Attribute::MustProgress:
|
||||
break;
|
||||
}
|
||||
|
||||
|
7
test/Assembler/mustprogress-parse-error-0.ll
Normal file
7
test/Assembler/mustprogress-parse-error-0.ll
Normal file
@ -0,0 +1,7 @@
|
||||
; RUN: not llvm-as < %s 2>&1 | FileCheck %s
|
||||
|
||||
; CHECK: [[@LINE+1]]:35: error: invalid use of function-only attribute
|
||||
define void @test_mustprogress(i8 mustprogress %a) {
|
||||
ret void
|
||||
}
|
||||
|
7
test/Assembler/mustprogress-parse-error-1.ll
Normal file
7
test/Assembler/mustprogress-parse-error-1.ll
Normal file
@ -0,0 +1,7 @@
|
||||
; RUN: not llvm-as < %s 2>&1 | FileCheck %s
|
||||
|
||||
; CHECK: [[@LINE+1]]:8: error: invalid use of function-only attribute
|
||||
define mustprogress void @test_mustprogress(i8 %a) {
|
||||
ret void
|
||||
}
|
||||
|
7
test/Assembler/mustprogress-parse-error-2.ll
Normal file
7
test/Assembler/mustprogress-parse-error-2.ll
Normal file
@ -0,0 +1,7 @@
|
||||
; RUN: not llvm-as < %s 2>&1 | FileCheck %s
|
||||
|
||||
; CHECK: [[@LINE+1]]:52: error: expected '{' in function body
|
||||
define i32* @test_mustprogress(i8 %a) mustprogress 8 {
|
||||
ret void
|
||||
}
|
||||
|
@ -398,6 +398,12 @@ define void @f67(i32* byref(i32) %a)
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: define void @f68() #41
|
||||
define void @f68() mustprogress
|
||||
{
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: attributes #0 = { noreturn }
|
||||
; CHECK: attributes #1 = { nounwind }
|
||||
; CHECK: attributes #2 = { readnone }
|
||||
@ -439,4 +445,5 @@ define void @f67(i32* byref(i32) %a)
|
||||
; CHECK: attributes #38 = { nosync }
|
||||
; CHECK: attributes #39 = { sanitize_memtag }
|
||||
; CHECK: attributes #40 = { null_pointer_is_valid }
|
||||
; CHECK: attributes #41 = { mustprogress }
|
||||
; CHECK: attributes #[[NOBUILTIN]] = { nobuiltin }
|
||||
|
Loading…
Reference in New Issue
Block a user