================
@@ -704,3 +703,165 @@ bool DependencyScanningAction::runInvocation(
return Result;
}
+
+const std::string CompilerInstanceWithContext::FakeFileBuffer =
+ std::string(MAX_NUM_NAMES, ' ');
+
+llvm::Error CompilerInstanceWithContext::initialize() {
+ std::tie(OverlayFS, CommandLine) = initVFSForByNameScanning(
+ Worker.BaseFS, CommandLine, CWD, "ScanningByName");
+
+ DiagPrinterWithOS =
+ std::make_unique<TextDiagnosticsPrinterWithOutput>(CommandLine);
+ DiagEngineWithCmdAndOpts = std::make_unique<DignosticsEngineWithDiagOpts>(
+ CommandLine, OverlayFS, DiagPrinterWithOS->DiagPrinter);
+
+ std::tie(Driver, Compilation) = buildCompilation(
+ CommandLine, *DiagEngineWithCmdAndOpts->DiagEngine, OverlayFS, Alloc);
+
+ if (!Compilation) {
+ return llvm::make_error<llvm::StringError>("Failed to build compilation",
+ llvm::inconvertibleErrorCode());
+ }
+
+ assert(Compilation->getJobs().size() &&
+ "Must have a job list of non-zero size");
+ const driver::Command &Command = *(Compilation->getJobs().begin());
+ const auto &CommandArgs = Command.getArguments();
+ size_t ArgSize = CommandArgs.size();
+ assert(ArgSize >= 1 && "Cannot have a command with 0 args");
+ const char *FirstArg = CommandArgs[0];
+ if (StringRef(FirstArg) != "-cc1")
+ return llvm::make_error<llvm::StringError>(
+ "Incorrect compilation command, missing cc1",
+ llvm::inconvertibleErrorCode());
+ OriginalInvocation = std::make_unique<CompilerInvocation>();
+
+ if (!CompilerInvocation::CreateFromArgs(
+ *OriginalInvocation, Command.getArguments(),
+ *DiagEngineWithCmdAndOpts->DiagEngine, Command.getExecutable())) {
+ DiagEngineWithCmdAndOpts->DiagEngine->Report(
+ diag::err_fe_expected_compiler_job)
+ << llvm::join(CommandLine, " ");
+ return llvm::make_error<llvm::StringError>(
+ "Cannot create CompilerInvocation from Args",
+ llvm::inconvertibleErrorCode());
+ }
+
+ if (any(Worker.Service.getOptimizeArgs() & ScanningOptimizations::Macros))
+ canonicalizeDefines(OriginalInvocation->getPreprocessorOpts());
+
+ // Create the CompilerInstance.
+ IntrusiveRefCntPtr<ModuleCache> ModCache =
+ makeInProcessModuleCache(Worker.Service.getModuleCacheEntries());
+ CIPtr = std::make_unique<CompilerInstance>(
+ std::make_shared<CompilerInvocation>(*OriginalInvocation),
+ Worker.PCHContainerOps, ModCache.get());
+ auto &CI = *CIPtr;
+
+ if (!initializeScanCompilerInstance(
+ CI, OverlayFS, DiagEngineWithCmdAndOpts->DiagEngine->getClient(),
+ Worker.Service, Worker.DepFS)) {
+ return llvm::make_error<llvm::StringError>(
+ "Cannot initialize scanning compiler instance",
+ llvm::inconvertibleErrorCode());
+ }
+
+ llvm::SmallVector<StringRef> StableDirs = getInitialStableDirs(CI);
+ auto MaybePrebuiltModulesASTMap =
+ computePrebuiltModulesASTMap(CI, StableDirs);
+ if (!MaybePrebuiltModulesASTMap)
+ return llvm::make_error<llvm::StringError>(
+ "Prebuilt module scanning failed", llvm::inconvertibleErrorCode());
+
+ PrebuiltModuleASTMap = std::move(*MaybePrebuiltModulesASTMap);
+ OutputOpts = takeDependencyOutputOptionsFrom(CI);
+
+ CI.createTarget();
+
+ return llvm::Error::success();
+}
+
+llvm::Error CompilerInstanceWithContext::computeDependencies(
+ StringRef ModuleName, DependencyConsumer &Consumer,
+ DependencyActionController &Controller) {
+ auto &CI = *CIPtr;
+
+ CI.clearDependencyCollectors();
+ auto MDC = initializeScanInstanceDependencyCollector(
+ CI, std::make_unique<DependencyOutputOptions>(*OutputOpts), CWD,
Consumer,
+ Worker.Service,
+ /* The MDC's constructor makes a copy of the OriginalInvocation, so
+ we can pass it in without worrying that it might be changed across
+ invocations of computeDependencies. */
+ *OriginalInvocation, Controller, PrebuiltModuleASTMap, StableDirs);
+
+ if (!SrcLocOffset) {
+ // When SrcLocOffset is zero, we are at the beginning of the fake source
+ // file. In this case, we call BeginSourceFile to initialize.
+ std::unique_ptr<FrontendAction> Action =
+ std::make_unique<PreprocessOnlyAction>();
+ auto InputFile = CI.getFrontendOpts().Inputs.begin();
+ Action->BeginSourceFile(CI, *InputFile);
+ }
+
+ Preprocessor &PP = CI.getPreprocessor();
+ SourceManager &SM = PP.getSourceManager();
+ FileID MainFileID = SM.getMainFileID();
+ SourceLocation FileStart = SM.getLocForStartOfFile(MainFileID);
+ SourceLocation IDLocation = FileStart.getLocWithOffset(SrcLocOffset);
+ if (!SrcLocOffset) {
+ // We need to call EnterSourceFile when SrcLocOffset is zero to initialize
+ // the preprocessor.
+ PP.EnterSourceFile(MainFileID, nullptr, SourceLocation());
+ } else {
+ // When SrcLocOffset is non-zero, the preprocessor has already been
+ // initialized through a previous call of computeDependencies. We want to
+ // preserve the PP's state, hence we do not call EnterSourceFile again.
+ auto DCs = CI.getDependencyCollectors();
+ for (auto &DC : DCs) {
+ DC->attachToPreprocessor(PP);
+ auto *CB = DC->getPPCallbacks();
+
+ FileID PrevFID;
+ SrcMgr::CharacteristicKind FileType =
+ SM.getFileCharacteristic(IDLocation);
+ CB->LexedFileChanged(MainFileID,
+
PPChainedCallbacks::LexedFileChangeReason::EnterFile,
+ FileType, PrevFID, IDLocation);
+ }
+ }
+
+ SrcLocOffset++;
+ SmallVector<IdentifierLoc, 2> Path;
+ IdentifierInfo *ModuleID = PP.getIdentifierInfo(ModuleName);
+ Path.emplace_back(IDLocation, ModuleID);
+ auto ModResult = CI.loadModule(IDLocation, Path, Module::Hidden, false);
+
+ auto DCs = CI.getDependencyCollectors();
+ for (auto &DC : DCs) {
+ auto *CB = DC->getPPCallbacks();
+ if (CB) {
+ CB->moduleImport(SourceLocation(), Path, ModResult);
+
+ // Note that we are calling the CB's EndOfMainFile function, which
+ // forwards the results to the dependency consumer.
+ // It does not indicate the end of processing the fake file.
+ CB->EndOfMainFile();
+ }
+ }
+
+ CompilerInvocation ModuleInvocation(*OriginalInvocation);
+ MDC->applyDiscoveredDependencies(ModuleInvocation);
+ Consumer.handleBuildCommand(
+ {CommandLine[0], ModuleInvocation.getCC1CommandLine()});
+
+ // Remove the PPCallbacks since they are going out of scope.
+ CI.getPreprocessor().removePPCallbacks();
----------------
qiongsiwu wrote:
Hmmm this is actually implemented but probably not at an obvious place. We call
`CI.clearDependencyCollectors();` at the top of `computeDependencies`. See
https://github.com/llvm/llvm-project/pull/164345/files#diff-21c3ef2cbef83e227ed3d53b663555058d239f57b1998e94ea55143e896460a6R790.
Let me move `CI.clearDependencyCollectors();` to the bottom to make it more
obvious.
https://github.com/llvm/llvm-project/pull/164345
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits