Skip to content

Commit 5a6de1b

Browse files
committed
IRGen: Use opaque storage types for non-fixed indirect result types
LLVM does type based analysis on sret storage types. This is a problem with non-fixed types whose storage type does not contain the non-fixed part. rdar://73778591
1 parent a41fadb commit 5a6de1b

17 files changed

+145
-35
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,14 @@ void SignatureExpansion::expandResult() {
668668
for (auto indirectResultType :
669669
fnConv.getIndirectSILResultTypes(IGM.getMaximalTypeExpansionContext())) {
670670
auto storageTy = IGM.getStorageType(indirectResultType);
671-
addIndirectResultAttributes(IGM, Attrs, ParamIRTypes.size(), claimSRet(), storageTy);
671+
auto useSRet = claimSRet();
672+
// We need to use opaque types or non fixed size storage types because llvm
673+
// does type based analysis based on the type of sret arguments.
674+
if (useSRet && !isa<FixedTypeInfo>(IGM.getTypeInfo(indirectResultType))) {
675+
storageTy = IGM.OpaqueTy;
676+
}
677+
addIndirectResultAttributes(IGM, Attrs, ParamIRTypes.size(), useSRet,
678+
storageTy);
672679
addPointerParameter(storageTy);
673680
}
674681
}
@@ -2573,8 +2580,12 @@ void CallEmission::emitToUnmappedMemory(Address result) {
25732580
llvm::Type *storageTy = Args[0]->getType()->getPointerElementType();;
25742581
if (FnConv.getNumIndirectSILResults() == 1) {
25752582
for (auto indirectResultType : FnConv.getIndirectSILResultTypes(
2576-
IGF.IGM.getMaximalTypeExpansionContext()))
2577-
storageTy = IGF.IGM.getStorageType(indirectResultType);
2583+
IGF.IGM.getMaximalTypeExpansionContext())) {
2584+
bool isFixedSize =
2585+
isa<FixedTypeInfo>(IGF.IGM.getTypeInfo(indirectResultType));
2586+
storageTy = isFixedSize ? IGF.IGM.getStorageType(indirectResultType)
2587+
: IGF.IGM.OpaqueTy;
2588+
}
25782589
}
25792590
addIndirectResultAttributes(IGF.IGM, CurCallee.getMutableAttributes(), 0,
25802591
FnConv.getNumIndirectSILResults() <= 1,

lib/IRGen/GenFunc.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,13 +823,15 @@ class SyncPartialApplicationForwarderEmission
823823

824824
// Forward the indirect return values. We might have to reabstract the
825825
// return value.
826+
bool useSRet = true;
826827
if (nativeResultSchema.requiresIndirect()) {
827828
assert(origNativeSchema.requiresIndirect());
828829
auto resultAddr = origParams.claimNext();
829830
resultAddr = subIGF.Builder.CreateBitCast(
830831
resultAddr, IGM.getStoragePointerType(origConv.getSILResultType(
831832
IGM.getMaximalTypeExpansionContext())));
832833
args.add(resultAddr);
834+
useSRet = false;
833835
} else if (origNativeSchema.requiresIndirect()) {
834836
assert(!nativeResultSchema.requiresIndirect());
835837
auto stackAddr = outResultTI.allocateStack(
@@ -841,14 +843,22 @@ class SyncPartialApplicationForwarderEmission
841843
resultValueAddr, IGM.getStoragePointerType(origConv.getSILResultType(
842844
IGM.getMaximalTypeExpansionContext())));
843845
args.add(resultAddr.getAddress());
846+
useSRet = false;
847+
} else if (!origNativeSchema.empty()) {
848+
useSRet = false;
844849
}
845-
850+
useSRet = useSRet && origConv.getNumIndirectSILResults() == 1;
846851
for (auto resultType : origConv.getIndirectSILResultTypes(
847852
IGM.getMaximalTypeExpansionContext())) {
848853
auto addr = origParams.claimNext();
849854
addr = subIGF.Builder.CreateBitCast(
850855
addr, IGM.getStoragePointerType(resultType));
856+
auto useOpaque =
857+
useSRet && !isa<FixedTypeInfo>(IGM.getTypeInfo(resultType));
858+
if (useOpaque)
859+
addr = subIGF.Builder.CreateBitCast(addr, IGM.OpaquePtrTy);
851860
args.add(addr);
861+
useSRet = false;
852862
}
853863

854864
// Reemit the parameters as unsubstituted.

lib/IRGen/IRGenSIL.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1631,10 +1631,13 @@ static ArrayRef<SILArgument *> emitEntryPointIndirectReturn(
16311631
auto &paramTI = IGF.IGM.getTypeInfo(inContextResultType);
16321632

16331633
// The parameter's type might be different due to looking through opaque
1634-
// archetypes.
1634+
// archetypes or for non-fixed types (llvm likes to do type based analysis
1635+
// for sret arguments and so we use opaque storage types for them).
16351636
llvm::Value *ptr = emission.getIndirectResult(idx);
1636-
if (paramTI.getStorageType() != retTI.getStorageType()) {
1637-
assert(inContextResultType.getASTType()->hasOpaqueArchetype());
1637+
bool isFixedSize = isa<FixedTypeInfo>(paramTI);
1638+
if (paramTI.getStorageType() != retTI.getStorageType() || !isFixedSize) {
1639+
assert(!isFixedSize ||
1640+
inContextResultType.getASTType()->hasOpaqueArchetype());
16381641
ptr = IGF.Builder.CreateBitCast(ptr,
16391642
retTI.getStorageType()->getPointerTo());
16401643
}

test/IRGen/TestABIInaccessible.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public struct AnotherType<T> {
88
}
99

1010
// Don't pass the metadata of Private<T> to AnotherType<T>'s outlined destroy.
11-
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s4main4copyyAA11AnotherTypeVyxGAElF"(%T4main11AnotherTypeV* noalias nocapture sret({{.*}}) %0, %T4main11AnotherTypeV* noalias nocapture %1, %swift.type* %T)
11+
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s4main4copyyAA11AnotherTypeVyxGAElF"(%swift.opaque* noalias nocapture sret({{.*}}) %0, %T4main11AnotherTypeV* noalias nocapture %1, %swift.type* %T)
1212
// CHECK: [[MD:%.*]] = call swiftcc %swift.metadata_response @"$s4main11AnotherTypeVMa"(i{{.*}} 0, %swift.type* %T)
1313
// CHECK: [[MD1:%.*]] = extractvalue %swift.metadata_response [[MD]], 0
1414
// CHECK: [[MD2:%.*]] = call swiftcc %swift.metadata_response @"$s4main6PublicVMa"(i{{.*}} 0, %swift.type* %T)

test/IRGen/big_types_corner_cases.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ public func testGetFunc() {
203203
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} hidden swiftcc void @"$s22big_types_corner_cases7TestBigC4testyyF"(%T22big_types_corner_cases7TestBigC* swiftself %0)
204204
// CHECK: [[CALL1:%.*]] = call {{.*}} @__swift_instantiateConcreteTypeFromMangledName({{.*}} @"$sSayy22big_types_corner_cases9BigStructVcSgGMD"
205205
// CHECK: [[CALL2:%.*]] = call i8** @"$sSayy22big_types_corner_cases9BigStructVcSgGSayxGSlsWl
206-
// CHECK: call swiftcc void @"$sSlsE10firstIndex5where0B0QzSgSb7ElementQzKXE_tKF"(%TSq.{{.*}}* noalias nocapture sret({{.*}}) %{{[0-9]+}}, i8* bitcast ({{.*}}* @"$s22big_types_corner_cases9BigStruct{{.*}}_TRTA{{(\.ptrauth)?}}" to i8*), %swift.opaque* %{{[0-9]+}}, %swift.type* %{{[0-9]+}}, i8** [[CALL2]]
206+
// CHECK: call swiftcc void @"$sSlsE10firstIndex5where0B0QzSgSb7ElementQzKXE_tKF"(%swift.opaque* noalias nocapture sret({{.*}}) %{{[0-9]+}}, i8* bitcast ({{.*}}* @"$s22big_types_corner_cases9BigStruct{{.*}}_TRTA{{(\.ptrauth)?}}" to i8*), %swift.opaque* %{{[0-9]+}}, %swift.type* %{{[0-9]+}}, i8** [[CALL2]]
207207
class TestBig {
208208
typealias Handler = (BigStruct) -> Void
209209

test/IRGen/dynamic_self_cast.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public class SelfCasts {
7171
return s as? Self
7272
}
7373

74-
// CHECK-LABEL: define {{(dllexport )?}}{{(protected )?}}swiftcc void @"$s17dynamic_self_cast9SelfCastsC011genericFromD11ConditionalxSgylFZ"(%TSq* noalias nocapture sret({{.*}}) %0, %swift.type* %T, %swift.type* swiftself %1)
74+
// CHECK-LABEL: define {{(dllexport )?}}{{(protected )?}}swiftcc void @"$s17dynamic_self_cast9SelfCastsC011genericFromD11ConditionalxSgylFZ"(%swift.opaque* noalias nocapture sret({{.*}}) %0, %swift.type* %T, %swift.type* swiftself %1)
7575
// CHECK: call i1 @swift_dynamicCast(%swift.opaque* {{%.*}}, %swift.opaque* {{%.*}}, %swift.type* %1, %swift.type* %T, {{.*}})
7676
// CHECK: ret
7777
public static func genericFromSelfConditional<T>() -> T? {

test/IRGen/enum.sil

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,8 +1265,9 @@ end:
12651265
return %v : $()
12661266
}
12671267

1268-
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_single_payload_inject_x(%T4enum20DynamicSinglePayloadO* noalias nocapture sret({{.*}}) %0, %swift.opaque* noalias nocapture %1, %swift.type* %T) {{.*}} {
1269-
// CHECK: [[OPAQUE_ENUM:%.*]] = bitcast %T4enum20DynamicSinglePayloadO* %0 to %swift.opaque*
1268+
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_single_payload_inject_x(%swift.opaque* noalias nocapture sret({{.*}}) %0, %swift.opaque* noalias nocapture %1, %swift.type* %T) {{.*}} {
1269+
// CHECK: [[ARG:%.*]] = bitcast %swift.opaque* %0 to %T4enum20DynamicSinglePayloadO*
1270+
// CHECK: [[OPAQUE_ENUM:%.*]] = bitcast %T4enum20DynamicSinglePayloadO* [[ARG]] to %swift.opaque*
12701271
// CHECK: [[TMP:%.*]] = bitcast %swift.type* %T to i8***
12711272
// CHECK: [[TMP2:%.*]] = getelementptr inbounds i8**, i8*** [[TMP]], i{{.*}} -1
12721273
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[TMP2]]
@@ -1281,8 +1282,9 @@ entry(%r : $*DynamicSinglePayload<T>, %t : $*T):
12811282
return %v : $()
12821283
}
12831284

1284-
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_single_payload_inject_y(%T4enum20DynamicSinglePayloadO* noalias nocapture sret({{.*}}) %0, %swift.type* %T) {{.*}} {
1285-
// CHECK: [[OPAQUE_ENUM:%.*]] = bitcast %T4enum20DynamicSinglePayloadO* %0 to %swift.opaque*
1285+
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_single_payload_inject_y(%swift.opaque* noalias nocapture sret({{.*}}) %0, %swift.type* %T) {{.*}} {
1286+
// CHECK: [[ARG:%.*]] = bitcast %swift.opaque* %0 to %T4enum20DynamicSinglePayloadO*
1287+
// CHECK: [[OPAQUE_ENUM:%.*]] = bitcast %T4enum20DynamicSinglePayloadO* [[ARG]] to %swift.opaque*
12861288
// CHECK: [[TMP:%.*]] = bitcast %swift.type* %T to i8***
12871289
// CHECK: [[TMP2:%.*]] = getelementptr inbounds i8**, i8*** [[TMP]], i{{.*}} -1
12881290
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[TMP2]]

test/IRGen/enum_dynamic_multi_payload.sil

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ entry:
264264
}
265265

266266
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_inject
267-
// CHECK: ([[EITHER_OR:%T26enum_dynamic_multi_payload8EitherOrO.*]]* noalias nocapture sret({{.*}}) %0, %swift.type* %T)
267+
// CHECK: ([[EITHER_OR:%swift.opaque]]* noalias nocapture sret({{.*}}) %0, %swift.type* %T)
268268
sil @dynamic_inject : $@convention(thin) <T> () -> @out EitherOr<T, Builtin.Int64> {
269269
entry(%e : $*EitherOr<T, Builtin.Int64>):
270270
// CHECK: call void @swift_storeEnumTagMultiPayload(%swift.opaque* {{%.*}}, %swift.type* [[TYPE:%.*]], i32 0)
@@ -283,9 +283,10 @@ entry(%e : $*EitherOr<T, Builtin.Int64>):
283283
// CHECK: ([[EITHER_OR]]* noalias nocapture sret({{.*}}) %0, %swift.type* %T)
284284
sil @dynamic_project : $@convention(thin) <T> () -> @out EitherOr<T, Builtin.Int64> {
285285
entry(%e : $*EitherOr<T, Builtin.Int64>):
286-
// CHECK: bitcast [[EITHER_OR]]* %0 to %swift.opaque*
286+
// CHECK: [[ARG:%.*]] = bitcast %swift.opaque* %0 to %T26enum_dynamic_multi_payload8EitherOrO.0
287+
// CHECK: bitcast %T26enum_dynamic_multi_payload8EitherOrO.0* [[ARG]] to %swift.opaque*
287288
%l = unchecked_take_enum_data_addr %e : $*EitherOr<T, Builtin.Int64>, #EitherOr.Left!enumelt
288-
// CHECK: bitcast [[EITHER_OR]]* %0 to i64*
289+
// CHECK: bitcast %T26enum_dynamic_multi_payload8EitherOrO.0* [[ARG]] to i64*
289290
%r = unchecked_take_enum_data_addr %e : $*EitherOr<T, Builtin.Int64>, #EitherOr.Right!enumelt
290291

291292
return undef : $()
@@ -333,7 +334,7 @@ next(%x : $Builtin.Int8):
333334
}
334335

335336
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_value_semantics
336-
// CHECK: ([[EITHER_OR]]* noalias nocapture sret({{.*}}) %0, [[EITHER_OR]]* noalias nocapture %1, %swift.type* %T)
337+
// CHECK: ([[EITHER_OR]]* noalias nocapture sret({{.*}}) %0, %T26enum_dynamic_multi_payload8EitherOrO.0* noalias nocapture %1, %swift.type* %T)
337338
sil @dynamic_value_semantics : $@convention(thin) <T> (@in EitherOr<T, Builtin.Int64>) -> @out EitherOr<T, Builtin.Int64> {
338339
entry(%a : $*EitherOr<T, Builtin.Int64>, %b : $*EitherOr<T, Builtin.Int64>):
339340
// CHECK: [[TAG:%.*]] = call i32 @swift_getEnumCaseMultiPayload
@@ -367,7 +368,7 @@ entry(%a : $*EitherOr<T, Builtin.Int64>, %b : $*EitherOr<T, Builtin.Int64>):
367368
}
368369

369370
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_value_semantics2
370-
// CHECK: ([[EITHER_OR:%T26enum_dynamic_multi_payload8EitherOrO.*]]* noalias nocapture sret({{.*}}) %0, [[EITHER_OR]]* noalias nocapture %1, %swift.type* %T)
371+
// CHECK: (%swift.opaque* noalias nocapture sret({{.*}}) %0, %T26enum_dynamic_multi_payload8EitherOrO.1* noalias nocapture %1, %swift.type* %T)
371372
sil @dynamic_value_semantics2 : $@convention(thin) <T> (@in EitherOr<T, C>) -> @out EitherOr<T, C> {
372373
entry(%a : $*EitherOr<T, C>, %b : $*EitherOr<T, C>):
373374
// CHECK: [[TAG:%.*]] = call i32 @swift_getEnumCaseMultiPayload

test/IRGen/enum_future.sil

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,8 +1269,9 @@ end:
12691269
return %v : $()
12701270
}
12711271

1272-
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_single_payload_inject_x(%T11enum_future20DynamicSinglePayloadO* noalias nocapture sret({{.*}}) %0, %swift.opaque* noalias nocapture %1, %swift.type* %T) {{.*}} {
1273-
// CHECK: [[OPAQUE_ENUM:%.*]] = bitcast %T11enum_future20DynamicSinglePayloadO* %0 to %swift.opaque*
1272+
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_single_payload_inject_x(%swift.opaque* noalias nocapture sret({{.*}}) %0, %swift.opaque* noalias nocapture %1, %swift.type* %T) {{.*}} {
1273+
// CHECK: [[ARG:%.*]] = bitcast %swift.opaque* %0 to %T11enum_future20DynamicSinglePayloadO*
1274+
// CHECK: [[OPAQUE_ENUM:%.*]] = bitcast %T11enum_future20DynamicSinglePayloadO* [[ARG]] to %swift.opaque*
12741275
// CHECK: [[TMP:%.*]] = bitcast %swift.type* %T to i8***
12751276
// CHECK: [[TMP2:%.*]] = getelementptr inbounds i8**, i8*** [[TMP]], i{{.*}} -1
12761277
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[TMP2]]
@@ -1285,8 +1286,9 @@ entry(%r : $*DynamicSinglePayload<T>, %t : $*T):
12851286
return %v : $()
12861287
}
12871288

1288-
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_single_payload_inject_y(%T11enum_future20DynamicSinglePayloadO* noalias nocapture sret({{.*}}) %0, %swift.type* %T) {{.*}} {
1289-
// CHECK: [[OPAQUE_ENUM:%.*]] = bitcast %T11enum_future20DynamicSinglePayloadO* %0 to %swift.opaque*
1289+
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_single_payload_inject_y(%swift.opaque* noalias nocapture sret({{.*}}) %0, %swift.type* %T) {{.*}} {
1290+
// CHECK: [[ARG:%.*]] = bitcast %swift.opaque* %0 to %T11enum_future20DynamicSinglePayloadO*
1291+
// CHECK: [[OPAQUE_ENUM:%.*]] = bitcast %T11enum_future20DynamicSinglePayloadO* [[ARG]] to %swift.opaque*
12901292
// CHECK: [[TMP:%.*]] = bitcast %swift.type* %T to i8***
12911293
// CHECK: [[TMP2:%.*]] = getelementptr inbounds i8**, i8*** [[TMP]], i{{.*}} -1
12921294
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[TMP2]]

test/IRGen/enum_resilience.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,8 +341,9 @@ extension ResilientMultiPayloadGenericEnum {
341341
}
342342
}
343343

344-
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s15enum_resilience39constructExhaustiveWithResilientMembers010resilient_A011SimpleShapeOyF"(%T14resilient_enum11SimpleShapeO* noalias nocapture sret({{.*}}) %0)
345-
// CHECK: [[BUFFER:%.*]] = bitcast %T14resilient_enum11SimpleShapeO* %0 to %swift.opaque*
344+
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s15enum_resilience39constructExhaustiveWithResilientMembers010resilient_A011SimpleShapeOyF"(%swift.opaque* noalias nocapture sret({{.*}}) %0)
345+
// CHECK: [[ARG:%.*]] = bitcast %swift.opaque* %0 to %T14resilient_enum11SimpleShapeO*
346+
// CHECK: [[BUFFER:%.*]] = bitcast %T14resilient_enum11SimpleShapeO* [[ARG]] to %swift.opaque*
346347
// CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s16resilient_struct4SizeVMa"([[INT]] 0)
347348
// CHECK-NEXT: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
348349
// CHECK: [[STORE_TAG:%.*]] = bitcast i8* {{%.+}} to void (%swift.opaque*, i32, i32, %swift.type*)*

0 commit comments

Comments
 (0)