Skip to content

Commit f570204

Browse files
committed
[CAS] Provide an API to canonicalize a CompilerInvocation
This patch adds a new function that canonicalizes the CompilerInvocation. An initial use case is to allow serialization of the invocation, where serializing a non canonical invocation might lead to cache poisoning.
1 parent 3e1acda commit f570204

File tree

5 files changed

+39
-12
lines changed

5 files changed

+39
-12
lines changed

clang/include/clang/Frontend/CompileJobCacheKey.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ llvm::Error printCompileJobCacheKey(llvm::cas::ObjectStore &CAS,
7979
const llvm::cas::CASID &Key,
8080
llvm::raw_ostream &OS);
8181

82+
void canonicalizeCASCompilerInvocation(const llvm::cas::ObjectStore &CAS,
83+
CompilerInvocation &CI);
84+
8285
} // namespace clang
8386

8487
#endif // LLVM_CLANG_FRONTEND_COMPILEJOBCACHEKEY_H

clang/include/clang/Frontend/CompilerInstance.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "clang/Basic/Diagnostic.h"
1414
#include "clang/Basic/SourceManager.h"
1515
#include "clang/Basic/TargetInfo.h"
16+
#include "clang/Frontend/CompileJobCacheKey.h"
1617
#include "clang/Frontend/CompilerInvocation.h"
1718
#include "clang/Frontend/PCHContainerOperations.h"
1819
#include "clang/Frontend/Utils.h"
@@ -213,8 +214,6 @@ class CompilerInstance : public ModuleLoader {
213214
/// Force an output buffer.
214215
std::unique_ptr<llvm::raw_pwrite_stream> OutputStream;
215216

216-
void createCASDatabases();
217-
218217
CompilerInstance(const CompilerInstance &) = delete;
219218
void operator=(const CompilerInstance &) = delete;
220219
public:
@@ -753,6 +752,15 @@ class CompilerInstance : public ModuleLoader {
753752
getInvocation().getModuleHash(getDiagnostics()));
754753
}
755754

755+
CompilerInvocation getCacheCanonicalInvocation() {
756+
if (!CAS)
757+
return *Invocation;
758+
759+
CompilerInvocation Copy(*Invocation);
760+
canonicalizeCASCompilerInvocation(*CAS, Copy);
761+
return Copy;
762+
}
763+
756764
/// Create the AST context.
757765
void createASTContext();
758766

@@ -994,6 +1002,10 @@ class CompilerInstance : public ModuleLoader {
9941002
StringRef Provider);
9951003

9961004
ModuleCache &getModuleCache() const { return *ModCache; }
1005+
1006+
std::pair<std::shared_ptr<llvm::cas::ObjectStore>,
1007+
std::shared_ptr<llvm::cas::ActionCache>>
1008+
createCASDatabases();
9971009
};
9981010

9991011
} // end namespace clang

