Skip to content

Cherry-picking swiftasync support to the new stable branch. #2321

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/include/clang/AST/Attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ class ParameterABIAttr : public InheritableParamAttr {
switch (getKind()) {
case attr::SwiftContext:
return ParameterABI::SwiftContext;
case attr::SwiftAsyncContext:
return ParameterABI::SwiftAsyncContext;
case attr::SwiftErrorResult:
return ParameterABI::SwiftErrorResult;
case attr::SwiftIndirectResult:
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -2418,6 +2418,11 @@ def SwiftContext : ParameterABIAttr {
let Documentation = [SwiftContextDocs];
}

def SwiftAsyncContext : ParameterABIAttr {
let Spellings = [Clang<"swift_async_context">];
let Documentation = [SwiftAsyncContextDocs];
}

def SwiftErrorResult : ParameterABIAttr {
let Spellings = [Clang<"swift_error_result">];
let Documentation = [SwiftErrorResultDocs];
Expand Down
13 changes: 13 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -4551,6 +4551,19 @@ A context parameter must have pointer or reference type.
}];
}

def SwiftAsyncContextDocs : Documentation {
let Category = DocCatVariable;
let Content = [{
The ``swift_async_context`` attribute marks a parameter as having the
special asynchronous context-parameter ABI treatment.

This treatment generally passes the context value in a special register
which is normally callee-preserved.

A context parameter must have pointer or reference type.
}];
}

