Skip to content

Commit cd5b4a9

Browse files
authored
Merge pull request #7143 from benlangmuir/cp-cas
[stable/20221013] Cherry-pick CAS changes
2 parents b926896 + 1b5110b commit cd5b4a9

File tree

97 files changed

+2950
-1248
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+2950
-1248
lines changed

clang-tools-extra/clangd/Compiler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ void disableUnsupportedOptions(CompilerInvocation &CI) {
7373
// Always default to raw container format as clangd doesn't registry any other
7474
// and clang dies when faced with unknown formats.
7575
CI.getHeaderSearchOpts().ModuleFormat =
76-
PCHContainerOperations().getRawReader().getFormat().str();
76+
PCHContainerOperations().getRawReader().getFormats().front().str();
7777

7878
CI.getFrontendOpts().Plugins.clear();
7979
CI.getFrontendOpts().AddPluginActions.clear();

clang/include/clang/Basic/DiagnosticIDs.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ class DiagnosticMapping {
160160
Result.Severity = Bits & 0x7;
161161
return Result;
162162
}
163+
164+
bool operator==(DiagnosticMapping Other) const {
165+
return serialize() == Other.serialize();
166+
}
163167
};
164168

165169
/// Used for handling and querying diagnostic IDs.
@@ -209,6 +213,9 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
209213
/// default.
210214
static bool isDefaultMappingAsError(unsigned DiagID);
211215

216+
/// Get the default mapping for this diagnostic.
217+
static DiagnosticMapping getDefaultMapping(unsigned DiagID);
218+
212219
/// Determine whether the given built-in diagnostic ID is a Note.
213220
static bool isBuiltinNote(unsigned DiagID);
214221

clang/include/clang/Basic/DiagnosticLexKinds.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,8 @@ def warn_pp_date_time : Warning<
764764

765765
def warn_pp_encounter_nonreproducible: Warning<
766766
"encountered non-reproducible token, caching will be skipped">,
767-
InGroup<DiagGroup<"reproducible-caching">>, DefaultIgnore;
767+
InGroup<DiagGroup<"reproducible-caching">>,
768+
DefaultWarnNoWerror, ShowInSystemHeader, ShowInSystemMacro;
768769
def err_pp_encounter_nonreproducible: Error<
769770
"encountered non-reproducible token, caching failed">;
770771

clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class ObjectFilePCHContainerWriter : public PCHContainerWriter {
3232
/// A PCHContainerReader implementation that uses LLVM to
3333
/// wraps Clang modules inside a COFF, ELF, or Mach-O container.
3434
class ObjectFilePCHContainerReader : public PCHContainerReader {
35-
StringRef getFormat() const override { return "obj"; }
35+
ArrayRef<StringRef> getFormats() const override;
3636

3737
/// Returns the serialized AST inside the PCH container Buffer.
3838
StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const override;

clang/include/clang/Driver/Options.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6650,6 +6650,11 @@ defm cache_disable_replay : BoolFOption<"cache-disable-replay",
66506650
PosFlag<SetTrue, [], "Disable replaying a cached compile job">,
66516651
NegFlag<SetFalse>>;
66526652

6653+
defm modules_skip_diagnostic_options : BoolFOption<"modules-skip-diagnostic-options",
6654+
HeaderSearchOpts<"ModulesSkipDiagnosticOptions">, DefaultFalse,
6655+
PosFlag<SetTrue, [], "Disable writing diagnostic options">,
6656+
NegFlag<SetFalse>>;
6657+
66536658
def fcompilation_caching_service_path : Separate<["-"], "fcompilation-caching-service-path">,
66546659
Group<f_Group>, MetaVarName<"<pathname>">,
66556660
HelpText<"Specify the socket path for connecting to a remote caching service">,
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
//===- CompileJobCache.h ----------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_FRONTEND_COMPILEJOBCACHE_H
10+
#define LLVM_CLANG_FRONTEND_COMPILEJOBCACHE_H
11+
12+
#include "clang/Frontend/CompileJobCacheResult.h"
13+
14+
namespace clang {
15+
16+
class CompilerInstance;
17+
class DiagnosticsEngine;
18+
19+
// Manage caching and replay of compile jobs.
20+
//
21+
// The high-level model is:
22+
//
23+
// 1. Extract options from the CompilerInvocation:
24+
// - that can be simulated and
25+
// - that don't affect the compile job's result.
26+
// 2. Canonicalize the options extracted in (1).
27+
// 3. Compute the result of the compile job using the canonicalized
28+
// CompilerInvocation, with hooks installed to redirect outputs and
29+
// enable live-streaming of a running compile job to stdout or stderr.
30+
// - Compute a cache key.
31+
// - Check the cache, and run the compile job if there's a cache miss.
32+
// - Store the result of the compile job in the cache.
33+
// 4. Replay the compile job, using the options extracted in (1).
34+
//
35+
// An example (albeit not yet implemented) is handling options controlling
36+
// output of diagnostics. The CompilerInvocation can be canonicalized to
37+
// serialize the diagnostics to a virtual path (<output>.diag or something).
38+
//
39+
// - On a cache miss, the compile job runs, and the diagnostics are
40+
// serialized and stored in the cache per the canonicalized options
41+
// from (2).
42+
// - Either way, the diagnostics are replayed according to the options
43+
// extracted from (1) during (4).
44+
//
45+
// The above will produce the correct output for diagnostics, but the experience
46+
// will be degraded in the common command-line case (emitting to stderr)
47+
// because the diagnostics will not be streamed live. This can be improved:
48+
//
49+
// - Change (3) to accept a hook: a DiagnosticsConsumer that diagnostics
50+
// are mirrored to (in addition to canonicalized options from (2)).
51+
// - If diagnostics would be live-streamed, send in a diagnostics consumer
52+
// that matches (1). Otherwise, send in an IgnoringDiagnosticsConsumer.
53+
// - In step (4), only skip replaying the diagnostics if they were already
54+
// handled.
55+
class CompileJobCache {
56+
public:
57+
CompileJobCache();
58+
~CompileJobCache();
59+
60+
using OutputKind = clang::cas::CompileJobCacheResult::OutputKind;
61+
62+
StringRef getPathForOutputKind(OutputKind Kind);
63+
64+
/// Canonicalize \p Clang.
65+
///
66+
/// \returns status if should exit immediately, otherwise None.
67+
///
68+
/// TODO: Refactor \a cc1_main() so that instead this canonicalizes the
69+
/// CompilerInvocation before Clang gets access to command-line arguments, to
70+
/// control what might leak.
71+
std::optional<int> initialize(CompilerInstance &Clang);
72+
73+
/// Try looking up a cached result and replaying it.
74+
///
75+
/// \returns status if should exit immediately, otherwise None.
76+
std::optional<int> tryReplayCachedResult(CompilerInstance &Clang);
77+
78+
/// Finish writing outputs from a computed result, after a cache miss.
79+
///
80+
/// \returns true if finished successfully.
81+
bool finishComputedResult(CompilerInstance &Clang, bool Success);
82+
83+
class CachingOutputs;
84+
85+
private:
86+
int reportCachingBackendError(DiagnosticsEngine &Diag, llvm::Error &&E);
87+
88+
bool CacheCompileJob = false;
89+
bool DisableCachedCompileJobReplay = false;
90+
91+
std::shared_ptr<llvm::cas::ObjectStore> CAS;
92+
std::shared_ptr<llvm::cas::ActionCache> Cache;
93+
llvm::Optional<llvm::cas::CASID> ResultCacheKey;
94+
95+
std::unique_ptr<CachingOutputs> CacheBackend;
96+
};
97+
98+
} // namespace clang
99+
100+
#endif // LLVM_CLANG_FRONTEND_COMPILEJOBCACHE_H

clang/include/clang/Frontend/CompilerInstance.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "llvm/CAS/CASOutputBackend.h"
2626
#include "llvm/Support/BuryPointer.h"
2727
#include "llvm/Support/FileSystem.h"
28+
#include "llvm/Support/PrefixMapper.h"
2829
#include "llvm/Support/VirtualOutputBackend.h"
2930
#include <cassert>
3031
#include <list>
@@ -94,6 +95,9 @@ class CompilerInstance : public ModuleLoader {
9495
/// The \c ActionCache key for this compilation, if caching is enabled.
9596
Optional<cas::CASID> CompileJobCacheKey;
9697

98+
/// The prefix mapper; empty by default.
99+
llvm::PrefixMapper PrefixMapper;
100+
97101
/// The file manager.
98102
IntrusiveRefCntPtr<FileManager> FileMgr;
99103

@@ -362,6 +366,10 @@ class CompilerInstance : public ModuleLoader {
362366
}
363367
bool isSourceNonReproducible() const;
364368

369+
llvm::PrefixMapper &getPrefixMapper() { return PrefixMapper; }
370+
371+
void setPrefixMapper(llvm::PrefixMapper PM) { PrefixMapper = std::move(PM); }
372+
365373
/// }
366374
/// @name Diagnostics Engine
367375
/// {

clang/include/clang/Frontend/FrontendOptions.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,10 @@ class FrontendOptions {
375375
/// caching of compilation outputs. This is used for testing purposes.
376376
unsigned DisableCachedCompileJobReplay : 1;
377377

378+
/// Keep the diagnostic client open for receiving diagnostics after the source
379+
/// files have been processed.
380+
unsigned MayEmitDiagnosticsAfterProcessingSourceFiles : 1;
381+
378382
/// Output (and read) PCM files regardless of compiler errors.
379383
unsigned AllowPCMWithCompilerErrors : 1;
380384

@@ -570,7 +574,9 @@ class FrontendOptions {
570574
ASTDumpLookups(false), BuildingImplicitModule(false),
571575
BuildingImplicitModuleUsesLock(true), ModulesEmbedAllFiles(false),
572576
IncludeTimestamps(true), UseTemporary(true), CacheCompileJob(false),
573-
DisableCachedCompileJobReplay(false), AllowPCMWithCompilerErrors(false),
577+
DisableCachedCompileJobReplay(false),
578+
MayEmitDiagnosticsAfterProcessingSourceFiles(false),
579+
AllowPCMWithCompilerErrors(false),
574580
ModulesShareFileManager(true), TimeTraceGranularity(500) {}
575581

576582
/// getInputKindForExtension - Return the appropriate input kind for a file

clang/include/clang/Lex/DependencyDirectivesScanner.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ enum DirectiveKind : uint8_t {
6868
pp_pragma_push_macro,
6969
pp_pragma_pop_macro,
7070
pp_pragma_include_alias,
71+
pp_pragma_system_header,
7172
pp_include_next,
7273
pp_if,
7374
pp_ifdef,

clang/include/clang/Lex/HeaderSearch.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,9 +653,13 @@ class HeaderSearch {
653653

654654
/// Retrieve all the modules corresponding to the given file.
655655
///
656+
/// \param AllowCreation Whether to allow inference of a new submodule, or to
657+
/// only return existing known modules.
658+
///
656659
/// \ref findModuleForHeader should typically be used instead of this.
657660
ArrayRef<ModuleMap::KnownHeader>
658-
findAllModulesForHeader(const FileEntry *File) const;
661+
findAllModulesForHeader(const FileEntry *File,
662+
bool AllowCreation = true) const;
659663

660664
/// Read the contents of the given module map file.
661665
///

clang/include/clang/Lex/HeaderSearchOptions.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,9 @@ class HeaderSearchOptions {
216216

217217
unsigned ModulesValidateDiagnosticOptions : 1;
218218

219+
/// Whether to entirely skip writing diagnostic options.
220+
unsigned ModulesSkipDiagnosticOptions : 1;
221+
219222
unsigned ModulesHashContent : 1;
220223

221224
/// Whether we should include all things that could impact the module in the
@@ -234,7 +237,8 @@ class HeaderSearchOptions {
234237
ModulesValidateOncePerBuildSession(false),
235238
ModulesValidateSystemHeaders(false),
236239
ValidateASTInputFilesContent(false), UseDebugInfo(false),
237-
ModulesValidateDiagnosticOptions(true), ModulesHashContent(false),
240+
ModulesValidateDiagnosticOptions(true),
241+
ModulesSkipDiagnosticOptions(false), ModulesHashContent(false),
238242
ModulesStrictContextHash(false) {}
239243

240244
/// AddPath - Add the \p Path path to the specified \p Group list.

clang/include/clang/Lex/ModuleMap.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,9 +458,13 @@ class ModuleMap {
458458
/// and does not consult the external source. (Those checks are the
459459
/// responsibility of \ref HeaderSearch.)
460460
///
461+
/// \param AllowCreation Whether to allow inference of a new submodule, or to
462+
/// only return existing known modules.
463+
///
461464
/// Typically, \ref findModuleForHeader should be used instead, as it picks
462465
/// the preferred module for the header.
463-
ArrayRef<KnownHeader> findAllModulesForHeader(const FileEntry *File);
466+
ArrayRef<KnownHeader> findAllModulesForHeader(const FileEntry *File,
467+
bool AllowCreation = true);
464468

465469
/// Like \ref findAllModulesForHeader, but do not attempt to infer module
466470
/// ownership from umbrella headers if we've not already done so.

clang/include/clang/Lex/Pragma.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,13 @@ class PragmaNamespace : public PragmaHandler {
123123
PragmaNamespace *getIfNamespace() override { return this; }
124124
};
125125

126+
/// Destringize a \c _Pragma("") string according to C11 6.10.9.1:
127+
/// "The string literal is destringized by deleting any encoding prefix,
128+
/// deleting the leading and trailing double-quotes, replacing each escape
129+
/// sequence \" by a double-quote, and replacing each escape sequence \\ by a
130+
/// single backslash."
131+
void prepare_PragmaString(SmallVectorImpl<char> &StrVal);
132+
126133
} // namespace clang
127134

128135
#endif // LLVM_CLANG_LEX_PRAGMA_H

clang/include/clang/Serialization/ASTReader.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -961,8 +961,14 @@ class ASTReader
961961

962962
private:
963963
/// A list of modules that were imported by precompiled headers or
964-
/// any other non-module AST file.
965-
SmallVector<ImportedSubmodule, 2> ImportedModules;
964+
/// any other non-module AST file and have not yet been made visible. If a
965+
/// module is made visible in the ASTReader, it will be transfered to
966+
/// \c PendingImportedModulesSema.
967+
SmallVector<ImportedSubmodule, 2> PendingImportedModules;
968+
969+
/// A list of modules that were imported by precompiled headers or
970+
/// any other non-module AST file and have not yet been made visible for Sema.
971+
SmallVector<ImportedSubmodule, 2> PendingImportedModulesSema;
966972
//@}
967973

968974
/// The system include root to be used when loading the

clang/include/clang/Serialization/PCHContainerOperations.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class PCHContainerReader {
5656
public:
5757
virtual ~PCHContainerReader() = 0;
5858
/// Equivalent to the format passed to -fmodule-format=
59-
virtual llvm::StringRef getFormat() const = 0;
59+
virtual llvm::ArrayRef<llvm::StringRef> getFormats() const = 0;
6060

6161
/// Returns the serialized AST inside the PCH container Buffer.
6262
virtual llvm::StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const = 0;
@@ -78,16 +78,17 @@ class RawPCHContainerWriter : public PCHContainerWriter {
7878

7979
/// Implements read operations for a raw pass-through PCH container.
8080
class RawPCHContainerReader : public PCHContainerReader {
81-
llvm::StringRef getFormat() const override { return "raw"; }
82-
81+
llvm::ArrayRef<llvm::StringRef> getFormats() const override;
8382
/// Simply returns the buffer contained in Buffer.
8483
llvm::StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const override;
8584
};
8685

8786
/// A registry of PCHContainerWriter and -Reader objects for different formats.
8887
class PCHContainerOperations {
8988
llvm::StringMap<std::unique_ptr<PCHContainerWriter>> Writers;
90-
llvm::StringMap<std::unique_ptr<PCHContainerReader>> Readers;
89+
llvm::StringMap<PCHContainerReader *> Readers;
90+
llvm::SmallVector<std::unique_ptr<PCHContainerReader>> OwnedReaders;
91+
9192
public:
9293
/// Automatically registers a RawPCHContainerWriter and
9394
/// RawPCHContainerReader.
@@ -96,13 +97,17 @@ class PCHContainerOperations {
9697
Writers[Writer->getFormat()] = std::move(Writer);
9798
}
9899
void registerReader(std::unique_ptr<PCHContainerReader> Reader) {
99-
Readers[Reader->getFormat()] = std::move(Reader);
100+
assert(!Reader->getFormats().empty() &&
101+
"PCHContainerReader must handle >=1 format");
102+
for (llvm::StringRef Fmt : Reader->getFormats())
103+
Readers[Fmt] = Reader.get();
104+
OwnedReaders.push_back(std::move(Reader));
100105
}
101106
const PCHContainerWriter *getWriterOrNull(llvm::StringRef Format) {
102107
return Writers[Format].get();
103108
}
104109
const PCHContainerReader *getReaderOrNull(llvm::StringRef Format) {
105-
return Readers[Format].get();
110+
return Readers[Format];
106111
}
107112
const PCHContainerReader &getRawReader() {
108113
return *getReaderOrNull("raw");

clang/lib/Basic/Diagnostic.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,18 @@ void DiagnosticsEngine::ReportDelayed() {
184184
Report(ID) << DelayedDiagArg1 << DelayedDiagArg2 << DelayedDiagArg3;
185185
}
186186

187+
DiagnosticMapping &
188+
DiagnosticsEngine::DiagState::getOrAddMapping(diag::kind Diag) {
189+
std::pair<iterator, bool> Result =
190+
DiagMap.insert(std::make_pair(Diag, DiagnosticMapping()));
191+
192+
// Initialize the entry if we added it.
193+
if (Result.second)
194+
Result.first->second = DiagnosticIDs::getDefaultMapping(Diag);
195+
196+
return Result.first->second;
197+
}
198+
187199
void DiagnosticsEngine::DiagStateMap::appendFirst(DiagState *State) {
188200
assert(Files.empty() && "not first");
189201
FirstDiagState = CurDiagState = State;

0 commit comments

Comments
 (0)