mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Serialization] Store offset of decls in .swiftsourceinfo
The locations stored in .swiftsourceinfo included the presumed file, line, and column. When a location is requested it would read these, open the external file, create a line map, and find the offset corresponding to that line/column. The offset is known during serialization though, so output it as well to avoid having to read the file and generate the line map. Since the serialized location is returned from `Decl::getLoc()`, it should not be the presumed location. Instead, also output the line directives so that the presumed location can be built as per normal locations. Finally, move the cache out of `Decl` and into `ASTContext`, since very few declarations will actually have their locations deserialized. Make sure to actually write to that cache so it's used - the old cache was never written to.
This commit is contained in:
@@ -1020,16 +1020,36 @@ void ModuleFile::collectBasicSourceFileInfo(
|
||||
}
|
||||
}
|
||||
|
||||
Optional<BasicDeclLocs>
|
||||
ModuleFile::getBasicDeclLocsForDecl(const Decl *D) const {
|
||||
assert(D);
|
||||
static StringRef readLocString(const char *&Data, StringRef StringData) {
|
||||
auto Str =
|
||||
StringData.substr(endian::readNext<uint32_t, little, unaligned>(Data));
|
||||
size_t TerminatorOffset = Str.find('\0');
|
||||
assert(TerminatorOffset != StringRef::npos && "unterminated string data");
|
||||
return Str.slice(0, TerminatorOffset);
|
||||
}
|
||||
|
||||
static void readRawLoc(ExternalSourceLocs::RawLoc &Loc, const char *&Data,
|
||||
StringRef StringData) {
|
||||
Loc.Offset = endian::readNext<uint32_t, little, unaligned>(Data);
|
||||
Loc.Line = endian::readNext<uint32_t, little, unaligned>(Data);
|
||||
Loc.Column = endian::readNext<uint32_t, little, unaligned>(Data);
|
||||
|
||||
Loc.Directive.Offset = endian::readNext<uint32_t, little, unaligned>(Data);
|
||||
Loc.Directive.LineOffset = endian::readNext<int32_t, little, unaligned>(Data);
|
||||
Loc.Directive.Length = endian::readNext<uint32_t, little, unaligned>(Data);
|
||||
Loc.Directive.Name = readLocString(Data, StringData);
|
||||
}
|
||||
|
||||
Optional<ExternalSourceLocs::RawLocs>
|
||||
ModuleFile::getExternalRawLocsForDecl(const Decl *D) const {
|
||||
assert(D);
|
||||
// Keep these as assertions instead of early exits to ensure that we are not
|
||||
// doing extra work. These cases should be handled by clients of this API.
|
||||
assert(!D->hasClangNode() &&
|
||||
"cannot find comments for Clang decls in Swift modules");
|
||||
assert(D->getDeclContext()->getModuleScopeContext() == FileContext &&
|
||||
"Decl is from a different serialized file");
|
||||
|
||||
if (!Core->DeclUSRsTable)
|
||||
return None;
|
||||
// Future compilers may not provide BasicDeclLocsData anymore.
|
||||
@@ -1037,6 +1057,7 @@ ModuleFile::getBasicDeclLocsForDecl(const Decl *D) const {
|
||||
return None;
|
||||
if (D->isImplicit())
|
||||
return None;
|
||||
|
||||
// Compute the USR.
|
||||
llvm::SmallString<128> USRBuffer;
|
||||
llvm::raw_svector_ostream OS(USRBuffer);
|
||||
@@ -1046,52 +1067,39 @@ ModuleFile::getBasicDeclLocsForDecl(const Decl *D) const {
|
||||
auto It = Core->DeclUSRsTable->find(OS.str());
|
||||
if (It == Core->DeclUSRsTable->end())
|
||||
return None;
|
||||
|
||||
auto UsrId = *It;
|
||||
uint32_t NumSize = 4;
|
||||
// Size of BasicDeclLocs in the buffer.
|
||||
// FilePathOffset + LocNum * LineColumn
|
||||
uint32_t LineColumnCount = 3;
|
||||
uint32_t RecordSize =
|
||||
NumSize + // Offset into source filename blob
|
||||
NumSize + // Offset into doc ranges blob
|
||||
NumSize * 2 * LineColumnCount; // Line/column of: Loc, StartLoc, EndLoc
|
||||
4 + // Source filename offset
|
||||
4 + // Doc ranges offset
|
||||
4 * 3 * 7; // Loc/StartLoc/EndLoc each have 7 4-byte fields
|
||||
uint32_t RecordOffset = RecordSize * UsrId;
|
||||
assert(RecordOffset < Core->BasicDeclLocsData.size());
|
||||
assert(Core->BasicDeclLocsData.size() % RecordSize == 0);
|
||||
BasicDeclLocs Result;
|
||||
auto *Record = Core->BasicDeclLocsData.data() + RecordOffset;
|
||||
auto ReadNext = [&Record]() {
|
||||
return endian::readNext<uint32_t, little, unaligned>(Record);
|
||||
};
|
||||
|
||||
auto FilePath = Core->SourceLocsTextData.substr(ReadNext());
|
||||
size_t TerminatorOffset = FilePath.find('\0');
|
||||
assert(TerminatorOffset != StringRef::npos && "unterminated string data");
|
||||
Result.SourceFilePath = FilePath.slice(0, TerminatorOffset);
|
||||
ExternalSourceLocs::RawLocs Result;
|
||||
Result.SourceFilePath = readLocString(Record, Core->SourceLocsTextData);
|
||||
|
||||
const auto DocRangesOffset = ReadNext();
|
||||
const auto DocRangesOffset =
|
||||
endian::readNext<uint32_t, little, unaligned>(Record);
|
||||
if (DocRangesOffset) {
|
||||
assert(!Core->DocRangesData.empty());
|
||||
const auto *Data = Core->DocRangesData.data() + DocRangesOffset;
|
||||
const auto NumLocs = endian::readNext<uint32_t, little, unaligned>(Data);
|
||||
assert(NumLocs);
|
||||
|
||||
for (uint32_t i = 0; i < NumLocs; ++i) {
|
||||
SourcePosition LC;
|
||||
LC.Line = endian::readNext<uint32_t, little, unaligned>(Data);
|
||||
LC.Column = endian::readNext<uint32_t, little, unaligned>(Data);
|
||||
auto Length = endian::readNext<uint32_t, little, unaligned>(Data);
|
||||
Result.DocRanges.push_back(std::make_pair(LC, Length));
|
||||
for (uint32_t I = 0; I < NumLocs; ++I) {
|
||||
auto &Range =
|
||||
Result.DocRanges.emplace_back(ExternalSourceLocs::RawLoc(), 0);
|
||||
readRawLoc(Range.first, Data, Core->SourceLocsTextData);
|
||||
Range.second = endian::readNext<uint32_t, little, unaligned>(Data);
|
||||
}
|
||||
}
|
||||
|
||||
#define READ_FIELD(X) \
|
||||
Result.X.Line = ReadNext(); \
|
||||
Result.X.Column = ReadNext();
|
||||
READ_FIELD(Loc)
|
||||
READ_FIELD(StartLoc)
|
||||
READ_FIELD(EndLoc)
|
||||
#undef READ_FIELD
|
||||
readRawLoc(Result.Loc, Record, Core->SourceLocsTextData);
|
||||
readRawLoc(Result.StartLoc, Record, Core->SourceLocsTextData);
|
||||
readRawLoc(Result.EndLoc, Record, Core->SourceLocsTextData);
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user