Skip to content

Commit c1e1bf2

Browse files
committed
cross-module-optimization: Don't serialize functions which reference implementationOnly-imported functions
The check for implementationOnly imports was already done for types, but it was missing for functions. Fixes a crash when implementationOnly-importing a C module. https://bugs.swift.org/browse/SR-15048 rdar://81701218
1 parent 990fc4b commit c1e1bf2

12 files changed

+57
-18
lines changed

Diff for: include/swift/AST/Module.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -676,9 +676,10 @@ class ModuleDecl : public DeclContext, public TypeDecl {
676676
/// This assumes that \p module was imported.
677677
bool isImportedImplementationOnly(const ModuleDecl *module) const;
678678

679-
/// Returns true if a function, which is using \p nominal, can be serialized
680-
/// by cross-module-optimization.
681-
bool canBeUsedForCrossModuleOptimization(NominalTypeDecl *nominal) const;
679+
/// Returns true if decl context or its content can be serialized by
680+
/// cross-module-optimization.
681+
/// The \p ctxt can e.g. be a NominalType or the context of a function.
682+
bool canBeUsedForCrossModuleOptimization(DeclContext *ctxt) const;
682683

683684
/// Finds all top-level decls of this module.
684685
///

Diff for: lib/AST/Module.cpp

+7-6
Original file line numberDiff line numberDiff line change
@@ -2353,14 +2353,15 @@ bool ModuleDecl::isImportedImplementationOnly(const ModuleDecl *module) const {
23532353
}
23542354

23552355
bool ModuleDecl::
2356-
canBeUsedForCrossModuleOptimization(NominalTypeDecl *nominal) const {
2357-
ModuleDecl *moduleOfNominal = nominal->getParentModule();
2356+
canBeUsedForCrossModuleOptimization(DeclContext *ctxt) const {
2357+
ModuleDecl *moduleOfCtxt = ctxt->getParentModule();
23582358

2359-
// If the nominal is defined in the same module, it's fine.
2360-
if (moduleOfNominal == this)
2359+
// If the context defined in the same module - or is the same module, it's
2360+
// fine.
2361+
if (moduleOfCtxt == this)
23612362
return true;
23622363

2363-
// See if nominal is imported in a "regular" way, i.e. not with
2364+
// See if context is imported in a "regular" way, i.e. not with
23642365
// @_implementationOnly or @_spi.
23652366
ModuleDecl::ImportFilter filter = {
23662367
ModuleDecl::ImportFilterKind::Exported,
@@ -2370,7 +2371,7 @@ canBeUsedForCrossModuleOptimization(NominalTypeDecl *nominal) const {
23702371

23712372
auto &imports = getASTContext().getImportCache();
23722373
for (auto &desc : results) {
2373-
if (imports.isImportedBy(moduleOfNominal, desc.importedModule))
2374+
if (imports.isImportedBy(moduleOfCtxt, desc.importedModule))
23742375
return true;
23752376
}
23762377
return false;

Diff for: lib/SILOptimizer/IPO/CrossModuleSerializationSetup.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,11 @@ bool CrossModuleSerializationSetup::canUseFromInline(SILFunction *func,
386386
if (!func)
387387
return false;
388388

389+
if (DeclContext *funcCtxt = func->getDeclContext()) {
390+
if (!M.getSwiftModule()->canBeUsedForCrossModuleOptimization(funcCtxt))
391+
return false;
392+
}
393+
389394
switch (func->getLinkage()) {
390395
case SILLinkage::PublicNonABI:
391396
return func->isSerialized() != IsNotSerialized;

Diff for: test/SILOptimizer/Inputs/cross-module/c-module.c

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
#include "c-module.h"
3+
4+
long privateCFunc() {
5+
return 123;
6+
}
7+

Diff for: test/SILOptimizer/Inputs/cross-module/c-module.h

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
long privateCFunc();
3+

Diff for: test/SILOptimizer/Inputs/cross-module.swift renamed to test/SILOptimizer/Inputs/cross-module/cross-module.swift

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Submodule
22
@_implementationOnly import PrivateSubmodule
3+
@_implementationOnly import PrivateCModule
34

45
private enum PE<T> {
56
case A
@@ -268,11 +269,19 @@ public func callUnrelated<T>(_ t: T) -> T {
268269
return t
269270
}
270271

271-
public func callImplementationOnly<T>(_ t: T) -> T {
272+
public func callImplementationOnlyType<T>(_ t: T) -> T {
272273
let p = PrivateStr(i: 27)
273274
print(p.test())
274275
return t
275276
}
276277

278+
public func callImplementationOnlyFunc<T>(_ t: T) -> Int {
279+
return privateFunc()
280+
}
281+
282+
public func callCImplementationOnly<T>(_ t: T) -> Int {
283+
return Int(privateCFunc())
284+
}
285+
277286

278287
public let globalLet = 529387

Diff for: test/SILOptimizer/Inputs/cross-private-submodule.swift renamed to test/SILOptimizer/Inputs/cross-module/cross-private-submodule.swift

+3
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@ public struct PrivateStr {
1212
}
1313
}
1414

15+
public func privateFunc() -> Int {
16+
return 40
17+
}
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module PrivateCModule {
2+
header "c-module.h"
3+
}

Diff for: test/SILOptimizer/cross-module-optimization-objc.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// First test: functional correctness
22

33
// RUN: %empty-directory(%t)
4-
// RUN: %target-build-swift -O -wmo -parse-as-library -cross-module-optimization -emit-module -emit-module-path=%t/Test.swiftmodule -module-name=Test -I%t %S/Inputs/cross-module-objc.swift -c -o %t/test.o
4+
// RUN: %target-build-swift -O -wmo -parse-as-library -cross-module-optimization -emit-module -emit-module-path=%t/Test.swiftmodule -module-name=Test -I%t %S/Inputs/cross-module/cross-module-objc.swift -c -o %t/test.o
55
// RUN: %target-build-swift -O -wmo -module-name=Main -I%t %s -c -o %t/main.o
66
// RUN: %target-swiftc_driver %t/main.o %t/test.o -o %t/a.out
77
// RUN: %target-codesign %t/a.out

Diff for: test/SILOptimizer/cross-module-optimization.swift

+14-7
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
// First test: functional correctness
22

33
// RUN: %empty-directory(%t)
4-
// RUN: %target-build-swift -O -wmo -parse-as-library -cross-module-optimization -emit-module -emit-module-path=%t/Submodule.swiftmodule -module-name=Submodule %S/Inputs/cross-submodule.swift -c -o %t/submodule.o
5-
// RUN: %target-build-swift -O -wmo -parse-as-library -cross-module-optimization -emit-module -emit-module-path=%t/PrivateSubmodule.swiftmodule -module-name=PrivateSubmodule %S/Inputs/cross-private-submodule.swift -c -o %t/privatesubmodule.o
6-
// RUN: %target-build-swift -O -wmo -parse-as-library -cross-module-optimization -emit-module -emit-module-path=%t/Test.swiftmodule -module-name=Test -I%t %S/Inputs/cross-module.swift -c -o %t/test.o
4+
// RUN: %target-build-swift -O -wmo -parse-as-library -cross-module-optimization -emit-module -emit-module-path=%t/Submodule.swiftmodule -module-name=Submodule %S/Inputs/cross-module/cross-submodule.swift -c -o %t/submodule.o
5+
// RUN: %target-build-swift -O -wmo -parse-as-library -cross-module-optimization -emit-module -emit-module-path=%t/PrivateSubmodule.swiftmodule -module-name=PrivateSubmodule %S/Inputs/cross-module/cross-private-submodule.swift -c -o %t/privatesubmodule.o
6+
// RUN: %target-clang -c --language=c %S/Inputs/cross-module/c-module.c -o %t/c-module.o
7+
// RUN: %target-build-swift -O -wmo -parse-as-library -cross-module-optimization -emit-module -emit-module-path=%t/Test.swiftmodule -module-name=Test -I%t -I%S/Inputs/cross-module %S/Inputs/cross-module/cross-module.swift -c -o %t/test.o
78
// RUN: %target-build-swift -O -wmo -module-name=Main -I%t %s -c -o %t/main.o
8-
// RUN: %target-swiftc_driver %t/main.o %t/test.o %t/submodule.o %t/privatesubmodule.o -o %t/a.out
9+
// RUN: %target-swiftc_driver %t/main.o %t/test.o %t/submodule.o %t/privatesubmodule.o %t/c-module.o -o %t/a.out
910
// RUN: %target-codesign %t/a.out
1011
// RUN: %target-run %t/a.out | %FileCheck %s -check-prefix=CHECK-OUTPUT
1112

1213
// Check if it also works if the main module is compiled with -Onone:
1314

1415
// RUN: %target-build-swift -Onone -wmo -module-name=Main -I%t %s -c -o %t/main-onone.o
15-
// RUN: %target-swiftc_driver %t/main-onone.o %t/test.o %t/submodule.o %t/privatesubmodule.o -o %t/a.out
16+
// RUN: %target-swiftc_driver %t/main-onone.o %t/test.o %t/submodule.o %t/privatesubmodule.o %t/c-module.o -o %t/a.out
1617
// RUN: %target-codesign %t/a.out
1718
// RUN: %target-run %t/a.out | %FileCheck %s -check-prefix=CHECK-OUTPUT
1819

@@ -146,8 +147,14 @@ func testGlobal() {
146147
@inline(never)
147148
func testImplementationOnly() {
148149
// CHECK-OUTPUT: 27
149-
// CHECK-SIL2: function_ref @$s4Test22callImplementationOnlyyxxlF
150-
print(callImplementationOnly(27))
150+
// CHECK-SIL2: function_ref @$s4Test26callImplementationOnlyTypeyxxlF
151+
print(callImplementationOnlyType(27))
152+
// CHECK-OUTPUT: 40
153+
// CHECK-SIL2: function_ref @$s4Test26callImplementationOnlyFuncySixlF
154+
print(callImplementationOnlyFunc(0))
155+
// CHECK-OUTPUT: 123
156+
// CHECK-SIL2: function_ref @$s4Test23callCImplementationOnlyySixlF
157+
print(callCImplementationOnly(0))
151158
// CHECK-SIL2: } // end sil function '$s4Main22testImplementationOnlyyyF'
152159
}
153160

0 commit comments

Comments
 (0)