Skip to content

Commit db44012

Browse files
committed
Serialization: Support '@_usableFromInline import'
Progress on <rdar://problem/39338239>; we still need to infer this attribute though.
1 parent cfa0ab3 commit db44012

12 files changed

+97
-14
lines changed

include/swift/Serialization/ModuleFile.h

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,27 +132,40 @@ class ModuleFile
132132
const StringRef RawPath;
133133

134134
private:
135-
unsigned IsExported : 1;
136135
const unsigned IsHeader : 1;
136+
const unsigned IsExported : 1;
137+
const unsigned IsUsableFromInline : 1;
137138
const unsigned IsScoped : 1;
138139

139-
Dependency(StringRef path, bool isHeader, bool exported, bool isScoped)
140-
: RawPath(path), IsExported(exported), IsHeader(isHeader),
141-
IsScoped(isScoped) {}
140+
Dependency(bool isHeader,
141+
StringRef path, bool exported,
142+
bool isUsableFromInline, bool isScoped)
143+
: RawPath(path),
144+
IsHeader(isHeader),
145+
IsExported(exported),
146+
IsUsableFromInline(isUsableFromInline),
147+
IsScoped(isScoped) {
148+
assert(!(IsExported && IsUsableFromInline));
149+
assert(!(IsHeader && IsScoped));
150+
}
142151

143152
public:
144-
Dependency(StringRef path, bool exported, bool isScoped)
145-
: Dependency(path, false, exported, isScoped) {}
153+
Dependency(StringRef path, bool exported, bool isUsableFromInline,
154+
bool isScoped)
155+
: Dependency(false, path, exported, isUsableFromInline, isScoped) {}
146156

147157
static Dependency forHeader(StringRef headerPath, bool exported) {
148-
return Dependency(headerPath, true, exported, false);
158+
return Dependency(true, headerPath, exported,
159+
/*isUsableFromInline=*/false,
160+
/*isScoped=*/false);
149161
}
150162

151163
bool isLoaded() const {
152164
return Import.second != nullptr;
153165
}
154166

155167
bool isExported() const { return IsExported; }
168+
bool isUsableFromInline() const { return IsUsableFromInline; }
156169
bool isHeader() const { return IsHeader; }
157170
bool isScoped() const { return IsScoped; }
158171

include/swift/Serialization/ModuleFormat.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
5757
/// Don't worry about adhering to the 80-column limit for this line.
58-
const uint16_t VERSION_MINOR = 411; // Last change: copy_block_without_escaping
58+
const uint16_t VERSION_MINOR = 412; // Last change: @usableFromInline import
5959

6060
using DeclIDField = BCFixed<31>;
6161

