Skip to content

Commit 6c178c7

Browse files
committed
[prespecialized metadata] Require same file without wmo.
Without whole module optimization, the metadata accessors are emitted on a per-file basis. The result is that if the file containing a generic type is processed before the file containing a usage of that type that would result in that prespecialization, the metadata accessor would have already been emitted by the time that the usage is noted, making it impossible for the newly created prespecialization to be returned from the already-emitted metadata accessor. Here, require that either whole module optimization is enabled so that the metadata accessors are all emitted at once at the end, or else that the usage of the prespecialization is in the same file as the type is declared.
1 parent 5f8fece commit 6c178c7

8 files changed

+85
-38
lines changed

lib/IRGen/IRGen.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -960,9 +960,8 @@ performIRGeneration(const IRGenOptions &Opts, ModuleDecl *M,
960960
if (!targetMachine) return nullptr;
961961

962962
// Create the IR emitter.
963-
IRGenModule IGM(irgen, std::move(targetMachine), nullptr, LLVMContext,
964-
ModuleName, PSPs.OutputFilename,
965-
PSPs.MainInputFilenameForDebugInfo,
963+
IRGenModule IGM(irgen, std::move(targetMachine), SF, LLVMContext, ModuleName,
964+
PSPs.OutputFilename, PSPs.MainInputFilenameForDebugInfo,
966965
PrivateDiscriminator);
967966

968967
initLLVMModule(IGM, *SILMod->getSwiftModule());

lib/IRGen/IRGenModule.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,16 @@ class IRGenerator {
324324
assert(IGM);
325325
return IGM;
326326
}
327-
327+
328+
SourceFile *getSourceFile(IRGenModule *module) {
329+
for (auto pair : GenModules) {
330+
if (pair.second == module) {
331+
return pair.first;
332+
}
333+
}
334+
return nullptr;
335+
}
336+
328337
/// Get an IRGenModule for a declaration context.
329338
/// Returns the IRGenModule of the containing source file, or if this cannot
330339
/// be determined, returns the primary IRGenModule.

lib/IRGen/MetadataRequest.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -708,9 +708,23 @@ bool irgen::isNominalGenericContextTypeMetadataAccessTrivial(
708708
return false;
709709
}
710710

711-
if (nominal.getModuleContext() != IGM.getSwiftModule() ||
712-
nominal.isResilient(IGM.getSwiftModule(), ResilienceExpansion::Minimal)) {
713-
return false;
711+
if (IGM.getSILModule().isWholeModule()) {
712+
if (nominal.isResilient(IGM.getSwiftModule(),
713+
ResilienceExpansion::Maximal)) {
714+
return false;
715+
}
716+
} else {
717+
// If whole module optimization is not enabled, we can only construct a
718+
// canonical prespecialization if the usage is in the same *file* as that
719+
// containing the type's decl! The reason is that the generic metadata
720+
// accessor is defined in the IRGenModule corresponding to the source file
721+
// containing the type's decl.
722+
SourceFile *nominalFile = nominal.getDeclContext()->getParentSourceFile();
723+
if (auto *moduleFile = IGM.IRGen.getSourceFile(&IGM)) {
724+
if (nominalFile != moduleFile) {
725+
return false;
726+
}
727+
}
714728
}
715729

716730
if (isa<ClassType>(type) || isa<BoundGenericClassType>(type)) {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
func unsafePointerToMetadata<T>(of ty: T.Type) -> UnsafePointer<T.Type> {
2+
unsafeBitCast(ty, to: UnsafePointer<T.Type>.self)
3+
}
4+
5+
@inline(never)
6+
func consume<T>(_ value: T) {
7+
withExtendedLifetime(value) {
8+
print(unsafePointerToMetadata(of: T.self), value)
9+
}
10+
}
11+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
doit()
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
struct OneArgument<First> {
2+
let first: First
3+
4+
let line: UInt
5+
6+
init(_ first: First, line: UInt = #line) {
7+
self.first = first
8+
self.line = line
9+
}
10+
}
11+
12+
extension OneArgument : CustomStringConvertible {
13+
var description: String {
14+
"\(first) @ \(line)"
15+
}
16+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %target-run-simple-swift(%S/Inputs/main.swift %S/Inputs/consume-logging-metadata-value.swift %S/Inputs/struct-nonfrozen-1argument.swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future) | %FileCheck %s
2+
// REQUIRES: executable_test
3+
4+
// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu
5+
// UNSUPPORTED: CPU=i386 && OS=ios
6+
// UNSUPPORTED: CPU=armv7 && OS=ios
7+
// UNSUPPORTED: CPU=armv7s && OS=ios
8+
// Executing on the simulator within __abort_with_payload with "No ABI plugin located for triple x86_64h-apple-ios -- shared libraries will not be registered!"
9+
// UNSUPPORTED: CPU=x86_64 && OS=ios
10+
// UNSUPPORTED: CPU=x86_64 && OS=tvos
11+
// UNSUPPORTED: CPU=x86_64 && OS=watchos
12+
// UNSUPPORTED: CPU=i386 && OS=watchos
13+
// UNSUPPORTED: use_os_stdlib
14+
15+
func consume<First>(oneArgument: OneArgument<First>) {
16+
consume(oneArgument)
17+
}
18+
19+
func doit() {
20+
// CHECK: [[METADATA_ADDRESS:[0-9a-f]+]] 3 @ 21
21+
consume(OneArgument(3))
22+
// CHECK: [[METADATA_ADDRESS]] 3 @ 23
23+
consume(oneArgument: OneArgument(3))
24+
}

test/IRGen/signature_conformances_multifile_future.swift

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,11 @@
1111
// CHECK-LABEL: define hidden swiftcc void @"$s39signature_conformances_multifile_future5passQyyF"()
1212
func passQ() {
1313
// CHECK: call swiftcc void @"$s39signature_conformances_multifile_future12AlsoConformsVACyxGycfC"(%swift.type* @"$sSiN")
14+
// CHECK: [[METADATA:%[0-9]+]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s39signature_conformances_multifile_future12AlsoConformsVySiGMD")
1415
// CHECK: [[WITNESS_TABLE:%[0-9]+]] = call i8** @"$s39signature_conformances_multifile_future12AlsoConformsVySiGACyxGAA1QAAWl"()
1516
// CHECK: call swiftcc void @"$s39signature_conformances_multifile_future6takesQyyxAA1QRzlF"(
1617
// CHECK-SAME: %swift.opaque* noalias nocapture undef,
17-
// CHECK-SAME: %swift.type* getelementptr inbounds (
18-
// CHECK-SAME: %swift.full_type,
19-
// CHECK-SAME: %swift.full_type* bitcast (
20-
// CHECK-SAME: <{
21-
// CHECK-SAME: i8**,
22-
// CHECK-SAME: [[INT]],
23-
// CHECK-SAME: %swift.type_descriptor*,
24-
// CHECK-SAME: %swift.type*,
25-
// CHECK-SAME: i64
26-
// CHECK-SAME: }>* @"$s39signature_conformances_multifile_future12AlsoConformsVySiGMf"
27-
// CHECK-SAME: to %swift.full_type*
28-
// CHECK-SAME: ),
29-
// CHECK-SAME: i32 0,
30-
// CHECK-SAME: i32 1
31-
// CHECK-SAME: ),
18+
// CHECK-SAME: %swift.type* [[METADATA]],
3219
// CHECK-SAME: i8** [[WITNESS_TABLE]]
3320
// CHECK-SAME: )
3421
takesQ(AlsoConforms<Int>())
@@ -39,25 +26,11 @@ func passQ() {
3926
// CHECK-LABEL: define hidden swiftcc void @"$s39signature_conformances_multifile_future5passPyyF"()
4027
func passP() {
4128
// CHECK: call swiftcc void @"$s39signature_conformances_multifile_future8ConformsVACyxq_GycfC"(%swift.type* @"$sSiN", %swift.type* @"$sSSN")
29+
// CHECK: [[METADATA:%[0-9]+]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s39signature_conformances_multifile_future8ConformsVySiSSGMD")
4230
// CHECK: [[WITNESS_TABLE:%[0-9]+]] = call i8** @"$s39signature_conformances_multifile_future8ConformsVySiSSGACyxq_GAA1PAAWl"()
4331
// CHECK: call swiftcc void @"$s39signature_conformances_multifile_future6takesPyyxAA1PRzlF"(
4432
// CHECK-SAME: %swift.opaque* noalias nocapture undef,
45-
// CHECK-SAME: %swift.type* getelementptr inbounds (
46-
// CHECK-SAME: %swift.full_type,
47-
// CHECK-SAME: %swift.full_type* bitcast (
48-
// CHECK-SAME: <{
49-
// CHECK-SAME: i8**,
50-
// CHECK-SAME: [[INT]],
51-
// CHECK-SAME: %swift.type_descriptor*,
52-
// CHECK-SAME: %swift.type*,
53-
// CHECK-SAME: %swift.type*,
54-
// CHECK-SAME: i64
55-
// CHECK-SAME: }>* @"$s39signature_conformances_multifile_future8ConformsVySiSSGMf"
56-
// CHECK-SAME: to %swift.full_type*
57-
// CHECK-SAME: ),
58-
// CHECK-SAME: i32 0,
59-
// CHECK-SAME: i32 1
60-
// CHECK-SAME: ),
33+
// CHECK-SAME: %swift.type* [[METADATA]],
6134
// CHECK-SAME: i8** [[WITNESS_TABLE]]
6235
// CHECK-SAME: )
6336
takesP(Conforms<Int, String>())

0 commit comments

Comments
 (0)