def SwiftErrorResultDocs : Documentation {
let Category = DocCatVariable;
let Content = [{
Expand Down
7 changes: 6 additions & 1 deletion clang/include/clang/Basic/Specifiers.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,12 @@ namespace clang {
/// This parameter (which must have pointer type) uses the special
/// Swift context-pointer ABI treatment. There can be at
/// most one parameter on a given function that uses this treatment.
SwiftContext
SwiftContext,

/// This parameter (which must have pointer type) uses the special
/// Swift asynchronous context-pointer ABI treatment. There can be at
/// most one parameter on a given function that uses this treatment.
SwiftAsyncContext,
};

/// Assigned inheritance model for a class in the MS C++ ABI. Must match order
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2941,6 +2941,7 @@ CXXNameMangler::mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo PI) {

// All of these start with "swift", so they come before "ns_consumed".
case ParameterABI::SwiftContext:
case ParameterABI::SwiftAsyncContext:
case ParameterABI::SwiftErrorResult:
case ParameterABI::SwiftIndirectResult:
mangleVendorQualifier(getParameterABISpelling(PI.getABI()));
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,8 @@ StringRef clang::getParameterABISpelling(ParameterABI ABI) {
llvm_unreachable("asking for spelling of ordinary parameter ABI");
case ParameterABI::SwiftContext:
return "swift_context";
case ParameterABI::SwiftAsyncContext:
return "swift_async_context";
case ParameterABI::SwiftErrorResult:
return "swift_error_result";
case ParameterABI::SwiftIndirectResult:
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2356,6 +2356,10 @@ void CodeGenModule::ConstructAttributeList(
case ParameterABI::SwiftContext:
Attrs.addAttribute(llvm::Attribute::SwiftSelf);
break;

case ParameterABI::SwiftAsyncContext:
Attrs.addAttribute(llvm::Attribute::SwiftAsync);
break;
}

if (FI.getExtParameterInfo(ArgNo).isNoEscape())
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4958,6 +4958,14 @@ void Sema::AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
D->addAttr(::new (Context) SwiftContextAttr(Context, CI));
return;

case ParameterABI::SwiftAsyncContext:
if (!isValidSwiftContextType(type)) {
Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
<< getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type;
}
D->addAttr(::new (Context) SwiftAsyncContextAttr(Context, CI));
return;

case ParameterABI::SwiftErrorResult:
if (!isValidSwiftErrorResultType(type)) {
Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
Expand Down Expand Up @@ -8020,6 +8028,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_SwiftContext:
S.AddParameterABIAttr(D, AL, ParameterABI::SwiftContext);
break;
case ParsedAttr::AT_SwiftAsyncContext:
S.AddParameterABIAttr(D, AL, ParameterABI::SwiftAsyncContext);
break;
case ParsedAttr::AT_SwiftErrorResult:
S.AddParameterABIAttr(D, AL, ParameterABI::SwiftErrorResult);
break;
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2783,6 +2783,10 @@ static void checkExtParameterInfos(Sema &S, ArrayRef<QualType> paramTypes,
checkForSwiftCC(paramIndex);
continue;

case ParameterABI::SwiftAsyncContext:
// FIXME: might want to require swiftasynccc when it exists
continue;

// swift_error parameters must be preceded by a swift_context parameter.
case ParameterABI::SwiftErrorResult:
checkForSwiftCC(paramIndex);
Expand Down
4 changes: 4 additions & 0 deletions clang/test/CodeGen/arm-swiftcall.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define OUT __attribute__((swift_indirect_result))
#define ERROR __attribute__((swift_error_result))
#define CONTEXT __attribute__((swift_context))
#define ASYNC_CONTEXT __attribute__((swift_async_context))

/*****************************************************************************/
/****************************** PARAMETER ABIS *******************************/
Expand Down Expand Up @@ -53,6 +54,9 @@ void test_context_error_1() {
SWIFTCALL void context_error_2(short s, CONTEXT int *self, ERROR float **error) {}
// CHECK-LABEL: define{{.*}} void @context_error_2(i16{{.*}}, i32* swiftself{{.*}}, float** swifterror %0)

SWIFTCALL void async_context_1(ASYNC_CONTEXT void *self) {}
// CHECK-LABEL: define {{.*}} void @async_context_1(i8* swiftasync

/*****************************************************************************/
/********************************** LOWERING *********************************/
/*****************************************************************************/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@
// CHECK-NEXT: SetTypestate (SubjectMatchRule_function_is_member)
// CHECK-NEXT: SpeculativeLoadHardening (SubjectMatchRule_function, SubjectMatchRule_objc_method)
// CHECK-NEXT: SwiftAsync (SubjectMatchRule_function, SubjectMatchRule_objc_method)
// CHECK-NEXT: SwiftAsyncContext (SubjectMatchRule_variable_is_parameter)
// CHECK-NEXT: SwiftAsyncName (SubjectMatchRule_objc_method, SubjectMatchRule_function)
// CHECK-NEXT: SwiftBridgedTypedef (SubjectMatchRule_type_alias)
// CHECK-NEXT: SwiftContext (SubjectMatchRule_variable_is_parameter)
Expand Down
6 changes: 6 additions & 0 deletions clang/test/Sema/attr-swiftcall.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#define INDIRECT_RESULT __attribute__((swift_indirect_result))
#define ERROR_RESULT __attribute__((swift_error_result))
#define CONTEXT __attribute__((swift_context))
#define ASYNC_CONTEXT __attribute__((swift_async_context))

int notAFunction SWIFTCALL; // expected-warning {{'swiftcall' only applies to function types; type here is 'int'}}
void variadic(int x, ...) SWIFTCALL; // expected-error {{variadic function cannot use swiftcall calling convention}}
Expand All @@ -29,3 +30,8 @@ void context_nonswift(CONTEXT void *context); // expected-error {{'swift_context
void context_bad_type(CONTEXT int context) SWIFTCALL; // expected-error {{'swift_context' parameter must have pointer type; type here is 'int'}}
void context_okay(CONTEXT void *context) SWIFTCALL;
void context_okay2(CONTEXT void *context, void *selfType, char **selfWitnessTable) SWIFTCALL;

void async_context_okay_for_now(ASYNC_CONTEXT void *context);
void async_context_bad_type(ASYNC_CONTEXT int context) SWIFTCALL; // expected-error {{'swift_async_context' parameter must have pointer type; type here is 'int'}}
void async_context_okay(ASYNC_CONTEXT void *context) SWIFTCALL;
void async_context_okay2(ASYNC_CONTEXT void *context, void *selfType, char **selfWitnessTable) SWIFTCALL;
29 changes: 29 additions & 0 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1254,6 +1254,12 @@ Currently, only the following parameter attributes are defined:
a valid attribute for return values and can only be applied to one
parameter.

``swiftasync``
This indicates that the parameter is the asynchronous context parameter and
triggers the creation of a target-specific extended frame record to store
this pointer. This is not a valid attribute for return values and can only
be applied to one parameter.

``swifterror``
This attribute is motivated to model and optimize Swift error handling. It
can be applied to a parameter with pointer to pointer type or a
Expand Down Expand Up @@ -11826,6 +11832,29 @@ Note that calling this intrinsic does not prevent function inlining or
other aggressive transformations, so the value returned may not be that
of the obvious source-language caller.

'``llvm.swift.async.context.addr``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Syntax:
"""""""

::

declare i8** @llvm.swift.async.context.addr()

Overview:
"""""""""

The '``llvm.swift.async.context.addr``' intrinsic returns a pointer to
the part of the extended frame record containing the asynchronous
context of a Swift execution.

Semantics:
""""""""""

If the function has a ``swiftasync`` parameter, that argument will initially
be stored at the returned address. If not, it will be initialized to null.

'``llvm.localescape``' and '``llvm.localrecover``' Intrinsics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/Bitcode/LLVMBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,7 @@ enum AttributeKindCodes {
ATTR_KIND_MUSTPROGRESS = 70,
ATTR_KIND_NO_CALLBACK = 71,
ATTR_KIND_HOT = 72,
ATTR_KIND_SWIFT_ASYNC = 73,
};

enum ComdatSelectionKindCodes {
Expand Down
15 changes: 10 additions & 5 deletions llvm/include/llvm/CodeGen/TargetCallingConv.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ namespace ISD {
unsigned IsPreallocated : 1; ///< ByVal without the copy
unsigned IsSplitEnd : 1; ///< Last part of a split
unsigned IsSwiftSelf : 1; ///< Swift self parameter
unsigned IsSwiftAsync : 1; ///< Swift async context parameter
unsigned IsSwiftError : 1; ///< Swift error parameter
unsigned IsCFGuardTarget : 1; ///< Control Flow Guard target
unsigned IsHva : 1; ///< HVA field for
Expand All @@ -63,11 +64,12 @@ namespace ISD {

public:
ArgFlagsTy()
: IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsByRef(0),
IsNest(0), IsReturned(0), IsSplit(0), IsInAlloca(0), IsPreallocated(0),
IsSplitEnd(0), IsSwiftSelf(0), IsSwiftError(0), IsCFGuardTarget(0),
IsHva(0), IsHvaStart(0), IsSecArgPass(0), ByValOrByRefAlign(0),
OrigAlign(0), IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0),
: IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsByRef(0),
IsNest(0), IsReturned(0), IsSplit(0), IsInAlloca(0),
IsPreallocated(0), IsSplitEnd(0), IsSwiftSelf(0), IsSwiftAsync(0),
IsSwiftError(0), IsCFGuardTarget(0), IsHva(0), IsHvaStart(0),
IsSecArgPass(0), ByValOrByRefAlign(0), OrigAlign(0),
IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0),
IsCopyElisionCandidate(0), IsPointer(0), ByValOrByRefSize(0),
PointerAddrSpace(0) {
static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big");
Expand Down Expand Up @@ -100,6 +102,9 @@ namespace ISD {
bool isSwiftSelf() const { return IsSwiftSelf; }
void setSwiftSelf() { IsSwiftSelf = 1; }

bool isSwiftAsync() const { return IsSwiftAsync; }
void setSwiftAsync() { IsSwiftAsync = 1; }

bool isSwiftError() const { return IsSwiftError; }
void setSwiftError() { IsSwiftError = 1; }

Expand Down
8 changes: 8 additions & 0 deletions llvm/include/llvm/CodeGen/TargetFrameLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,14 @@ class TargetFrameLowering {
/// returns false, spill slots will be assigned using generic implementation.
/// assignCalleeSavedSpillSlots() may add, delete or rearrange elements of
/// CSI.
virtual bool assignCalleeSavedSpillSlots(MachineFunction &MF,
const TargetRegisterInfo *TRI,
std::vector<CalleeSavedInfo> &CSI,
unsigned &MinCSFrameIndex,
unsigned &MaxCSFrameIndex) const {
return assignCalleeSavedSpillSlots(MF, TRI, CSI);
}

virtual bool
assignCalleeSavedSpillSlots(MachineFunction &MF,
const TargetRegisterInfo *TRI,
Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/CodeGen/TargetLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ class TargetLoweringBase {
bool IsPreallocated : 1;
bool IsReturned : 1;
bool IsSwiftSelf : 1;
bool IsSwiftAsync : 1;
bool IsSwiftError : 1;
bool IsCFGuardTarget : 1;
MaybeAlign Alignment = None;
Expand All @@ -293,7 +294,7 @@ class TargetLoweringBase {
: IsSExt(false), IsZExt(false), IsInReg(false), IsSRet(false),
IsNest(false), IsByVal(false), IsByRef(false), IsInAlloca(false),
IsPreallocated(false), IsReturned(false), IsSwiftSelf(false),
IsSwiftError(false), IsCFGuardTarget(false) {}
IsSwiftAsync(false), IsSwiftError(false), IsCFGuardTarget(false) {}

void setAttributes(const CallBase *Call, unsigned ArgIdx);
};
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/IR/Attributes.td
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,9 @@ def SwiftError : EnumAttr<"swifterror">;
/// Argument is swift self/context.
def SwiftSelf : EnumAttr<"swiftself">;

/// Argument is swift async context.
def SwiftAsync : EnumAttr<"swiftasync">;

/// Function must be in a unwind table.
def UWTable : EnumAttr<"uwtable">;

Expand Down
5 changes: 5 additions & 0 deletions llvm/include/llvm/IR/Intrinsics.td
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,12 @@ def int_objc_arc_annotation_bottomup_bbstart : Intrinsic<[],
def int_objc_arc_annotation_bottomup_bbend : Intrinsic<[],
[llvm_ptrptr_ty,
llvm_ptrptr_ty]>;
//===--------------- Swift asynchronous context intrinsics ----------------===//

// Returns the location of the Swift asynchronous context (usually stored just
// before the frame pointer), and triggers the creation of a null context if it
// would otherwise be unneeded.
def int_swift_async_context_addr : Intrinsic<[llvm_ptrptr_ty], [], [IntrNoMem]>;

//===--------------------- Code Generator Intrinsics ----------------------===//
//
Expand Down
5 changes: 5 additions & 0 deletions llvm/include/llvm/Target/TargetCallingConv.td
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ class CCIfPreallocated<CCAction A> : CCIf<"ArgFlags.isPreallocated()", A> {
class CCIfSwiftSelf<CCAction A> : CCIf<"ArgFlags.isSwiftSelf()", A> {
}

/// CCIfSwiftAsync - If the current argument has swiftasync parameter attribute,
/// apply Action A.
class CCIfSwiftAsync<CCAction A> : CCIf<"ArgFlags.isSwiftAsync()", A> {
}

/// CCIfSwiftError - If the current argument has swifterror parameter attribute,
/// apply Action A.
class CCIfSwiftError<CCAction A> : CCIf<"ArgFlags.isSwiftError()", A> {
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/AsmParser/LLLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(speculative_load_hardening);
KEYWORD(swifterror);
KEYWORD(swiftself);
KEYWORD(swiftasync);
KEYWORD(uwtable);
KEYWORD(willreturn);
KEYWORD(writeonly);
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1433,6 +1433,7 @@ bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B,
case lltok::kw_sret:
case lltok::kw_swifterror:
case lltok::kw_swiftself:
case lltok::kw_swiftasync:
case lltok::kw_immarg:
case lltok::kw_byref:
HaveError |=
Expand Down Expand Up @@ -1759,6 +1760,7 @@ bool LLParser::parseOptionalParamAttrs(AttrBuilder &B) {
case lltok::kw_signext: B.addAttribute(Attribute::SExt); break;
case lltok::kw_swifterror: B.addAttribute(Attribute::SwiftError); break;
case lltok::kw_swiftself: B.addAttribute(Attribute::SwiftSelf); break;
case lltok::kw_swiftasync: B.addAttribute(Attribute::SwiftAsync); break;
case lltok::kw_writeonly: B.addAttribute(Attribute::WriteOnly); break;
case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break;
case lltok::kw_immarg: B.addAttribute(Attribute::ImmArg); break;
Expand Down Expand Up @@ -1864,6 +1866,7 @@ bool LLParser::parseOptionalReturnAttrs(AttrBuilder &B) {
case lltok::kw_sret:
case lltok::kw_swifterror:
case lltok::kw_swiftself:
case lltok::kw_swiftasync:
case lltok::kw_immarg:
case lltok::kw_byref:
HaveError |=
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/AsmParser/LLToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ enum Kind {
kw_strictfp,
kw_swifterror,
kw_swiftself,
kw_swiftasync,
kw_uwtable,
kw_willreturn,
kw_writeonly,
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Bitcode/Reader/BitcodeReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1519,6 +1519,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
return Attribute::SwiftError;
case bitc::ATTR_KIND_SWIFT_SELF:
return Attribute::SwiftSelf;
case bitc::ATTR_KIND_SWIFT_ASYNC:
return Attribute::SwiftAsync;
case bitc::ATTR_KIND_UW_TABLE:
return Attribute::UWTable;
case bitc::ATTR_KIND_WILLRETURN:
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
return bitc::ATTR_KIND_SWIFT_ERROR;
case Attribute::SwiftSelf:
return bitc::ATTR_KIND_SWIFT_SELF;
case Attribute::SwiftAsync:
return bitc::ATTR_KIND_SWIFT_ASYNC;
case Attribute::UWTable:
return bitc::ATTR_KIND_UW_TABLE;
case Attribute::WillReturn:
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ addFlagsUsingAttrFn(ISD::ArgFlagsTy &Flags,
Flags.setReturned();
if (AttrFn(Attribute::SwiftSelf))
Flags.setSwiftSelf();
if (AttrFn(Attribute::SwiftAsync))
Flags.setSwiftAsync();
if (AttrFn(Attribute::SwiftError))
Flags.setSwiftError();
}
Expand Down
Loading