Skip to content

Commit 05f55cf

Browse files
authored
🍒[clang][DependencyScanning] Implementation of CompilerInstanceWithContext to Improve By-Name Queries (llvm#11821)
This PR cherry-picks llvm#164345 to `stable/21.x`, and fixes two bugs introduced when it was merged into `next`. rdar://136303612
1 parent 18ffb87 commit 05f55cf

22 files changed

+654
-128
lines changed

‎clang/include/clang/Frontend/CompilerInstance.h‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,12 @@ class CompilerInstance : public ModuleLoader {
10161016
DependencyCollectors.push_back(std::move(Listener));
10171017
}
10181018

1019+
void clearDependencyCollectors() { DependencyCollectors.clear(); }
1020+
1021+
std::vector<std::shared_ptr<DependencyCollector>> &getDependencyCollectors() {
1022+
return DependencyCollectors;
1023+
}
1024+
10191025
void setExternalSemaSource(IntrusiveRefCntPtr<ExternalSemaSource> ESS);
10201026

10211027
/// Adds a module to the \c InMemoryModuleCache at \p Path by retrieving the

‎clang/include/clang/Frontend/FrontendActions.h‎

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -319,16 +319,6 @@ class PrintPreprocessedAction : public PreprocessorFrontendAction {
319319

320320
bool hasPCHSupport() const override { return true; }
321321
};
322-
323-
class GetDependenciesByModuleNameAction : public PreprocessOnlyAction {
324-
StringRef ModuleName;
325-
void ExecuteAction() override;
326-
327-
public:
328-
GetDependenciesByModuleNameAction(StringRef ModuleName)
329-
: ModuleName(ModuleName) {}
330-
};
331-
332322
} // end namespace clang
333323

334324
#endif

‎clang/include/clang/Lex/Preprocessor.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,6 +1337,7 @@ class Preprocessor {
13371337
std::move(Callbacks));
13381338
Callbacks = std::move(C);
13391339
}
1340+
void removePPCallbacks() { Callbacks.reset(); }
13401341
/// \}
13411342

13421343
PPCachedActions *getPPCachedActions() const { return CachedActions.get(); }

