Skip to content

Commit 096828e

Browse files
authored
Merge pull request swiftlang#34358 from jckarter/imported-async-type-lowering
Type lowering and SILGen for imported ObjC async decls.
2 parents ed3ac15 + 7ab9e87 commit 096828e

19 files changed

+591
-247
lines changed

docs/ABI/Mangling.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@ types where the metadata itself has unknown layout.)
218218
global ::= global 'Tm' // merged function
219219
global ::= entity // some identifiable thing
220220
global ::= from-type to-type generic-signature? 'TR' // reabstraction thunk
221+
global ::= from-type to-type generic-signature? 'TR' // reabstraction thunk
222+
global ::= impl-function-type 'Tz' // objc-to-swift-async completion handler block implementation
221223
global ::= from-type to-type self-type generic-signature? 'Ty' // reabstraction thunk with dynamic 'Self' capture
222224
global ::= from-type to-type generic-signature? 'Tr' // obsolete mangling for reabstraction thunk
223225
global ::= entity generic-signature? type type* 'TK' // key path getter

include/swift/AST/ForeignAsyncConvention.h

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,42 +26,51 @@ namespace swift {
2626
class ForeignAsyncConvention {
2727
public:
2828
struct Info {
29+
private:
2930
/// The index of the completion handler parameters.
3031
unsigned CompletionHandlerParamIndex;
3132

3233
/// When non-zero, indicates which parameter to the completion handler is
3334
/// the Error? parameter (minus one) that makes this async function also
3435
/// throwing.
35-
unsigned CompletionHandlerErrorParamIndex;
36-
36+
unsigned CompletionHandlerErrorParamIndexPlusOneOrZero;
37+
38+
public:
3739
Info()
38-
: CompletionHandlerParamIndex(0), CompletionHandlerErrorParamIndex(0) { }
40+
: CompletionHandlerParamIndex(0),
41+
CompletionHandlerErrorParamIndexPlusOneOrZero(0) { }
3942

4043
Info(
4144
unsigned completionHandlerParamIndex,
4245
Optional<unsigned> completionHandlerErrorParamIndex)
4346
: CompletionHandlerParamIndex(completionHandlerParamIndex),
44-
CompletionHandlerErrorParamIndex(
47+
CompletionHandlerErrorParamIndexPlusOneOrZero(
4548
completionHandlerErrorParamIndex
4649
? *completionHandlerErrorParamIndex + 1
4750
: 0) {}
4851

52+
/// Retrieve the index of the completion handler argument in the method's
53+
/// parameter list.
54+
unsigned completionHandlerParamIndex() const {
55+
return CompletionHandlerParamIndex;
56+
}
57+
4958
/// Retrieve the index of the \c Error? parameter in the completion handler's
5059
/// parameter list. When argument passed to this parameter is non-null, the
5160
/// provided error will be thrown by the async function.
5261
Optional<unsigned> completionHandlerErrorParamIndex() const {
53-
if (CompletionHandlerErrorParamIndex == 0)
62+
if (CompletionHandlerErrorParamIndexPlusOneOrZero == 0)
5463
return None;
5564

56-
return CompletionHandlerErrorParamIndex - 1;
65+
return CompletionHandlerErrorParamIndexPlusOneOrZero - 1;
5766
}
5867

5968
/// Whether the async function is throwing due to the completion handler
6069
/// having an \c Error? parameter.
6170
///
6271
/// Equivalent to \c static_cast<bool>(completionHandlerErrorParamIndex()).
6372
bool isThrowing() const {
64-
return CompletionHandlerErrorParamIndex != 0;
73+
return CompletionHandlerErrorParamIndexPlusOneOrZero != 0;
6574
}
6675
};
6776

@@ -88,7 +97,7 @@ class ForeignAsyncConvention {
8897
/// Retrieve the index of the completion handler parameter, which will be
8998
/// erased from the Swift signature of the imported async function.
9099
unsigned completionHandlerParamIndex() const {
91-
return TheInfo.CompletionHandlerParamIndex;
100+
return TheInfo.completionHandlerParamIndex();
92101
}
93102

94103
/// Retrieve the index of the \c Error? parameter in the completion handler's
@@ -108,10 +117,10 @@ class ForeignAsyncConvention {
108117

109118
bool operator==(ForeignAsyncConvention other) const {
110119
return CompletionHandlerType == other.CompletionHandlerType
111-
&& TheInfo.CompletionHandlerParamIndex ==
112-
other.TheInfo.CompletionHandlerParamIndex
113-
&& TheInfo.CompletionHandlerErrorParamIndex ==
114-
other.TheInfo.CompletionHandlerErrorParamIndex;
120+
&& TheInfo.completionHandlerParamIndex()
121+
== other.TheInfo.completionHandlerParamIndex()
122+
&& TheInfo.completionHandlerErrorParamIndex()
123+
== other.TheInfo.completionHandlerErrorParamIndex();
115124
}
116125

117126
bool operator!=(ForeignAsyncConvention other) const {

include/swift/AST/ForeignInfo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#ifndef SWIFT_FOREIGN_INFO_H
2020
#define SWIFT_FOREIGN_INFO_H
2121

22+
#include "swift/AST/ForeignAsyncConvention.h"
2223
#include "swift/AST/ForeignErrorConvention.h"
2324
#include "swift/AST/Decl.h"
2425

@@ -27,6 +28,7 @@ namespace swift {
2728
struct ForeignInfo {
2829
ImportAsMemberStatus Self;
2930
Optional<ForeignErrorConvention> Error;
31+
Optional<ForeignAsyncConvention> Async;
3032
};
3133

3234
} // end namespace swift

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ CONTEXT_NODE(NativePinningMutableAddressor)
159159
NODE(NominalTypeDescriptor)
160160
NODE(NonObjCAttribute)
161161
NODE(Number)
162+
NODE(ObjCAsyncCompletionHandlerImpl)
162163
NODE(ObjCAttribute)
163164
NODE(ObjCBlock)
164165
NODE(EscapingObjCBlock)

include/swift/SIL/AbstractionPattern.h

Lines changed: 118 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -260,46 +260,116 @@ class AbstractionPattern {
260260
OpaqueDerivativeFunction,
261261
};
262262

263-
class EncodedForeignErrorInfo {
263+
class EncodedForeignInfo {
264264
unsigned Value;
265+
266+
enum Error_t {
267+
Error,
268+
};
269+
270+
enum Async_t {
271+
Async,
272+
};
273+
274+
public:
275+
enum ForeignKind {
276+
IsNotForeign,
277+
IsError,
278+
IsAsync,
279+
};
280+
281+
private:
282+
friend AbstractionPattern;
283+
284+
EncodedForeignInfo() : Value(0) {}
285+
EncodedForeignInfo(Error_t,
286+
unsigned errorParameterIndex,
287+
bool replaceParamWithVoid,
288+
bool stripsResultOptionality)
289+
: Value(1
290+
+ (unsigned(IsError) - 1)
291+
+ (unsigned(stripsResultOptionality) << 1)
292+
+ (unsigned(replaceParamWithVoid) << 2)
293+
+ (errorParameterIndex << 3)) {
294+
assert(getKind() == IsError);
295+
assert(getErrorParamIndex() == errorParameterIndex);
296+
assert(hasErrorParameterReplacedWithVoid() == replaceParamWithVoid);
297+
assert(errorStripsResultOptionality() == stripsResultOptionality);
298+
}
299+
300+
EncodedForeignInfo(Async_t,
301+
unsigned completionParameterIndex,
302+
Optional<unsigned> completionErrorParameterIndex)
303+
: Value(1
304+
+ (unsigned(IsAsync) - 1)
305+
+ (unsigned(completionParameterIndex) << 1)
306+
+ ((completionErrorParameterIndex ? *completionErrorParameterIndex + 1
307+
: 0) << 21)) {
308+
assert(getKind() == IsAsync);
309+
assert(getAsyncCompletionHandlerParamIndex() == completionParameterIndex);
310+
assert(getAsyncCompletionHandlerErrorParamIndex() == completionErrorParameterIndex);
311+
}
265312

266313
public:
267-
EncodedForeignErrorInfo() : Value(0) {}
268-
EncodedForeignErrorInfo(unsigned errorParameterIndex,
269-
bool replaceParamWithVoid,
270-
bool stripsResultOptionality)
271-
: Value(1 +
272-
(unsigned(stripsResultOptionality)) +
273-
(unsigned(replaceParamWithVoid) << 1) +
274-
(errorParameterIndex << 2)) {}
275-
276-
static EncodedForeignErrorInfo
277-
encode(const Optional<ForeignErrorConvention> &foreignError);
314+
static EncodedForeignInfo
315+
encode(const Optional<ForeignErrorConvention> &foreignError,
316+
const Optional<ForeignAsyncConvention> &foreignAsync);
278317

279318
bool hasValue() const { return Value != 0; }
280-
bool hasErrorParameter() const { return hasValue(); }
281-
bool hasUnreplacedErrorParameter() const {
282-
return hasValue() && !isErrorParameterReplacedWithVoid();
319+
ForeignKind getKind() const {
320+
if (!hasValue())
321+
return IsNotForeign;
322+
323+
return ForeignKind((Value - 1 & 1) + 1);
324+
}
325+
326+
bool errorStripsResultOptionality() const {
327+
if (getKind() != IsError) return false;
328+
return (Value - 1) & 2;
283329
}
284330

285-
bool stripsResultOptionality() const {
286-
assert(hasValue());
287-
return (Value - 1) & 1;
331+
bool hasErrorParameterReplacedWithVoid() const {
332+
if (getKind() != IsError) return false;
333+
return (Value - 1) & 4;
288334
}
289335

290-
bool isErrorParameterReplacedWithVoid() const {
291-
assert(hasValue());
292-
return (Value - 1) & 2;
336+
unsigned getErrorParamIndex() const {
337+
assert(getKind() == IsError);
338+
return (Value - 1) >> 3;
293339
}
340+
341+
unsigned getAsyncCompletionHandlerParamIndex() const {
342+
assert(getKind() == IsAsync);
343+
return ((Value - 1) >> 1) & 0xFFFFFu;
344+
}
345+
346+
Optional<unsigned> getAsyncCompletionHandlerErrorParamIndex() const {
347+
assert(getKind() == IsAsync);
294348

295-
unsigned getErrorParameterIndex() const {
296-
assert(hasValue());
297-
return (Value - 1) >> 2;
349+
unsigned encodedValue = (Value - 1) >> 21;
350+
if (encodedValue == 0) {
351+
return llvm::None;
352+
}
353+
return encodedValue - 1;
354+
}
355+
356+
unsigned getForeignParamIndex() const {
357+
switch (getKind()) {
358+
case IsNotForeign:
359+
llvm_unreachable("no foreign param");
360+
361+
case IsError:
362+
return getErrorParamIndex();
363+
364+
case IsAsync:
365+
return getAsyncCompletionHandlerParamIndex();
366+
}
367+
llvm_unreachable("uncovered switch");
298368
}
299369

300370
unsigned getOpaqueValue() const { return Value; }
301-
static EncodedForeignErrorInfo fromOpaqueValue(unsigned value) {
302-
EncodedForeignErrorInfo result;
371+
static EncodedForeignInfo fromOpaqueValue(unsigned value) {
372+
EncodedForeignInfo result;
303373
result.Value = value;
304374
return result;
305375
}
@@ -374,7 +444,7 @@ class AbstractionPattern {
374444
}
375445
}
376446

377-
bool hasStoredForeignErrorInfo() const {
447+
bool hasStoredForeignInfo() const {
378448
return hasStoredObjCMethod();
379449
}
380450

@@ -411,7 +481,7 @@ class AbstractionPattern {
411481

412482
void initObjCMethod(CanGenericSignature signature,
413483
CanType origType, const clang::ObjCMethodDecl *method,
414-
Kind kind, EncodedForeignErrorInfo errorInfo) {
484+
Kind kind, EncodedForeignInfo errorInfo) {
415485
initSwiftType(signature, origType, kind);
416486
ObjCMethod = method;
417487
OtherData = errorInfo.getOpaqueValue();
@@ -519,7 +589,8 @@ class AbstractionPattern {
519589
/// Objective-C method.
520590
static AbstractionPattern
521591
getCurriedObjCMethod(CanType origType, const clang::ObjCMethodDecl *method,
522-
const Optional<ForeignErrorConvention> &foreignError);
592+
const Optional<ForeignErrorConvention> &foreignError,
593+
const Optional<ForeignAsyncConvention> &foreignAsync);
523594

524595
/// Return an abstraction pattern for the uncurried type of a C function
525596
/// imported as a method.
@@ -644,7 +715,7 @@ class AbstractionPattern {
644715
/// Objective-C method.
645716
static AbstractionPattern
646717
getCurriedObjCMethod(CanType origType, const clang::ObjCMethodDecl *method,
647-
EncodedForeignErrorInfo errorInfo) {
718+
EncodedForeignInfo errorInfo) {
648719
assert(isa<AnyFunctionType>(origType));
649720
AbstractionPattern pattern;
650721
pattern.initObjCMethod(nullptr, origType, method,
@@ -670,7 +741,7 @@ class AbstractionPattern {
670741
getPartialCurriedObjCMethod(CanGenericSignature signature,
671742
CanType origType,
672743
const clang::ObjCMethodDecl *method,
673-
EncodedForeignErrorInfo errorInfo) {
744+
EncodedForeignInfo errorInfo) {
674745
assert(isa<AnyFunctionType>(origType));
675746
AbstractionPattern pattern;
676747
pattern.initObjCMethod(signature, origType, method,
@@ -733,14 +804,15 @@ class AbstractionPattern {
733804
/// Return an abstraction pattern for the type of an Objective-C method.
734805
static AbstractionPattern
735806
getObjCMethod(CanType origType, const clang::ObjCMethodDecl *method,
736-
const Optional<ForeignErrorConvention> &foreignError);
807+
const Optional<ForeignErrorConvention> &foreignError,
808+
const Optional<ForeignAsyncConvention> &foreignAsync);
737809

738810
private:
739811
/// Return an abstraction pattern for the uncurried type of an
740812
/// Objective-C method.
741813
static AbstractionPattern
742814
getObjCMethod(CanType origType, const clang::ObjCMethodDecl *method,
743-
EncodedForeignErrorInfo errorInfo) {
815+
EncodedForeignInfo errorInfo) {
744816
assert(isa<AnyFunctionType>(origType));
745817
AbstractionPattern pattern;
746818
pattern.initObjCMethod(nullptr, origType, method, Kind::ObjCMethodType,
@@ -998,9 +1070,9 @@ class AbstractionPattern {
9981070
getKind() == Kind::OpaqueDerivativeFunction);
9991071
}
10001072

1001-
EncodedForeignErrorInfo getEncodedForeignErrorInfo() const {
1002-
assert(hasStoredForeignErrorInfo());
1003-
return EncodedForeignErrorInfo::fromOpaqueValue(OtherData);
1073+
EncodedForeignInfo getEncodedForeignInfo() const {
1074+
assert(hasStoredForeignInfo());
1075+
return EncodedForeignInfo::fromOpaqueValue(OtherData);
10041076
}
10051077

10061078
bool hasForeignErrorStrippingResultOptionality() const {
@@ -1029,8 +1101,8 @@ class AbstractionPattern {
10291101
case Kind::PartialCurriedObjCMethodType:
10301102
case Kind::CurriedObjCMethodType:
10311103
case Kind::ObjCMethodType: {
1032-
auto errorInfo = getEncodedForeignErrorInfo();
1033-
return (errorInfo.hasValue() && errorInfo.stripsResultOptionality());
1104+
auto errorInfo = getEncodedForeignInfo();
1105+
return errorInfo.errorStripsResultOptionality();
10341106
}
10351107
}
10361108
llvm_unreachable("bad kind");
@@ -1203,6 +1275,14 @@ class AbstractionPattern {
12031275
GenericSignature derivativeGenericSignature = GenericSignature(),
12041276
bool makeSelfParamFirst = false);
12051277

1278+
/// If this pattern refers to a foreign ObjC method that was imported as async, this returns
1279+
/// the abstraction pattern for the completion callback with the original ObjC block type.
1280+
///
1281+
/// Otherwise, this produces the default fully-concrete abstraction pattern for the given
1282+
/// Swift type.
1283+
AbstractionPattern getObjCMethodAsyncCompletionHandlerType(
1284+
CanType swiftCompletionHandlerType) const;
1285+
12061286
void dump() const LLVM_ATTRIBUTE_USED;
12071287
void print(raw_ostream &OS) const;
12081288
};

lib/ClangImporter/ImportName.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1965,12 +1965,12 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
19651965
method->hasRelatedResultType(), method->isInstanceMethod(),
19661966
result.getAsyncInfo().map(
19671967
[](const ForeignAsyncConvention::Info &info) {
1968-
return info.CompletionHandlerParamIndex;
1968+
return info.completionHandlerParamIndex();
19691969
}),
19701970
result.getAsyncInfo().map(
19711971
[&](const ForeignAsyncConvention::Info &info) {
19721972
return method->getDeclName().getObjCSelector().getNameForSlot(
1973-
info.CompletionHandlerParamIndex);
1973+
info.completionHandlerParamIndex());
19741974
}),
19751975
*this);
19761976
}

lib/ClangImporter/ImportType.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2218,7 +2218,7 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
22182218
}
22192219

22202220
bool paramIsCompletionHandler =
2221-
asyncInfo && paramIndex == asyncInfo->CompletionHandlerParamIndex;
2221+
asyncInfo && paramIndex == asyncInfo->completionHandlerParamIndex();
22222222

22232223
// Import the parameter type into Swift.
22242224

@@ -2392,8 +2392,8 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
23922392

23932393
if (asyncInfo) {
23942394
asyncConvention = ForeignAsyncConvention(
2395-
completionHandlerType, asyncInfo->CompletionHandlerParamIndex,
2396-
asyncInfo->CompletionHandlerErrorParamIndex);
2395+
completionHandlerType, asyncInfo->completionHandlerParamIndex(),
2396+
asyncInfo->completionHandlerErrorParamIndex());
23972397
}
23982398

23992399
if (errorInfo) {

0 commit comments

Comments
 (0)