mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
SerializeLoc: serialize basic decl source location information to .swiftsourceinfo file
After setting up the .swiftsourceinfo file, this patch starts to actually serialize and de-serialize source locations for declaration. The binary format of .swiftsourceinfo currently contains these three records: BasicDeclLocs: a hash table mapping from a USR ID to a list of basic source locations. The USR id could be retrieved from the following DeclUSRs record using an actual decl USR. The basic source locations include a file ID and the results from Decl::getLoc(), ValueDecl::getNameLoc(), Decl::getStartLoc() and Decl::getEndLoc(). The file ID could be used to retrieve the actual file name from the following SourceFilePaths record. Each location is encoded as a line:column pair. DeclUSRS: a hash table mapping from USR to a USR ID used by location records. SourceFilePaths: a hash table mapping from a file ID to actual file name. BasicDeclLocs should be sufficient for most diagnostic cases. If additional source locations are needed, we could always add new source location records without breaking the backward compatibility. When de-serializing the source location from a module-imported decl, we calculate its USR, retrieve the USR ID from the DeclUSRS record, and use the USR ID to look up the basic location list in the BasicDeclLocs record. For more details about .swiftsourceinfo file: https://forums.swift.org/t/proposal-emitting-source-information-file-during-compilation
This commit is contained in:
@@ -263,10 +263,43 @@ std::error_code SerializedModuleLoaderBase::openModuleDocFile(
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
std::error_code
|
||||
SerializedModuleLoaderBase::openModuleSourceInfoFile(AccessPathElem ModuleID,
|
||||
StringRef ModulePath,
|
||||
StringRef ModuleSourceInfoPath,
|
||||
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer) {
|
||||
if (!ModuleSourceInfoBuffer)
|
||||
return std::error_code();
|
||||
|
||||
llvm::vfs::FileSystem &FS = *Ctx.SourceMgr.getFileSystem();
|
||||
|
||||
// Try to open the module source info file. If it does not exist, ignore
|
||||
// the error. However, pass though all other errors.
|
||||
if (llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ModuleSourceInfoOrErr =
|
||||
FS.getBufferForFile(ModuleSourceInfoPath)) {
|
||||
*ModuleSourceInfoBuffer = std::move(*ModuleSourceInfoOrErr);
|
||||
return std::error_code();
|
||||
}
|
||||
llvm::SmallString<128> Path(ModulePath);
|
||||
llvm::sys::path::replace_extension(Path,
|
||||
file_types::getExtension(file_types::TY_SwiftSourceInfoFile));
|
||||
|
||||
// Try to open the module source info file adjacent to the .swiftmodule file.
|
||||
if (llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ModuleSourceInfoOrErr =
|
||||
FS.getBufferForFile(Path.str())) {
|
||||
*ModuleSourceInfoBuffer = std::move(*ModuleSourceInfoOrErr);
|
||||
return std::error_code();
|
||||
}
|
||||
// Failing to load .swiftsourceinfo file isn't critical, so don't return any errors.
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
std::error_code SerializedModuleLoaderBase::openModuleFiles(
|
||||
AccessPathElem ModuleID, StringRef ModulePath, StringRef ModuleDocPath,
|
||||
StringRef ModuleSourceInfoPath,
|
||||
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
|
||||
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer) {
|
||||
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
|
||||
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer) {
|
||||
assert(((ModuleBuffer && ModuleDocBuffer) ||
|
||||
(!ModuleBuffer && !ModuleDocBuffer)) &&
|
||||
"Module and Module Doc buffer must both be initialized or NULL");
|
||||
@@ -299,6 +332,11 @@ std::error_code SerializedModuleLoaderBase::openModuleFiles(
|
||||
if (ModuleDocErr)
|
||||
return ModuleDocErr;
|
||||
|
||||
auto ModuleSourceInfoErr =
|
||||
openModuleSourceInfoFile(ModuleID, ModulePath, ModuleSourceInfoPath, ModuleSourceInfoBuffer);
|
||||
if (ModuleSourceInfoErr)
|
||||
return ModuleSourceInfoErr;
|
||||
|
||||
*ModuleBuffer = std::move(ModuleOrErr.get());
|
||||
|
||||
return std::error_code();
|
||||
@@ -306,9 +344,10 @@ std::error_code SerializedModuleLoaderBase::openModuleFiles(
|
||||
|
||||
std::error_code SerializedModuleLoader::findModuleFilesInDirectory(
|
||||
AccessPathElem ModuleID, StringRef DirPath, StringRef ModuleFilename,
|
||||
StringRef ModuleDocFilename,
|
||||
StringRef ModuleDocFilename, StringRef ModuleSourceInfoFilename,
|
||||
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
|
||||
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer) {
|
||||
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
|
||||
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer) {
|
||||
if (LoadMode == ModuleLoadingMode::OnlyInterface)
|
||||
return std::make_error_code(std::errc::not_supported);
|
||||
|
||||
@@ -316,11 +355,16 @@ std::error_code SerializedModuleLoader::findModuleFilesInDirectory(
|
||||
llvm::sys::path::append(ModulePath, ModuleFilename);
|
||||
llvm::SmallString<256> ModuleDocPath{DirPath};
|
||||
llvm::sys::path::append(ModuleDocPath, ModuleDocFilename);
|
||||
llvm::SmallString<256> ModuleSourceInfoPath{DirPath};
|
||||
llvm::sys::path::append(ModuleSourceInfoPath, "Private");
|
||||
llvm::sys::path::append(ModuleSourceInfoPath, ModuleSourceInfoFilename);
|
||||
return SerializedModuleLoaderBase::openModuleFiles(ModuleID,
|
||||
ModulePath,
|
||||
ModuleDocPath,
|
||||
ModuleSourceInfoPath,
|
||||
ModuleBuffer,
|
||||
ModuleDocBuffer);
|
||||
ModuleDocBuffer,
|
||||
ModuleSourceInfoBuffer);
|
||||
}
|
||||
|
||||
bool SerializedModuleLoader::maybeDiagnoseTargetMismatch(
|
||||
@@ -361,15 +405,19 @@ bool SerializedModuleLoader::maybeDiagnoseTargetMismatch(
|
||||
struct ModuleFilenamePair {
|
||||
llvm::SmallString<64> module;
|
||||
llvm::SmallString<64> moduleDoc;
|
||||
llvm::SmallString<64> moduleSourceInfo;
|
||||
|
||||
ModuleFilenamePair(StringRef baseName)
|
||||
: module(baseName), moduleDoc(baseName)
|
||||
: module(baseName), moduleDoc(baseName), moduleSourceInfo(baseName)
|
||||
{
|
||||
module += '.';
|
||||
module += file_types::getExtension(file_types::TY_SwiftModuleFile);
|
||||
|
||||
moduleDoc += '.';
|
||||
moduleDoc += file_types::getExtension(file_types::TY_SwiftModuleDocFile);
|
||||
|
||||
moduleSourceInfo += '.';
|
||||
moduleSourceInfo += file_types::getExtension(file_types::TY_SwiftSourceInfoFile);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -377,6 +425,7 @@ bool
|
||||
SerializedModuleLoaderBase::findModule(AccessPathElem moduleID,
|
||||
std::unique_ptr<llvm::MemoryBuffer> *moduleBuffer,
|
||||
std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
|
||||
std::unique_ptr<llvm::MemoryBuffer> *moduleSourceInfoBuffer,
|
||||
bool &isFramework, bool &isSystemModule) {
|
||||
llvm::SmallString<64> moduleName(moduleID.first.str());
|
||||
ModuleFilenamePair fileNames(moduleName);
|
||||
@@ -400,7 +449,9 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID,
|
||||
for (const auto &targetFileNames : targetFileNamePairs) {
|
||||
auto result = findModuleFilesInDirectory(moduleID, currPath,
|
||||
targetFileNames.module, targetFileNames.moduleDoc,
|
||||
moduleBuffer, moduleDocBuffer);
|
||||
targetFileNames.moduleSourceInfo,
|
||||
moduleBuffer, moduleDocBuffer,
|
||||
moduleSourceInfoBuffer);
|
||||
if (!result) {
|
||||
return true;
|
||||
} else if (result == std::errc::not_supported) {
|
||||
@@ -452,7 +503,8 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID,
|
||||
|
||||
auto result = findModuleFilesInDirectory(
|
||||
moduleID, path, fileNames.module.str(), fileNames.moduleDoc.str(),
|
||||
moduleBuffer, moduleDocBuffer);
|
||||
fileNames.moduleSourceInfo.str(),
|
||||
moduleBuffer, moduleDocBuffer, moduleSourceInfoBuffer);
|
||||
if (!result)
|
||||
return true;
|
||||
else if (result == std::errc::not_supported)
|
||||
@@ -520,6 +572,7 @@ FileUnit *SerializedModuleLoaderBase::loadAST(
|
||||
ModuleDecl &M, Optional<SourceLoc> diagLoc,
|
||||
std::unique_ptr<llvm::MemoryBuffer> moduleInputBuffer,
|
||||
std::unique_ptr<llvm::MemoryBuffer> moduleDocInputBuffer,
|
||||
std::unique_ptr<llvm::MemoryBuffer> moduleSourceInfoInputBuffer,
|
||||
bool isFramework, bool treatAsPartialModule) {
|
||||
assert(moduleInputBuffer);
|
||||
|
||||
@@ -540,6 +593,7 @@ FileUnit *SerializedModuleLoaderBase::loadAST(
|
||||
serialization::ValidationInfo loadInfo =
|
||||
ModuleFile::load(std::move(moduleInputBuffer),
|
||||
std::move(moduleDocInputBuffer),
|
||||
std::move(moduleSourceInfoInputBuffer),
|
||||
isFramework, loadedModuleFile,
|
||||
&extendedInfo);
|
||||
if (loadInfo.status == serialization::Status::Valid) {
|
||||
@@ -770,7 +824,7 @@ bool SerializedModuleLoaderBase::canImportModule(
|
||||
// Look on disk.
|
||||
bool isFramework = false;
|
||||
bool isSystemModule = false;
|
||||
return findModule(mID, nullptr, nullptr, isFramework, isSystemModule);
|
||||
return findModule(mID, nullptr, nullptr, nullptr, isFramework, isSystemModule);
|
||||
}
|
||||
|
||||
bool MemoryBufferSerializedModuleLoader::canImportModule(
|
||||
@@ -792,9 +846,11 @@ SerializedModuleLoaderBase::loadModule(SourceLoc importLoc,
|
||||
|
||||
std::unique_ptr<llvm::MemoryBuffer> moduleInputBuffer;
|
||||
std::unique_ptr<llvm::MemoryBuffer> moduleDocInputBuffer;
|
||||
std::unique_ptr<llvm::MemoryBuffer> moduleSourceInfoInputBuffer;
|
||||
|
||||
// Look on disk.
|
||||
if (!findModule(moduleID, &moduleInputBuffer, &moduleDocInputBuffer,
|
||||
&moduleSourceInfoInputBuffer,
|
||||
isFramework, isSystemModule)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -814,8 +870,8 @@ SerializedModuleLoaderBase::loadModule(SourceLoc importLoc,
|
||||
SWIFT_DEFER { M->setHasResolvedImports(); };
|
||||
|
||||
if (!loadAST(*M, moduleID.second, std::move(moduleInputBuffer),
|
||||
std::move(moduleDocInputBuffer), isFramework,
|
||||
/*treatAsPartialModule*/false)) {
|
||||
std::move(moduleDocInputBuffer), std::move(moduleSourceInfoInputBuffer),
|
||||
isFramework, /*treatAsPartialModule*/false)) {
|
||||
M->setFailedToLoad();
|
||||
}
|
||||
|
||||
@@ -850,7 +906,7 @@ MemoryBufferSerializedModuleLoader::loadModule(SourceLoc importLoc,
|
||||
auto *M = ModuleDecl::create(moduleID.first, Ctx);
|
||||
SWIFT_DEFER { M->setHasResolvedImports(); };
|
||||
|
||||
if (!loadAST(*M, moduleID.second, std::move(moduleInputBuffer), {},
|
||||
if (!loadAST(*M, moduleID.second, std::move(moduleInputBuffer), {}, {},
|
||||
isFramework, treatAsPartialModule)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -884,9 +940,10 @@ void SerializedModuleLoaderBase::loadObjCMethods(
|
||||
|
||||
std::error_code MemoryBufferSerializedModuleLoader::findModuleFilesInDirectory(
|
||||
AccessPathElem ModuleID, StringRef DirPath, StringRef ModuleFilename,
|
||||
StringRef ModuleDocFilename,
|
||||
StringRef ModuleDocFilename, StringRef ModuleSourceInfoFilename,
|
||||
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
|
||||
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer) {
|
||||
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
|
||||
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer) {
|
||||
// This is a soft error instead of an llvm_unreachable because this API is
|
||||
// primarily used by LLDB which makes it more likely that unwitting changes to
|
||||
// the Swift compiler accidentally break the contract.
|
||||
@@ -1010,6 +1067,11 @@ SerializedASTFile::getCommentForDecl(const Decl *D) const {
|
||||
return File.getCommentForDecl(D);
|
||||
}
|
||||
|
||||
Optional<BasicDeclLocs>
|
||||
SerializedASTFile::getBasicLocsForDecl(const Decl *D) const {
|
||||
return File.getBasicDeclLocsForDecl(D);
|
||||
}
|
||||
|
||||
Optional<StringRef>
|
||||
SerializedASTFile::getGroupNameForDecl(const Decl *D) const {
|
||||
return File.getGroupNameForDecl(D);
|
||||
|
||||
Reference in New Issue
Block a user