‎clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,11 +201,52 @@ class DependencyScanningTool {
201201
/// Given a compilation context specified via the Clang driver command-line,
202202
/// gather modular dependencies of module with the given name, and return the
203203
/// information needed for explicit build.
204+
/// TODO: this method should be removed as soon as Swift and our C-APIs adopt
205+
/// CompilerInstanceWithContext. We are keeping it here so that it is easier
206+
/// to coordinate with Swift and C-API changes.
204207
llvm::Expected<TranslationUnitDeps> getModuleDependencies(
205208
StringRef ModuleName, const std::vector<std::string> &CommandLine,
206209
StringRef CWD, const llvm::DenseSet<ModuleID> &AlreadySeen,
207210
LookupModuleOutputCallback LookupModuleOutput);
208211

212+
/// The following three methods provide a new interface to perform
213+
/// by name dependency scan. The new interface's intention is to improve
214+
/// dependency scanning performance when a sequence of name is looked up
215+
/// with the same current working directory and the command line.
216+
217+
/// @brief Initializing the context and the compiler instance.
218+
/// This method must be called before calling
219+
/// computeDependenciesByNameWithContext.
220+
/// @param CWD The current working directory used during the scan.
221+
/// @param CommandLine The commandline used for the scan.
222+
/// @return Error if the initializaiton fails.
223+
llvm::Error initializeCompilerInstanceWithContext(
224+
StringRef CWD, const std::vector<std::string> &CommandLine);
225+
226+
/// @brief Computes the dependeny for the module named ModuleName.
227+
/// @param ModuleName The name of the module for which this method computes
228+
///. dependencies.
229+
/// @param AlreadySeen This stores modules which have previously been
230+
/// reported. Use the same instance for all calls to this
231+
/// function for a single \c DependencyScanningTool in a
232+
/// single build. Note that this parameter is not part of
233+
/// the context because it can be shared across different
234+
/// worker threads and each worker thread may update it.
235+
/// @param LookupModuleOutput This function is called to fill in
236+
/// "-fmodule-file=", "-o" and other output
237+
/// arguments for dependencies.
238+
/// @return An instance of \c TranslationUnitDeps if the scan is successful.
239+
/// Otherwise it returns an error.
240+
llvm::Expected<TranslationUnitDeps> computeDependenciesByNameWithContext(
241+
StringRef ModuleName, const llvm::DenseSet<ModuleID> &AlreadySeen,
242+
LookupModuleOutputCallback LookupModuleOutput);
243+
244+
/// @brief This method finializes the compiler instance. It finalizes the
245+
/// diagnostics and deletes the compiler instance. Call this method
246+
/// once all names for a same commandline are scanned.
247+
/// @return Error if an error occured during finalization.
248+
llvm::Error finalizeCompilerInstanceWithContext();
249+
209250
llvm::vfs::FileSystem &getWorkerVFS() const { return Worker.getVFS(); }
210251

211252
ScanningOutputFormat getScanningFormat() const {

‎clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h‎

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ using CachingOnDiskFileSystemPtr =
3333
llvm::IntrusiveRefCntPtr<llvm::cas::CachingOnDiskFileSystem>;
3434

3535
class DependencyScanningWorkerFilesystem;
36+
class CompilerInstanceWithContext;
3637

3738
/// A command-line tool invocation that is part of building a TU.
3839
///
@@ -130,6 +131,8 @@ class DependencyScanningWorker {
130131
DependencyScanningWorker(DependencyScanningService &Service,
131132
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS);
132133

134+
~DependencyScanningWorker();
135+
133136
/// Run the dependency scanning tool for a given clang driver command-line,
134137
/// and report the discovered dependencies to the provided consumer. If
135138
/// TUBuffer is not nullopt, it is used as TU input for the dependency
@@ -144,18 +147,6 @@ class DependencyScanningWorker {
144147
DiagnosticConsumer &DiagConsumer,
145148
std::optional<llvm::MemoryBufferRef> TUBuffer = std::nullopt);
146149

147-
/// Run the dependency scanning tool for a given clang driver command-line
148-
/// for a specific module.
149-
///
150-
/// \returns false if clang errors occurred (with diagnostics reported to
151-
/// \c DiagConsumer), true otherwise.
152-
bool computeDependencies(StringRef WorkingDirectory,
153-
const std::vector<std::string> &CommandLine,
154-
DependencyConsumer &DepConsumer,
155-
DependencyActionController &Controller,
156-
DiagnosticConsumer &DiagConsumer,
157-
StringRef ModuleName);
158-
159150
/// Run the dependency scanning tool for a given clang driver command-line
160151
/// for a specific translation unit via file system or memory buffer.
161152
///
@@ -166,16 +157,46 @@ class DependencyScanningWorker {
166157
DependencyConsumer &Consumer, DependencyActionController &Controller,
167158
std::optional<llvm::MemoryBufferRef> TUBuffer = std::nullopt);
168159

169-
/// Run the dependency scanning tool for a given clang driver command-line
170-
/// for a specific module.
171-
///
172-
/// \returns A \c StringError with the diagnostic output if clang errors
173-
/// occurred, success otherwise.
174-
llvm::Error computeDependencies(StringRef WorkingDirectory,
175-
const std::vector<std::string> &CommandLine,
176-
DependencyConsumer &Consumer,
177-
DependencyActionController &Controller,
178-
StringRef ModuleName);
160+
/// The three method below implements a new interface for by name
161+
/// dependency scanning. They together enable the dependency scanning worker
162+
/// to more effectively perform scanning for a sequence of modules
163+
/// by name when the CWD and CommandLine do not change across the queries.
164+
165+
/// @brief Initializing the context and the compiler instance.
166+
/// @param CWD The current working directory used during the scan.
167+
/// @param CommandLine The commandline used for the scan.
168+
/// @return Error if the initializaiton fails.
169+
llvm::Error initializeCompilerInstanceWithContextOrError(
170+
StringRef CWD, const std::vector<std::string> &CommandLine);
171+
172+
/// @brief Performaces dependency scanning for the module whose name is
173+
/// specified.
174+
/// @param ModuleName The name of the module whose dependency will be
175+
/// scanned.
176+
/// @param Consumer The dependency consumer that stores the results.
177+
/// @param Controller The controller for the dependency scanning action.
178+
/// @return Error if the scanner incurs errors.
179+
llvm::Error computeDependenciesByNameWithContextOrError(
180+
StringRef ModuleName, DependencyConsumer &Consumer,
181+
DependencyActionController &Controller);
182+
183+
/// @brief Finalizes the diagnostics engine and deletes the compiler instance.
184+
/// @return Error if errors occur during finalization.
185+
llvm::Error finalizeCompilerInstanceWithContextOrError();
186+
187+
/// The three methods below provides the same functionality as the
188+
/// three methods above. Instead of returning `llvm::Error`s, these
189+
/// three methods return a flag to indicate if the call is successful.
190+
/// The initialization function asks the client for a DiagnosticsConsumer
191+
/// that it direct the diagnostics to.
192+
bool initializeCompilerInstanceWithContext(
193+
StringRef CWD, const std::vector<std::string> &CommandLine,
194+
DiagnosticConsumer *DC = nullptr);
195+
bool
196+
computeDependenciesByNameWithContext(StringRef ModuleName,
197+
DependencyConsumer &Consumer,
198+
DependencyActionController &Controller);
199+
bool finalizeCompilerInstance();
179200

180201
/// Scan from a compiler invocation.
181202
/// If \p DiagGenerationAsCompilation is true it will generate error
@@ -221,14 +242,16 @@ class DependencyScanningWorker {
221242
CASOptions CASOpts;
222243
std::shared_ptr<cas::ObjectStore> CAS;
223244

245+
friend CompilerInstanceWithContext;
246+
std::unique_ptr<CompilerInstanceWithContext> CIWithContext;
247+
224248
/// Private helper functions.
225249
bool scanDependencies(StringRef WorkingDirectory,
226250
const std::vector<std::string> &CommandLine,
227251
DependencyConsumer &Consumer,
228252
DependencyActionController &Controller,
229253
DiagnosticConsumer &DC,
230-
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
231-
std::optional<StringRef> ModuleName);
254+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS);
232255
};
233256

234257
} // end namespace dependencies

‎clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,8 @@ class ModuleDepCollector final : public DependencyCollector {
308308
void attachToPreprocessor(Preprocessor &PP) override;
309309
void attachToASTReader(ASTReader &R) override;
310310

311+
PPCallbacks *getPPCallbacks() { return CollectorPPPtr; }
312+
311313
/// Apply any changes implied by the discovered dependencies to the given
312314
/// invocation, (e.g. disable implicit modules, add explicit module paths).
313315
void applyDiscoveredDependencies(CompilerInvocation &CI);
@@ -359,6 +361,11 @@ class ModuleDepCollector final : public DependencyCollector {
359361
std::optional<P1689ModuleInfo> ProvidedStdCXXModule;
360362
std::vector<P1689ModuleInfo> RequiredStdCXXModules;
361363

364+
/// A pointer to the preprocessor callback so we can invoke it directly
365+
/// if needed. The callback is created and added to a Preprocessor instance by
366+
/// attachToPreprocessor and the Preprocessor instance owns it.
367+
ModuleDepCollectorPP *CollectorPPPtr = nullptr;
368+
362369
/// Checks whether the module is known as being prebuilt.
363370
bool isPrebuiltModule(const Module *M);
364371

‎clang/lib/Frontend/FrontendActions.cpp‎

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,18 +1228,3 @@ void PrintDependencyDirectivesSourceMinimizerAction::ExecuteAction() {
12281228
printDependencyDirectivesAsSource(FromFile.getBuffer(), Directives,
12291229
llvm::outs());
12301230
}
1231-
1232-
void GetDependenciesByModuleNameAction::ExecuteAction() {
1233-
CompilerInstance &CI = getCompilerInstance();
1234-
Preprocessor &PP = CI.getPreprocessor();
1235-
SourceManager &SM = PP.getSourceManager();
1236-
FileID MainFileID = SM.getMainFileID();
1237-
PP.EnterSourceFile(MainFileID, nullptr, SourceLocation());
1238-
SourceLocation FileStart = SM.getLocForStartOfFile(MainFileID);
1239-
SmallVector<IdentifierLoc, 2> Path;
1240-
IdentifierInfo *ModuleID = PP.getIdentifierInfo(ModuleName);
1241-
Path.emplace_back(FileStart, ModuleID);
1242-
auto ModResult = CI.loadModule(FileStart, Path, Module::Hidden, false);
1243-
PPCallbacks *CB = PP.getPPCallbacks();
1244-
CB->moduleImport(SourceLocation(), Path, ModResult);
1245-
}

0 commit comments

Comments
 (0)