Merge pull request #76743 from swiftlang/coro-pa-context

Fix partial apply forwarder emission for coroutines that are methods of structs with type parameters
This commit is contained in:
Dario Rexin
2024-11-21 03:05:25 -08:00
committed by GitHub
2 changed files with 59 additions and 52 deletions

View File

@@ -1120,11 +1120,11 @@ public:
virtual void addDynamicFunctionContext(Explosion &explosion) = 0;
virtual void addDynamicFunctionPointer(Explosion &explosion) = 0;
virtual void addSelf(Explosion &explosion) { addArgument(explosion); }
virtual void addWitnessSelfMetadata(llvm::Value *value) {
void addSelf(Explosion &explosion) { addArgument(explosion); }
void addWitnessSelfMetadata(llvm::Value *value) {
addArgument(value);
}
virtual void addWitnessSelfWitnessTable(llvm::Value *value) {
void addWitnessSelfWitnessTable(llvm::Value *value) {
addArgument(value);
}
virtual void forwardErrorResult() = 0;
@@ -1438,12 +1438,6 @@ class CoroPartialApplicationForwarderEmission
: public PartialApplicationForwarderEmission {
using super = PartialApplicationForwarderEmission;
private:
llvm::Value *Self;
llvm::Value *FirstData;
llvm::Value *SecondData;
WitnessMetadata Witness;
public:
CoroPartialApplicationForwarderEmission(
IRGenModule &IGM, IRGenFunction &subIGF, llvm::Function *fwd,
@@ -1454,8 +1448,7 @@ public:
ArrayRef<ParameterConvention> conventions)
: PartialApplicationForwarderEmission(
IGM, subIGF, fwd, staticFnPtr, calleeHasContext, origSig, origType,
substType, outType, subs, layout, conventions),
Self(nullptr), FirstData(nullptr), SecondData(nullptr) {}
substType, outType, subs, layout, conventions) {}
void begin() override {
auto unsubstType = substType->getUnsubstitutedType(IGM.getSILModule());
@@ -1499,41 +1492,13 @@ public:
void gatherArgumentsFromApply() override {
super::gatherArgumentsFromApply(false);
}
llvm::Value *getDynamicFunctionPointer() override {
llvm::Value *Ret = SecondData;
SecondData = nullptr;
return Ret;
}
llvm::Value *getDynamicFunctionContext() override {
llvm::Value *Ret = FirstData;
FirstData = nullptr;
return Ret;
}
llvm::Value *getDynamicFunctionPointer() override { return args.takeLast(); }
llvm::Value *getDynamicFunctionContext() override { return args.takeLast(); }
void addDynamicFunctionContext(Explosion &explosion) override {
assert(!Self && "context value overrides 'self'");
FirstData = explosion.claimNext();
addArgument(explosion);
}
void addDynamicFunctionPointer(Explosion &explosion) override {
SecondData = explosion.claimNext();
}
void addSelf(Explosion &explosion) override {
assert(!FirstData && "'self' overrides another context value");
if (!hasSelfContextParameter(origType)) {
// witness methods can be declared on types that are not classes. Pass
// such "self" argument as a plain argument.
addArgument(explosion);
return;
}
Self = explosion.claimNext();
FirstData = Self;
}
void addWitnessSelfMetadata(llvm::Value *value) override {
Witness.SelfMetadata = value;
}
void addWitnessSelfWitnessTable(llvm::Value *value) override {
Witness.SelfWitnessTable = value;
addArgument(explosion);
}
void forwardErrorResult() override {
@@ -1554,13 +1519,26 @@ public:
}
Explosion callCoroutine(FunctionPointer &fnPtr) {
Callee callee({origType, substType, subs}, fnPtr, FirstData, SecondData);
bool isWitnessMethodCallee = origType->getRepresentation() ==
SILFunctionTypeRepresentation::WitnessMethod;
WitnessMetadata witnessMetadata;
if (isWitnessMethodCallee) {
witnessMetadata.SelfWitnessTable = args.takeLast();
witnessMetadata.SelfMetadata = args.takeLast();
}
llvm::Value *selfValue = nullptr;
if (calleeHasContext || hasSelfContextParameter(origType))
selfValue = args.takeLast();
Callee callee({origType, substType, subs}, fnPtr, selfValue);
std::unique_ptr<CallEmission> emitSuspend =
getCallEmission(subIGF, Self, std::move(callee));
getCallEmission(subIGF, callee.getSwiftContext(), std::move(callee));
emitSuspend->begin();
emitSuspend->setArgs(args, /*isOutlined=*/false, &Witness);
emitSuspend->setArgs(args, /*isOutlined=*/false, &witnessMetadata);
Explosion yieldedValues;
emitSuspend->emitToExplosion(yieldedValues, /*isOutlined=*/false);
emitSuspend->end();
@@ -1966,12 +1944,7 @@ static llvm::Value *emitPartialApplicationForwarder(
} else {
argValue = subIGF.Builder.CreateBitCast(rawData, expectedArgTy);
}
if (haveContextArgument) {
Explosion e;
e.add(argValue);
emission->addDynamicFunctionContext(e);
} else
emission->addArgument(argValue);
emission->addArgument(argValue);
// If there's a data pointer required, grab it and load out the
// extra, previously-curried parameters.