Skip to content

Commit d32b935

Browse files
Merge pull request #34211 from nate-chandler/concurrency/irgen/protocol-witness-methods
[Async CC] Support for protocol witness methods.
2 parents 1e6ea76 + 4c298db commit d32b935

8 files changed

+387
-110
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,28 @@ AsyncContextLayout irgen::getAsyncContextLayout(
181181
paramInfos.push_back({ty, parameter.getConvention()});
182182
}
183183

184+
Optional<AsyncContextLayout::TrailingWitnessInfo> trailingWitnessInfo;
185+
if (originalType->getRepresentation() ==
186+
SILFunctionTypeRepresentation::WitnessMethod) {
187+
assert(getTrailingWitnessSignatureLength(IGF.IGM, originalType) == 2);
188+
189+
// First, the Self metadata.
190+
{
191+
auto ty = SILType();
192+
auto &ti = IGF.IGM.getTypeMetadataPtrTypeInfo();
193+
valTypes.push_back(ty);
194+
typeInfos.push_back(&ti);
195+
}
196+
// Then, the Self witness table.
197+
{
198+
auto ty = SILType();
199+
auto &ti = IGF.IGM.getWitnessTablePtrTypeInfo();
200+
valTypes.push_back(ty);
201+
typeInfos.push_back(&ti);
202+
}
203+
trailingWitnessInfo = AsyncContextLayout::TrailingWitnessInfo();
204+
}
205+
184206
// ResultTypes directResults...;
185207
auto directResults = fnConv.getDirectSILResults();
186208
for (auto result : directResults) {
@@ -192,20 +214,20 @@ AsyncContextLayout irgen::getAsyncContextLayout(
192214
directReturnInfos.push_back(result);
193215
}
194216

195-
return AsyncContextLayout(IGF.IGM, LayoutStrategy::Optimal, valTypes,
196-
typeInfos, IGF, originalType, substitutedType,
197-
substitutionMap, std::move(bindings), errorType,
198-
canHaveValidError, paramInfos, indirectReturnInfos,
199-
directReturnInfos, localContextInfo);
217+
return AsyncContextLayout(
218+
IGF.IGM, LayoutStrategy::Optimal, valTypes, typeInfos, IGF, originalType,
219+
substitutedType, substitutionMap, std::move(bindings),
220+
trailingWitnessInfo, errorType, canHaveValidError, paramInfos,
221+
indirectReturnInfos, directReturnInfos, localContextInfo);
200222
}
201223

