Skip to content

Commit 4716371

Browse files
authored
Merge pull request #36061 from jckarter/foreign-async-flag-silgen
SILGen/ClangImporter: Handle async imports with a boolean error flag argument.
2 parents 6189e8e + fb199df commit 4716371

File tree

17 files changed

+338
-63
lines changed

17 files changed

+338
-63
lines changed

docs/ABI/Mangling.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,8 @@ types where the metadata itself has unknown layout.)
222222
global ::= global 'Tm' // merged function
223223
global ::= entity // some identifiable thing
224224
global ::= from-type to-type generic-signature? 'TR' // reabstraction thunk
225-
global ::= impl-function-type type 'Tz' // objc-to-swift-async completion handler block implementation
226-
global ::= impl-function-type type 'TZ' // objc-to-swift-async completion handler block implementation (predefined by runtime)
225+
global ::= impl-function-type type 'Tz' index? // objc-to-swift-async completion handler block implementation
226+
global ::= impl-function-type type 'TZ' index? // objc-to-swift-async completion handler block implementation (predefined by runtime)
227227
global ::= from-type to-type generic-signature? 'TR' // reabstraction thunk
228228
global ::= impl-function-type type generic-signature? 'Tz' // objc-to-swift-async completion handler block implementation
229229
global ::= impl-function-type type generic-signature? 'TZ' // objc-to-swift-async completion handler block implementation (predefined by runtime)

