Skip to content

Commit b3fd453

Browse files
committed
[IRGen] Fix crasher in emitPartialApplicationForwarder when the return type is not a POD struct.
1 parent 01339e7 commit b3fd453

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

lib/IRGen/GenFunc.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1247,7 +1247,21 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM,
12471247
// cast to the result type - it could be substituted.
12481248
if (origConv.getSILResultType().hasTypeParameter()) {
12491249
auto ResType = fwd->getReturnType();
1250-
callResult = subIGF.Builder.CreateBitCast(callResult, ResType);
1250+
// SWIFT_ENABLE_TENSORFLOW
1251+
if (auto *structType = dyn_cast<llvm::StructType>(ResType)) {
1252+
// Cast all struct elements to the desired type.
1253+
llvm::Value *castResult = llvm::UndefValue::get(structType);
1254+
for (auto i : range(structType->getStructNumElements())) {
1255+
auto desiredEltTy = structType->getElementType(i);
1256+
auto elt = subIGF.Builder.CreateExtractValue(callResult, {i});
1257+
auto castElt = subIGF.Builder.CreateBitCast(elt, desiredEltTy);
1258+
castResult =
1259+
subIGF.Builder.CreateInsertValue(castResult, castElt, {i});
1260+
}
1261+
callResult = castResult;
1262+
}
1263+
else
1264+
callResult = subIGF.Builder.CreateBitCast(callResult, ResType);
12511265
}
12521266
subIGF.Builder.CreateRet(callResult);
12531267
}

test/IRGen/partial_apply_forwarder.sil

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,35 @@ bb0(%0 : $*τ_0_1, %1: $S):
222222
return %9 : $@callee_owned () -> ()
223223
}
224224

225+
public class Empty<T> {}
226+
227+
sil private @inner_closure : $@convention(thin) <T> (Empty<T>) -> @owned Empty<T> {
228+
bb0(%0 : $Empty<T>):
229+
return %0 : $Empty<T>
230+
}
231+
232+
sil hidden @returns_closure : $@convention(thin) <T> (Empty<T>) -> (@owned Empty<T>, @callee_guaranteed @owned (Empty<T>) -> @owned Empty<T>) {
233+
bb0(%0 : $Empty<T>):
234+
%1 = function_ref @inner_closure : $@convention(thin) <τ_0_0> (Empty<τ_0_0>) -> @owned Empty<τ_0_0>
235+
%2 = partial_apply [callee_guaranteed] %1<T>() : $@convention(thin) <τ_0_0> (Empty<τ_0_0>) -> @owned Empty<τ_0_0>
236+
%5 = tuple (%0 : $Empty<T>, %2 : $@callee_guaranteed (Empty<T>) -> @owned Empty<T>)
237+
return %5 : $(Empty<T>, @callee_guaranteed (Empty<T>) -> @owned Empty<T>)
238+
}
239+
240+
sil hidden @specializes_closure_returning_closure : $@convention(thin) () -> @callee_guaranteed (Empty<S>) -> (@owned Empty<S>, @owned @callee_guaranteed (Empty<S>) -> @owned Empty<S>) {
241+
bb0:
242+
%0 = function_ref @returns_closure : $@convention(thin) <τ_0_0> (Empty<τ_0_0>) -> (@owned Empty<τ_0_0>, @owned @callee_guaranteed (Empty<τ_0_0>) -> @owned Empty<τ_0_0>)
243+
%1 = partial_apply [callee_guaranteed] %0<S>() : $@convention(thin) <τ_0_0> (Empty<τ_0_0>) -> (@owned Empty<τ_0_0>, @owned @callee_guaranteed (Empty<τ_0_0>) -> @owned Empty<τ_0_0>)
244+
return %1 : $@callee_guaranteed (Empty<S>) -> (@owned Empty<S>, @owned @callee_guaranteed (Empty<S>) -> @owned Empty<S>)
245+
}
246+
247+
// CHECK-LABEL: define hidden swiftcc { i8*, %swift.refcounted* } @specializes_closure_returning_closure() #0 {
248+
// CHECK: entry:
249+
// CHECK: ret { i8*, %swift.refcounted* } { i8* bitcast ({ %{{.*}}Empty{{.*}}*, i8*, %swift.refcounted* } (%{{.*}}Empty{{.*}}*, %swift.refcounted*)* @"{{.*}}returns_closure{{.*}}" to i8*), %swift.refcounted* null }
250+
225251
sil_vtable WeakBox {}
226252
sil_vtable C {}
227253
sil_vtable D {}
228254
sil_vtable E {}
255+
sil_vtable Empty {}
229256
sil_witness_table C: P module main {}

0 commit comments

Comments
 (0)