Skip to content

Commit 011c127

Browse files
authored
Merge pull request #75987 from eeckstein/fix-embedded-errors
CrossModuleOptimization: serialized witness tables in embedded mode
2 parents abce071 + 44d85c1 commit 011c127

File tree

2 files changed

+90
-31
lines changed

2 files changed

+90
-31
lines changed

lib/SILOptimizer/IPO/CrossModuleOptimization.cpp

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -301,43 +301,53 @@ void CrossModuleOptimization::serializeFunctionsInModule(SILPassManager *manager
301301
}
302302

303303
void CrossModuleOptimization::serializeWitnessTablesInModule() {
304-
if (!isPackageCMOEnabled(M.getSwiftModule()))
304+
if (!isPackageCMOEnabled(M.getSwiftModule()) && !everything)
305305
return;
306306

307307
for (auto &wt : M.getWitnessTables()) {
308-
if (wt.getSerializedKind() != getRightSerializedKind(M) &&
309-
hasPublicOrPackageVisibility(wt.getLinkage(), /*includePackage*/ true)) {
310-
auto unserializedWTMethodRange = llvm::make_filter_range(
311-
wt.getEntries(), [&](const SILWitnessTable::Entry &entry) {
312-
return entry.getKind() == SILWitnessTable::Method &&
313-
entry.getMethodWitness().Witness->getSerializedKind() !=
314-
getRightSerializedKind(M);
315-
});
316-
// In Package CMO, we try serializing witness thunks that
317-
// are private if they don't contain hidden or private
318-
// references. If they are serialized, they are set to
319-
// a shared linkage. If they can't be serialized, we set
320-
// the linkage to package so that the witness table itself
321-
// can still be serialized, thus giving a chance for entires
322-
// that _are_ serialized to be accessed directly.
323-
for (const SILWitnessTable::Entry &entry: unserializedWTMethodRange) {
324-
if (entry.getMethodWitness().Witness->getLinkage() == SILLinkage::Private)
325-
entry.getMethodWitness().Witness->setLinkage(SILLinkage::Package);
308+
if (wt.getSerializedKind() == getRightSerializedKind(M))
309+
continue;
310+
311+
if (!hasPublicOrPackageVisibility(wt.getLinkage(), /*includePackage*/ true) && !everything)
312+
continue;
313+
314+
bool containsInternal = false;
315+
316+
for (const SILWitnessTable::Entry &entry : wt.getEntries()) {
317+
if (entry.getKind() != SILWitnessTable::Method)
318+
continue;
319+
320+
SILFunction *witness = entry.getMethodWitness().Witness;
321+
if (!witness)
322+
continue;
323+
324+
if (everything) {
325+
makeFunctionUsableFromInline(witness);
326+
} else {
327+
assert(isPackageCMOEnabled(M.getSwiftModule()));
328+
329+
// In Package CMO, we try serializing witness thunks that
330+
// are private if they don't contain hidden or private
331+
// references. If they are serialized, they are set to
332+
// a shared linkage. If they can't be serialized, we set
333+
// the linkage to package so that the witness table itself
334+
// can still be serialized, thus giving a chance for entires
335+
// that _are_ serialized to be accessed directly.
336+
if (witness->getSerializedKind() != getRightSerializedKind(M) &&
337+
witness->getLinkage() == SILLinkage::Private) {
338+
witness->setLinkage(SILLinkage::Package);
339+
}
326340
}
327341

328-
bool containsInternal = llvm::any_of(
329-
wt.getEntries(), [&](const SILWitnessTable::Entry &entry) {
330-
return entry.getKind() == SILWitnessTable::Method &&
331-
!entry.getMethodWitness()
332-
.Witness->hasValidLinkageForFragileRef(
333-
getRightSerializedKind(M));
334-
});
335-
// FIXME: This check shouldn't be necessary but added as a caution
336-
// to ensure we don't serialize witness table if it contains an
337-
// internal entry.
338-
if (!containsInternal)
339-
wt.setSerializedKind(getRightSerializedKind(M));
342+
if (!witness->hasValidLinkageForFragileRef(getRightSerializedKind(M)))
343+
containsInternal = true;
340344
}
345+
346+
// FIXME: This check shouldn't be necessary but added as a caution
347+
// to ensure we don't serialize witness table if it contains an
348+
// internal entry.
349+
if (!containsInternal)
350+
wt.setSerializedKind(getRightSerializedKind(M));
341351
}
342352
}
343353

test/embedded/generic-modules.swift

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %{python} %utils/split_file.py -o %t %s
3+
4+
// Check that this compiles successfully.
5+
6+
// RUN: %target-swift-frontend -emit-module -o %t/MyModule.swiftmodule %t/MyModule.swift -enable-experimental-feature Embedded -parse-as-library
7+
// RUN: %target-swift-frontend -c -o %t/Main.o -I %t %t/Main.swift -enable-experimental-feature Embedded -parse-as-library
8+
9+
// REQUIRES: OS=macosx || OS=linux-gnu
10+
11+
// BEGIN MyModule.swift
12+
13+
public func foo<Info: Collection>(info: Info) {
14+
let b = MyContainer()
15+
_ = b.dropFirst()
16+
}
17+
18+
struct MyContainer {
19+
var x = 42
20+
init() { }
21+
}
22+
23+
extension MyContainer: Collection {
24+
typealias Index = Int
25+
var startIndex: Index { fatalError() }
26+
var endIndex: Index { fatalError() }
27+
28+
subscript(_ index: Index) -> UInt8 {
29+
get {
30+
fatalError()
31+
}
32+
set {
33+
fatalError()
34+
}
35+
}
36+
37+
func index(after i: Int) -> Int {
38+
fatalError()
39+
}
40+
}
41+
42+
// BEGIN Main.swift
43+
44+
import MyModule
45+
46+
public func main() {
47+
foo(info: [1, 2, 3])
48+
}
49+

0 commit comments

Comments
 (0)