include/swift/AST/ASTMangler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ class ASTMangler : public Mangler {
172172
std::string mangleObjCAsyncCompletionHandlerImpl(CanSILFunctionType BlockType,
173173
CanType ResultType,
174174
CanGenericSignature Sig,
175+
Optional<bool> FlagParamIsZeroOnError,
175176
bool predefined);
176177

177178
/// Mangle the derivative function (JVP/VJP), or optionally its vtable entry

include/swift/SIL/AbstractionPattern.h

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,20 @@ class AbstractionPattern {
276276
Async,
277277
};
278278

279+
enum {
280+
AsyncCompletionParameterIndexMask = 0xFFEu,
281+
AsyncCompletionParameterIndexShift = 1,
282+
283+
AsyncCompletionErrorParameterIndexMask = 0x1FF000u,
284+
AsyncCompletionErrorParameterIndexShift = 12,
285+
286+
AsyncCompletionErrorFlagParameterIndexMask = 0x3FE00000u,
287+
AsyncCompletionErrorFlagParameterIndexShift = 21,
288+
289+
AsyncCompletionErrorFlagParameterPolarityMask = 0x40000000u,
290+
AsyncCompletionErrorFlagParameterPolarityShift = 30,
291+
};
292+
279293
public:
280294
enum ForeignKind {
281295
IsNotForeign,
@@ -304,16 +318,24 @@ class AbstractionPattern {
304318

305319
EncodedForeignInfo(Async_t,
306320
unsigned completionParameterIndex,
307-
Optional<unsigned> completionErrorParameterIndex)
308-
: Value(1
309-
+ (unsigned(IsAsync) - 1)
310-
+ (unsigned(completionParameterIndex) << 1)
311-
+ ((completionErrorParameterIndex ? *completionErrorParameterIndex + 1
312-
: 0) << 21)) {
313-
assert(getKind() == IsAsync);
314-
assert(getAsyncCompletionHandlerParamIndex() == completionParameterIndex);
315-
assert(getAsyncCompletionHandlerErrorParamIndex() == completionErrorParameterIndex);
316-
}
321+
Optional<unsigned> completionErrorParameterIndex,
322+
Optional<unsigned> completionErrorFlagParameterIndex,
323+
bool completionErrorFlagIsZeroOnError)
324+
: Value(1
325+
+ (unsigned(IsAsync) - 1)
326+
+ (unsigned(completionParameterIndex) << AsyncCompletionParameterIndexShift)
327+
+ ((completionErrorParameterIndex ? *completionErrorParameterIndex + 1
328+
: 0) << AsyncCompletionErrorParameterIndexShift)
329+
+ ((completionErrorFlagParameterIndex ? *completionErrorFlagParameterIndex + 1
330+
: 0) << AsyncCompletionErrorFlagParameterIndexShift)
331+
+ (unsigned(completionErrorFlagIsZeroOnError) << AsyncCompletionErrorFlagParameterPolarityShift)){
332+
333+
assert(getKind() == IsAsync);
334+
assert(getAsyncCompletionHandlerParamIndex() == completionParameterIndex);
335+
assert(getAsyncCompletionHandlerErrorParamIndex() == completionErrorParameterIndex);
336+
assert(getAsyncCompletionHandlerErrorFlagParamIndex() == completionErrorFlagParameterIndex);
337+
assert(isCompletionErrorFlagZeroOnError() == completionErrorFlagIsZeroOnError);
338+
}
317339

318340
public:
319341
static EncodedForeignInfo
@@ -345,18 +367,37 @@ class AbstractionPattern {
345367

346368
unsigned getAsyncCompletionHandlerParamIndex() const {
347369
assert(getKind() == IsAsync);
348-
return ((Value - 1) >> 1) & 0xFFFFFu;
370+
return ((Value - 1) & AsyncCompletionParameterIndexMask)
371+
>> AsyncCompletionParameterIndexShift;
349372
}
350373

351374
Optional<unsigned> getAsyncCompletionHandlerErrorParamIndex() const {
352375
assert(getKind() == IsAsync);
353376

354-
unsigned encodedValue = (Value - 1) >> 21;
377+
unsigned encodedValue = ((Value - 1) & AsyncCompletionErrorParameterIndexMask)
378+
>> AsyncCompletionErrorParameterIndexShift;
379+
if (encodedValue == 0) {
380+
return llvm::None;
381+
}
382+
return encodedValue - 1;
383+
}
384+
385+
Optional<unsigned> getAsyncCompletionHandlerErrorFlagParamIndex() const {
386+
assert(getKind() == IsAsync);
387+
388+
unsigned encodedValue = ((Value - 1) & AsyncCompletionErrorFlagParameterIndexMask)
389+
>> AsyncCompletionErrorFlagParameterIndexShift;
355390
if (encodedValue == 0) {
356391
return llvm::None;
357392
}
358393
return encodedValue - 1;
359394
}
395+
396+
bool isCompletionErrorFlagZeroOnError() const {
397+
assert(getKind() == IsAsync);
398+
399+
return (Value - 1) & AsyncCompletionErrorFlagParameterPolarityMask;
400+
}
360401

361402
unsigned getForeignParamIndex() const {
362403
switch (getKind()) {

lib/AST/ASTMangler.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,13 +399,17 @@ std::string ASTMangler::mangleObjCAsyncCompletionHandlerImpl(
399399
CanSILFunctionType BlockType,
400400
CanType ResultType,
401401
CanGenericSignature Sig,
402+
Optional<bool> ErrorOnZero,
402403
bool predefined) {
403404
beginMangling();
404405
appendType(BlockType);
405406
appendType(ResultType);
406407
if (Sig)
407408
appendGenericSignature(Sig);
408-
appendOperator(predefined ? "TZ" : "Tz");
409+
if (ErrorOnZero)
410+
appendOperator(predefined ? "TZ" : "Tz", Index(*ErrorOnZero + 1));
411+
else
412+
appendOperator(predefined ? "TZ" : "Tz", Index(0));
409413
return finalize();
410414
}
411415

lib/ClangImporter/ImportName.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,8 +1497,23 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
14971497
swiftAsyncAttr->getCompletionHandlerIndex().getASTIndex();
14981498
}
14991499

1500-
// TODO: Check for the swift_async_error attribute here when Clang
1501-
// implements it
1500+
if (const auto *asyncErrorAttr = D->getAttr<clang::SwiftAsyncErrorAttr>()) {
1501+
switch (auto convention = asyncErrorAttr->getConvention()) {
1502+
// No flag parameter in these cases.
1503+
case clang::SwiftAsyncErrorAttr::NonNullError:
1504+
case clang::SwiftAsyncErrorAttr::None:
1505+
break;
1506+
1507+
// Get the flag argument index and polarity from the attribute.
1508+
case clang::SwiftAsyncErrorAttr::NonZeroArgument:
1509+
case clang::SwiftAsyncErrorAttr::ZeroArgument:
1510+
// NB: Attribute is 1-based rather than 0-based.
1511+
completionHandlerFlagParamIndex = asyncErrorAttr->getHandlerParamIdx() - 1;
1512+
completionHandlerFlagIsZeroOnError =
1513+
convention == clang::SwiftAsyncErrorAttr::ZeroArgument;
1514+
break;
1515+
}
1516+
}
15021517
}
15031518

15041519
// FIXME: ugly to check here, instead perform unified check up front in

lib/ClangImporter/ImportType.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2120,11 +2120,14 @@ static Type decomposeCompletionHandlerType(
21202120
if (param.isInOut() || param.isVariadic())
21212121
return Type();
21222122

2123-
// If there is an error parameter to the completion handler, it is
2123+
// If there are error-related parameters to the completion handler, they are
21242124
// not part of the result type of the asynchronous function.
21252125
if (info.completionHandlerErrorParamIndex() &&
21262126
paramIdx == *info.completionHandlerErrorParamIndex())
21272127
continue;
2128+
if (info.completionHandlerFlagParamIndex() &&
2129+
paramIdx == *info.completionHandlerFlagParamIndex())
2130+
continue;
21282131

21292132
resultTypeElts.push_back(param.getPlainType());
21302133
}

lib/Demangling/Demangler.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2301,13 +2301,14 @@ NodePointer Demangler::demangleThunkOrSpecialization() {
23012301
}
23022302
case 'z':
23032303
case 'Z': {
2304+
NodePointer flagMode = demangleIndexAsNode();
23042305
NodePointer sig = popNode(Node::Kind::DependentGenericSignature);
23052306
NodePointer resultType = popNode(Node::Kind::Type);
23062307
NodePointer implType = popNode(Node::Kind::Type);
23072308
auto node = createWithChildren(c == 'z'
23082309
? Node::Kind::ObjCAsyncCompletionHandlerImpl
23092310
: Node::Kind::PredefinedObjCAsyncCompletionHandlerImpl,
2310-
implType, resultType);
2311+
implType, resultType, flagMode);
23112312
if (sig)
23122313
addChild(node, sig);
23132314
return node;

lib/Demangling/NodePrinter.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2742,9 +2742,24 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
27422742
LLVM_FALLTHROUGH;
27432743
case Node::Kind::ObjCAsyncCompletionHandlerImpl:
27442744
Printer << "@objc completion handler block implementation for ";
2745+
if (Node->getNumChildren() >= 4)
2746+
print(Node->getChild(3));
27452747
print(Node->getChild(0));
27462748
Printer << " with result type ";
27472749
print(Node->getChild(1));
2750+
switch (Node->getChild(2)->getIndex()) {
2751+
case 0:
2752+
break;
2753+
case 1:
2754+
Printer << " nonzero on error";
2755+
break;
2756+
case 2:
2757+
Printer << " zero on error";
2758+
break;
2759+
default:
2760+
Printer << " <invalid error flag>";
2761+
break;
2762+
}
27482763
return nullptr;
27492764
case Node::Kind::CanonicalPrespecializedGenericTypeCachingOnceToken:
27502765
Printer << "flag for loading of canonical specialized generic type "

lib/Demangling/Remangler.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -820,8 +820,12 @@ void Remangler::manglePredefinedObjCAsyncCompletionHandlerImpl(Node *node) {
820820
}
821821

822822
void Remangler::mangleObjCAsyncCompletionHandlerImpl(Node *node) {
823-
mangleChildNodes(node);
823+
mangleChildNode(node, 0);
824+
mangleChildNode(node, 1);
825+
if (node->getNumChildren() == 4)
826+
mangleChildNode(node, 3);
824827
Buffer << "Tz";
828+
mangleChildNode(node, 2);
825829
}
826830

827831
void Remangler::mangleDeallocator(Node *node) {

lib/SIL/IR/AbstractionPattern.cpp

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,9 @@ AbstractionPattern::EncodedForeignInfo::encode(
132132
if (foreignAsync.hasValue()) {
133133
return EncodedForeignInfo(EncodedForeignInfo::Async,
134134
foreignAsync->completionHandlerParamIndex(),
135-
foreignAsync->completionHandlerErrorParamIndex());
135+
foreignAsync->completionHandlerErrorParamIndex(),
136+
foreignAsync->completionHandlerFlagParamIndex(),
137+
foreignAsync->completionHandlerFlagIsErrorOnZero());
136138
} else if (foreignError.hasValue()) {
137139
return EncodedForeignInfo(EncodedForeignInfo::Error,
138140
foreignError->getErrorParameterIndex(),
@@ -404,11 +406,17 @@ AbstractionPattern::getTupleElementType(unsigned index) const {
404406

405407
case Kind::ObjCCompletionHandlerArgumentsType: {
406408
// Match up the tuple element with the parameter from the Clang block type,
407-
// skipping the error parameter index if any.
409+
// skipping the error parameter and flag indexes if any.
408410
auto callback = cast<clang::FunctionProtoType>(getClangType());
409411
auto errorIndex = getEncodedForeignInfo()
410412
.getAsyncCompletionHandlerErrorParamIndex();
411-
unsigned paramIndex = index + (errorIndex && index >= *errorIndex);
413+
auto flagIndex = getEncodedForeignInfo()
414+
.getAsyncCompletionHandlerErrorFlagParamIndex();
415+
unsigned paramIndex = index;
416+
if (errorIndex && paramIndex >= *errorIndex)
417+
++paramIndex;
418+
if (flagIndex && paramIndex >= *flagIndex)
419+
++paramIndex;
412420
return AbstractionPattern(getGenericSignature(),
413421
getCanTupleElementType(getType(), index),
414422
callback->getParamType(paramIndex).getTypePtr());
@@ -544,12 +552,18 @@ AbstractionPattern AbstractionPattern::getFunctionResultType() const {
544552
// any.
545553

546554
auto callbackErrorIndex = getEncodedForeignInfo()
547-
.getAsyncCompletionHandlerErrorParamIndex();
555+
.getAsyncCompletionHandlerErrorParamIndex();
556+
auto callbackErrorFlagIndex = getEncodedForeignInfo()
557+
.getAsyncCompletionHandlerErrorFlagParamIndex();
548558
assert((!callbackErrorIndex.hasValue()
549559
|| callbackParamTy->getNumParams() > *callbackErrorIndex)
550560
&& "completion handler has invalid error param index?!");
561+
assert((!callbackErrorFlagIndex.hasValue()
562+
|| callbackParamTy->getNumParams() > *callbackErrorFlagIndex)
563+
&& "completion handler has invalid error param index?!");
551564
unsigned numNonErrorParams
552-
= callbackParamTy->getNumParams() - callbackErrorIndex.hasValue();
565+
= callbackParamTy->getNumParams() - callbackErrorIndex.hasValue()
566+
- callbackErrorFlagIndex.hasValue();
553567

554568
switch (numNonErrorParams) {
555569
case 0:
@@ -560,8 +574,13 @@ AbstractionPattern AbstractionPattern::getFunctionResultType() const {
560574
case 1: {
561575
// If there's a single argument, abstract it according to its formal type
562576
// in the ObjC signature.
563-
unsigned callbackResultIndex
564-
= callbackErrorIndex && *callbackErrorIndex == 0;
577+
unsigned callbackResultIndex = 0;
578+
if (callbackErrorIndex && callbackResultIndex >= *callbackErrorIndex)
579+
++callbackResultIndex;
580+
if (callbackErrorFlagIndex
581+
&& callbackResultIndex >= *callbackErrorFlagIndex)
582+
++callbackResultIndex;
583+
565584
auto clangResultType = callbackParamTy
566585
->getParamType(callbackResultIndex)
567586
.getTypePtr();
@@ -1031,7 +1050,14 @@ void AbstractionPattern::print(raw_ostream &out) const {
10311050
case EncodedForeignInfo::IsAsync:
10321051
out << ", completionHandlerParameter=" << errorInfo.getAsyncCompletionHandlerParamIndex();
10331052
if (auto errorParam = errorInfo.getAsyncCompletionHandlerErrorParamIndex()) {
1034-
out << " (errorParam=" << *errorParam << ')';
1053+
out << " (errorParam=" << *errorParam;
1054+
if (auto errorFlag = errorInfo.getAsyncCompletionHandlerErrorFlagParamIndex()) {
1055+
out << ", errorFlagParam=" << *errorFlag
1056+
<< (errorInfo.isCompletionErrorFlagZeroOnError()
1057+
? ", zeroOnError"
1058+
: ", nonzeroOnError");
1059+
}
1060+
out << ')';
10351061
}
10361062
}
10371063
out << ", ";

0 commit comments

Comments
 (0)