Skip to content

Commit 3a570e0

Browse files
authored
Merge pull request #76551 from DougGregor/one-loc-to-file-lookup
Reimplement ModuleDecl::getSourceFileContainingLocation() using SourceManager
2 parents 6ab4f36 + 8febd3f commit 3a570e0

File tree

9 files changed

+55
-143
lines changed

9 files changed

+55
-143
lines changed

include/swift/AST/Module.h

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,6 @@ enum class ResilienceStrategy : unsigned {
162162

163163
class OverlayFile;
164164

165-
/// A mapping used to find the source file that contains a particular source
166-
/// location.
167-
class ModuleSourceFileLocationMap;
168-
169165
/// A unit that allows grouping of modules by a package name.
170166
///
171167
/// PackageUnit is treated as an enclosing scope of ModuleDecl. Unlike other
@@ -302,13 +298,6 @@ class ModuleDecl
302298

303299
SmallVector<FileUnit *, 2> Files;
304300

305-
/// Mapping used to find the source file associated with a given source
306-
/// location.
307-
ModuleSourceFileLocationMap *sourceFileLocationMap = nullptr;
308-
309-
/// The set of auxiliary source files build as part of this module.
310-
SmallVector<SourceFile *, 2> AuxiliaryFiles;
311-
312301
llvm::SmallDenseMap<Identifier, SmallVector<OverlayFile *, 1>>
313302
declaredCrossImports;
314303

@@ -410,9 +399,6 @@ class ModuleDecl
410399
/// SynthesizedFileUnit instead.
411400
void addFile(FileUnit &newFile);
412401

413-
/// Add an auxiliary source file, introduced as part of the translation.
414-
void addAuxiliaryFile(SourceFile &sourceFile);
415-
416402
/// Produces the source file that contains the given source location, or
417403
/// \c nullptr if the source location isn't in this module.
418404
SourceFile *getSourceFileContainingLocation(SourceLoc loc);
@@ -566,9 +552,6 @@ class ModuleDecl
566552
/// present overlays as if they were part of their underlying module.
567553
std::pair<ModuleDecl *, Identifier> getDeclaringModuleAndBystander();
568554

569-
/// Update the source-file location map to make it current.
570-
void updateSourceFileLocationMap();
571-
572555
public:
573556
/// If this is a traditional (non-cross-import) overlay, get its underlying
574557
/// module if one exists.

include/swift/Basic/SourceManager.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,34 @@
1818
#include "clang/Basic/FileManager.h"
1919
#include "llvm/ADT/ArrayRef.h"
2020
#include "llvm/ADT/DenseSet.h"
21+
#include "llvm/ADT/TinyPtrVector.h"
2122
#include "llvm/Support/SourceMgr.h"
2223
#include <map>
2324
#include <optional>
2425
#include <vector>
2526

27+
namespace swift {
28+
class SourceFile;
29+
}
30+
31+
namespace llvm {
32+
template <> struct PointerLikeTypeTraits<swift::SourceFile *> {
33+
public:
34+
static inline swift::SourceFile *getFromVoidPointer(void *P) {
35+
return (swift::SourceFile *)P;
36+
}
37+
static inline void *getAsVoidPointer(swift::SourceFile *S) {
38+
return (void *)S;
39+
}
40+
enum { NumLowBitsAvailable = /*swift::DeclContextAlignInBits=*/ 3 };
41+
};
42+
}
43+
2644
namespace swift {
2745

2846
class CustomAttr;
2947
class DeclContext;
48+
class SourceFile;
3049

3150
/// Augments a buffer that was created specifically to hold generated source
3251
/// code with the reasons for it being generated.
@@ -123,6 +142,13 @@ class SourceManager {
123142
/// is an unfortunate hack needed to allow for correct re-lexing.
124143
llvm::DenseSet<SourceLoc> RegexLiteralStartLocs;
125144

145+
/// Mapping from each buffer ID to the source files that describe it
146+
/// semantically.
147+
llvm::DenseMap<
148+
unsigned,
149+
llvm::TinyPtrVector<SourceFile *>
150+
> bufferIDToSourceFiles;
151+
126152
std::map<const char *, VirtualFile> VirtualFiles;
127153
mutable std::pair<const char *, const VirtualFile*> CachedVFile = {nullptr, nullptr};
128154

@@ -323,6 +349,13 @@ class SourceManager {
323349
/// Adds a memory buffer to the SourceManager, taking ownership of it.
324350
unsigned addNewSourceBuffer(std::unique_ptr<llvm::MemoryBuffer> Buffer);
325351

352+
/// Record the source file as having the given buffer ID.
353+
void recordSourceFile(unsigned bufferID, SourceFile *sourceFile);
354+
355+
/// Retrieve the source files for the given buffer ID.
356+
llvm::TinyPtrVector<SourceFile *>
357+
getSourceFilesForBufferID(unsigned bufferID) const;
358+
326359
/// Add a \c #sourceLocation-defined virtual file region of \p Length.
327360
void createVirtualFile(SourceLoc Loc, StringRef Name, int LineOffset,
328361
unsigned Length);

lib/AST/Module.cpp

Lines changed: 9 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -764,101 +764,14 @@ void ModuleDecl::addFile(FileUnit &newFile) {
764764
clearLookupCache();
765765
}
766766

767-
void ModuleDecl::addAuxiliaryFile(SourceFile &sourceFile) {
768-
AuxiliaryFiles.push_back(&sourceFile);
769-
}
770-
771-
namespace {
772-
/// Compare the source location ranges for two files, as an ordering to
773-
/// use for fast searches.
774-
struct SourceFileRangeComparison {
775-
SourceManager *sourceMgr;
776-
777-
bool operator()(SourceFile *lhs, SourceFile *rhs) const {
778-
auto lhsRange = sourceMgr->getRangeForBuffer(lhs->getBufferID());
779-
auto rhsRange = sourceMgr->getRangeForBuffer(rhs->getBufferID());
780-
781-
std::less<const char *> pointerCompare;
782-
return pointerCompare(
783-
(const char *)lhsRange.getStart().getOpaquePointerValue(),
784-
(const char *)rhsRange.getStart().getOpaquePointerValue());
785-
}
786-
787-
bool operator()(SourceFile *lhs, SourceLoc rhsLoc) const {
788-
auto lhsRange = sourceMgr->getRangeForBuffer(lhs->getBufferID());
789-
790-
std::less<const char *> pointerCompare;
791-
return pointerCompare(
792-
(const char *)lhsRange.getEnd().getOpaquePointerValue(),
793-
(const char *)rhsLoc.getOpaquePointerValue());
794-
}
795-
796-
bool operator()(SourceLoc lhsLoc, SourceFile *rhs) const {
797-
auto rhsRange = sourceMgr->getRangeForBuffer(rhs->getBufferID());
798-
799-
std::less<const char *> pointerCompare;
800-
return pointerCompare(
801-
(const char *)lhsLoc.getOpaquePointerValue(),
802-
(const char *)rhsRange.getEnd().getOpaquePointerValue());
803-
}
804-
};
805-
}
806-
807-
class swift::ModuleSourceFileLocationMap {
808-
public:
809-
unsigned numFiles = 0;
810-
unsigned numAuxiliaryFiles = 0;
811-
std::vector<SourceFile *> allSourceFiles;
812-
SourceFile *lastSourceFile = nullptr;
813-
};
814-
815-
void ModuleDecl::updateSourceFileLocationMap() {
816-
// Allocate a source file location map, if we don't have one already.
817-
if (!sourceFileLocationMap) {
818-
ASTContext &ctx = getASTContext();
819-
sourceFileLocationMap = ctx.Allocate<ModuleSourceFileLocationMap>();
820-
ctx.addCleanup([sourceFileLocationMap=sourceFileLocationMap]() {
821-
sourceFileLocationMap->~ModuleSourceFileLocationMap();
822-
});
823-
}
824-
825-
// If we are up-to-date, there's nothing to do.
826-
ArrayRef<FileUnit *> files = Files;
827-
if (sourceFileLocationMap->numFiles == files.size() &&
828-
sourceFileLocationMap->numAuxiliaryFiles ==
829-
AuxiliaryFiles.size())
830-
return;
831-
832-
// Rebuild the range structure.
833-
sourceFileLocationMap->allSourceFiles.clear();
834-
835-
// First, add all of the source files with a backing buffer.
836-
for (auto *fileUnit : files) {
837-
if (auto sourceFile = dyn_cast<SourceFile>(fileUnit)) {
838-
sourceFileLocationMap->allSourceFiles.push_back(sourceFile);
839-
}
840-
}
841-
842-
// Next, add all of the macro expansion files.
843-
for (auto *sourceFile : AuxiliaryFiles)
844-
sourceFileLocationMap->allSourceFiles.push_back(sourceFile);
845-
846-
// Finally, sort them all so we can do a binary search for lookup.
847-
std::sort(sourceFileLocationMap->allSourceFiles.begin(),
848-
sourceFileLocationMap->allSourceFiles.end(),
849-
SourceFileRangeComparison{&getASTContext().SourceMgr});
850-
851-
sourceFileLocationMap->numFiles = files.size();
852-
sourceFileLocationMap->numAuxiliaryFiles = AuxiliaryFiles.size();
853-
}
854-
855767
SourceFile *ModuleDecl::getSourceFileContainingLocation(SourceLoc loc) {
856768
if (loc.isInvalid())
857769
return nullptr;
858770

771+
auto &sourceMgr = getASTContext().SourceMgr;
772+
859773
// Check whether this location is in a "replaced" range, in which case
860774
// we want to use the original source file.
861-
auto &sourceMgr = getASTContext().SourceMgr;
862775
SourceLoc adjustedLoc = loc;
863776
for (const auto &pair : sourceMgr.getReplacedRanges()) {
864777
if (sourceMgr.rangeContainsTokenLoc(pair.second, loc)) {
@@ -867,35 +780,14 @@ SourceFile *ModuleDecl::getSourceFileContainingLocation(SourceLoc loc) {
867780
}
868781
}
869782

870-
// Before we do any extra work, check the last source file we found a result
871-
// in to see if it contains this.
872-
if (sourceFileLocationMap) {
873-
if (auto lastSourceFile = sourceFileLocationMap->lastSourceFile) {
874-
auto range = sourceMgr.getRangeForBuffer(lastSourceFile->getBufferID());
875-
if (range.contains(adjustedLoc))
876-
return lastSourceFile;
877-
}
783+
auto bufferID = sourceMgr.findBufferContainingLoc(adjustedLoc);
784+
auto sourceFiles = sourceMgr.getSourceFilesForBufferID(bufferID);
785+
for (auto sourceFile: sourceFiles) {
786+
if (sourceFile->getParentModule() == this)
787+
return sourceFile;
878788
}
879789

880-
updateSourceFileLocationMap();
881-
882-
auto found = std::lower_bound(sourceFileLocationMap->allSourceFiles.begin(),
883-
sourceFileLocationMap->allSourceFiles.end(),
884-
adjustedLoc,
885-
SourceFileRangeComparison{&sourceMgr});
886-
if (found == sourceFileLocationMap->allSourceFiles.end())
887-
return nullptr;
888-
889-
auto foundSourceFile = *found;
890-
auto foundRange = sourceMgr.getRangeForBuffer(foundSourceFile->getBufferID());
891-
// Positions inside an empty file or at EOF should still be considered within
892-
// this file.
893-
if (!foundRange.contains(adjustedLoc) && adjustedLoc != foundRange.getEnd())
894-
return nullptr;
895-
896-
// Update the last source file.
897-
sourceFileLocationMap->lastSourceFile = foundSourceFile;
898-
return foundSourceFile;
790+
return nullptr;
899791
}
900792

901793
std::pair<unsigned, SourceLoc>
@@ -3446,9 +3338,7 @@ SourceFile::SourceFile(ModuleDecl &M, SourceFileKind K,
34463338
(void)problem;
34473339
}
34483340

3449-
if (Kind == SourceFileKind::MacroExpansion ||
3450-
Kind == SourceFileKind::DefaultArgument)
3451-
M.addAuxiliaryFile(*this);
3341+
M.getASTContext().SourceMgr.recordSourceFile(bufferID, this);
34523342
}
34533343

34543344
SourceFile::ParsingOptions

lib/Basic/SourceLoc.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,19 @@ SourceManager::getIDForBufferIdentifier(StringRef BufIdentifier) const {
215215
return It->second;
216216
}
217217

218+
void SourceManager::recordSourceFile(unsigned bufferID, SourceFile *sourceFile){
219+
bufferIDToSourceFiles[bufferID].push_back(sourceFile);
220+
}
221+
222+
llvm::TinyPtrVector<SourceFile *>
223+
SourceManager::getSourceFilesForBufferID(unsigned bufferID) const {
224+
auto found = bufferIDToSourceFiles.find(bufferID);
225+
if (found == bufferIDToSourceFiles.end())
226+
return { };
227+
228+
return found->second;
229+
}
230+
218231
SourceManager::~SourceManager() {
219232
for (auto &generated : GeneratedSourceInfos) {
220233
free((void*)generated.second.onDiskBufferCopyFileName.data());

lib/ClangImporter/ImportDecl.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8141,9 +8141,6 @@ SourceFile &ClangImporter::Implementation::getClangSwiftAttrSourceFile(
81418141
SourceFile(module, SourceFileKind::Library, bufferID);
81428142
ClangSwiftAttrSourceFiles.insert({&module, sourceFile});
81438143

8144-
// Record this attribute in the module.
8145-
module.addAuxiliaryFile(*sourceFile);
8146-
81478144
return *sourceFile;
81488145
}
81498146

lib/IDETool/CompileInstance.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,6 @@ getModifiedFunctionDeclList(const SourceFile &SF, SourceManager &tmpSM,
140140
auto tmpBufferID = tmpSM.addNewSourceBuffer(std::move(*tmpBuffer));
141141
SourceFile *tmpSF = new (tmpCtx)
142142
SourceFile(*tmpM, SF.Kind, tmpBufferID, SF.getParsingOptions());
143-
tmpM->addAuxiliaryFile(*tmpSF);
144143

145144
// If the top-level code has been changed, we can't do anything.
146145
if (SF.getInterfaceHash() != tmpSF->getInterfaceHash())

lib/IDETool/IDEInspectionInstance.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,6 @@ bool IDEInspectionInstance::performCachedOperationIfPossible(
254254
ModuleDecl *tmpM = ModuleDecl::create(Identifier(), *tmpCtx);
255255
SourceFile *tmpSF = new (*tmpCtx)
256256
SourceFile(*tmpM, oldSF->Kind, tmpBufferID, oldSF->getParsingOptions());
257-
tmpM->addAuxiliaryFile(*tmpSF);
258257

259258
// FIXME: Since we don't setup module loaders on the temporary AST context,
260259
// 'canImport()' conditional compilation directive always fails. That causes

lib/Parse/Parser.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1144,7 +1144,6 @@ struct ParserUnit::Implementation {
11441144

11451145
auto *M = ModuleDecl::create(Ctx.getIdentifier(ModuleName), Ctx);
11461146
SF = new (Ctx) SourceFile(*M, SFKind, BufferID, parsingOpts);
1147-
M->addAuxiliaryFile(*SF);
11481147
}
11491148

11501149
~Implementation() {

lib/Serialization/ScanningLoaders.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,6 @@ SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath,
226226
SourceFile::ParsingOptions parsingOpts;
227227
auto sourceFile = new (Ctx) SourceFile(
228228
*moduleDecl, SourceFileKind::Interface, bufferID, parsingOpts);
229-
moduleDecl->addAuxiliaryFile(*sourceFile);
230229
std::vector<StringRef> ArgsRefs(Args.begin(), Args.end());
231230
std::vector<StringRef> compiledCandidatesRefs(compiledCandidates.begin(),
232231
compiledCandidates.end());

0 commit comments

Comments
 (0)