Skip to content

Commit cb4d0fa

Browse files
authored
Merge pull request #28560 from eeckstein/fix-cmo2
2 parents 41a116b + 1b20134 commit cb4d0fa

File tree

4 files changed

+66
-14
lines changed

4 files changed

+66
-14
lines changed

lib/AST/Decl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3115,7 +3115,7 @@ static AccessLevel getAdjustedFormalAccess(const ValueDecl *VD,
31153115
return getMaximallyOpenAccessFor(VD);
31163116

31173117
if (treatUsableFromInlineAsPublic &&
3118-
(access == AccessLevel::Internal || access == AccessLevel::Private) &&
3118+
access <= AccessLevel::Internal &&
31193119
VD->isUsableFromInline()) {
31203120
return AccessLevel::Public;
31213121
}

lib/SILOptimizer/IPO/CrossModuleSerializationSetup.cpp

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -137,25 +137,25 @@ class InstructionVisitor : public SILCloner<InstructionVisitor> {
137137
};
138138

139139
/// Make a nominal type, including it's context, usable from inline.
140-
static void makeNominalUsableFromInline(NominalTypeDecl *NT, SILModule &M) {
141-
if (NT->getEffectiveAccess() >= AccessLevel::Public)
140+
static void makeDeclUsableFromInline(ValueDecl *decl, SILModule &M) {
141+
if (decl->getEffectiveAccess() >= AccessLevel::Public)
142142
return;
143143

144-
if (!NT->isUsableFromInline()) {
144+
if (!decl->isUsableFromInline()) {
145145
// Mark the nominal type as "usableFromInline".
146146
// TODO: find a way to do this without modifying the AST. The AST should be
147147
// immutable at this point.
148-
auto &ctx = NT->getASTContext();
148+
auto &ctx = decl->getASTContext();
149149
auto *attr = new (ctx) UsableFromInlineAttr(/*implicit=*/true);
150-
NT->getAttrs().add(attr);
150+
decl->getAttrs().add(attr);
151151
}
152-
if (auto *enclosingNominal = dyn_cast<NominalTypeDecl>(NT->getDeclContext())) {
153-
makeNominalUsableFromInline(enclosingNominal, M);
154-
} else if (auto *enclosingExt = dyn_cast<ExtensionDecl>(NT->getDeclContext())) {
155-
if (auto *extendedNominal = enclosingExt->getExtendedNominal()) {
156-
makeNominalUsableFromInline(extendedNominal, M);
152+
if (auto *nominalCtx = dyn_cast<NominalTypeDecl>(decl->getDeclContext())) {
153+
makeDeclUsableFromInline(nominalCtx, M);
154+
} else if (auto *extCtx = dyn_cast<ExtensionDecl>(decl->getDeclContext())) {
155+
if (auto *extendedNominal = extCtx->getExtendedNominal()) {
156+
makeDeclUsableFromInline(extendedNominal, M);
157157
}
158-
} else if (NT->getDeclContext()->isLocalContext()) {
158+
} else if (decl->getDeclContext()->isLocalContext()) {
159159
// TODO
160160
}
161161
}
@@ -166,15 +166,15 @@ void CrossModuleSerializationSetup::makeTypeUsableFromInline(CanType type) {
166166
return;
167167

168168
if (NominalTypeDecl *NT = type->getNominalOrBoundGenericNominal()) {
169-
makeNominalUsableFromInline(NT, M);
169+
makeDeclUsableFromInline(NT, M);
170170
}
171171

172172
// Also make all sub-types usable from inline.
173173
type.visit([this](Type rawSubType) {
174174
CanType subType = rawSubType->getCanonicalType();
175175
if (typesHandled.insert(subType.getPointer()).second) {
176176
if (NominalTypeDecl *subNT = subType->getNominalOrBoundGenericNominal()) {
177-
makeNominalUsableFromInline(subNT, M);
177+
makeDeclUsableFromInline(subNT, M);
178178
}
179179
}
180180
});
@@ -235,6 +235,9 @@ prepareInstructionForSerialization(SILInstruction *inst) {
235235
[this](SILDeclRef method) { handleReferencedMethod(method); });
236236
return;
237237
}
238+
if (auto *REAI = dyn_cast<RefElementAddrInst>(inst)) {
239+
makeDeclUsableFromInline(REAI->getField(), M);
240+
}
238241
}
239242

240243
void CrossModuleSerializationSetup::handleReferencedFunction(SILFunction *func) {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import Foundation
2+
3+
final class ObjcClass : NSObject {
4+
fileprivate var ii: Int = 127
5+
}
6+
7+
@inline(never)
8+
func returnObjcClassMember<T>(_ c: ObjcClass, _ t: T) -> Int {
9+
return c.ii
10+
}
11+
12+
@inline(never)
13+
public func callObjcClassMember<T>(_ t: T) -> Int {
14+
let c = ObjcClass()
15+
return returnObjcClassMember(c, t)
16+
}
17+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// First test: functional correctness
2+
3+
// 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
5+
// RUN: %target-build-swift -O -wmo -module-name=Main -I%t %s -c -o %t/main.o
6+
// RUN: %target-swiftc_driver %t/main.o %t/test.o -o %t/a.out
7+
// RUN: %target-run %t/a.out | %FileCheck %s -check-prefix=CHECK-OUTPUT
8+
9+
// Check if it also works if the main module is compiled with -Onone:
10+
11+
// RUN: %target-build-swift -Onone -wmo -module-name=Main -I%t %s -c -o %t/main-onone.o
12+
// RUN: %target-swiftc_driver %t/main-onone.o %t/test.o -o %t/a.out
13+
// RUN: %target-run %t/a.out | %FileCheck %s -check-prefix=CHECK-OUTPUT
14+
15+
// REQUIRES: executable_test
16+
// REQUIRES: objc_interop
17+
18+
// Second test: check if CMO really imports the SIL of functions in other modules.
19+
20+
// RUN: %target-build-swift -O -wmo -module-name=Main -I%t %s -Xllvm -sil-disable-pass=FunctionSignatureOpts -emit-sil | %FileCheck %s -check-prefix=CHECK-SIL
21+
22+
23+
import Test
24+
25+
func testClass() {
26+
// CHECK-OUTPUT: 127
27+
// CHECK-SIL-DAG: sil shared [noinline] @$s4Test21returnObjcClassMemberySiAA0cD0C_xtlFSi_Tg5
28+
print(callObjcClassMember(0))
29+
}
30+
31+
testClass()
32+

0 commit comments

Comments
 (0)