Skip to content

Commit

Permalink
Merge pull request swiftlang#25953 from JDevlieghere/swift-overlay-vfs
Browse files Browse the repository at this point in the history
[ClangImporter] Merge Swift & Clang VFS
  • Loading branch information
JDevlieghere authored Jul 5, 2019
2 parents 259571a + f359cef commit c5c6f3b
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 37 deletions.
4 changes: 0 additions & 4 deletions include/swift/AST/DiagnosticsClangImporter.def
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,6 @@ WARNING(implicit_bridging_header_imported_from_module,none,
"is deprecated and will be removed in a later version of Swift",
(StringRef, Identifier))

WARNING(clang_vfs_overlay_is_ignored,none,
"ignoring '-ivfsoverlay' options provided to '-Xcc' in favor of "
"'-vfsoverlay'", ())

#ifndef DIAG_NO_UNDEF
# if defined(DIAG)
# undef DIAG
Expand Down
20 changes: 13 additions & 7 deletions include/swift/Basic/SourceManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,16 @@

namespace swift {

static inline llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>
getRealOverlayFileSystem() {
return llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>(
new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem()));
}

/// This class manages and owns source buffers.
class SourceManager {
llvm::SourceMgr LLVMSourceMgr;
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem;
llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> FileSystem;
unsigned CodeCompletionBufferID = 0U;
unsigned CodeCompletionOffset;

Expand All @@ -49,9 +55,9 @@ class SourceManager {
mutable std::pair<const char *, const VirtualFile*> CachedVFile = {nullptr, nullptr};

public:
SourceManager(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
llvm::vfs::getRealFileSystem())
: FileSystem(FS) {}
SourceManager(llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> FS =
getRealOverlayFileSystem())
: FileSystem(FS) {}

llvm::SourceMgr &getLLVMSourceMgr() {
return LLVMSourceMgr;
Expand All @@ -60,11 +66,12 @@ class SourceManager {
return LLVMSourceMgr;
}

void setFileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
void
setFileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> FS) {
FileSystem = FS;
}

llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> getFileSystem() {
llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> getFileSystem() {
return FileSystem;
}

Expand Down Expand Up @@ -254,4 +261,3 @@ class SourceManager {
} // end namespace swift

#endif // SWIFT_BASIC_SOURCEMANAGER_H

35 changes: 28 additions & 7 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1012,14 +1012,35 @@ ClangImporter::create(ASTContext &ctx,

// Set up the file manager.
{
if (!ctx.SearchPathOpts.VFSOverlayFiles.empty()) {
// If the clang instance has overlays it means the user has provided
// -ivfsoverlay options and swift -vfsoverlay options. We're going to
// clobber their file system with our own, so warn about it.
if (!instance.getHeaderSearchOpts().VFSOverlayFiles.empty()) {
ctx.Diags.diagnose(SourceLoc(), diag::clang_vfs_overlay_is_ignored);
}
if (instance.getHeaderSearchOpts().VFSOverlayFiles.empty()) {
instance.setVirtualFileSystem(ctx.SourceMgr.getFileSystem());
} else {
// Initialize the clang VFS from its compiler invocation.
instance.createFileManager();

// Create a new overlay file system for the clang importer with the clang
// VFS as its root.
auto ClangImporterFS =
llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>(
new llvm::vfs::OverlayFileSystem(
&instance.getVirtualFileSystem()));

auto SwiftFS = ctx.SourceMgr.getFileSystem();
auto it = SwiftFS->overlays_rbegin();
auto end = SwiftFS->overlays_rend();

// The Swift file system is an overlay file system with the real file
// system as its root. Skip the root so we query the other overlays
// before falling back to the real file system.
it++;

// Add all remaining Swift overlay file systems to the new file system.
while (it != end) {
ClangImporterFS->pushOverlay(*it);
it++;
}

instance.setVirtualFileSystem(ClangImporterFS);
}
instance.createFileManager();
}
Expand Down
12 changes: 1 addition & 11 deletions lib/Frontend/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,9 +235,6 @@ static bool loadAndValidateVFSOverlay(
const llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &BaseFS,
const llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> &OverlayFS,
DiagnosticEngine &Diag) {
// FIXME: It should be possible to allow chained lookup of later VFS overlays
// through the mapping defined by earlier overlays.
// See rdar://problem/39440687
auto Buffer = BaseFS->getBufferForFile(File);
if (!Buffer) {
Diag.diagnose(SourceLoc(), diag::cannot_open_file, File,
Expand All @@ -264,14 +261,7 @@ bool CompilerInstance::setUpVirtualFileSystemOverlays() {
hadAnyFailure |=
loadAndValidateVFSOverlay(File, BaseFS, OverlayFS, Diagnostics);
}

// If we successfully loaded all the overlays, let the source manager and
// diagnostic engine take advantage of the overlay file system.
if (!hadAnyFailure &&
(OverlayFS->overlays_begin() != OverlayFS->overlays_end())) {
SourceMgr.setFileSystem(OverlayFS);
}

SourceMgr.setFileSystem(OverlayFS);
return hadAnyFailure;
}

Expand Down
4 changes: 2 additions & 2 deletions lib/Frontend/ParseableInterfaceModuleLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ static Optional<StringRef> getRelativeDepPath(StringRef DepPath,
/// output path.
/// \note Needs to be in the swift namespace so CompilerInvocation can see it.
class swift::ParseableInterfaceBuilder {
llvm::vfs::FileSystem &fs;
llvm::vfs::OverlayFileSystem &fs;
DiagnosticEngine &diags;
const StringRef interfacePath;
const StringRef moduleName;
Expand Down Expand Up @@ -765,7 +765,7 @@ class ParseableInterfaceModuleLoaderImpl {
using AccessPathElem = std::pair<Identifier, SourceLoc>;
friend class swift::ParseableInterfaceModuleLoader;
ASTContext &ctx;
llvm::vfs::FileSystem &fs;
llvm::vfs::OverlayFileSystem &fs;
DiagnosticEngine &diags;
ModuleRebuildInfo rebuildInfo;
const StringRef modulePath;
Expand Down
4 changes: 4 additions & 0 deletions test/Frontend/Inputs/vfs/a-modulemap
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
module VFSMappedModule {
header "VFSMappedModule.h"
}

module YetAnotherVFSMappedModule {
header "YetAnotherVFSMappedModule.h"
}
1 change: 1 addition & 0 deletions test/Frontend/Inputs/vfs/b-header
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#define MAJOR_SUCCESS 1
17 changes: 17 additions & 0 deletions test/Frontend/Inputs/vfs/quaternary-vfsoverlay.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
'version': 0,
'use-external-names': false,
'roots': [
{
'name': 'OUT_DIR', 'type': 'directory',
'contents': [
{ 'name': 'YetAnotherVFSMappedModule.h', 'type': 'file',
'external-contents': 'INPUT_DIR/vfs/b-header'
},
{ 'name': 'YetAnotherVFSMappedModule.framework/Headers/VFSMappedModule.h', 'type': 'file',
'external-contents': 'INPUT_DIR/vfs/b-header'
},
]
},
]
}
8 changes: 5 additions & 3 deletions test/Frontend/vfs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// RUN: sed -e "s|INPUT_DIR|%/S/Inputs|g" -e "s|OUT_DIR|%/t|g" %S/Inputs/vfs/vfsoverlay.yaml > %t/overlay.yaml
// RUN: sed -e "s|INPUT_DIR|%/S/Inputs|g" -e "s|OUT_DIR|%/t|g" %S/Inputs/vfs/secondary-vfsoverlay.yaml > %t/secondary-overlay.yaml
// RUN: sed -e "s|INPUT_DIR|%/S/Inputs|g" -e "s|OUT_DIR|%/t|g" %S/Inputs/vfs/tertiary-vfsoverlay.yaml > %t/tertiary-overlay.yaml
// RUN: sed -e "s|INPUT_DIR|%/S/Inputs|g" -e "s|OUT_DIR|%/t|g" %S/Inputs/vfs/quaternary-vfsoverlay.yaml > %t/quaternary-vfsoverlay.yaml

// RUN: not %target-swift-frontend -vfsoverlay %/t/overlay.yaml -typecheck %s %/t/mapped-file.swift -serialize-diagnostics-path %/t/basic.dia 2>&1 | %FileCheck -check-prefix=BASIC_MAPPING_ERROR %s
// RUN: c-index-test -read-diagnostics %/t/basic.dia 2>&1 | %FileCheck -check-prefix=BASIC_MAPPING_ERROR %s
Expand All @@ -20,10 +21,11 @@
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %/t -DTEST_VFS_CLANG_IMPORTER -Xcc -ivfsoverlay -Xcc %/t/overlay.yaml -typecheck %/s

// If we see -ivfsoverlay and -vfsoverlay, we'll clobber Clang's VFS with our own.
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %/t -DTEST_VFS_CLANG_IMPORTER -vfsoverlay %/t/overlay.yaml -Xcc -ivfsoverlay -Xcc %/t/overlay.yaml -typecheck %/s 2>&1 | %FileCheck -check-prefix=WARN_VFS_CLOBBERED %s

// WARN_VFS_CLOBBERED: warning: ignoring '-ivfsoverlay' options provided to '-Xcc' in favor of '-vfsoverlay'
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %/t -DTEST_VFS_CLANG_IMPORTER -DTEST_VFS_CLANG_IMPORTER_MERGE -vfsoverlay %/t/overlay.yaml -Xcc -ivfsoverlay -Xcc %/t/quaternary-vfsoverlay.yaml -typecheck %/s 2>&1

#if TEST_VFS_CLANG_IMPORTER
import VFSMappedModule
#if TEST_VFS_CLANG_IMPORTER_MERGE
import YetAnotherVFSMappedModule
#endif
#endif
8 changes: 5 additions & 3 deletions unittests/FrontendTool/ModuleLoadingTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,10 @@ class ParseableInterfaceModuleLoaderTest : public testing::Test {
SourceManager sourceMgr;

// Create a file system that tracks how many times a file has been opened.
llvm::IntrusiveRefCntPtr<OpenTrackingFileSystem> fs(
new OpenTrackingFileSystem(sourceMgr.getFileSystem()));
llvm::IntrusiveRefCntPtr<OpenTrackingFileSystem> baseFS(
new OpenTrackingFileSystem(sourceMgr.getFileSystem()));
auto fs = llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>(
new llvm::vfs::OverlayFileSystem(baseFS));

sourceMgr.setFileSystem(fs);
PrintingDiagnosticConsumer printingConsumer;
Expand Down Expand Up @@ -126,7 +128,7 @@ class ParseableInterfaceModuleLoaderTest : public testing::Test {
ASSERT_TRUE(fs->exists(cachedModulePath));

// Assert that we've only opened this file once, to write it.
ASSERT_EQ((unsigned)1, fs->numberOfOpens(cachedModulePath));
ASSERT_EQ((unsigned)1, baseFS->numberOfOpens(cachedModulePath));

auto bufOrErr = fs->getBufferForFile(cachedModulePath);
ASSERT_TRUE(bufOrErr);
Expand Down

0 comments on commit c5c6f3b

Please sign in to comment.