[Caching] Identify input type from filename correctly

When loading input from CAS, `swift-frontend` relies on the input file
name to determine the type to look from CAS entry. In the case where
file extension is `.private.swiftinterface`, swift mis-identify that as
`.swiftinterface` file and look up the wrong input file. Add a new
file type lookup function that can figure out the type from the full
filename.

Also add few diagnostics during the CAS lookup for the input file to
error out immediately, rather than rely on the lookup failure later.
This commit is contained in:
Steven Wu
2024-01-05 13:40:13 -08:00
parent dfe1e691a8
commit 7150e54003
6 changed files with 96 additions and 7 deletions

View File

@@ -504,6 +504,10 @@ ERROR(error_cas, none, "CAS error encountered: %0", (StringRef))
ERROR(error_failed_cached_diag, none, "failed to serialize cached diagnostics: %0", (StringRef))
ERROR(error_replay_cached_diag, none, "failed to replay cached diagnostics: %0", (StringRef))
ERROR(error_load_input_from_cas, none, "failed to load input '%0' from CAS", (StringRef))
ERROR(error_wrong_input_num_for_input_file_key, none, "-input-file-key only support one input file", ())
// Dependency Verifier Diagnostics
ERROR(missing_member_dependency,none,
"expected "

View File

@@ -39,6 +39,11 @@ StringRef getExtension(ID Id);
/// the invalid type \c TY_INVALID.
ID lookupTypeForExtension(StringRef Ext);
/// Lookup the type to use for the file name \p Filename.
/// If the filename is empty or type cannot be recognoized, return
/// the invalid type \c TY_INVALID.
ID lookupTypeFromFilename(StringRef Filename);
/// Lookup the type to use for the name \p Name.
ID lookupTypeForName(StringRef Name);

View File

@@ -56,6 +56,29 @@ ID file_types::lookupTypeForExtension(StringRef Ext) {
.Default(TY_INVALID);
}
// Compute the file type from filename. This handles the lookup for extensions
// with multiple dots, like `.private.swiftinterface` correctly.
ID file_types::lookupTypeFromFilename(StringRef Filename) {
StringRef MaybeExt = Filename;
// Search from leftmost `.`, return the first match or till all dots are
// consumed.
size_t Pos = MaybeExt.find_first_of('.');
while(Pos != StringRef::npos) {
MaybeExt = MaybeExt.substr(Pos);
// If size is 1, that means only `.` is left, return invalid.
if (MaybeExt.size() == 1)
return TY_INVALID;
ID Type = lookupTypeForExtension(MaybeExt);
if (Type != TY_INVALID)
return Type;
// Drop `.` and keep looking.
MaybeExt = MaybeExt.drop_front();
Pos = MaybeExt.find_first_of('.');
}
return TY_INVALID;
}
ID file_types::lookupTypeForName(StringRef Name) {
return llvm::StringSwitch<file_types::ID>(Name)
#define TYPE(NAME, ID, EXTENSION, FLAGS) \

View File

@@ -585,15 +585,27 @@ bool CompilerInstance::setUpVirtualFileSystemOverlays() {
ClangOpts.BridgingHeader))
MemFS->addFile(Invocation.getClangImporterOptions().BridgingHeader, 0,
std::move(loadedBuffer));
else
Diagnostics.diagnose(
SourceLoc(), diag::error_load_input_from_cas,
Invocation.getClangImporterOptions().BridgingHeader);
}
if (!Opts.InputFileKey.empty()) {
auto InputPath = Opts.InputsAndOutputs.getFilenameOfFirstInput();
auto Type = file_types::lookupTypeForExtension(
llvm::sys::path::extension(InputPath));
if (auto loadedBuffer = loadCachedCompileResultFromCacheKey(
getObjectStore(), getActionCache(), Diagnostics,
Opts.InputFileKey, Type, InputPath))
MemFS->addFile(InputPath, 0, std::move(loadedBuffer));
if (Opts.InputsAndOutputs.getAllInputs().size() != 1)
Diagnostics.diagnose(SourceLoc(),
diag::error_wrong_input_num_for_input_file_key);
else {
auto InputPath = Opts.InputsAndOutputs.getFilenameOfFirstInput();
auto Type = file_types::lookupTypeFromFilename(
llvm::sys::path::filename(InputPath));
if (auto loadedBuffer = loadCachedCompileResultFromCacheKey(
getObjectStore(), getActionCache(), Diagnostics,
Opts.InputFileKey, Type, InputPath))
MemFS->addFile(InputPath, 0, std::move(loadedBuffer));
else
Diagnostics.diagnose(SourceLoc(), diag::error_load_input_from_cas,
InputPath);
}
}
llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayVFS =
new llvm::vfs::OverlayFileSystem(SourceMgr.getFileSystem());

View File

@@ -17,6 +17,7 @@ add_swift_unittest(SwiftBasicTests
EncodedSequenceTest.cpp
ExponentialGrowthAppendingBinaryByteStreamTests.cpp
FileSystemTest.cpp
FileTypes.cpp
FixedBitSetTest.cpp
FrozenMultiMapTest.cpp
ImmutablePointerSetTest.cpp

View File

@@ -0,0 +1,44 @@
//===--- FileTypes.cpp - for swift/Basic/FileTypes.h ----------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/Basic/FileTypes.h"
#include "gtest/gtest.h"
namespace {
using namespace swift;
using namespace swift::file_types;
static const std::vector<std::pair<std::string, ID>> ExtIDs = {
#define TYPE(NAME, ID, EXTENSION, FLAGS) {EXTENSION, TY_##ID},
#include "swift/Basic/FileTypes.def"
};
TEST(FileSystem, lookupTypeFromFilename) {
for (auto &Entry: ExtIDs) {
// no extension, skip.
if (Entry.first.empty())
continue;
// raw-sil and raw-sib do not have unique extension.
if (Entry.second == TY_RawSIL || Entry.second == TY_RawSIB)
continue;
std::string Filename = "Myfile." + Entry.first;
ID Type = lookupTypeFromFilename(Filename);
ASSERT_EQ(getTypeName(Type), getTypeName(Entry.second));
}
ASSERT_EQ(lookupTypeFromFilename(""), TY_INVALID);
ASSERT_EQ(lookupTypeFromFilename("."), TY_INVALID);
ASSERT_EQ(lookupTypeFromFilename(".."), TY_INVALID);
}
} // namespace