Skip to content

Commit 6fce6d9

Browse files
committed
[Async CC] Pull poly params from entry point emission.
Previously, EmitPolymorphicParameters dealt directly with an Explosion from which it pulled values. In one place, there was a conditional check for async which handled some cases. There was however another place where the polymorphic parameter was pulled directly from the explosion. That missed case resulted in attempting to pull a polymorphic parameter directly from an Explosion which contains only a %swift.context* per the async calling convention. Here, those parameters are now pulled from an EntryPointArgumentEmission subclasses of which are able to provide the relevant definition of what pulling a parameter means. rdar://problem/70144083
1 parent b33b4f0 commit 6fce6d9

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.
@@ -2689,12 +2659,12 @@ void irgen::collectTrailingWitnessMetadata(
26892659
}
26902660

26912661
/// Perform all the bindings necessary to emit the given declaration.
2692-
void irgen::emitPolymorphicParameters(IRGenFunction &IGF,
2693-
SILFunction &Fn,
2694-
Explosion &in,
2662+
void irgen::emitPolymorphicParameters(IRGenFunction &IGF, SILFunction &Fn,
2663+
EntryPointArgumentEmission &emission,
26952664
WitnessMetadata *witnessMetadata,
26962665
const GetParameterFn &getParameter) {
2697-
EmitPolymorphicParameters(IGF, Fn).emit(in, witnessMetadata, getParameter);
2666+
EmitPolymorphicParameters(IGF, Fn).emit(emission, witnessMetadata,
2667+
getParameter);
26982668
}
26992669

27002670
/// 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
@@ -1147,6 +1147,13 @@ class SyncEntryPointArgumentEmission
11471147
llvm::Value *getIndirectResult(unsigned index) override {
11481148
return allParamValues.claimNext();
11491149
};
1150+
llvm::Value *
1151+
getNextPolymorphicParameter(GenericRequirement &requirement) override {
1152+
return allParamValues.claimNext();
1153+
}
1154+
llvm::Value *getNextPolymorphicParameterAsMetadata() override {
1155+
return allParamValues.claimNext();
1156+
}
11501157
};
11511158
class AsyncEntryPointArgumentEmission
11521159
: public virtual EntryPointArgumentEmission {
@@ -1206,6 +1213,7 @@ class AsyncNativeCCEntryPointArgumentEmission final
12061213
llvm::Value *context;
12071214
/*const*/ AsyncContextLayout layout;
12081215
const Address dataAddr;
1216+
unsigned polymorphicParameterIndex = 0;
12091217

12101218
llvm::Value *loadValue(ElementLayout layout) {
12111219
Address addr = layout.project(IGF, dataAddr, /*offsets*/ llvm::None);
@@ -1248,6 +1256,46 @@ class AsyncNativeCCEntryPointArgumentEmission final
12481256
"into indirect IR results because all results are already "
12491257
"indirected through the context");
12501258
}
1259+
Address getNextUncastBinding() {
1260+
auto index = polymorphicParameterIndex;
1261+
++polymorphicParameterIndex;
1262+
1263+
assert(layout.hasBindings());
1264+
1265+
auto bindingLayout = layout.getBindingsLayout();
1266+
auto bindingsAddr = bindingLayout.project(IGF, dataAddr, /*offsets*/ None);
1267+
auto erasedBindingsAddr =
1268+
IGF.Builder.CreateBitCast(bindingsAddr, IGF.IGM.Int8PtrPtrTy);
1269+
auto uncastBindingAddr = IGF.Builder.CreateConstArrayGEP(
1270+
erasedBindingsAddr, index, IGF.IGM.getPointerSize());
1271+
return uncastBindingAddr;
1272+
}
1273+
llvm::Value *castUncastBindingToMetadata(Address uncastBindingAddr) {
1274+
auto bindingAddrAddr = IGF.Builder.CreateBitCast(
1275+
uncastBindingAddr.getAddress(), IGF.IGM.TypeMetadataPtrPtrTy);
1276+
auto bindingAddr =
1277+
IGF.Builder.CreateLoad(bindingAddrAddr, IGF.IGM.getPointerAlignment());
1278+
return bindingAddr;
1279+
}
1280+
llvm::Value *castUncastBindingToWitnessTable(Address uncastBindingAddr) {
1281+
auto bindingAddrAddr = IGF.Builder.CreateBitCast(
1282+
uncastBindingAddr.getAddress(), IGF.IGM.WitnessTablePtrPtrTy);
1283+
auto bindingAddr =
1284+
IGF.Builder.CreateLoad(bindingAddrAddr, IGF.IGM.getPointerAlignment());
1285+
return bindingAddr;
1286+
}
1287+
llvm::Value *
1288+
getNextPolymorphicParameter(GenericRequirement &requirement) override {
1289+
auto uncastBindingAddr = getNextUncastBinding();
1290+
if (requirement.Protocol) {
1291+
return castUncastBindingToWitnessTable(uncastBindingAddr);
1292+
} else {
1293+
return castUncastBindingToMetadata(uncastBindingAddr);
1294+
}
1295+
}
1296+
llvm::Value *getNextPolymorphicParameterAsMetadata() override {
1297+
return castUncastBindingToMetadata(getNextUncastBinding());
1298+
}
12511299
llvm::Value *getIndirectResult(unsigned index) override {
12521300
auto fieldLayout = layout.getIndirectReturnLayout(index);
12531301
return loadValue(fieldLayout);
@@ -1675,13 +1723,13 @@ static void emitEntryPointArgumentsNativeCC(IRGenSILFunction &IGF,
16751723
// Bind polymorphic arguments. This can only be done after binding
16761724
// all the value parameters.
16771725
if (hasPolymorphicParameters(funcTy)) {
1678-
emitPolymorphicParameters(IGF, *IGF.CurSILFn, allParamValues,
1679-
&witnessMetadata,
1680-
[&](unsigned paramIndex) -> llvm::Value* {
1681-
SILValue parameter =
1682-
IGF.CurSILFn->getArgumentsWithoutIndirectResults()[paramIndex];
1683-
return IGF.getLoweredSingletonExplosion(parameter);
1684-
});
1726+
emitPolymorphicParameters(
1727+
IGF, *IGF.CurSILFn, *emission, &witnessMetadata,
1728+
[&](unsigned paramIndex) -> llvm::Value * {
1729+
SILValue parameter =
1730+
IGF.CurSILFn->getArgumentsWithoutIndirectResults()[paramIndex];
1731+
return IGF.getLoweredSingletonExplosion(parameter);
1732+
});
16851733
}
16861734

16871735
assert(allParamValues.empty() && "didn't claim all parameters!");
@@ -1776,7 +1824,7 @@ static void emitEntryPointArgumentsCOrObjC(IRGenSILFunction &IGF,
17761824
// all the value parameters, and must be done even for non-polymorphic
17771825
// functions because of imported Objective-C generics.
17781826
emitPolymorphicParameters(
1779-
IGF, *IGF.CurSILFn, params, nullptr,
1827+
IGF, *IGF.CurSILFn, *emission, nullptr,
17801828
[&](unsigned paramIndex) -> llvm::Value * {
17811829
SILValue parameter = entry->getArguments()[paramIndex];
17821830
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)