202224
AsyncContextLayout::AsyncContextLayout(
203225
IRGenModule &IGM, LayoutStrategy strategy, ArrayRef<SILType> fieldTypes,
204226
ArrayRef<const TypeInfo *> fieldTypeInfos, IRGenFunction &IGF,
205227
CanSILFunctionType originalType, CanSILFunctionType substitutedType,
206228
SubstitutionMap substitutionMap, NecessaryBindings &&bindings,
207-
SILType errorType, bool canHaveValidError,
208-
ArrayRef<ArgumentInfo> argumentInfos,
229+
Optional<TrailingWitnessInfo> trailingWitnessInfo, SILType errorType,
230+
bool canHaveValidError, ArrayRef<ArgumentInfo> argumentInfos,
209231
ArrayRef<SILResultInfo> indirectReturnInfos,
210232
ArrayRef<SILResultInfo> directReturnInfos,
211233
Optional<AsyncContextLayout::ArgumentInfo> localContextInfo)
@@ -218,6 +240,7 @@ AsyncContextLayout::AsyncContextLayout(
218240
indirectReturnInfos(indirectReturnInfos.begin(),
219241
indirectReturnInfos.end()),
220242
localContextInfo(localContextInfo), bindings(std::move(bindings)),
243+
trailingWitnessInfo(trailingWitnessInfo),
221244
argumentInfos(argumentInfos.begin(), argumentInfos.end()) {
222245
#ifndef NDEBUG
223246
assert(fieldTypeInfos.size() == fieldTypes.size() &&
@@ -1929,6 +1952,17 @@ class AsyncCallEmission final : public CallEmission {
19291952
getCallee().getSubstitutions());
19301953
}
19311954

1955+
void saveValue(ElementLayout layout, Explosion &explosion, bool isOutlined) {
1956+
Address addr = layout.project(IGF, context, /*offsets*/ llvm::None);
1957+
auto &ti = cast<LoadableTypeInfo>(layout.getType());
1958+
ti.initialize(IGF, explosion, addr, isOutlined);
1959+
}
1960+
void loadValue(ElementLayout layout, Explosion &explosion) {
1961+
Address addr = layout.project(IGF, context, /*offsets*/ llvm::None);
1962+
auto &ti = layout.getType();
1963+
cast<LoadableTypeInfo>(ti).loadAsTake(IGF, addr, explosion);
1964+
}
1965+
19321966
public:
19331967
AsyncCallEmission(IRGenFunction &IGF, llvm::Value *selfValue, Callee &&callee)
19341968
: CallEmission(IGF, selfValue, std::move(callee)) {
@@ -1974,21 +2008,15 @@ class AsyncCallEmission final : public CallEmission {
19742008
llArgs.add(selfValue);
19752009
}
19762010
auto layout = getAsyncContextLayout();
1977-
for (unsigned index = 0, count = layout.getArgumentCount(); index < count;
1978-
++index) {
1979-
auto fieldLayout = layout.getArgumentLayout(index);
1980-
Address fieldAddr =
1981-
fieldLayout.project(IGF, context, /*offsets*/ llvm::None);
1982-
auto &ti = cast<LoadableTypeInfo>(fieldLayout.getType());
1983-
ti.initialize(IGF, llArgs, fieldAddr, isOutlined);
1984-
}
19852011
for (unsigned index = 0, count = layout.getIndirectReturnCount();
19862012
index < count; ++index) {
19872013
auto fieldLayout = layout.getIndirectReturnLayout(index);
1988-
Address fieldAddr =
1989-
fieldLayout.project(IGF, context, /*offsets*/ llvm::None);
1990-
cast<LoadableTypeInfo>(fieldLayout.getType())
1991-
.initialize(IGF, llArgs, fieldAddr, isOutlined);
2014+
saveValue(fieldLayout, llArgs, isOutlined);
2015+
}
2016+
for (unsigned index = 0, count = layout.getArgumentCount(); index < count;
2017+
++index) {
2018+
auto fieldLayout = layout.getArgumentLayout(index);
2019+
saveValue(fieldLayout, llArgs, isOutlined);
19922020
}
19932021
if (layout.hasBindings()) {
19942022
auto bindingLayout = layout.getBindingsLayout();
@@ -1997,10 +2025,7 @@ class AsyncCallEmission final : public CallEmission {
19972025
}
19982026
if (selfValue) {
19992027
auto fieldLayout = layout.getLocalContextLayout();
2000-
Address fieldAddr =
2001-
fieldLayout.project(IGF, context, /*offsets*/ llvm::None);
2002-
auto &ti = cast<LoadableTypeInfo>(fieldLayout.getType());
2003-
ti.initialize(IGF, llArgs, fieldAddr, isOutlined);
2028+
saveValue(fieldLayout, llArgs, isOutlined);
20042029
}
20052030
}
20062031
void emitCallToUnmappedExplosion(llvm::CallInst *call, Explosion &out) override {
@@ -2016,20 +2041,13 @@ class AsyncCallEmission final : public CallEmission {
20162041
// argument buffer.
20172042
return;
20182043
}
2019-
assert(call->arg_size() == 1);
2020-
auto context = call->arg_begin()->get();
20212044
// Gather the values.
20222045
Explosion nativeExplosion;
20232046
auto layout = getAsyncContextLayout();
2024-
auto dataAddr = layout.emitCastTo(IGF, context);
20252047
for (unsigned index = 0, count = layout.getDirectReturnCount();
20262048
index < count; ++index) {
20272049
auto fieldLayout = layout.getDirectReturnLayout(index);
2028-
Address fieldAddr =
2029-
fieldLayout.project(IGF, dataAddr, /*offsets*/ llvm::None);
2030-
auto &fieldTI = fieldLayout.getType();
2031-
cast<LoadableTypeInfo>(fieldTI).loadAsTake(IGF, fieldAddr,
2032-
nativeExplosion);
2050+
loadValue(fieldLayout, nativeExplosion);
20332051
}
20342052

20352053
out = nativeSchema.mapFromNative(IGF.IGM, IGF, nativeExplosion, resultType);

lib/IRGen/GenCall.h

Lines changed: 60 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ namespace irgen {
8989
SILType type;
9090
ParameterConvention convention;
9191
};
92+
struct TrailingWitnessInfo {};
9293

9394
private:
9495
enum class FixedIndex : unsigned {
@@ -107,28 +108,59 @@ namespace irgen {
107108
SmallVector<SILResultInfo, 4> indirectReturnInfos;
108109
Optional<ArgumentInfo> localContextInfo;
109110
NecessaryBindings bindings;
111+
Optional<TrailingWitnessInfo> trailingWitnessInfo;
110112
SmallVector<ArgumentInfo, 4> argumentInfos;
111113

114+
unsigned getErrorIndex() { return (unsigned)FixedIndex::Error; }
115+
unsigned getFirstIndirectReturnIndex() {
116+
return getErrorIndex() + getErrorCount();
117+
}
118+
unsigned getLocalContextIndex() {
119+
assert(hasLocalContext());
120+
return getFirstIndirectReturnIndex() + getIndirectReturnCount();
121+
}
122+
unsigned getIndexAfterLocalContext() {
123+
return getFirstIndirectReturnIndex() + getIndirectReturnCount() +
124+
(hasLocalContext() ? 1 : 0);
125+
}
126+
unsigned getBindingsIndex() {
127+
assert(hasBindings());
128+
return getIndexAfterLocalContext();
129+
}
130+
unsigned getIndexAfterBindings() {
131+
return getIndexAfterLocalContext() + (hasBindings() ? 1 : 0);
132+
}
133+
unsigned getFirstArgumentIndex() { return getIndexAfterBindings(); }
134+
unsigned getIndexAfterArguments() {
135+
return getFirstArgumentIndex() + getArgumentCount();
136+
}
137+
unsigned getSelfMetadataIndex() {
138+
assert(hasTrailingWitnesses());
139+
return getIndexAfterArguments();
140+
}
141+
unsigned getSelfWitnessTableIndex() {
142+
assert(hasTrailingWitnesses());
143+
return getIndexAfterArguments() + 1;
144+
}
145+
unsigned getIndexAfterTrailingWitnesses() {
146+
return getIndexAfterArguments() + (hasTrailingWitnesses() ? 2 : 0);
147+
}
148+
unsigned getFirstDirectReturnIndex() {
149+
return getIndexAfterTrailingWitnesses();
150+
}
151+
112152
public:
113153
bool canHaveError() { return canHaveValidError; }
114-
unsigned getErrorIndex() { return (unsigned)FixedIndex::Error; }
115154
ElementLayout getErrorLayout() { return getElement(getErrorIndex()); }
116155
unsigned getErrorCount() { return (unsigned)FixedCount::Error; }
117156
SILType getErrorType() { return errorType; }
118157

119-
unsigned getFirstIndirectReturnIndex() {
120-
return getErrorIndex() + getErrorCount();
121-
}
122158
ElementLayout getIndirectReturnLayout(unsigned index) {
123159
return getElement(getFirstIndirectReturnIndex() + index);
124160
}
125161
unsigned getIndirectReturnCount() { return indirectReturnInfos.size(); }
126162

127163
bool hasLocalContext() { return (bool)localContextInfo; }
128-
unsigned getLocalContextIndex() {
129-
assert(hasLocalContext());
130-
return getFirstIndirectReturnIndex() + getIndirectReturnCount();
131-
}
132164
ElementLayout getLocalContextLayout() {
133165
assert(hasLocalContext());
134166
return getElement(getLocalContextIndex());
@@ -141,65 +173,53 @@ namespace irgen {
141173
assert(hasLocalContext());
142174
return localContextInfo->type;
143175
}
144-
unsigned getIndexAfterLocalContext() {
145-
return getFirstIndirectReturnIndex() + getIndirectReturnCount() +
146-
(hasLocalContext() ? 1 : 0);
147-
}
148176

149177
bool hasBindings() const { return !bindings.empty(); }
150-
unsigned getBindingsIndex() {
151-
assert(hasBindings());
152-
return getIndexAfterLocalContext();
153-
}
154178
ElementLayout getBindingsLayout() {
155179
assert(hasBindings());
156180
return getElement(getBindingsIndex());
157181
}
158-
ParameterConvention getBindingsConvention() {
159-
return ParameterConvention::Direct_Unowned;
160-
}
161182
const NecessaryBindings &getBindings() const { return bindings; }
162183

163-
unsigned getFirstArgumentIndex() {
164-
return getIndexAfterLocalContext() + (hasBindings() ? 1 : 0);
165-
}
166184
ElementLayout getArgumentLayout(unsigned index) {
167185
return getElement(getFirstArgumentIndex() + index);
168186
}
169-
ParameterConvention getArgumentConvention(unsigned index) {
170-
return argumentInfos[index].convention;
171-
}
172187
SILType getArgumentType(unsigned index) {
173188
return argumentInfos[index].type;
174189
}
190+
// Returns the type of a parameter of the substituted function using the
191+
// indexing of the function parameters, *not* the indexing of
192+
// AsyncContextLayout.
175193
SILType getParameterType(unsigned index) {
176194
SILFunctionConventions origConv(substitutedType, IGF.getSILModule());
177195
return origConv.getSILArgumentType(
178196
index, IGF.IGM.getMaximalTypeExpansionContext());
179197
}
180198
unsigned getArgumentCount() { return argumentInfos.size(); }
181-
unsigned getIndexAfterArguments() {
182-
return getFirstArgumentIndex() + getArgumentCount();
199+
bool hasTrailingWitnesses() { return (bool)trailingWitnessInfo; }
200+
ElementLayout getSelfMetadataLayout() {
201+
assert(hasTrailingWitnesses());
202+
return getElement(getSelfMetadataIndex());
203+
}
204+
ElementLayout getSelfWitnessTableLayout() {
205+
return getElement(getSelfWitnessTableIndex());
183206
}
184207

185-
unsigned getFirstDirectReturnIndex() { return getIndexAfterArguments(); }
186208
unsigned getDirectReturnCount() { return directReturnInfos.size(); }
187209
ElementLayout getDirectReturnLayout(unsigned index) {
188210
return getElement(getFirstDirectReturnIndex() + index);
189211
}
190212

191-
AsyncContextLayout(IRGenModule &IGM, LayoutStrategy strategy,
192-
ArrayRef<SILType> fieldTypes,
193-
ArrayRef<const TypeInfo *> fieldTypeInfos,
194-
IRGenFunction &IGF, CanSILFunctionType originalType,
195-
CanSILFunctionType substitutedType,
196-
SubstitutionMap substitutionMap,
197-
NecessaryBindings &&bindings, SILType errorType,
198-
bool canHaveValidError,
199-
ArrayRef<ArgumentInfo> argumentInfos,
200-
ArrayRef<SILResultInfo> directReturnInfos,
201-
ArrayRef<SILResultInfo> indirectReturnInfos,
202-
Optional<ArgumentInfo> localContextInfo);
213+
AsyncContextLayout(
214+
IRGenModule &IGM, LayoutStrategy strategy, ArrayRef<SILType> fieldTypes,
215+
ArrayRef<const TypeInfo *> fieldTypeInfos, IRGenFunction &IGF,
216+
CanSILFunctionType originalType, CanSILFunctionType substitutedType,
217+
SubstitutionMap substitutionMap, NecessaryBindings &&bindings,
218+
Optional<TrailingWitnessInfo> trailingWitnessInfo, SILType errorType,
219+
bool canHaveValidError, ArrayRef<ArgumentInfo> argumentInfos,
220+
ArrayRef<SILResultInfo> directReturnInfos,
221+
ArrayRef<SILResultInfo> indirectReturnInfos,
222+
Optional<ArgumentInfo> localContextInfo);
203223
};
204224

205225
AsyncContextLayout getAsyncContextLayout(IRGenFunction &IGF,

lib/IRGen/GenProto.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3100,7 +3100,11 @@ NecessaryBindings NecessaryBindings::computeBindings(
31003100
continue;
31013101

31023102
case MetadataSource::Kind::SelfMetadata:
3103-
bindings.addTypeMetadata(getSubstSelfType(IGM, origType, subs));
3103+
// Async functions pass the SelfMetadata and SelfWitnessTable parameters
3104+
// along explicitly.
3105+
if (forPartialApplyForwarder) {
3106+
bindings.addTypeMetadata(getSubstSelfType(IGM, origType, subs));
3107+
}
31043108
continue;
31053109

31063110
case MetadataSource::Kind::SelfWitnessTable:

0 commit comments

Comments
 (0)