Skip to content

Commit 3ea61ef

Browse files
committed
Fix some IRGen bugs with coroutine lowering:
- The large-loadable-types pass was not rewriting function signatures correctly if only a yield type was rewritten. - GenCall was not rewriting multiple yield types correctly.
1 parent c1b31b4 commit 3ea61ef

File tree

3 files changed

+61
-5
lines changed

3 files changed

+61
-5
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1738,9 +1738,11 @@ void CallEmission::emitYieldsToExplosion(Explosion &out) {
17381738
}
17391739

17401740
// Otherwise, it's direct. Remap.
1741-
auto temp = schema.getDirectSchema().mapFromNative(IGF.IGM, IGF,
1742-
rawYieldComponents,
1743-
schema.getSILType());
1741+
const auto &directSchema = schema.getDirectSchema();
1742+
Explosion eltValues;
1743+
rawYieldComponents.transferInto(eltValues, directSchema.size());
1744+
auto temp = directSchema.mapFromNative(IGF.IGM, IGF, eltValues,
1745+
schema.getSILType());
17441746

17451747
auto &yieldTI = cast<LoadableTypeInfo>(schema.getTypeInfo());
17461748
emitCastToSubstSchema(IGF, temp, yieldTI.getSchema(), out);

lib/IRGen/LoadableByAddress.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,18 @@ struct StructLoweringState {
539539
SILType getNewSILType(SILType type) {
540540
return Mapper.getNewSILType(F->getGenericEnvironment(), type, Mod);
541541
}
542+
543+
bool hasLargeLoadableYields() {
544+
auto fnType = F->getLoweredFunctionType();
545+
if (!fnType->isCoroutine()) return false;
546+
547+
auto env = F->getGenericEnvironment();
548+
for (auto yield : fnType->getYields()) {
549+
if (Mapper.shouldTransformParameter(env, yield, Mod))
550+
return true;
551+
}
552+
return false;
553+
}
542554
};
543555
} // end anonymous namespace
544556

@@ -2296,8 +2308,10 @@ void LoadableByAddress::runOnFunction(SILFunction *F) {
22962308

22972309
// If we modified the function arguments - add to list of functions to clone
22982310
if (modifiableFunction(funcType) &&
2299-
(rewrittenReturn || !pass.largeLoadableArgs.empty() ||
2300-
!pass.funcSigArgs.empty())) {
2311+
(rewrittenReturn ||
2312+
!pass.largeLoadableArgs.empty() ||
2313+
!pass.funcSigArgs.empty() ||
2314+
pass.hasLargeLoadableYields())) {
23012315
modFuncs.insert(F);
23022316
}
23032317
// If we modified any applies - add them to the global list for recreation

test/IRGen/yield_once.sil

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,5 +90,45 @@ cont:
9090
return %ret : $()
9191
}
9292

93+
sil @yields_pair : $@yield_once @convention(thin) () -> (@yields Builtin.Int32, @yields Builtin.Int32)
94+
95+
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @test_yields_pair()
96+
sil @test_yields_pair : $() -> () {
97+
entry:
98+
%marker = function_ref @marker : $@convention(thin) (Builtin.Int32) -> ()
99+
100+
// Allocate the buffer.
101+
// CHECK: [[T0:%.*]] = alloca {{\[}}[[BUFFER_SIZE]] x i8], align [[BUFFER_ALIGN]]
102+
// CHECK-NEXT: [[BUFFER:%.*]] = getelementptr inbounds {{\[}}[[BUFFER_SIZE]] x i8], {{\[}}[[BUFFER_SIZE]] x i8]* [[T0]], i32 0, i32 0
103+
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 [[BUFFER_SIZE]], i8* [[BUFFER]])
104+
105+
// Prepare the continuation function pointer to block analysis.
106+
// CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.coro.prepare.retcon(i8* bitcast ({ i8*, i32, i32 } (i8*)* @yields_pair to i8*))
107+
// CHECK-NEXT: [[PREPARE:%.*]] = bitcast i8* [[T0]] to { i8*, i32, i32 } (i8*)*
108+
// Call the function pointer.
109+
// CHECK-NEXT: [[PACKED:%.*]] = call swiftcc { i8*, i32, i32 } [[PREPARE]](i8* noalias dereferenceable([[BUFFER_SIZE]]) [[BUFFER]])
110+
// CHECK-NEXT: [[CONTINUATION:%.*]] = extractvalue { i8*, i32, i32 } [[PACKED]], 0
111+
// CHECK-NEXT: [[FIRST:%.*]] = extractvalue { i8*, i32, i32 } [[PACKED]], 1
112+
// CHECK-NEXT: [[SECOND:%.*]] = extractvalue { i8*, i32, i32 } [[PACKED]], 2
113+
%coro = function_ref @yields_pair : $@yield_once @convention(thin) () -> (@yields Builtin.Int32, @yields Builtin.Int32)
114+
(%first, %second, %token) = begin_apply %coro() : $@yield_once @convention(thin) () -> (@yields Builtin.Int32, @yields Builtin.Int32)
115+
116+
// CHECK-NEXT: call swiftcc void @marker(i32 [[FIRST]])
117+
apply %marker(%first) : $@convention(thin) (Builtin.Int32) -> ()
118+
119+
// CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[CONTINUATION]] to void (i8*, i1)*
120+
// CHECK-NEXT: call swiftcc void [[T0]](i8* noalias dereferenceable([[BUFFER_SIZE]]) [[BUFFER]], i1 false)
121+
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 [[BUFFER_SIZE]], i8* [[BUFFER]])
122+
end_apply %token
123+
124+
// CHECK-NEXT: call swiftcc void @marker(i32 [[SECOND]])
125+
apply %marker(%second) : $@convention(thin) (Builtin.Int32) -> ()
126+
127+
// CHECK-NEXT: ret void
128+
%ret = tuple ()
129+
return %ret : $()
130+
}
131+
132+
93133
// CHECK: attributes [[CORO_ATTRIBUTES]] =
94134
// CHECK-SAME: noinline

0 commit comments

Comments
 (0)