[Serialization] Serialize/deserialize source file list

This commit is contained in:
Rintaro Ishizaki
2021-01-11 15:59:44 -08:00
parent 9f6d351bc7
commit 1b6e7857c2
12 changed files with 101 additions and 1 deletions

View File

@@ -402,6 +402,9 @@ public:
return false; return false;
} }
virtual void
collectSourceFileNames(llvm::function_ref<void(StringRef)> callback) const {}
static bool classof(const FileUnit *file) { static bool classof(const FileUnit *file) {
return file->getKind() == FileUnitKind::SerializedAST || return file->getKind() == FileUnitKind::SerializedAST ||
file->getKind() == FileUnitKind::ClangModule || file->getKind() == FileUnitKind::ClangModule ||

View File

@@ -728,6 +728,8 @@ public:
return ReverseFullNameIterator(this); return ReverseFullNameIterator(this);
} }
void collectSourceFileNames(llvm::function_ref<void(StringRef)> callback);
SourceRange getSourceRange() const { return SourceRange(); } SourceRange getSourceRange() const { return SourceRange(); }
static bool classof(const DeclContext *DC) { static bool classof(const DeclContext *DC) {

View File

@@ -446,6 +446,9 @@ public:
StringRef getTargetTriple() const; StringRef getTargetTriple() const;
virtual void collectSourceFileNames(
llvm::function_ref<void(StringRef)>) const override;
static bool classof(const FileUnit *file) { static bool classof(const FileUnit *file) {
return file->getKind() == FileUnitKind::SerializedAST; return file->getKind() == FileUnitKind::SerializedAST;
} }

View File

@@ -1514,6 +1514,17 @@ const clang::Module *ModuleDecl::findUnderlyingClangModule() const {
return nullptr; return nullptr;
} }
void ModuleDecl::collectSourceFileNames(
llvm::function_ref<void(StringRef)> callback) {
for (FileUnit *fileUnit : getFiles()) {
if (SourceFile *SF = dyn_cast<SourceFile>(fileUnit)) {
callback(SF->getFilename());
} else if (auto *serialized = dyn_cast<LoadedFile>(fileUnit)) {
serialized->collectSourceFileNames(callback);
}
}
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Cross-Import Overlays // Cross-Import Overlays
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@@ -959,6 +959,24 @@ Optional<CommentInfo> ModuleFile::getCommentForDecl(const Decl *D) const {
return getCommentForDeclByUSR(USRBuffer.str()); return getCommentForDeclByUSR(USRBuffer.str());
} }
void ModuleFile::collectSourceFileNames(
llvm::function_ref<void(StringRef)> callback) const {
if (Core->SourceFileListData.empty())
return;
assert(!Core->SourceLocsTextData.empty());
auto *Cursor = Core->SourceFileListData.bytes_begin();
auto *End = Core->SourceFileListData.bytes_end();
while (Cursor < End) {
auto fileID = endian::readNext<uint32_t, little, unaligned>(Cursor);
assert(fileID < Core->SourceLocsTextData.size());
auto filePath = Core->SourceLocsTextData.substr(fileID);
size_t terminatorOffset = filePath.find('\0');
filePath = filePath.slice(0, terminatorOffset);
callback(filePath);
}
}
Optional<BasicDeclLocs> Optional<BasicDeclLocs>
ModuleFile::getBasicDeclLocsForDecl(const Decl *D) const { ModuleFile::getBasicDeclLocsForDecl(const Decl *D) const {
assert(D); assert(D);

View File

@@ -694,6 +694,7 @@ public:
Optional<BasicDeclLocs> getBasicDeclLocsForDecl(const Decl *D) const; Optional<BasicDeclLocs> getBasicDeclLocsForDecl(const Decl *D) const;
Identifier getDiscriminatorForPrivateValue(const ValueDecl *D); Identifier getDiscriminatorForPrivateValue(const ValueDecl *D);
Optional<Fingerprint> loadFingerprint(const IterableDeclContext *IDC) const; Optional<Fingerprint> loadFingerprint(const IterableDeclContext *IDC) const;
void collectSourceFileNames(llvm::function_ref<void(StringRef)> callback) const;
// MARK: Deserialization interface // MARK: Deserialization interface

View File

@@ -974,6 +974,9 @@ bool ModuleFileSharedCore::readDeclLocsBlock(llvm::BitstreamCursor &cursor) {
return false; return false;
} }
switch (*kind) { switch (*kind) {
case decl_locs_block::SOURCE_FILE_LIST:
SourceFileListData = blobData;
break;
case decl_locs_block::BASIC_DECL_LOCS: case decl_locs_block::BASIC_DECL_LOCS:
BasicDeclLocsData = blobData; BasicDeclLocsData = blobData;
break; break;

View File

@@ -289,6 +289,9 @@ private:
/// A blob of 0 terminated string segments referenced in \c SourceLocsTextData /// A blob of 0 terminated string segments referenced in \c SourceLocsTextData
StringRef SourceLocsTextData; StringRef SourceLocsTextData;
/// A blob of source file list.
StringRef SourceFileListData;
/// An array of fixed size source location data for each USR appearing in /// An array of fixed size source location data for each USR appearing in
/// \c DeclUSRsTable. /// \c DeclUSRsTable.
StringRef BasicDeclLocsData; StringRef BasicDeclLocsData;

View File

@@ -783,6 +783,46 @@ static void emitBasicLocsRecord(llvm::BitstreamWriter &Out,
DeclLocsList.emit(scratch, Writer.Buffer); DeclLocsList.emit(scratch, Writer.Buffer);
} }
static void emitFileListRecord(llvm::BitstreamWriter &Out,
ModuleOrSourceFile MSF, StringWriter &FWriter) {
assert(MSF);
struct SourceFileListWriter {
StringWriter &FWriter;
llvm::SmallString<1024> Buffer;
llvm::StringSet<> seenFilenames;
void emitFilename(StringRef filename) {
if (filename.empty())
return;
llvm::SmallString<128> absolutePath = filename;
llvm::sys::fs::make_absolute(absolutePath);
if (!seenFilenames.insert(absolutePath).second)
return;
auto fileID = FWriter.getTextOffset(absolutePath);
llvm::raw_svector_ostream out(Buffer);
endian::Writer writer(out, little);
writer.write<uint32_t>(fileID);
}
SourceFileListWriter(StringWriter &FWriter) : FWriter(FWriter) {}
} writer(FWriter);
if (SourceFile *SF = MSF.dyn_cast<SourceFile *>()) {
writer.emitFilename(SF->getFilename());
} else {
auto *M = MSF.get<ModuleDecl *>();
M->collectSourceFileNames(
[&](StringRef filename) { writer.emitFilename(filename); });
}
const decl_locs_block::SourceFileListLayout FileList(Out);
SmallVector<uint64_t, 8> scratch;
FileList.emit(scratch, writer.Buffer);
}
class SourceInfoSerializer : public SerializerBase { class SourceInfoSerializer : public SerializerBase {
public: public:
using SerializerBase::SerializerBase; using SerializerBase::SerializerBase;
@@ -807,6 +847,7 @@ public:
BLOCK_RECORD(control_block, TARGET); BLOCK_RECORD(control_block, TARGET);
BLOCK(DECL_LOCS_BLOCK); BLOCK(DECL_LOCS_BLOCK);
BLOCK_RECORD(decl_locs_block, SOURCE_FILE_LIST);
BLOCK_RECORD(decl_locs_block, BASIC_DECL_LOCS); BLOCK_RECORD(decl_locs_block, BASIC_DECL_LOCS);
BLOCK_RECORD(decl_locs_block, DECL_USRS); BLOCK_RECORD(decl_locs_block, DECL_USRS);
BLOCK_RECORD(decl_locs_block, TEXT_DATA); BLOCK_RECORD(decl_locs_block, TEXT_DATA);
@@ -849,6 +890,7 @@ void serialization::writeSourceInfoToStream(raw_ostream &os,
DeclUSRsTableWriter USRWriter; DeclUSRsTableWriter USRWriter;
StringWriter FPWriter; StringWriter FPWriter;
DocRangeWriter DocWriter; DocRangeWriter DocWriter;
emitFileListRecord(S.Out, DC, FPWriter);
emitBasicLocsRecord(S.Out, DC, USRWriter, FPWriter, DocWriter); emitBasicLocsRecord(S.Out, DC, USRWriter, FPWriter, DocWriter);
// Emit USR table mapping from a USR to USR Id. // Emit USR table mapping from a USR to USR Id.
// The basic locs record uses USR Id instead of actual USR, so that we // The basic locs record uses USR Id instead of actual USR, so that we

View File

@@ -1327,3 +1327,8 @@ SerializedASTFile::getDiscriminatorForPrivateValue(const ValueDecl *D) const {
assert(!discriminator.empty() && "no discriminator found for value"); assert(!discriminator.empty() && "no discriminator found for value");
return discriminator; return discriminator;
} }
void SerializedASTFile::collectSourceFileNames(
llvm::function_ref<void(StringRef)> callback) const {
File.collectSourceFileNames(callback);
}

View File

@@ -49,7 +49,7 @@ const uint16_t SWIFTSOURCEINFO_VERSION_MAJOR = 2;
/// interesting to test for. A backwards-compatible change is one where an \e /// interesting to test for. A backwards-compatible change is one where an \e
/// old compiler can read the new format without any problems (usually by /// old compiler can read the new format without any problems (usually by
/// ignoring new information). /// ignoring new information).
const uint16_t SWIFTSOURCEINFO_VERSION_MINOR = 0; // Last change: add doc comment ranges const uint16_t SWIFTSOURCEINFO_VERSION_MINOR = 1; // Last change: add source file list
/// The hash seed used for the string hashes(llvm::djbHash) in a .swiftsourceinfo file. /// The hash seed used for the string hashes(llvm::djbHash) in a .swiftsourceinfo file.
const uint32_t SWIFTSOURCEINFO_HASH_SEED = 5387; const uint32_t SWIFTSOURCEINFO_HASH_SEED = 5387;
@@ -72,6 +72,7 @@ namespace decl_locs_block {
DECL_USRS, DECL_USRS,
TEXT_DATA, TEXT_DATA,
DOC_RANGES, DOC_RANGES,
SOURCE_FILE_LIST,
}; };
using BasicDeclLocsLayout = BCRecordLayout< using BasicDeclLocsLayout = BCRecordLayout<
@@ -79,6 +80,11 @@ namespace decl_locs_block {
BCBlob // an array of fixed size location data BCBlob // an array of fixed size location data
>; >;
using SourceFileListLayout = BCRecordLayout<
SOURCE_FILE_LIST, // record ID
BCBlob // An array of string offsets in TextDataLayout
>;
using DeclUSRSLayout = BCRecordLayout< using DeclUSRSLayout = BCRecordLayout<
DECL_USRS, // record ID DECL_USRS, // record ID
BCVBR<16>, // table offset within the blob (an llvm::OnDiskHashTable) BCVBR<16>, // table offset within the blob (an llvm::OnDiskHashTable)

View File

@@ -2519,6 +2519,9 @@ static void printModuleMetadata(ModuleDecl *MD) {
OS << "link library: " << lib.getName() OS << "link library: " << lib.getName()
<< ", force load: " << (lib.shouldForceLoad() ? "true" : "false") << "\n"; << ", force load: " << (lib.shouldForceLoad() ? "true" : "false") << "\n";
}); });
MD->collectSourceFileNames([&](StringRef filename) {
OS << filename << "\n";
});
} }
static int doPrintModuleMetaData(const CompilerInvocation &InitInvok, static int doPrintModuleMetaData(const CompilerInvocation &InitInvok,