Skip to content

Commit 5417ca0

Browse files
committed
[ParseableInterfaces] Handle swiftdoc files correctly
The previous 'openModuleFiles' interface in SerializedModuleLoaderBase still assumed that swiftmodule files and swiftdoc files would be found next to each other, but that's not true anymore with swiftinterfaces-built-to-modules. Give up on this assumption (and on the minor optimization of passing down a scratch buffer) and split out the interface into the customization point 'findModuleFilesInDirectory' and the implementation 'openModuleFiles'. The latter now takes two full paths: one for the swiftmodule, one for the swiftdoc.
1 parent 1c3d467 commit 5417ca0

File tree

5 files changed

+97
-75
lines changed

5 files changed

+97
-75
lines changed

include/swift/Frontend/ParseableInterfaceSupport.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,11 @@ class ParseableInterfaceModuleLoader : public SerializedModuleLoaderBase {
7979
static void configureSubInvocationInputsAndOutputs(
8080
CompilerInvocation &SubInvocation, StringRef InPath, StringRef OutPath);
8181

82-
std::error_code
83-
openModuleFiles(AccessPathElem ModuleID, StringRef DirName,
84-
StringRef ModuleFilename, StringRef ModuleDocFilename,
85-
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
86-
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
87-
llvm::SmallVectorImpl<char> &Scratch) override;
82+
std::error_code findModuleFilesInDirectory(
83+
AccessPathElem ModuleID, StringRef DirPath, StringRef ModuleFilename,
84+
StringRef ModuleDocFilename,
85+
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
86+
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer) override;
8887

8988
public:
9089
static std::unique_ptr<ParseableInterfaceModuleLoader>

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,17 @@ class SerializedModuleLoaderBase : public ModuleLoader {
5151
std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
5252
bool &isFramework);
5353

54-
virtual std::error_code
55-
openModuleFiles(AccessPathElem ModuleID, StringRef DirName,
56-
StringRef ModuleFilename, StringRef ModuleDocFilename,
54+
virtual std::error_code findModuleFilesInDirectory(
55+
AccessPathElem ModuleID, StringRef DirPath, StringRef ModuleFilename,
56+
StringRef ModuleDocFilename,
57+
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
58+
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer) = 0;
59+
60+
std::error_code
61+
openModuleFiles(AccessPathElem ModuleID,
62+
StringRef ModulePath, StringRef ModuleDocPath,
5763
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
58-
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
59-
llvm::SmallVectorImpl<char> &Scratch);
64+
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer);
6065

6166
/// If the module loader subclass knows that all options have been tried for
6267
/// loading an architecture-specific file out of a swiftmodule bundle, try
@@ -128,12 +133,11 @@ class SerializedModuleLoader : public SerializedModuleLoaderBase {
128133
: SerializedModuleLoaderBase(ctx, tracker, loadMode)
129134
{}
130135

131-
std::error_code
132-
openModuleFiles(AccessPathElem ModuleID, StringRef DirName,
133-
StringRef ModuleFilename, StringRef ModuleDocFilename,
134-
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
135-
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
136-
llvm::SmallVectorImpl<char> &Scratch) override;
136+
std::error_code findModuleFilesInDirectory(
137+
AccessPathElem ModuleID, StringRef DirPath, StringRef ModuleFilename,
138+
StringRef ModuleDocFilename,
139+
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
140+
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer) override;
137141

138142
bool maybeDiagnoseArchitectureMismatch(SourceLoc sourceLocation,
139143
StringRef moduleName,

lib/Frontend/ParseableInterfaceSupport.cpp

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ createInvocationForBuildingFromInterface(ASTContext &Ctx, StringRef ModuleName,
168168
static void computeCachedOutputPath(ASTContext &Ctx,
169169
const CompilerInvocation &SubInvocation,
170170
StringRef InPath,
171-
llvm::SmallString<128> &OutPath) {
171+
llvm::SmallString<256> &OutPath) {
172172
OutPath = SubInvocation.getClangModuleCachePath();
173173
llvm::sys::path::append(OutPath, SubInvocation.getModuleName());
174174
OutPath.append("-");
@@ -437,12 +437,11 @@ static bool serializedASTLooksValidOrCannotBeRead(clang::vfs::FileSystem &FS,
437437
/// Load a .swiftmodule associated with a .swiftinterface either from a
438438
/// cache or by converting it in a subordinate \c CompilerInstance, caching
439439
/// the results.
440-
std::error_code ParseableInterfaceModuleLoader::openModuleFiles(
441-
AccessPathElem ModuleID, StringRef DirName, StringRef ModuleFilename,
440+
std::error_code ParseableInterfaceModuleLoader::findModuleFilesInDirectory(
441+
AccessPathElem ModuleID, StringRef DirPath, StringRef ModuleFilename,
442442
StringRef ModuleDocFilename,
443443
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
444-
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
445-
llvm::SmallVectorImpl<char> &Scratch) {
444+
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer) {
446445

447446
namespace path = llvm::sys::path;
448447

@@ -452,10 +451,10 @@ std::error_code ParseableInterfaceModuleLoader::openModuleFiles(
452451

453452
auto &FS = *Ctx.SourceMgr.getFileSystem();
454453
auto &Diags = Ctx.Diags;
455-
llvm::SmallString<128> ModPath, InPath, OutPath;
454+
llvm::SmallString<256> ModPath, InPath, OutPath;
456455

457456
// First check to see if the .swiftinterface exists at all. Bail if not.
458-
ModPath = DirName;
457+
ModPath = DirPath;
459458
path::append(ModPath, ModuleFilename);
460459

461460
auto Ext = file_types::getExtension(file_types::TY_SwiftParseableInterfaceFile);
@@ -531,12 +530,10 @@ std::error_code ParseableInterfaceModuleLoader::openModuleFiles(
531530
// routine that can load the recently-manufactured serialized module.
532531
LLVM_DEBUG(llvm::dbgs() << "Loading " << OutPath
533532
<< " via normal module loader\n");
534-
// FIXME: This will never find the swiftdoc file, because that's in the
535-
// original directory. We should probably just not try to match the signature
536-
// of the overridable entry point.
533+
llvm::SmallString<256> DocPath{DirPath};
534+
path::append(DocPath, ModuleDocFilename);
537535
auto ErrorCode = SerializedModuleLoaderBase::openModuleFiles(
538-
ModuleID, path::parent_path(OutPath), path::filename(OutPath),
539-
ModuleDocFilename, ModuleBuffer, ModuleDocBuffer, Scratch);
536+
ModuleID, OutPath, DocPath, ModuleBuffer, ModuleDocBuffer);
540537
LLVM_DEBUG(llvm::dbgs() << "Loaded " << OutPath
541538
<< " via normal module loader");
542539
if (ErrorCode) {

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,9 @@ SerializedModuleLoaderBase::~SerializedModuleLoaderBase() = default;
4343
SerializedModuleLoader::~SerializedModuleLoader() = default;
4444

4545
std::error_code SerializedModuleLoaderBase::openModuleFiles(
46-
AccessPathElem ModuleID, StringRef DirName, StringRef ModuleFilename,
47-
StringRef ModuleDocFilename,
46+
AccessPathElem ModuleID, StringRef ModulePath, StringRef ModuleDocPath,
4847
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
49-
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
50-
llvm::SmallVectorImpl<char> &Scratch) {
48+
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer) {
5149
assert(((ModuleBuffer && ModuleDocBuffer) ||
5250
(!ModuleBuffer && !ModuleDocBuffer)) &&
5351
"Module and Module Doc buffer must both be initialized or NULL");
@@ -56,12 +54,11 @@ std::error_code SerializedModuleLoaderBase::openModuleFiles(
5654

5755
// Try to open the module file first. If we fail, don't even look for the
5856
// module documentation file.
59-
Scratch.clear();
60-
llvm::sys::path::append(Scratch, DirName, ModuleFilename);
57+
6158
// If there are no buffers to load into, simply check for the existence of
6259
// the module file.
6360
if (!(ModuleBuffer || ModuleDocBuffer)) {
64-
llvm::ErrorOr<clang::vfs::Status> statResult = FS.status(Scratch);
61+
llvm::ErrorOr<clang::vfs::Status> statResult = FS.status(ModulePath);
6562
if (!statResult)
6663
return statResult.getError();
6764
if (!statResult->exists())
@@ -72,16 +69,14 @@ std::error_code SerializedModuleLoaderBase::openModuleFiles(
7269
}
7370

7471
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ModuleOrErr =
75-
FS.getBufferForFile(StringRef(Scratch.data(), Scratch.size()));
72+
FS.getBufferForFile(ModulePath);
7673
if (!ModuleOrErr)
7774
return ModuleOrErr.getError();
7875

7976
// Try to open the module documentation file. If it does not exist, ignore
8077
// the error. However, pass though all other errors.
81-
Scratch.clear();
82-
llvm::sys::path::append(Scratch, DirName, ModuleDocFilename);
8378
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ModuleDocOrErr =
84-
FS.getBufferForFile(StringRef(Scratch.data(), Scratch.size()));
79+
FS.getBufferForFile(ModuleDocPath);
8580
if (!ModuleDocOrErr &&
8681
ModuleDocOrErr.getError() != std::errc::no_such_file_or_directory) {
8782
return ModuleDocOrErr.getError();
@@ -94,20 +89,23 @@ std::error_code SerializedModuleLoaderBase::openModuleFiles(
9489
return std::error_code();
9590
}
9691

97-
std::error_code SerializedModuleLoader::openModuleFiles(
98-
AccessPathElem ModuleID, StringRef DirName, StringRef ModuleFilename,
92+
std::error_code SerializedModuleLoader::findModuleFilesInDirectory(
93+
AccessPathElem ModuleID, StringRef DirPath, StringRef ModuleFilename,
9994
StringRef ModuleDocFilename,
10095
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
101-
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
102-
llvm::SmallVectorImpl<char> &Scratch) {
96+
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer) {
10397
if (LoadMode == ModuleLoadingMode::OnlyParseable)
10498
return std::make_error_code(std::errc::not_supported);
10599

106-
return SerializedModuleLoaderBase::openModuleFiles(ModuleID, DirName,
107-
ModuleFilename,
108-
ModuleDocFilename,
100+
llvm::SmallString<256> ModulePath{DirPath};
101+
llvm::sys::path::append(ModulePath, ModuleFilename);
102+
llvm::SmallString<256> ModuleDocPath{DirPath};
103+
llvm::sys::path::append(ModuleDocPath, ModuleDocFilename);
104+
return SerializedModuleLoaderBase::openModuleFiles(ModuleID,
105+
ModulePath,
106+
ModuleDocPath,
109107
ModuleBuffer,
110-
ModuleDocBuffer, Scratch);
108+
ModuleDocBuffer);
111109
}
112110

113111
bool SerializedModuleLoader::maybeDiagnoseArchitectureMismatch(
@@ -194,10 +192,7 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID,
194192
auto &fs = *Ctx.SourceMgr.getFileSystem();
195193
isFramework = false;
196194

197-
// Declare some reusable buffers up front; if we end up spilling onto the
198-
// heap once, we're likely to do so again.
199-
llvm::SmallString<128> scratch;
200-
llvm::SmallString<128> currPath;
195+
llvm::SmallString<256> currPath;
201196
for (auto path : Ctx.SearchPathOpts.ImportSearchPaths) {
202197
std::error_code result;
203198

@@ -207,18 +202,17 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID,
207202

208203
if (statResult && statResult->isDirectory()) {
209204
// A .swiftmodule directory contains architecture-specific files.
210-
result = openModuleFiles(moduleID, currPath,
211-
archFileNames.first, archFileNames.second,
212-
moduleBuffer, moduleDocBuffer,
213-
scratch);
205+
result = findModuleFilesInDirectory(moduleID, currPath,
206+
archFileNames.first,
207+
archFileNames.second,
208+
moduleBuffer, moduleDocBuffer);
214209

215210
if (result == std::errc::no_such_file_or_directory &&
216211
!alternateArchName.empty()) {
217-
result = openModuleFiles(moduleID, currPath,
218-
alternateArchFileNames.first,
219-
alternateArchFileNames.second,
220-
moduleBuffer, moduleDocBuffer,
221-
scratch);
212+
result = findModuleFilesInDirectory(moduleID, currPath,
213+
alternateArchFileNames.first,
214+
alternateArchFileNames.second,
215+
moduleBuffer, moduleDocBuffer);
222216
}
223217

224218
if (result == std::errc::no_such_file_or_directory) {
@@ -231,10 +225,10 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID,
231225
} else {
232226
// We can't just return the error; the path we're looking for might not
233227
// be "Foo.swiftmodule".
234-
result = openModuleFiles(moduleID, path,
235-
moduleFilename.str(), moduleDocFilename.str(),
236-
moduleBuffer, moduleDocBuffer,
237-
scratch);
228+
result = findModuleFilesInDirectory(moduleID, path,
229+
moduleFilename.str(),
230+
moduleDocFilename.str(),
231+
moduleBuffer, moduleDocBuffer);
238232
}
239233
if (!result)
240234
return true;
@@ -257,16 +251,17 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID,
257251
// Frameworks always use architecture-specific files within a .swiftmodule
258252
// directory.
259253
llvm::sys::path::append(currPath, "Modules", moduleFilename.str());
260-
auto err = openModuleFiles(moduleID, currPath,
261-
archFileNames.first, archFileNames.second,
262-
moduleBuffer, moduleDocBuffer, scratch);
254+
auto err = findModuleFilesInDirectory(moduleID, currPath,
255+
archFileNames.first,
256+
archFileNames.second,
257+
moduleBuffer, moduleDocBuffer);
263258

264259
if (err == std::errc::no_such_file_or_directory &&
265260
!alternateArchName.empty()) {
266-
err = openModuleFiles(moduleID, currPath,
267-
alternateArchFileNames.first,
268-
alternateArchFileNames.second,
269-
moduleBuffer, moduleDocBuffer, scratch);
261+
err = findModuleFilesInDirectory(moduleID, currPath,
262+
alternateArchFileNames.first,
263+
alternateArchFileNames.second,
264+
moduleBuffer, moduleDocBuffer);
270265
}
271266

272267
if (err == std::errc::no_such_file_or_directory) {
@@ -287,6 +282,7 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID,
287282
if (Ctx.LangOpts.Target.isOSDarwin()) {
288283
// Apple platforms have extra implicit framework search paths:
289284
// $SDKROOT/System/Library/Frameworks/ and $SDKROOT/Library/Frameworks/
285+
SmallString<256> scratch;
290286
scratch = Ctx.SearchPathOpts.SDKPath;
291287
llvm::sys::path::append(scratch, "System", "Library", "Frameworks");
292288
if (tryFrameworkImport(scratch))
@@ -305,9 +301,10 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID,
305301

306302
// Search the runtime import path.
307303
isFramework = false;
308-
return !openModuleFiles(moduleID, Ctx.SearchPathOpts.RuntimeLibraryImportPath,
309-
moduleFilename.str(), moduleDocFilename.str(),
310-
moduleBuffer, moduleDocBuffer, scratch);
304+
return !findModuleFilesInDirectory(
305+
moduleID, Ctx.SearchPathOpts.RuntimeLibraryImportPath,
306+
moduleFilename.str(), moduleDocFilename.str(), moduleBuffer,
307+
moduleDocBuffer);
311308
}
312309

313310
static std::pair<StringRef, clang::VersionTuple>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -emit-parseable-module-interface-path %t/Lib.swiftinterface -emit-module-doc -parse-stdlib -o %t/Lib.swiftmodule %s
3+
// RUN: %target-swift-ide-test -print-module -module-to-print=Lib -access-filter-public -I %t -source-filename=x > %t/from-module.txt
4+
// RUN: %FileCheck %s < %t/from-module.txt
5+
6+
// RUN: rm %t/Lib.swiftmodule
7+
// RUN: env SWIFT_FORCE_MODULE_LOADING=prefer-serialized %target-swift-ide-test -print-module -module-to-print=Lib -access-filter-public -I %t -source-filename=x > %t/from-interface.txt
8+
// RUN: diff %t/from-module.txt %t/from-interface.txt
9+
10+
// Try again with architecture-specific subdirectories.
11+
// RUN: %empty-directory(%t)
12+
// RUN: %empty-directory(%t/Lib.swiftmodule)
13+
// RUN: %target-swift-frontend -emit-module -emit-parseable-module-interface-path %t/Lib.swiftmodule/$(basename %target-swiftmodule-name .swiftmodule).swiftinterface -emit-module-doc -parse-stdlib -o %t/Lib.swiftmodule/%target-swiftmodule-name -module-name Lib %s
14+
// RUN: %target-swift-ide-test -print-module -module-to-print=Lib -access-filter-public -I %t -source-filename=x > %t/from-module.txt
15+
// RUN: %FileCheck %s < %t/from-module.txt
16+
17+
// RUN: rm %t/Lib.swiftmodule/%target-swiftmodule-name
18+
// RUN: env SWIFT_FORCE_MODULE_LOADING=prefer-serialized %target-swift-ide-test -print-module -module-to-print=Lib -access-filter-public -I %t -source-filename=x > %t/from-interface.txt
19+
// RUN: diff %t/from-module.txt %t/from-interface.txt
20+
21+
/// Very important documentation!
22+
public struct SomeStructWithDocumentation {}
23+
24+
// CHECK: Very important documentation!
25+
// CHECK-NEXT: struct SomeStructWithDocumentation {

0 commit comments

Comments
 (0)