Skip to content

Commit ec6cdfa

Browse files
[Caching] Reduce the number of cas ID passed on frontend commandline
Using IncludeTree::FileList to concat the include tree file systems that are passed on the command-line. This significantly reduce the command-line size, and also makes the cache key computation a lot faster. rdar://148752988
1 parent 485b8f6 commit ec6cdfa

File tree

11 files changed

+101
-88
lines changed

11 files changed

+101
-88
lines changed

include/swift/AST/DiagnosticsFrontend.def

+1
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ ERROR(error_cache_key_creation, none, "cannot create cache key for compilation %
534534
ERROR(error_cas_file_ref, none, "cannot load file %0 from CAS filesystem", (StringRef))
535535
ERROR(error_cas_conflict_options, none, "cannot setup CAS due to conflicting '-cas-*' options", ())
536536
ERROR(error_cas_initialization, none, "CAS cannot be initialized from the specified '-cas-*' options: %0", (StringRef))
537+
ERROR(error_cas_malformed_input, none, "CAS input '%0' is malformed: %1", (StringRef, StringRef))
537538
WARNING(cache_replay_failed, none, "cache replay failed: %0", (StringRef))
538539

539540
ERROR(error_failed_cached_diag, none, "failed to serialize cached diagnostics: %0", (StringRef))

include/swift/Basic/CASOptions.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ class CASOptions final {
4141
std::vector<std::string> CASFSRootIDs;
4242

4343
/// Clang Include Trees.
44-
std::vector<std::string> ClangIncludeTrees;
44+
std::string ClangIncludeTree;
4545

4646
/// Clang Include Tree FileList.
47-
std::vector<std::string> ClangIncludeTreeFileList;
47+
std::string ClangIncludeTreeFileList;
4848

4949
/// CacheKey for input file.
5050
std::string InputFileKey;
@@ -62,7 +62,7 @@ class CASOptions final {
6262
/// Check to see if a CASFileSystem is required.
6363
bool requireCASFS() const {
6464
return EnableCaching &&
65-
(!CASFSRootIDs.empty() || !ClangIncludeTrees.empty() ||
65+
(!CASFSRootIDs.empty() || !ClangIncludeTree.empty() ||
6666
!ClangIncludeTreeFileList.empty() || !InputFileKey.empty() ||
6767
!BridgingHeaderPCHCacheKey.empty());
6868
}

include/swift/Frontend/CachingUtils.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ std::unique_ptr<llvm::MemoryBuffer> loadCachedCompileResultFromCacheKey(
7171

7272
llvm::Expected<llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>>
7373
createCASFileSystem(llvm::cas::ObjectStore &CAS, ArrayRef<std::string> FSRoots,
74-
ArrayRef<std::string> IncludeTreeRoots,
75-
ArrayRef<std::string> IncludeTreeFileList);
74+
const std::string &IncludeTreeRoot,
75+
const std::string &IncludeTreeFileList);
7676

7777
std::vector<std::string> remapPathsFromCommandLine(
7878
ArrayRef<std::string> Args,

lib/AST/PluginLoader.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ static StringRef pluginModuleNameStringFromPath(StringRef path) {
6464

6565
static llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
6666
getPluginLoadingFS(ASTContext &Ctx) {
67-
// If there is a clang include tree FS, using real file system to load plugin
67+
// If there is an immutable file system, using real file system to load plugin
6868
// as the FS in SourceMgr doesn't support directory iterator.
69-
if (Ctx.ClangImporterOpts.HasClangIncludeTreeRoot)
69+
if (Ctx.CASOpts.HasImmutableFileSystem)
7070
return llvm::vfs::getRealFileSystem();
7171
return Ctx.SourceMgr.getFileSystem();
7272
}

lib/ClangImporter/ClangImporter.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -1187,8 +1187,7 @@ std::optional<std::vector<std::string>> ClangImporter::getClangCC1Arguments(
11871187
CI->getFrontendOpts().ProgramAction ==
11881188
clang::frontend::ActionKind::GeneratePCH) &&
11891189
ctx.ClangImporterOpts.HasClangIncludeTreeRoot) {
1190-
CI->getFrontendOpts().CASIncludeTreeID =
1191-
ctx.CASOpts.ClangIncludeTrees.back();
1190+
CI->getFrontendOpts().CASIncludeTreeID = ctx.CASOpts.ClangIncludeTree;
11921191
CI->getFrontendOpts().Inputs.clear();
11931192
}
11941193
}
@@ -1247,7 +1246,7 @@ std::optional<std::vector<std::string>> ClangImporter::getClangCC1Arguments(
12471246

12481247
std::vector<std::string> FilteredModuleMapFiles;
12491248
for (auto ModuleMapFile : CI->getFrontendOpts().ModuleMapFiles) {
1250-
if (ctx.ClangImporterOpts.HasClangIncludeTreeRoot) {
1249+
if (ctx.CASOpts.HasClangIncludeTreeRoot) {
12511250
// There is no need to add any module map file here. Issue a warning and
12521251
// drop the option.
12531252
Impl.diagnose(SourceLoc(), diag::module_map_ignored, ModuleMapFile);
@@ -1327,7 +1326,7 @@ ClangImporter::create(ASTContext &ctx,
13271326
fileMapping.requiresBuiltinHeadersInSystemModules;
13281327

13291328
// Avoid creating indirect file system when using include tree.
1330-
if (!ctx.ClangImporterOpts.HasClangIncludeTreeRoot) {
1329+
if (!ctx.CASOpts.HasImmutableFileSystem) {
13311330
// Wrap Swift's FS to allow Clang to override the working directory
13321331
VFS = llvm::vfs::RedirectingFileSystem::create(
13331332
fileMapping.redirectedFiles, true, *ctx.SourceMgr.getFileSystem());

lib/DependencyScan/ScanDependencies.cpp

+63-28
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
#include "swift/Frontend/FrontendOptions.h"
4646
#include "swift/Frontend/ModuleInterfaceLoader.h"
4747
#include "swift/Strings.h"
48-
#include "clang/Basic/Module.h"
48+
#include "clang/CAS/IncludeTree.h"
4949
#include "llvm/ADT/STLExtras.h"
5050
#include "llvm/ADT/SetOperations.h"
5151
#include "llvm/ADT/SetVector.h"
@@ -69,7 +69,6 @@
6969
#include <sstream>
7070
#include <stack>
7171
#include <string>
72-
#include <algorithm>
7372

7473
using namespace swift;
7574
using namespace swift::dependencies;
@@ -101,9 +100,6 @@ class ExplicitModuleDependencyResolver {
101100
if (resolvingDepInfo.isFinalized())
102101
return false;
103102

104-
if (auto ID = resolvingDepInfo.getClangIncludeTree())
105-
includeTrees.push_back(*ID);
106-
107103
for (const auto &depModuleID : dependencies) {
108104
const auto &depInfo = cache.findKnownDependency(depModuleID);
109105
switch (depModuleID.Kind) {
@@ -322,8 +318,10 @@ class ExplicitModuleDependencyResolver {
322318
// Collect CAS deppendencies from clang modules.
323319
if (!clangDepDetails.CASFileSystemRootID.empty())
324320
rootIDs.push_back(clangDepDetails.CASFileSystemRootID);
325-
if (!clangDepDetails.CASClangIncludeTreeRootID.empty())
326-
includeTrees.push_back(clangDepDetails.CASClangIncludeTreeRootID);
321+
if (!clangDepDetails.CASClangIncludeTreeRootID.empty()) {
322+
if (addIncludeTree(clangDepDetails.CASClangIncludeTreeRootID))
323+
return true;
324+
}
327325

328326
collectUsedVFSOverlay(clangDepDetails);
329327

@@ -358,12 +356,14 @@ class ExplicitModuleDependencyResolver {
358356
auto bridgeRoot = tracker->createTreeFromDependencies();
359357
if (!bridgeRoot)
360358
return diagnoseCASFSCreationError(bridgeRoot.takeError());
361-
fileListIDs.push_back(bridgeRoot->getID().toString());
359+
360+
fileListRefs.push_back(bridgeRoot->getRef());
362361
}
363362
}
364-
} else
365-
includeTrees.push_back(sourceDepDetails.textualModuleDetails
366-
.CASBridgingHeaderIncludeTreeRootID);
363+
} else if (addIncludeTree(sourceDepDetails.textualModuleDetails
364+
.CASBridgingHeaderIncludeTreeRootID))
365+
return true;
366+
367367
return false;
368368
};
369369

@@ -499,9 +499,7 @@ class ExplicitModuleDependencyResolver {
499499
auto root = tracker->createTreeFromDependencies();
500500
if (!root)
501501
return diagnoseCASFSCreationError(root.takeError());
502-
auto rootID = root->getID().toString();
503-
dependencyInfoCopy.updateCASFileSystemRootID(rootID);
504-
fileListIDs.push_back(rootID);
502+
fileListRefs.push_back(root->getRef());
505503
} else if (auto *textualDep =
506504
resolvingDepInfo.getAsSwiftInterfaceModule()) {
507505
tracker->startTracking();
@@ -516,9 +514,7 @@ class ExplicitModuleDependencyResolver {
516514
auto root = tracker->createTreeFromDependencies();
517515
if (!root)
518516
return diagnoseCASFSCreationError(root.takeError());
519-
auto rootID = root->getID().toString();
520-
dependencyInfoCopy.updateCASFileSystemRootID(rootID);
521-
fileListIDs.push_back(rootID);
517+
fileListRefs.push_back(root->getRef());
522518
}
523519

524520
// Update build command line.
@@ -530,15 +526,8 @@ class ExplicitModuleDependencyResolver {
530526
commandline.push_back(rootID);
531527
}
532528

533-
for (auto tree : includeTrees) {
534-
commandline.push_back("-clang-include-tree-root");
535-
commandline.push_back(tree);
536-
}
537-
538-
for (auto list : fileListIDs) {
539-
commandline.push_back("-clang-include-tree-filelist");
540-
commandline.push_back(list);
541-
}
529+
if (computeCASFileSystem(dependencyInfoCopy))
530+
return true;
542531
}
543532

544533
// Compute and update module cache key.
@@ -636,6 +625,53 @@ class ExplicitModuleDependencyResolver {
636625
cmd.push_back("-cache-disable-replay");
637626
}
638627

628+
bool addIncludeTree(StringRef includeTree) {
629+
auto &db = cache.getScanService().getCAS();
630+
auto casID = db.parseID(includeTree);
631+
if (!casID) {
632+
instance.getDiags().diagnose(SourceLoc(), diag::error_invalid_cas_id,
633+
includeTree, toString(casID.takeError()));
634+
return true;
635+
}
636+
auto ref = db.getReference(*casID);
637+
if (!ref) {
638+
instance.getDiags().diagnose(SourceLoc(), diag::error_load_input_from_cas,
639+
includeTree);
640+
return true;
641+
}
642+
643+
auto root = clang::cas::IncludeTreeRoot::get(db, *ref);
644+
if (!root) {
645+
instance.getDiags().diagnose(SourceLoc(), diag::error_cas_malformed_input,
646+
includeTree, toString(root.takeError()));
647+
return true;
648+
}
649+
650+
fileListRefs.push_back(root->getFileListRef());
651+
return false;
652+
}
653+
654+
bool computeCASFileSystem(ModuleDependencyInfo &dependencyInfoCopy) {
655+
if (fileListRefs.empty())
656+
return false;
657+
658+
auto &db = cache.getScanService().getCAS();
659+
auto casFS =
660+
clang::cas::IncludeTree::FileList::create(db, {}, fileListRefs);
661+
if (!casFS) {
662+
instance.getDiags().diagnose(SourceLoc(), diag::error_cas,
663+
"CAS IncludeTree FileList creation",
664+
toString(casFS.takeError()));
665+
return true;
666+
}
667+
668+
auto casID = casFS->getID().toString();
669+
dependencyInfoCopy.updateCASFileSystemRootID(casID);
670+
commandline.push_back("-clang-include-tree-filelist");
671+
commandline.push_back(casID);
672+
return false;
673+
}
674+
639675
private:
640676
const ModuleDependencyID &moduleID;
641677
ModuleDependenciesCache &cache;
@@ -644,8 +680,7 @@ class ExplicitModuleDependencyResolver {
644680

645681
std::optional<SwiftDependencyTracker> tracker;
646682
std::vector<std::string> rootIDs;
647-
std::vector<std::string> includeTrees;
648-
std::vector<std::string> fileListIDs;
683+
std::vector<llvm::cas::ObjectRef> fileListRefs;
649684
std::vector<std::string> commandline;
650685
std::vector<std::string> bridgingHeaderBuildCmd;
651686
llvm::StringMap<MacroPluginDependency> macros;

lib/Frontend/CachingUtils.cpp

+19-40
Original file line numberDiff line numberDiff line change
@@ -472,16 +472,10 @@ static Expected<ObjectRef> mergeCASFileSystem(ObjectStore &CAS,
472472

473473
Expected<IntrusiveRefCntPtr<vfs::FileSystem>>
474474
createCASFileSystem(ObjectStore &CAS, ArrayRef<std::string> FSRoots,
475-
ArrayRef<std::string> IncludeTrees,
476-
ArrayRef<std::string> IncludeTreeFileList) {
477-
assert(!FSRoots.empty() || !IncludeTrees.empty() ||
475+
const std::string &IncludeTree,
476+
const std::string &IncludeTreeFileList) {
477+
assert(!FSRoots.empty() || !IncludeTree.empty() ||
478478
!IncludeTreeFileList.empty() && "no root ID provided");
479-
if (FSRoots.size() == 1 && IncludeTrees.empty()) {
480-
auto ID = CAS.parseID(FSRoots.front());
481-
if (!ID)
482-
return ID.takeError();
483-
return createCASFileSystem(CAS, *ID);
484-
}
485479

486480
auto NewRoot = mergeCASFileSystem(CAS, FSRoots);
487481
if (!NewRoot)
@@ -492,10 +486,9 @@ createCASFileSystem(ObjectStore &CAS, ArrayRef<std::string> FSRoots,
492486
return FS.takeError();
493487

494488
auto CASFS = makeIntrusiveRefCnt<vfs::OverlayFileSystem>(std::move(*FS));
495-
std::vector<clang::cas::IncludeTree::FileList::FileEntry> Files;
496-
// Push all Include File System onto overlay.
497-
for (auto &Tree : IncludeTrees) {
498-
auto ID = CAS.parseID(Tree);
489+
490+
if (!IncludeTree.empty()) {
491+
auto ID = CAS.parseID(IncludeTree);
499492
if (!ID)
500493
return ID.takeError();
501494

@@ -510,46 +503,32 @@ createCASFileSystem(ObjectStore &CAS, ArrayRef<std::string> FSRoots,
510503
if (!ITF)
511504
return ITF.takeError();
512505

513-
auto Err = ITF->forEachFile(
514-
[&](clang::cas::IncludeTree::File File,
515-
clang::cas::IncludeTree::FileList::FileSizeTy Size) -> llvm::Error {
516-
Files.push_back({File.getRef(), Size});
517-
return llvm::Error::success();
518-
});
506+
auto ITFS = clang::cas::createIncludeTreeFileSystem(*ITF);
507+
if (!ITFS)
508+
return ITFS.takeError();
519509

520-
if (Err)
521-
return std::move(Err);
510+
CASFS->pushOverlay(*ITFS);
522511
}
523512

524-
for (auto &List: IncludeTreeFileList) {
525-
auto ID = CAS.parseID(List);
513+
if (!IncludeTreeFileList.empty()) {
514+
auto ID = CAS.parseID(IncludeTreeFileList);
526515
if (!ID)
527516
return ID.takeError();
528517

529518
auto Ref = CAS.getReference(*ID);
530519
if (!Ref)
531520
return createCASObjectNotFoundError(*ID);
532-
auto IT = clang::cas::IncludeTree::FileList::get(CAS, *Ref);
533-
if (!IT)
534-
return IT.takeError();
521+
auto ITF = clang::cas::IncludeTree::FileList::get(CAS, *Ref);
522+
if (!ITF)
523+
return ITF.takeError();
535524

536-
auto Err = IT->forEachFile(
537-
[&](clang::cas::IncludeTree::File File,
538-
clang::cas::IncludeTree::FileList::FileSizeTy Size) -> llvm::Error {
539-
Files.push_back({File.getRef(), Size});
540-
return llvm::Error::success();
541-
});
525+
auto ITFS = clang::cas::createIncludeTreeFileSystem(*ITF);
526+
if (!ITFS)
527+
return ITFS.takeError();
542528

543-
if (Err)
544-
return std::move(Err);
529+
CASFS->pushOverlay(std::move(*ITFS));
545530
}
546531

547-
auto ITFS = clang::cas::createIncludeTreeFileSystem(CAS, Files);
548-
if (!ITFS)
549-
return ITFS.takeError();
550-
551-
CASFS->pushOverlay(std::move(*ITFS));
552-
553532
return CASFS;
554533
}
555534

lib/Frontend/CompilerInvocation.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -763,18 +763,18 @@ static bool ParseCASArgs(CASOptions &Opts, ArgList &Args,
763763

764764
for (const auto &A : Args.getAllArgValues(OPT_cas_fs))
765765
Opts.CASFSRootIDs.emplace_back(A);
766-
for (const auto &A : Args.getAllArgValues(OPT_clang_include_tree_root))
767-
Opts.ClangIncludeTrees.emplace_back(A);
768-
for (const auto &A : Args.getAllArgValues(OPT_clang_include_tree_filelist))
769-
Opts.ClangIncludeTreeFileList.emplace_back(A);
766+
if (auto *A = Args.getLastArg(OPT_clang_include_tree_root))
767+
Opts.ClangIncludeTree = A->getValue();
768+
if (auto *A = Args.getLastArg(OPT_clang_include_tree_filelist))
769+
Opts.ClangIncludeTreeFileList = A->getValue();
770770

771771
if (const Arg *A = Args.getLastArg(OPT_input_file_key))
772772
Opts.InputFileKey = A->getValue();
773773

774774
if (const Arg*A = Args.getLastArg(OPT_bridging_header_pch_key))
775775
Opts.BridgingHeaderPCHCacheKey = A->getValue();
776776

777-
if (!Opts.CASFSRootIDs.empty() || !Opts.ClangIncludeTrees.empty() ||
777+
if (!Opts.CASFSRootIDs.empty() || !Opts.ClangIncludeTree.empty() ||
778778
!Opts.ClangIncludeTreeFileList.empty())
779779
Opts.HasImmutableFileSystem = true;
780780

lib/Frontend/Frontend.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -630,11 +630,11 @@ bool CompilerInstance::setUpVirtualFileSystemOverlays() {
630630
}
631631

632632
if (Invocation.getCASOptions().requireCASFS()) {
633-
if (!CASOpts.CASFSRootIDs.empty() || !CASOpts.ClangIncludeTrees.empty() ||
633+
if (!CASOpts.CASFSRootIDs.empty() || !CASOpts.ClangIncludeTree.empty() ||
634634
!CASOpts.ClangIncludeTreeFileList.empty()) {
635635
// Set up CASFS as BaseFS.
636636
auto FS = createCASFileSystem(*CAS, CASOpts.CASFSRootIDs,
637-
CASOpts.ClangIncludeTrees,
637+
CASOpts.ClangIncludeTree,
638638
CASOpts.ClangIncludeTreeFileList);
639639
if (!FS) {
640640
Diagnostics.diagnose(SourceLoc(), diag::error_cas_fs_creation,

lib/Sema/TypeCheckMacros.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ initializePlugin(ASTContext &ctx, CompilerPlugin *plugin, StringRef libraryPath,
282282
if (!libraryPath.empty()) {
283283
#if SWIFT_BUILD_SWIFT_SYNTAX
284284
llvm::SmallString<128> resolvedLibraryPath;
285-
auto fs = ctx.ClangImporterOpts.HasClangIncludeTreeRoot
285+
auto fs = ctx.CASOpts.HasImmutableFileSystem
286286
? llvm::vfs::getRealFileSystem()
287287
: ctx.SourceMgr.getFileSystem();
288288
if (auto err = fs->getRealPath(libraryPath, resolvedLibraryPath)) {

test/CAS/module_deps_include_tree.swift

-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
// INCLUDE_TREE_F-NEXT: CHeaders/F.h
4242

4343
// MAIN_CMD: -direct-clang-cc1-module-build
44-
// MAIN_CMD: -clang-include-tree-root
4544
// MAIN_CMD: -clang-include-tree-filelist
4645

4746
import C

0 commit comments

Comments
 (0)