@@ -595,6 +595,7 @@ namespace input_block {
595595
using ImportedModuleLayout = BCRecordLayout<
596596
IMPORTED_MODULE,
597597
BCFixed<1>, // exported?
598+
BCFixed<1>, // usable from inlinable functions?
598599
BCFixed<1>, // scoped?
599600
BCBlob // module name, with submodule path pieces separated by \0s.
600601
// If the 'scoped' flag is set, the final path piece is an access

lib/Serialization/ModuleFile.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,10 +1140,12 @@ ModuleFile::ModuleFile(
11401140
unsigned kind = cursor.readRecord(next.ID, scratch, &blobData);
11411141
switch (kind) {
11421142
case input_block::IMPORTED_MODULE: {
1143-
bool exported, scoped;
1143+
bool exported, usableFromInline, scoped;
11441144
input_block::ImportedModuleLayout::readRecord(scratch,
1145-
exported, scoped);
1146-
Dependencies.push_back({blobData, exported, scoped});
1145+
exported,
1146+
usableFromInline,
1147+
scoped);
1148+
Dependencies.push_back({blobData, exported, usableFromInline, scoped});
11471149
break;
11481150
}
11491151
case input_block::LINK_LIBRARY: {
@@ -1600,8 +1602,8 @@ void ModuleFile::getImportedModules(
16001602
break;
16011603

16021604
case ModuleDecl::ImportFilter::ForLinking:
1603-
// FIXME
1604-
if (!dep.isExported())
1605+
// Only include @_exported and @usableFromInline imports.
1606+
if (!dep.isExported() && !dep.isUsableFromInline())
16051607
continue;
16061608

16071609
break;
@@ -1673,6 +1675,9 @@ void ModuleFile::getImportDecls(SmallVectorImpl<Decl *> &Results) {
16731675
if (Dep.isExported())
16741676
ID->getAttrs().add(
16751677
new (Ctx) ExportedAttr(/*IsImplicit=*/false));
1678+
if (Dep.isUsableFromInline())
1679+
ID->getAttrs().add(
1680+
new (Ctx) UsableFromInlineImportAttr(/*IsImplicit=*/true));
16761681
ImportDecls.push_back(ID);
16771682
}
16781683
Bits.ComputedImportDecls = true;

lib/Serialization/Serialization.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1073,16 +1073,22 @@ void Serializer::writeInputBlock(const SerializationOptions &options) {
10731073
// FIXME: Having to deal with private imports as a superset of public imports
10741074
// is inefficient.
10751075
SmallVector<ModuleDecl::ImportedModule, 8> publicImports;
1076+
SmallVector<ModuleDecl::ImportedModule, 8> linkImports;
10761077
SmallVector<ModuleDecl::ImportedModule, 8> allImports;
10771078
for (auto file : M->getFiles()) {
10781079
file->getImportedModules(publicImports, ModuleDecl::ImportFilter::Public);
1080+
file->getImportedModules(linkImports, ModuleDecl::ImportFilter::ForLinking);
10791081
file->getImportedModules(allImports, ModuleDecl::ImportFilter::All);
10801082
}
10811083

10821084
llvm::SmallSet<ModuleDecl::ImportedModule, 8, ModuleDecl::OrderImportedModules>
10831085
publicImportSet;
10841086
publicImportSet.insert(publicImports.begin(), publicImports.end());
10851087

1088+
llvm::SmallSet<ModuleDecl::ImportedModule, 8, ModuleDecl::OrderImportedModules>
1089+
linkImportSet;
1090+
linkImportSet.insert(linkImports.begin(), linkImports.end());
1091+
10861092
removeDuplicateImports(allImports);
10871093
auto clangImporter =
10881094
static_cast<ClangImporter *>(M->getASTContext().getClangModuleLoader());
@@ -1111,7 +1117,10 @@ void Serializer::writeInputBlock(const SerializationOptions &options) {
11111117

11121118
ImportPathBlob importPath;
11131119
flattenImportPath(import, importPath);
1114-
ImportedModule.emit(ScratchRecord, publicImportSet.count(import),
1120+
ImportedModule.emit(ScratchRecord,
1121+
publicImportSet.count(import),
1122+
(linkImportSet.count(import) &&
1123+
!publicImportSet.count(import)),
11151124
!import.first.empty(), importPath);
11161125
}
11171126

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@_usableFromInline import InlinableImport
2+

test/IDE/Inputs/InlinableImport.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// Empty module
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-swift-frontend -emit-module -o %t/InlinableImport.swiftmodule %S/Inputs/InlinableImport.swift
4+
// RUN: %target-swift-frontend -I %t -emit-module -o %t/HasInlinableImport.swiftmodule %S/Inputs/HasInlinableImport.swift
5+
// RUN: %target-swift-ide-test -I %t -print-module -source-filename %s -module-to-print=HasInlinableImport -function-definitions=false | %FileCheck %s
6+
7+
// REQUIRES: objc_interop
8+
9+
import HasInlinableImport
10+
11+
// For now, don't print anything special for inlinable imports.
12+
13+
// CHECK: {{^}}import InlinableImport
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@_exported import autolinking_public
2+
@_usableFromInline import autolinking_other
3+
import autolinking_private
4+
5+
public func bfunc(x: Int = afunc()) {
6+
cfunc()
7+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
public func afunc() -> Int { return 0 }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
public func cfunc() {}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// Empty module
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-swift-frontend -emit-module %S/Inputs/autolinking_public.swift -emit-module-path %t/autolinking_public.swiftmodule -module-link-name autolinking_public -swift-version 4
4+
// RUN: %target-swift-frontend -emit-module %S/Inputs/autolinking_other.swift -emit-module-path %t/autolinking_other.swiftmodule -module-link-name autolinking_other -swift-version 4
5+
// RUN: %target-swift-frontend -emit-module %S/Inputs/autolinking_private.swift -emit-module-path %t/autolinking_private.swiftmodule -module-link-name autolinking_private -I %t -swift-version 4
6+
// RUN: %target-swift-frontend -emit-module %S/Inputs/autolinking_module.swift -emit-module-path %t/autolinking_module.swiftmodule -module-link-name autolinking_module -I %t -swift-version 4
7+
// RUN: %target-swift-frontend -emit-ir %s -I %t -swift-version 4 | %FileCheck %s
8+
9+
// Linux uses a different autolinking mechanism, based on
10+
// swift-autolink-extract. This file tests the Darwin mechanism.
11+
// UNSUPPORTED: OS=linux-gnu
12+
// UNSUPPORTED: OS=linux-gnueabihf
13+
// UNSUPPORTED: OS=freebsd
14+
// UNSUPPORTED: OS=linux-androideabi
15+
16+
import autolinking_module
17+
18+
bfunc()
19+
20+
// Note: we don't autolink autolinking_private even though autolinking_module imports it also.
21+
22+
// CHECK: !llvm.linker.options = !{[[SWIFTCORE:![0-9]+]], [[SWIFTONONESUPPORT:![0-9]+]], [[MODULE:![0-9]+]], [[PUBLIC:![0-9]+]], [[OTHER:![0-9]+]], [[OBJC:![0-9]+]]}
23+
24+
// CHECK: [[SWIFTCORE]] = !{!"-lswiftCore"}
25+
// CHECK: [[SWIFTONONESUPPORT]] = !{!"-lswiftSwiftOnoneSupport"}
26+
// CHECK: [[MODULE]] = !{!"-lautolinking_module"}
27+
// CHECK: [[PUBLIC]] = !{!"-lautolinking_public"}
28+
// CHECK: [[OTHER]] = !{!"-lautolinking_other"}
29+
// CHECK: [[OBJC]] = !{!"-lobjc"}

0 commit comments

Comments
 (0)