Skip to content

Commit c9115dc

Browse files
Merge pull request #34277 from nate-chandler/concurrency/irgen/thread-emission-through-emit-polymorphic
[Async CC] Pull polymorphic parameters from entry point emission.
2 parents 39ef28a + 6fce6d9 commit c9115dc

File tree

5 files changed

+116
-57
lines changed

5 files changed

+116
-57
lines changed

lib/IRGen/EntryPointArgumentEmission.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ namespace swift {
2020
namespace irgen {
2121

2222
class Explosion;
23+
struct GenericRequirement;
2324

2425
class EntryPointArgumentEmission {
2526

@@ -28,6 +29,9 @@ class EntryPointArgumentEmission {
2829
virtual bool requiresIndirectResult(SILType retType) = 0;
2930
virtual llvm::Value *getIndirectResultForFormallyDirectResult() = 0;
3031
virtual llvm::Value *getIndirectResult(unsigned index) = 0;
32+
virtual llvm::Value *getNextPolymorphicParameterAsMetadata() = 0;
33+
virtual llvm::Value *
34+
getNextPolymorphicParameter(GenericRequirement &requirement) = 0;
3135
};
3236

3337
class NativeCCEntryPointArgumentEmission

lib/IRGen/GenProto.cpp

Lines changed: 15 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,8 @@ class EmitPolymorphicParameters : public PolymorphicConvention {
489489
public:
490490
EmitPolymorphicParameters(IRGenFunction &IGF, SILFunction &Fn);
491491

492-
void emit(Explosion &in, WitnessMetadata *witnessMetadata,
492+
void emit(EntryPointArgumentEmission &emission,
493+
WitnessMetadata *witnessMetadata,
493494
const GetParameterFn &getParameter);
494495

495496
private:
@@ -499,7 +500,8 @@ class EmitPolymorphicParameters : public PolymorphicConvention {
499500

500501
/// Fulfill local type data from any extra information associated with
501502
/// the given source.
502-
void bindExtraSource(const MetadataSource &source, Explosion &in,
503+
void bindExtraSource(const MetadataSource &source,
504+
EntryPointArgumentEmission &emission,
503505
WitnessMetadata *witnessMetadata);
504506

505507
void bindParameterSources(const GetParameterFn &getParameter);
@@ -528,9 +530,9 @@ CanType EmitPolymorphicParameters::getArgTypeInContext(unsigned paramIndex) cons
528530
IGM.getSILModule(), FnType, IGM.getMaximalTypeExpansionContext()));
529531
}
530532

531-
void EmitPolymorphicParameters::bindExtraSource(const MetadataSource &source,
532-
Explosion &in,
533-
WitnessMetadata *witnessMetadata) {
533+
void EmitPolymorphicParameters::bindExtraSource(
534+
const MetadataSource &source, EntryPointArgumentEmission &emission,
535+
WitnessMetadata *witnessMetadata) {
534536
switch (source.getKind()) {
535537
case MetadataSource::Kind::Metadata:
536538
case MetadataSource::Kind::ClassPointer:
@@ -540,7 +542,7 @@ void EmitPolymorphicParameters::bindExtraSource(const MetadataSource &source,
540542
case MetadataSource::Kind::GenericLValueMetadata: {
541543
CanType argTy = getArgTypeInContext(source.getParamIndex());
542544

543-
llvm::Value *metadata = in.claimNext();
545+
llvm::Value *metadata = emission.getNextPolymorphicParameterAsMetadata();
544546
setTypeMetadataName(IGF.IGM, metadata, argTy);
545547

546548
IGF.bindLocalTypeDataFromTypeMetadata(argTy, IsExact, metadata,
@@ -2223,55 +2225,23 @@ bool irgen::hasPolymorphicParameters(CanSILFunctionType ty) {
22232225
}
22242226

22252227
/// Emit a polymorphic parameters clause, binding all the metadata necessary.
2226-
void EmitPolymorphicParameters::emit(Explosion &in,
2228+
void EmitPolymorphicParameters::emit(EntryPointArgumentEmission &emission,
22272229
WitnessMetadata *witnessMetadata,
22282230
const GetParameterFn &getParameter) {
22292231
// Collect any early sources and bind local type data from them.
22302232
for (auto &source : getSources()) {
2231-
bindExtraSource(source, in, witnessMetadata);
2233+
bindExtraSource(source, emission, witnessMetadata);
22322234
}
22332235

22342236
auto getInContext = [&](CanType type) -> CanType {
22352237
return getTypeInContext(type);
22362238
};
22372239

2238-
unsigned index = 0;
22392240
// Collect any concrete type metadata that's been passed separately.
22402241
enumerateUnfulfilledRequirements([&](GenericRequirement requirement) {
2241-
llvm::Value *value;
2242-
if (Fn.isAsync()) {
2243-
auto *context = in.peek(
2244-
/*the index of the swift.context in the async function CC*/ 0);
2245-
auto layout = getAsyncContextLayout(IGF, &Fn);
2246-
Address dataAddr = layout.emitCastTo(IGF, context);
2247-
assert(layout.hasBindings());
2248-
2249-
auto bindingLayout = layout.getBindingsLayout();
2250-
auto bindingsAddr =
2251-
bindingLayout.project(IGF, dataAddr, /*offsets*/ None);
2252-
auto erasedBindingsAddr =
2253-
IGF.Builder.CreateBitCast(bindingsAddr, IGF.IGM.Int8PtrPtrTy);
2254-
auto uncastBindingAddr = IGF.Builder.CreateConstArrayGEP(
2255-
erasedBindingsAddr, index, IGF.IGM.getPointerSize());
2256-
if (requirement.Protocol) {
2257-
auto bindingAddrAddr = IGF.Builder.CreateBitCast(
2258-
uncastBindingAddr.getAddress(), IGF.IGM.WitnessTablePtrPtrTy);
2259-
auto bindingAddr = IGF.Builder.CreateLoad(
2260-
bindingAddrAddr, IGF.IGM.getPointerAlignment());
2261-
value = bindingAddr;
2262-
} else {
2263-
auto bindingAddrAddr = IGF.Builder.CreateBitCast(
2264-
uncastBindingAddr.getAddress(), IGF.IGM.TypeMetadataPtrPtrTy);
2265-
auto bindingAddr = IGF.Builder.CreateLoad(
2266-
bindingAddrAddr, IGF.IGM.getPointerAlignment());
2267-
value = bindingAddr;
2268-
}
2269-
} else {
2270-
value = in.claimNext();
2271-
}
2242+
llvm::Value *value = emission.getNextPolymorphicParameter(requirement);
22722243
bindGenericRequirement(IGF, requirement, value, MetadataState::Complete,
22732244
getInContext);
2274-
++index;
22752245
});
22762246

22772247
// Bind all the fulfillments we can from the formal parameters.
@@ -2691,12 +2661,12 @@ void irgen::collectTrailingWitnessMetadata(
26912661
}
26922662

26932663
/// Perform all the bindings necessary to emit the given declaration.
2694-
void irgen::emitPolymorphicParameters(IRGenFunction &IGF,
2695-
SILFunction &Fn,
2696-
Explosion &in,
2664+
void irgen::emitPolymorphicParameters(IRGenFunction &IGF, SILFunction &Fn,
2665+
EntryPointArgumentEmission &emission,
26972666
WitnessMetadata *witnessMetadata,
26982667
const GetParameterFn &getParameter) {
2699-
EmitPolymorphicParameters(IGF, Fn).emit(in, witnessMetadata, getParameter);
2668+
EmitPolymorphicParameters(IGF, Fn).emit(emission, witnessMetadata,
2669+
getParameter);
27002670
}
27012671

27022672
/// Given an array of polymorphic arguments as might be set up by

lib/IRGen/GenProto.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ namespace swift {
4040
namespace irgen {
4141
class Address;
4242
class DynamicMetadataRequest;
43+
class EntryPointArgumentEmission;
4344
class Explosion;
4445
class FunctionPointer;
4546
class IRGenFunction;
@@ -133,12 +134,11 @@ namespace irgen {
133134
///
134135
/// \param witnessMetadata - can be omitted if the function is
135136
/// definitely not a witness method
136-
void emitPolymorphicParameters(IRGenFunction &IGF,
137-
SILFunction &Fn,
138-
Explosion &args,
137+
void emitPolymorphicParameters(IRGenFunction &IGF, SILFunction &Fn,
138+
EntryPointArgumentEmission &emission,
139139
WitnessMetadata *witnessMetadata,
140140
const GetParameterFn &getParameter);
141-
141+
142142
void emitPolymorphicParametersFromArray(IRGenFunction &IGF,
143143
NominalTypeDecl *typeDecl,
144144
Address array,

lib/IRGen/IRGenSIL.cpp

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,6 +1161,13 @@ class SyncEntryPointArgumentEmission
11611161
llvm::Value *getIndirectResult(unsigned index) override {
11621162
return allParamValues.claimNext();
11631163
};
1164+
llvm::Value *
1165+
getNextPolymorphicParameter(GenericRequirement &requirement) override {
1166+
return allParamValues.claimNext();
1167+
}
1168+
llvm::Value *getNextPolymorphicParameterAsMetadata() override {
1169+
return allParamValues.claimNext();
1170+
}
11641171
};
11651172
class AsyncEntryPointArgumentEmission
11661173
: public virtual EntryPointArgumentEmission {
@@ -1220,6 +1227,7 @@ class AsyncNativeCCEntryPointArgumentEmission final
12201227
llvm::Value *context;
12211228
/*const*/ AsyncContextLayout layout;
12221229
const Address dataAddr;
1230+
unsigned polymorphicParameterIndex = 0;
12231231

12241232
llvm::Value *loadValue(ElementLayout layout) {
12251233
Address addr = layout.project(IGF, dataAddr, /*offsets*/ llvm::None);
@@ -1262,6 +1270,46 @@ class AsyncNativeCCEntryPointArgumentEmission final
12621270
"into indirect IR results because all results are already "
12631271
"indirected through the context");
12641272
}
1273+
Address getNextUncastBinding() {
1274+
auto index = polymorphicParameterIndex;
1275+
++polymorphicParameterIndex;
1276+
1277+
assert(layout.hasBindings());
1278+
1279+
auto bindingLayout = layout.getBindingsLayout();
1280+
auto bindingsAddr = bindingLayout.project(IGF, dataAddr, /*offsets*/ None);
1281+
auto erasedBindingsAddr =
1282+
IGF.Builder.CreateBitCast(bindingsAddr, IGF.IGM.Int8PtrPtrTy);
1283+
auto uncastBindingAddr = IGF.Builder.CreateConstArrayGEP(
1284+
erasedBindingsAddr, index, IGF.IGM.getPointerSize());
1285+
return uncastBindingAddr;
1286+
}
1287+
llvm::Value *castUncastBindingToMetadata(Address uncastBindingAddr) {
1288+
auto bindingAddrAddr = IGF.Builder.CreateBitCast(
1289+
uncastBindingAddr.getAddress(), IGF.IGM.TypeMetadataPtrPtrTy);
1290+
auto bindingAddr =
1291+
IGF.Builder.CreateLoad(bindingAddrAddr, IGF.IGM.getPointerAlignment());
1292+
return bindingAddr;
1293+
}
1294+
llvm::Value *castUncastBindingToWitnessTable(Address uncastBindingAddr) {
1295+
auto bindingAddrAddr = IGF.Builder.CreateBitCast(
1296+
uncastBindingAddr.getAddress(), IGF.IGM.WitnessTablePtrPtrTy);
1297+
auto bindingAddr =
1298+
IGF.Builder.CreateLoad(bindingAddrAddr, IGF.IGM.getPointerAlignment());
1299+
return bindingAddr;
1300+
}
1301+
llvm::Value *
1302+
getNextPolymorphicParameter(GenericRequirement &requirement) override {
1303+
auto uncastBindingAddr = getNextUncastBinding();
1304+
if (requirement.Protocol) {
1305+
return castUncastBindingToWitnessTable(uncastBindingAddr);
1306+
} else {
1307+
return castUncastBindingToMetadata(uncastBindingAddr);
1308+
}
1309+
}
1310+
llvm::Value *getNextPolymorphicParameterAsMetadata() override {
1311+
return castUncastBindingToMetadata(getNextUncastBinding());
1312+
}
12651313
llvm::Value *getIndirectResult(unsigned index) override {
12661314
auto fieldLayout = layout.getIndirectReturnLayout(index);
12671315
return loadValue(fieldLayout);
@@ -1689,13 +1737,13 @@ static void emitEntryPointArgumentsNativeCC(IRGenSILFunction &IGF,
16891737
// Bind polymorphic arguments. This can only be done after binding
16901738
// all the value parameters.
16911739
if (hasPolymorphicParameters(funcTy)) {
1692-
emitPolymorphicParameters(IGF, *IGF.CurSILFn, allParamValues,
1693-
&witnessMetadata,
1694-
[&](unsigned paramIndex) -> llvm::Value* {
1695-
SILValue parameter =
1696-
IGF.CurSILFn->getArgumentsWithoutIndirectResults()[paramIndex];
1697-
return IGF.getLoweredSingletonExplosion(parameter);
1698-
});
1740+
emitPolymorphicParameters(
1741+
IGF, *IGF.CurSILFn, *emission, &witnessMetadata,
1742+
[&](unsigned paramIndex) -> llvm::Value * {
1743+
SILValue parameter =
1744+
IGF.CurSILFn->getArgumentsWithoutIndirectResults()[paramIndex];
1745+
return IGF.getLoweredSingletonExplosion(parameter);
1746+
});
16991747
}
17001748

17011749
assert(allParamValues.empty() && "didn't claim all parameters!");
@@ -1790,7 +1838,7 @@ static void emitEntryPointArgumentsCOrObjC(IRGenSILFunction &IGF,
17901838
// all the value parameters, and must be done even for non-polymorphic
17911839
// functions because of imported Objective-C generics.
17921840
emitPolymorphicParameters(
1793-
IGF, *IGF.CurSILFn, params, nullptr,
1841+
IGF, *IGF.CurSILFn, *emission, nullptr,
17941842
[&](unsigned paramIndex) -> llvm::Value * {
17951843
SILValue parameter = entry->getArguments()[paramIndex];
17961844
return IGF.getLoweredSingletonExplosion(parameter);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %target-swift-frontend -emit-ir %s -enable-experimental-concurrency
2+
3+
public protocol AsyncIteratorProtocol {
4+
associatedtype Element
5+
associatedtype Failure: Error
6+
7+
mutating func nextResult() async -> Result<Element, Failure>?
8+
mutating func cancel()
9+
}
10+
11+
public protocol AsyncSequence {
12+
associatedtype Element
13+
associatedtype Failure: Error
14+
associatedtype AsyncIterator: AsyncIteratorProtocol where AsyncIterator.Element == Element, AsyncIterator.Failure == Failure
15+
16+
func makeAsyncIterator() -> AsyncIterator
17+
}
18+
19+
struct Just<Element>: AsyncSequence {
20+
typealias Failure = Never
21+
22+
struct AsyncIterator: AsyncIteratorProtocol {
23+
var value: Element?
24+
mutating func nextResult() async -> Result<Element, Never>? {
25+
defer { value = nil }
26+
return value.map { .success($0) }
27+
}
28+
29+
mutating func cancel() {
30+
value = nil
31+
}
32+
}
33+
var value: Element
34+
func makeAsyncIterator() -> AsyncIterator {
35+
return AsyncIterator(value: value)
36+
}
37+
}

0 commit comments

Comments
 (0)