Skip to content

Commit eba057f

Browse files
committed
[Async CC] Move thick context into async context.
Previously, the thick context was passed as a fourth parameter to partial apply forwarders. Here, the thick context is instead moved into the async context at the local context position. To support this, the local context is made always available.
1 parent c2b3be4 commit eba057f

15 files changed

+101
-95
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 38 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ irgen::getAsyncContextLayout(IRGenModule &IGM, CanSILFunctionType originalType,
156156
typeInfos.push_back(&errorTypeInfo);
157157
valTypes.push_back(errorType);
158158

159+
bool canHaveValidError = substitutedType->hasErrorResult();
160+
159161
// IndirectResultTypes *indirectResults...;
160162
auto indirectResults = fnConv.getIndirectSILResults();
161163
for (auto indirectResult : indirectResults) {
@@ -196,15 +198,35 @@ irgen::getAsyncContextLayout(IRGenModule &IGM, CanSILFunctionType originalType,
196198
}
197199

198200
// SelfType self?;
199-
bool hasLocalContextParameter = hasSelfContextParameter(substitutedType);
200-
bool canHaveValidError = substitutedType->hasErrorResult();
201-
bool hasLocalContext = (hasLocalContextParameter || canHaveValidError);
201+
bool hasSelf = hasSelfContextParameter(substitutedType);
202202
SILParameterInfo localContextParameter =
203-
hasLocalContextParameter ? parameters.back() : SILParameterInfo();
204-
if (hasLocalContextParameter) {
203+
hasSelf ? parameters.back() : SILParameterInfo();
204+
if (hasSelf) {
205205
parameters = parameters.drop_back();
206206
}
207207

208+
Optional<AsyncContextLayout::ArgumentInfo> localContextInfo = llvm::None;
209+
if (hasSelf) {
210+
assert(originalType->getRepresentation() !=
211+
SILFunctionTypeRepresentation::Thick);
212+
SILType ty = IGM.silConv.getSILType(localContextParameter, substitutedType,
213+
IGM.getMaximalTypeExpansionContext());
214+
auto argumentLoweringType =
215+
getArgumentLoweringType(ty.getASTType(), localContextParameter,
216+
/*isNoEscape*/ true);
217+
218+
auto &ti = IGM.getTypeInfoForLowered(argumentLoweringType);
219+
valTypes.push_back(ty);
220+
typeInfos.push_back(&ti);
221+
localContextInfo = {ty, localContextParameter.getConvention()};
222+
} else {
223+
auto &ti = IGM.getNativeObjectTypeInfo();
224+
SILType ty = SILType::getNativeObjectType(IGM.Context);
225+
valTypes.push_back(ty);
226+
typeInfos.push_back(&ti);
227+
localContextInfo = {ty, substitutedType->getCalleeConvention()};
228+
}
229+
208230
// ArgTypes formalArguments...;
209231
for (auto parameter : parameters) {
210232
SILType ty = IGM.silConv.getSILType(parameter, substitutedType,
@@ -230,31 +252,6 @@ irgen::getAsyncContextLayout(IRGenModule &IGM, CanSILFunctionType originalType,
230252
typeInfos.push_back(&bindingsTI);
231253
}
232254

233-
Optional<AsyncContextLayout::ArgumentInfo> localContextInfo = llvm::None;
234-
if (hasLocalContext) {
235-
if (hasLocalContextParameter) {
236-
SILType ty =
237-
IGM.silConv.getSILType(localContextParameter, substitutedType,
238-
IGM.getMaximalTypeExpansionContext());
239-
auto argumentLoweringType =
240-
getArgumentLoweringType(ty.getASTType(), localContextParameter,
241-
/*isNoEscape*/ true);
242-
243-
auto &ti = IGM.getTypeInfoForLowered(argumentLoweringType);
244-
valTypes.push_back(ty);
245-
typeInfos.push_back(&ti);
246-
localContextInfo = {ty, localContextParameter.getConvention()};
247-
} else {
248-
// TODO: DETERMINE: Is there a field in this case to match the sync ABI?
249-
auto &ti = IGM.getNativeObjectTypeInfo();
250-
SILType ty = SILType::getNativeObjectType(IGM.Context);
251-
valTypes.push_back(ty);
252-
typeInfos.push_back(&ti);
253-
localContextInfo = {ty, substitutedType->getCalleeConvention()};
254-
}
255-
}
256-
257-
258255
Optional<AsyncContextLayout::TrailingWitnessInfo> trailingWitnessInfo;
259256
if (originalType->getRepresentation() ==
260257
SILFunctionTypeRepresentation::WitnessMethod) {
@@ -778,10 +775,6 @@ void SignatureExpansion::addAsyncParameters() {
778775
ParamIRTypes.push_back(IGM.SwiftTaskPtrTy);
779776
ParamIRTypes.push_back(IGM.SwiftExecutorPtrTy);
780777
ParamIRTypes.push_back(IGM.SwiftContextPtrTy);
781-
if (FnType->getRepresentation() == SILFunctionTypeRepresentation::Thick) {
782-
IGM.addSwiftSelfAttributes(Attrs, ParamIRTypes.size());
783-
ParamIRTypes.push_back(IGM.RefCountedPtrTy);
784-
}
785778
}
786779

787780
void SignatureExpansion::addCoroutineContextParameter() {
@@ -2314,10 +2307,6 @@ class AsyncCallEmission final : public CallEmission {
23142307
asyncExplosion.add(IGF.getAsyncTask());
23152308
asyncExplosion.add(IGF.getAsyncExecutor());
23162309
asyncExplosion.add(contextBuffer.getAddress());
2317-
if (getCallee().getRepresentation() ==
2318-
SILFunctionTypeRepresentation::Thick) {
2319-
asyncExplosion.add(getCallee().getSwiftContext());
2320-
}
23212310
super::setArgs(asyncExplosion, false, witnessMetadata);
23222311
SILFunctionConventions fnConv(getCallee().getSubstFunctionType(),
23232312
IGF.getSILModule());
@@ -2380,11 +2369,18 @@ class AsyncCallEmission final : public CallEmission {
23802369
auto bindingsAddr = bindingLayout.project(IGF, context, /*offsets*/ None);
23812370
layout.getBindings().save(IGF, bindingsAddr, llArgs);
23822371
}
2383-
if (selfValue) {
2384-
Explosion selfExplosion;
2385-
selfExplosion.add(selfValue);
2372+
auto isThick =
2373+
getCallee().getRepresentation() == SILFunctionTypeRepresentation::Thick;
2374+
if (selfValue || isThick) {
2375+
Explosion localExplosion;
2376+
if (selfValue) {
2377+
assert(!isThick);
2378+
localExplosion.add(selfValue);
2379+
} else {
2380+
localExplosion.add(getCallee().getSwiftContext());
2381+
}
23862382
auto fieldLayout = layout.getLocalContextLayout();
2387-
saveValue(fieldLayout, selfExplosion, isOutlined);
2383+
saveValue(fieldLayout, localExplosion, isOutlined);
23882384
}
23892385
}
23902386
void emitCallToUnmappedExplosion(llvm::CallInst *call, Explosion &out) override {

lib/IRGen/GenCall.h

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ namespace irgen {
8181
// };
8282
// ResultTypes directResults...;
8383
// };
84+
// SelfType self;
8485
// ArgTypes formalArguments...;
85-
// SelfType self?;
8686
// };
8787
struct AsyncContextLayout : StructLayout {
8888
struct ArgumentInfo {
@@ -177,7 +177,14 @@ namespace irgen {
177177
return getIndexAfterDirectReturns();
178178
}
179179
}
180-
unsigned getFirstArgumentIndex() { return getIndexAfterUnion(); }
180+
unsigned getLocalContextIndex() {
181+
assert(hasLocalContext());
182+
return getIndexAfterUnion();
183+
}
184+
unsigned getIndexAfterLocalContext() {
185+
return getIndexAfterUnion() + (hasLocalContext() ? 1 : 0);
186+
}
187+
unsigned getFirstArgumentIndex() { return getIndexAfterLocalContext(); }
181188
unsigned getIndexAfterArguments() {
182189
return getFirstArgumentIndex() + getArgumentCount();
183190
}
@@ -188,24 +195,16 @@ namespace irgen {
188195
unsigned getIndexAfterBindings() {
189196
return getIndexAfterArguments() + (hasBindings() ? 1 : 0);
190197
}
191-
unsigned getLocalContextIndex() {
192-
assert(hasLocalContext());
193-
return getIndexAfterBindings();
194-
}
195-
unsigned getIndexAfterLocalContext() {
196-
return getIndexAfterBindings() +
197-
(hasLocalContext() ? 1 : 0);
198-
}
199198
unsigned getSelfMetadataIndex() {
200199
assert(hasTrailingWitnesses());
201-
return getIndexAfterLocalContext();
200+
return getIndexAfterBindings();
202201
}
203202
unsigned getSelfWitnessTableIndex() {
204203
assert(hasTrailingWitnesses());
205-
return getIndexAfterLocalContext() + 1;
204+
return getIndexAfterBindings() + 1;
206205
}
207206
unsigned getIndexAfterTrailingWitnesses() {
208-
return getIndexAfterLocalContext() + (hasTrailingWitnesses() ? 2 : 0);
207+
return getIndexAfterBindings() + (hasTrailingWitnesses() ? 2 : 0);
209208
}
210209

211210
public:

lib/IRGen/GenFunc.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,7 +1019,6 @@ class AsyncPartialApplicationForwarderEmission
10191019
llvm::Value *contextBuffer;
10201020
Size contextSize;
10211021
Address context;
1022-
llvm::Value *heapContextBuffer;
10231022
unsigned currentArgumentIndex;
10241023
struct DynamicFunction {
10251024
using Kind = DynamicFunctionKind;
@@ -1072,13 +1071,13 @@ class AsyncPartialApplicationForwarderEmission
10721071
task = origParams.claimNext();
10731072
executor = origParams.claimNext();
10741073
contextBuffer = origParams.claimNext();
1075-
heapContextBuffer = origParams.claimNext();
10761074
}
10771075

10781076
void begin() override {
10791077
super::begin();
1078+
assert(task);
1079+
assert(executor);
10801080
assert(contextBuffer);
1081-
assert(heapContextBuffer);
10821081
context = layout.emitCastTo(subIGF, contextBuffer);
10831082
}
10841083
bool transformArgumentToNative(SILParameterInfo origParamInfo, Explosion &in,
@@ -1125,7 +1124,9 @@ class AsyncPartialApplicationForwarderEmission
11251124
SILParameterInfo getParameterInfo(unsigned index) override {
11261125
return origType->getParameters()[index];
11271126
}
1128-
llvm::Value *getContext() override { return heapContextBuffer; }
1127+
llvm::Value *getContext() override {
1128+
return loadValue(layout.getLocalContextLayout());
1129+
}
11291130
llvm::Value *getDynamicFunctionPointer() override {
11301131
assert(dynamicFunction && dynamicFunction->pointer);
11311132
auto *context = dynamicFunction->context;
@@ -1248,8 +1249,15 @@ class AsyncPartialApplicationForwarderEmission
12481249
asyncExplosion.add(contextBuffer);
12491250
if (dynamicFunction &&
12501251
dynamicFunction->kind == DynamicFunction::Kind::PartialApply) {
1252+
// Just before making the call, replace the old thick context with the
1253+
// new thick context so that (1) the new thick context is never used by
1254+
// this partial apply forwarder and (2) the old thick context is never
1255+
// used by the callee partial apply forwarder.
12511256
assert(dynamicFunction->context);
1252-
asyncExplosion.add(dynamicFunction->context);
1257+
auto fieldLayout = layout.getLocalContextLayout();
1258+
Explosion explosion;
1259+
explosion.add(dynamicFunction->context);
1260+
saveValue(fieldLayout, explosion);
12531261
}
12541262

12551263
return subIGF.Builder.CreateCall(fnPtr.getAsFunction(subIGF),

lib/IRGen/IRGenSIL.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1754,9 +1754,12 @@ static void emitEntryPointArgumentsNativeCC(IRGenSILFunction &IGF,
17541754

17551755
// Even if we don't have a 'self', if we have an error result, we
17561756
// should have a placeholder argument here.
1757-
} else if (funcTy->hasErrorResult() ||
1758-
funcTy->getRepresentation() == SILFunctionTypeRepresentation::Thick)
1759-
{
1757+
//
1758+
// For async functions, there will be a thick context within the async
1759+
// context whenever there is no self context.
1760+
} else if (funcTy->isAsync() || funcTy->hasErrorResult() ||
1761+
funcTy->getRepresentation() ==
1762+
SILFunctionTypeRepresentation::Thick) {
17601763
llvm::Value *contextPtr = emission->getContext();
17611764
(void)contextPtr;
17621765
assert(contextPtr->getType() == IGF.IGM.RefCountedPtrTy);

0 commit comments

Comments
 (0)