Skip to content

Commit 7ab9e87

Browse files
committed
SILGen: Stub out support for invoking foreign async methods.
Allow SILGen to not crash when invoking foreign async methods by emitting `undef` for the completion callback going into the call, and for the results that would be channeled back through awaiting the continuation.
1 parent 06c95cc commit 7ab9e87

File tree

7 files changed

+187
-119
lines changed

7 files changed

+187
-119
lines changed

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/SILGen/Callee.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef SWIFT_SILGEN_CALLEE_H
1414
#define SWIFT_SILGEN_CALLEE_H
1515

16+
#include "swift/AST/ForeignAsyncConvention.h"
1617
#include "swift/AST/ForeignErrorConvention.h"
1718
#include "swift/AST/Types.h"
1819
#include "swift/SIL/AbstractionPattern.h"
@@ -25,8 +26,12 @@ class CalleeTypeInfo {
2526
CanSILFunctionType substFnType;
2627
Optional<AbstractionPattern> origResultType;
2728
CanType substResultType;
28-
Optional<ForeignErrorConvention> foreignError;
29-
ImportAsMemberStatus foreignSelf;
29+
struct ForeignInfo {
30+
Optional<ForeignErrorConvention> error;
31+
Optional<ForeignAsyncConvention> async;
32+
ImportAsMemberStatus self;
33+
};
34+
ForeignInfo foreign;
3035

3136
private:
3237
Optional<SILFunctionTypeRepresentation> overrideRep;
@@ -37,17 +42,19 @@ class CalleeTypeInfo {
3742
CalleeTypeInfo(CanSILFunctionType substFnType,
3843
AbstractionPattern origResultType, CanType substResultType,
3944
const Optional<ForeignErrorConvention> &foreignError,
45+
const Optional<ForeignAsyncConvention> &foreignAsync,
4046
ImportAsMemberStatus foreignSelf,
4147
Optional<SILFunctionTypeRepresentation> overrideRep = None)
4248
: substFnType(substFnType), origResultType(origResultType),
43-
substResultType(substResultType), foreignError(foreignError),
44-
foreignSelf(foreignSelf), overrideRep(overrideRep) {}
49+
substResultType(substResultType),
50+
foreign{foreignError, foreignAsync, foreignSelf},
51+
overrideRep(overrideRep) {}
4552

4653
CalleeTypeInfo(CanSILFunctionType substFnType,
4754
AbstractionPattern origResultType, CanType substResultType,
4855
Optional<SILFunctionTypeRepresentation> overrideRep = None)
4956
: substFnType(substFnType), origResultType(origResultType),
50-
substResultType(substResultType), foreignError(), foreignSelf(),
57+
substResultType(substResultType), foreign(),
5158
overrideRep(overrideRep) {}
5259

5360
SILFunctionTypeRepresentation getOverrideRep() const {

lib/SILGen/ResultPlan.cpp

Lines changed: 75 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,33 @@ class TupleInitializationResultPlan final : public ResultPlan {
451451
}
452452
};
453453

454+
class ForeignAsyncInitializationPlan final : public ResultPlan {
455+
SILGenFunction &SGF;
456+
SILLocation loc;
457+
public:
458+
ForeignAsyncInitializationPlan(SILGenFunction &SGF, SILLocation loc)
459+
: SGF(SGF), loc(loc) {
460+
}
461+
462+
void
463+
gatherIndirectResultAddrs(SILGenFunction &SGF, SILLocation loc,
464+
SmallVectorImpl<SILValue> &outList) const override {
465+
// TODO: Move values from the continuation result buffer to the individual
466+
// out argument buffers, unless we were able to emit the resume buffer
467+
// in-place.
468+
}
469+
470+
RValue finish(SILGenFunction &SGF, SILLocation loc, CanType substType,
471+
ArrayRef<ManagedValue> &directResults) override {
472+
// There should be no direct results from the call.
473+
assert(directResults.empty());
474+
475+
// TODO: Get the actual result values from the awaited continuation.
476+
// For now, produce an undef RValue.
477+
return SGF.emitUndefRValue(loc, substType);
478+
}
479+
};
480+
454481
class ForeignErrorInitializationPlan final : public ResultPlan {
455482
SILLocation loc;
456483
LValue lvalue;
@@ -467,7 +494,7 @@ class ForeignErrorInitializationPlan final : public ResultPlan {
467494
ResultPlanPtr &&subPlan)
468495
: loc(loc), subPlan(std::move(subPlan)) {
469496
unsigned errorParamIndex =
470-
calleeTypeInfo.foreignError->getErrorParameterIndex();
497+
calleeTypeInfo.foreign.error->getErrorParameterIndex();
471498
auto substFnType = calleeTypeInfo.substFnType;
472499
SILParameterInfo errorParameter =
473500
substFnType->getParameters()[errorParamIndex];
@@ -543,51 +570,56 @@ class ForeignErrorInitializationPlan final : public ResultPlan {
543570
/// If the initialization is non-null, the result plan will emit into it.
544571
ResultPlanPtr ResultPlanBuilder::buildTopLevelResult(Initialization *init,
545572
SILLocation loc) {
546-
// First check if we do not have a foreign error. If we don't, just call
547-
// build.
548-
auto foreignError = calleeTypeInfo.foreignError;
549-
if (!foreignError) {
573+
// First check if we have a foreign error and/or async convention.
574+
if (auto foreignAsync = calleeTypeInfo.foreign.async) {
575+
// Create a result plan that gets the result schema from the completion
576+
// handler callback's arguments.
577+
// completion handler.
578+
return ResultPlanPtr(new ForeignAsyncInitializationPlan(SGF, loc));
579+
580+
} else if (auto foreignError = calleeTypeInfo.foreign.error) {
581+
// Handle the foreign error first.
582+
//
583+
// The plan needs to be built using the formal result type after foreign-error
584+
// adjustment.
585+
switch (foreignError->getKind()) {
586+
// These conventions make the formal result type ().
587+
case ForeignErrorConvention::ZeroResult:
588+
case ForeignErrorConvention::NonZeroResult:
589+
assert(calleeTypeInfo.substResultType->isVoid());
590+
allResults.clear();
591+
break;
592+
593+
// These conventions leave the formal result alone.
594+
case ForeignErrorConvention::ZeroPreservedResult:
595+
case ForeignErrorConvention::NonNilError:
596+
break;
597+
598+
// This convention changes the formal result to the optional object type; we
599+
// need to make our own make SILResultInfo array.
600+
case ForeignErrorConvention::NilResult: {
601+
assert(allResults.size() == 1);
602+
auto substFnTy = calleeTypeInfo.substFnType;
603+
CanType objectType = allResults[0]
604+
.getReturnValueType(SGF.SGM.M, substFnTy,
605+
SGF.getTypeExpansionContext())
606+
.getOptionalObjectType();
607+
SILResultInfo optResult = allResults[0].getWithInterfaceType(objectType);
608+
allResults.clear();
609+
allResults.push_back(optResult);
610+
break;
611+
}
612+
}
613+
614+
ResultPlanPtr subPlan = build(init, calleeTypeInfo.origResultType.getValue(),
615+
calleeTypeInfo.substResultType);
616+
return ResultPlanPtr(new ForeignErrorInitializationPlan(
617+
SGF, loc, calleeTypeInfo, std::move(subPlan)));
618+
} else {
619+
// Otherwise, we can just call build.
550620
return build(init, calleeTypeInfo.origResultType.getValue(),
551621
calleeTypeInfo.substResultType);
552622
}
553-
554-
// Otherwise, handle the foreign error first.
555-
//
556-
// The plan needs to be built using the formal result type after foreign-error
557-
// adjustment.
558-
switch (foreignError->getKind()) {
559-
// These conventions make the formal result type ().
560-
case ForeignErrorConvention::ZeroResult:
561-
case ForeignErrorConvention::NonZeroResult:
562-
assert(calleeTypeInfo.substResultType->isVoid());
563-
allResults.clear();
564-
break;
565-
566-
// These conventions leave the formal result alone.
567-
case ForeignErrorConvention::ZeroPreservedResult:
568-
case ForeignErrorConvention::NonNilError:
569-
break;
570-
571-
// This convention changes the formal result to the optional object type; we
572-
// need to make our own make SILResultInfo array.
573-
case ForeignErrorConvention::NilResult: {
574-
assert(allResults.size() == 1);
575-
auto substFnTy = calleeTypeInfo.substFnType;
576-
CanType objectType = allResults[0]
577-
.getReturnValueType(SGF.SGM.M, substFnTy,
578-
SGF.getTypeExpansionContext())
579-
.getOptionalObjectType();
580-
SILResultInfo optResult = allResults[0].getWithInterfaceType(objectType);
581-
allResults.clear();
582-
allResults.push_back(optResult);
583-
break;
584-
}
585-
}
586-
587-
ResultPlanPtr subPlan = build(init, calleeTypeInfo.origResultType.getValue(),
588-
calleeTypeInfo.substResultType);
589-
return ResultPlanPtr(new ForeignErrorInitializationPlan(
590-
SGF, loc, calleeTypeInfo, std::move(subPlan)));
591623
}
592624

593625
/// Build a result plan for the results of an apply.

0 commit comments

Comments
 (0)