Skip to content

Commit 836e3f0

Browse files
committed
Support remapping index store paths
- When indexing, `-fdebug-prefix-map` will be used to remap paths so the computed index data will be hermetic. This includes the unit files' names as well as all paths embedded in the unit files. - When reading, a reverse mapping can be used e.g. via `indexstore_store_create_with_prefix_mapping` to automatically remap the hermetic index data to the correct local paths.
1 parent 9b564bf commit 836e3f0

File tree

16 files changed

+312
-58
lines changed

16 files changed

+312
-58
lines changed

clang/include/clang/Index/IndexDataStore.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "llvm/ADT/STLExtras.h"
1616
#include "llvm/Support/Chrono.h"
1717
#include <functional>
18+
#include <map>
1819
#include <memory>
1920
#include <string>
2021

@@ -26,9 +27,14 @@ class IndexDataStore {
2627
~IndexDataStore();
2728

2829
static std::unique_ptr<IndexDataStore>
29-
create(StringRef IndexStorePath, std::string &Error);
30+
create(StringRef IndexStorePath,
31+
std::map<std::string, std::string, std::greater<std::string>>
32+
PrefixMap,
33+
std::string &Error);
3034

3135
StringRef getFilePath() const;
36+
std::map<llvm::StringRef, llvm::StringRef, std::greater<llvm::StringRef>>
37+
getPrefixMap() const;
3238
bool foreachUnitName(bool sorted,
3339
llvm::function_ref<bool(StringRef unitName)> receiver);
3440

clang/include/clang/Index/IndexUnitReader.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "llvm/ADT/StringRef.h"
1414
#include "llvm/ADT/STLExtras.h"
1515
#include "llvm/Support/Chrono.h"
16+
#include <map>
1617

1718
namespace clang {
1819
namespace index {
@@ -29,9 +30,12 @@ class IndexUnitReader {
2930

3031
static std::unique_ptr<IndexUnitReader>
3132
createWithUnitFilename(StringRef UnitFilename, StringRef StorePath,
33+
std::map<llvm::StringRef, llvm::StringRef, std::greater<llvm::StringRef>> PrefixMap,
3234
std::string &Error);
3335
static std::unique_ptr<IndexUnitReader>
34-
createWithFilePath(StringRef FilePath, std::string &Error);
36+
createWithFilePath(StringRef FilePath,
37+
std::map<llvm::StringRef, llvm::StringRef, std::greater<llvm::StringRef>> PrefixMap,
38+
std::string &Error);
3539

3640
static Optional<llvm::sys::TimePoint<>>
3741
getModificationTimeForUnit(StringRef UnitFilename, StringRef StorePath,

clang/include/clang/Index/IndexUnitWriter.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "clang/Basic/LLVM.h"
1313
#include "llvm/ADT/DenseSet.h"
1414
#include "llvm/ADT/SmallString.h"
15+
#include <map>
1516
#include <string>
1617
#include <vector>
1718

@@ -57,6 +58,8 @@ class IndexUnitWriter {
5758
std::string TargetTriple;
5859
std::string WorkDir;
5960
std::string SysrootPath;
61+
std::map<llvm::StringRef, llvm::StringRef, std::greater<llvm::StringRef>>
62+
PrefixMap;
6063
std::function<writer::ModuleInfo(writer::OpaqueModule,
6164
SmallVectorImpl<char> &Scratch)> GetInfoForModuleFn;
6265
struct FileInclude {
@@ -87,6 +90,8 @@ class IndexUnitWriter {
8790
/// \param MainFile the main file for a compiled source file. This should be
8891
/// null for PCH and module units.
8992
/// \param IsSystem true for system module units, false otherwise.
93+
/// \param PrefixMap Mapping to use to standardize file paths to make them
94+
/// hermetic/reproducible. This applies to all paths emitted in the unit file.
9095
IndexUnitWriter(FileManager &FileMgr,
9196
StringRef StorePath,
9297
StringRef ProviderIdentifier, StringRef ProviderVersion,
@@ -98,6 +103,8 @@ class IndexUnitWriter {
98103
bool IsDebugCompilation,
99104
StringRef TargetTriple,
100105
StringRef SysrootPath,
106+
std::map<llvm::StringRef, llvm::StringRef, std::greater<llvm::StringRef>>
107+
PrefixMap,
101108
writer::ModuleInfoWriterCallback GetInfoForModule);
102109
~IndexUnitWriter();
103110

@@ -120,7 +127,8 @@ class IndexUnitWriter {
120127
Optional<bool> isUnitUpToDateForOutputFile(StringRef FilePath,
121128
Optional<StringRef> TimeCompareFilePath,
122129
std::string &Error);
123-
static void getUnitNameForAbsoluteOutputFile(StringRef FilePath, SmallVectorImpl<char> &Str);
130+
static void getUnitNameForAbsoluteOutputFile(StringRef FilePath, SmallVectorImpl<char> &Str,
131+
std::map<llvm::StringRef, llvm::StringRef, std::greater<llvm::StringRef>> &PrefixMap);
124132
static bool initIndexDirectory(StringRef StorePath, std::string &Error);
125133

126134
private:

clang/include/indexstore/IndexStoreCXX.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "llvm/ADT/Optional.h"
1919
#include "llvm/ADT/STLExtras.h"
2020
#include "llvm/ADT/SmallString.h"
21+
#include <map>
2122

2223
namespace indexstore {
2324
using llvm::ArrayRef;
@@ -101,10 +102,19 @@ class IndexStore {
101102
friend class IndexUnitReader;
102103

103104
public:
104-
IndexStore(StringRef path, std::string &error) {
105+
IndexStore(StringRef path,
106+
std::map<std::string, std::string, std::greater<std::string>> prefix_map,
107+
std::string &error) {
105108
llvm::SmallString<64> buf = path;
106109
indexstore_error_t c_err = nullptr;
107-
obj = indexstore_store_create(buf.c_str(), &c_err);
110+
std::vector<std::string> mapping_storage;
111+
std::vector<const char *> c_strs;
112+
for (const auto &Mapping : prefix_map)
113+
mapping_storage.push_back(Mapping.first + "=" + Mapping.second);
114+
for (const auto &Str : mapping_storage)
115+
c_strs.push_back(Str.c_str());
116+
obj = indexstore_store_create_with_prefix_mapping(buf.c_str(), c_strs.data(),
117+
c_strs.size(), &c_err);
108118
if (c_err) {
109119
error = indexstore_error_get_description(c_err);
110120
indexstore_error_dispose(c_err);
@@ -119,8 +129,10 @@ class IndexStore {
119129
indexstore_store_dispose(obj);
120130
}
121131

122-
static IndexStoreRef create(StringRef path, std::string &error) {
123-
auto storeRef = std::make_shared<IndexStore>(path, error);
132+
static IndexStoreRef create(StringRef path,
133+
std::map<std::string, std::string, std::greater<std::string>> prefix_map,
134+
std::string &error) {
135+
auto storeRef = std::make_shared<IndexStore>(path, prefix_map, error);
124136
if (storeRef->isInvalid())
125137
return nullptr;
126138
return storeRef;

clang/include/indexstore/indexstore.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ typedef void *indexstore_t;
133133
INDEXSTORE_PUBLIC indexstore_t
134134
indexstore_store_create(const char *store_path, indexstore_error_t *error);
135135

136+
INDEXSTORE_PUBLIC indexstore_t
137+
indexstore_store_create_with_prefix_mapping(
138+
const char *store_path, const char **PrefixMappings,
139+
size_t NumMappings,indexstore_error_t *error);
140+
136141
INDEXSTORE_PUBLIC void
137142
indexstore_store_dispose(indexstore_t);
138143

clang/lib/Index/IndexUnitReader.cpp

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,18 @@ using namespace llvm;
2828

2929
namespace {
3030

31+
static std::string remapPath(std::map<llvm::StringRef, llvm::StringRef, std::greater<llvm::StringRef>>
32+
&PrefixMap, llvm::StringRef Path) {
33+
if (PrefixMap.empty())
34+
return Path.str();
35+
36+
SmallString<256> P = Path;
37+
for (const auto &Entry : PrefixMap)
38+
if (llvm::sys::path::replace_path_prefix(P, Entry.first, Entry.second))
39+
break;
40+
return P.str().str();
41+
}
42+
3143
typedef function_ref<bool(const IndexUnitReader::DependencyInfo &)> DependencyReceiver;
3244
typedef function_ref<bool(const IndexUnitReader::IncludeInfo &)> IncludeReceiver;
3345

@@ -43,14 +55,15 @@ class IndexUnitReaderImpl {
4355
bool IsSystemUnit;
4456
bool IsModuleUnit;
4557
bool IsDebugCompilation;
46-
StringRef WorkingDir;
47-
StringRef OutputFile;
48-
StringRef SysrootPath;
58+
SmallString<128> WorkingDir;
59+
SmallString<128> OutputFile;
60+
SmallString<128> SysrootPath;
4961
StringRef ModuleName;
5062
SmallString<128> MainFilePath;
5163
StringRef Target;
5264
std::vector<FileBitPath> Paths;
5365
StringRef PathsBuffer;
66+
std::map<llvm::StringRef, llvm::StringRef, std::greater<llvm::StringRef>> PrefixMap;
5467

5568
struct ModuleInfo {
5669
unsigned NameOffset;
@@ -60,15 +73,16 @@ class IndexUnitReaderImpl {
6073
StringRef ModuleNamesBuffer;
6174

6275
bool init(std::unique_ptr<MemoryBuffer> Buf, sys::TimePoint<> ModTime,
76+
std::map<llvm::StringRef, llvm::StringRef, std::greater<llvm::StringRef>> PrefixMap,
6377
std::string &Error);
6478

6579
StringRef getProviderIdentifier() const { return ProviderIdentifier; }
6680
StringRef getProviderVersion() const { return ProviderVersion; }
6781

6882
sys::TimePoint<> getModificationTime() const { return ModTime; }
69-
StringRef getWorkingDirectory() const { return WorkingDir; }
70-
StringRef getOutputFile() const { return OutputFile; }
71-
StringRef getSysrootPath() const { return SysrootPath; }
83+
StringRef getWorkingDirectory() const { return WorkingDir.str(); }
84+
StringRef getOutputFile() const { return OutputFile.str(); }
85+
StringRef getSysrootPath() const { return SysrootPath.str(); }
7286
StringRef getTarget() const { return Target; }
7387

7488
StringRef getModuleName() const { return ModuleName; }
@@ -88,6 +102,10 @@ class IndexUnitReaderImpl {
88102
return PathsBuffer.substr(Offset, Size);
89103
}
90104

105+
std::string getAndRemapPathFromBuffer(size_t Offset, size_t Size) {
106+
return remapPath(PrefixMap, getPathFromBuffer(Offset, Size));
107+
}
108+
91109
void constructFilePath(SmallVectorImpl<char> &Path, int PathIndex);
92110

93111
StringRef getModuleName(int ModuleIndex);
@@ -205,9 +223,9 @@ class IndexUnitBitstreamVisitor : public BitstreamVisitor<IndexUnitBitstreamVisi
205223
break;
206224
case UNIT_PATH_BUFFER:
207225
Reader.PathsBuffer = Blob;
208-
Reader.WorkingDir = Reader.getPathFromBuffer(WorkDirOffset, WorkDirSize);
209-
Reader.OutputFile = Reader.getPathFromBuffer(OutputFileOffset, OutputFileSize);
210-
Reader.SysrootPath = Reader.getPathFromBuffer(SysrootOffset, SysrootSize);
226+
Reader.WorkingDir = Reader.getAndRemapPathFromBuffer(WorkDirOffset, WorkDirSize);
227+
Reader.OutputFile = Reader.getAndRemapPathFromBuffer(OutputFileOffset, OutputFileSize);
228+
Reader.SysrootPath = Reader.getAndRemapPathFromBuffer(SysrootOffset, SysrootSize);
211229

212230
// now we can populate the main file's path
213231
Reader.constructFilePath(Reader.MainFilePath, MainPathIndex);
@@ -270,9 +288,12 @@ class IndexUnitBlockBitstreamVisitor : public BitstreamVisitor<IndexUnitBlockBit
270288
} // anonymous namespace
271289

272290
bool IndexUnitReaderImpl::init(std::unique_ptr<MemoryBuffer> Buf,
273-
sys::TimePoint<> ModTime, std::string &Error) {
291+
sys::TimePoint<> ModTime,
292+
std::map<llvm::StringRef, llvm::StringRef, std::greater<llvm::StringRef>> PrefixMap,
293+
std::string &Error) {
274294
this->ModTime = ModTime;
275295
this->MemBuf = std::move(Buf);
296+
this->PrefixMap = PrefixMap;
276297
llvm::BitstreamCursor Stream(*MemBuf);
277298

278299
if (Stream.AtEndOfStream()) {
@@ -374,6 +395,13 @@ void IndexUnitReaderImpl::constructFilePath(SmallVectorImpl<char> &PathBuf,
374395
sys::path::append(PathBuf,
375396
getPathFromBuffer(Path.Dir.Offset, Path.Dir.Size),
376397
getPathFromBuffer(Path.Filename.Offset, Path.Filename.Size));
398+
if (Path.PrefixKind == UNIT_PATH_PREFIX_NONE && !PrefixMap.empty()) {
399+
SmallString<256> PathStr;
400+
PathStr.assign(PathBuf);
401+
std::string Remapped = remapPath(PrefixMap, PathStr.str());
402+
PathBuf.clear();
403+
PathBuf.append(Remapped.begin(), Remapped.end());
404+
}
377405
}
378406

379407
StringRef IndexUnitReaderImpl::getModuleName(int ModuleIndex) {
@@ -391,15 +419,18 @@ StringRef IndexUnitReaderImpl::getModuleName(int ModuleIndex) {
391419
std::unique_ptr<IndexUnitReader>
392420
IndexUnitReader::createWithUnitFilename(StringRef UnitFilename,
393421
StringRef StorePath,
422+
std::map<llvm::StringRef, llvm::StringRef, std::greater<llvm::StringRef>> PrefixMap,
394423
std::string &Error) {
395424
SmallString<128> PathBuf = StorePath;
396425
appendUnitSubDir(PathBuf);
397426
sys::path::append(PathBuf, UnitFilename);
398-
return createWithFilePath(PathBuf.str(), Error);
427+
return createWithFilePath(PathBuf.str(), PrefixMap, Error);
399428
}
400429

401430
std::unique_ptr<IndexUnitReader>
402-
IndexUnitReader::createWithFilePath(StringRef FilePath, std::string &Error) {
431+
IndexUnitReader::createWithFilePath(StringRef FilePath,
432+
std::map<llvm::StringRef, llvm::StringRef, std::greater<llvm::StringRef>> PrefixMap,
433+
std::string &Error) {
403434
int FD;
404435
std::error_code EC = sys::fs::openFileForRead(FilePath, FD);
405436
if (EC) {
@@ -435,7 +466,7 @@ IndexUnitReader::createWithFilePath(StringRef FilePath, std::string &Error) {
435466

436467
std::unique_ptr<IndexUnitReaderImpl> Impl(new IndexUnitReaderImpl());
437468
bool Err = Impl->init(std::move(*ErrOrBuf), FileStat.getLastModificationTime(),
438-
Error);
469+
PrefixMap, Error);
439470
if (Err)
440471
return nullptr;
441472

0 commit comments

Comments
 (0)