Skip to content

Commit 58da061

Browse files
authored
Merge pull request #17736 from slavapestov/resilience-bypass-metadata-accessor-fix-4.2
IRGen: Always call metadata accessor for resilient types even when resilience bypass is enabled [4.2]
2 parents 7d3e78e + 7a5e090 commit 58da061

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

lib/IRGen/MetadataRequest.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,8 +572,28 @@ bool irgen::isTypeMetadataAccessTrivial(IRGenModule &IGM, CanType type) {
572572
if (nominalDecl->isGenericContext())
573573
return false;
574574

575+
auto expansion = ResilienceExpansion::Maximal;
576+
577+
// Normally, if a value type is known to have a fixed layout to us, we will
578+
// have emitted fully initialized metadata for it, including a payload size
579+
// field for enum metadata for example, allowing the type metadata to be
580+
// used in other resilience domains without initialization.
581+
//
582+
// However, when -enable-resilience-bypass is on, we might be using a value
583+
// type from another module built with resilience enabled. In that case, the
584+
// type looks like it has fixed size to us, since we're bypassing resilience,
585+
// but the metadata still requires runtime initialization, so its incorrect
586+
// to reference it directly.
587+
//
588+
// While unconditionally using minimal expansion is correct, it is not as
589+
// efficient as it should be, so only do so if -enable-resilience-bypass is on.
590+
//
591+
// FIXME: All of this goes away once lldb supports resilience.
592+
if (IGM.IRGen.Opts.EnableResilienceBypass)
593+
expansion = ResilienceExpansion::Minimal;
594+
575595
// Resiliently-sized metadata access always requires an accessor.
576-
return (IGM.getTypeInfoForUnlowered(type).isFixedSize());
596+
return (IGM.getTypeInfoForUnlowered(type).isFixedSize(expansion));
577597
}
578598

579599
// The empty tuple type has a singleton metadata.

test/IRGen/resilience_bypass.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,37 @@
44
// RUN: %target-swift-frontend -emit-module -emit-module-path=%t/second.swiftmodule -module-name=second %S/Inputs/resilience_bypass/second.swift -I %t
55
// RUN: %target-swift-frontend -emit-ir -enable-resilience-bypass %s -I %t | %FileCheck %s -DINT=i%target-ptrsize
66

7+
import first
78
import second
89

910
// CHECK: define{{( protected)?}} swiftcc [[INT]] @"$S17resilience_bypass7getSizeSiyF"() {{.*}} {
1011
// CHECK-NEXT: entry:
12+
13+
// FIXME: The metadata accessor call is not necessary
14+
// CHECK-NEXT: [[RESPONSE:%.*]] = call swiftcc %swift.metadata_response @"$S6second1EOMa"
15+
// CHECK-NEXT: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[RESPONSE]], 0
16+
1117
// CHECK-NEXT: ret [[INT]] {{5|9}}
1218
// CHECK-NEXT: }
1319

1420
public func getSize() -> Int {
1521
return MemoryLayout<E>.size
1622
}
23+
24+
public func makeE(_ s: S) -> E {
25+
return .b(s)
26+
}
27+
28+
// CHECK: define{{( dllexport| protected)?}} swiftcc void @"$S17resilience_bypass7makeAnyyyp5first1SVF"(
29+
// CHECK-NEXT: entry:
30+
31+
// Make sure we form the existential using the result of the metadata accessor, instead of
32+
// directly using the address of the metadata global.
33+
//
34+
// FIXME: The metadata global should have hidden linkage to rule out this kind of bug.
35+
36+
// CHECK-NEXT: [[RESPONSE:%.*]] = call swiftcc %swift.metadata_response @"$S6second1EOMa"
37+
38+
public func makeAny(_ s: S) -> Any {
39+
return makeE(s)
40+
}

0 commit comments

Comments
 (0)