clang/lib/Frontend/CompileJobCache.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ std::optional<int> CompileJobCache::initialize(CompilerInstance &Clang) {
296296
if (!CacheCompileJob)
297297
return std::nullopt;
298298

299-
std::tie(CAS, Cache) = Invocation.getCASOpts().getOrCreateDatabases(Diags);
299+
std::tie(CAS, Cache) = Clang.createCASDatabases();
300300
if (!CAS || !Cache)
301301
return 1; // Exit with error!
302302

clang/lib/Frontend/CompileJobCacheKey.cpp

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,7 @@ static llvm::cas::CASID createCompileJobCacheKeyForArgs(
6767
return llvm::cantFail(Builder.create(CAS)).getID();
6868
}
6969

70-
static std::optional<llvm::cas::CASID>
71-
createCompileJobCacheKeyImpl(ObjectStore &CAS, DiagnosticsEngine &Diags,
72-
CompilerInvocation CI) {
70+
static void canonicalizeForCacheKey(CompilerInvocation &CI) {
7371
FrontendOptions &FrontendOpts = CI.getFrontendOpts();
7472
DependencyOutputOptions &DepOpts = CI.getDependencyOutputOpts();
7573

@@ -136,7 +134,12 @@ createCompileJobCacheKeyImpl(ObjectStore &CAS, DiagnosticsEngine &Diags,
136134
// These are intended for caching introspection, they are not cached.
137135
return Remark.starts_with("compile-job-cache");
138136
});
137+
}
139138

139+
static std::optional<llvm::cas::CASID>
140+
createCompileJobCacheKeyImpl(ObjectStore &CAS, DiagnosticsEngine &Diags,
141+
CompilerInvocation CI) {
142+
canonicalizeForCacheKey(CI);
140143
// Generate a new command-line in case Invocation has been canonicalized.
141144
llvm::BumpPtrAllocator Alloc;
142145
llvm::StringSaver Saver(Alloc);
@@ -182,7 +185,7 @@ createCompileJobCacheKeyImpl(ObjectStore &CAS, DiagnosticsEngine &Diags,
182185
}
183186

184187
static CompileJobCachingOptions
185-
canonicalizeForCaching(llvm::cas::ObjectStore &CAS, DiagnosticsEngine &Diags,
188+
canonicalizeForCaching(const llvm::cas::ObjectStore &CAS,
186189
CompilerInvocation &Invocation) {
187190
CompileJobCachingOptions Opts;
188191
FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
@@ -220,6 +223,12 @@ canonicalizeForCaching(llvm::cas::ObjectStore &CAS, DiagnosticsEngine &Diags,
220223
return Opts;
221224
}
222225

226+
void clang::canonicalizeCASCompilerInvocation(const ObjectStore &CAS,
227+
CompilerInvocation &CI) {
228+
(void)canonicalizeForCaching(CAS, CI);
229+
canonicalizeForCacheKey(CI);
230+
}
231+
223232
std::optional<std::pair<llvm::cas::CASID, llvm::cas::CASID>>
224233
clang::canonicalizeAndCreateCacheKeys(ObjectStore &CAS,
225234
ActionCache &Cache,
@@ -231,7 +240,7 @@ clang::canonicalizeAndCreateCacheKeys(ObjectStore &CAS,
231240
CASOptions CASOpts(CI.getCASOpts());
232241
CASOpts.freezeConfig(Diags);
233242

234-
Opts = canonicalizeForCaching(CAS, Diags, CI);
243+
Opts = canonicalizeForCaching(CAS, CI);
235244
auto CacheKey = createCompileJobCacheKeyImpl(CAS, Diags, CI);
236245
if (!CacheKey)
237246
return std::nullopt;
@@ -265,7 +274,7 @@ clang::canonicalizeAndCreateCacheKeys(ObjectStore &CAS,
265274
CI.getFrontendOpts().CASInputFileCacheKey.clear();
266275

267276
CompilerInvocation CICopy = CI;
268-
(void)canonicalizeForCaching(CAS, Diags, CICopy);
277+
(void)canonicalizeForCaching(CAS, CICopy);
269278
auto CanonicalCacheKey = createCompileJobCacheKeyImpl(CAS, Diags, CICopy);
270279
if (!CanonicalCacheKey)
271280
return std::nullopt;
@@ -277,15 +286,15 @@ std::optional<llvm::cas::CASID>
277286
clang::createCompileJobCacheKey(ObjectStore &CAS, DiagnosticsEngine &Diags,
278287
const CompilerInvocation &OriginalCI) {
279288
CompilerInvocation CI(OriginalCI);
280-
(void)canonicalizeForCaching(CAS, Diags, CI);
289+
(void)canonicalizeForCaching(CAS, CI);
281290
return createCompileJobCacheKeyImpl(CAS, Diags, std::move(CI));
282291
}
283292

284293
std::optional<llvm::cas::CASID>
285294
clang::createCompileJobCacheKey(ObjectStore &CAS, DiagnosticsEngine &Diags,
286295
const CowCompilerInvocation &OriginalCI) {
287296
CompilerInvocation CI(OriginalCI);
288-
(void)canonicalizeForCaching(CAS, Diags, CI);
297+
(void)canonicalizeForCaching(CAS, CI);
289298
return createCompileJobCacheKeyImpl(CAS, Diags, std::move(CI));
290299
}
291300

clang/lib/Frontend/CompilerInstance.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -957,13 +957,16 @@ llvm::vfs::OutputBackend &CompilerInstance::getOrCreateOutputBackend() {
957957
return getOutputBackend();
958958
}
959959

960-
void CompilerInstance::createCASDatabases() {
960+
std::pair<std::shared_ptr<llvm::cas::ObjectStore>,
961+
std::shared_ptr<llvm::cas::ActionCache>>
962+
CompilerInstance::createCASDatabases() {
961963
// Create a new CAS databases from the CompilerInvocation. Future calls to
962964
// createFileManager() will use the same CAS.
963965
std::tie(CAS, ActionCache) =
964966
getInvocation().getCASOpts().getOrCreateDatabases(
965967
getDiagnostics(),
966968
/*CreateEmptyCASOnFailure=*/true);
969+
return {CAS, ActionCache};
967970
}
968971

969972
llvm::cas::ObjectStore &CompilerInstance::getOrCreateObjectStore() {

0 commit comments

Comments
 (0)