[clang] [clang-repl] Simplify the value printing logic to enable out-of-process. (PR #107737)
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 4 08:29:58 PST 2024
================
@@ -13,246 +13,40 @@
#include "IncrementalParser.h"
#include "clang/AST/DeclContextInternals.h"
-#include "clang/CodeGen/BackendUtil.h"
-#include "clang/CodeGen/CodeGenAction.h"
-#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/FrontendAction.h"
-#include "clang/FrontendTool/Utils.h"
-#include "clang/Interpreter/Interpreter.h"
+#include "clang/Interpreter/PartialTranslationUnit.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/Sema.h"
-#include "llvm/Option/ArgList.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/Error.h"
-#include "llvm/Support/Timer.h"
#include <sstream>
namespace clang {
-class IncrementalASTConsumer final : public ASTConsumer {
- Interpreter &Interp;
- std::unique_ptr<ASTConsumer> Consumer;
+// IncrementalParser::IncrementalParser() {}
-public:
- IncrementalASTConsumer(Interpreter &InterpRef, std::unique_ptr<ASTConsumer> C)
- : Interp(InterpRef), Consumer(std::move(C)) {}
-
- bool HandleTopLevelDecl(DeclGroupRef DGR) override final {
- if (DGR.isNull())
- return true;
- if (!Consumer)
- return true;
-
- for (Decl *D : DGR)
- if (auto *TSD = llvm::dyn_cast<TopLevelStmtDecl>(D);
- TSD && TSD->isSemiMissing())
- TSD->setStmt(Interp.SynthesizeExpr(cast<Expr>(TSD->getStmt())));
-
- return Consumer->HandleTopLevelDecl(DGR);
- }
- void HandleTranslationUnit(ASTContext &Ctx) override final {
- Consumer->HandleTranslationUnit(Ctx);
- }
- void HandleInlineFunctionDefinition(FunctionDecl *D) override final {
- Consumer->HandleInlineFunctionDefinition(D);
- }
- void HandleInterestingDecl(DeclGroupRef D) override final {
- Consumer->HandleInterestingDecl(D);
- }
- void HandleTagDeclDefinition(TagDecl *D) override final {
- Consumer->HandleTagDeclDefinition(D);
- }
- void HandleTagDeclRequiredDefinition(const TagDecl *D) override final {
- Consumer->HandleTagDeclRequiredDefinition(D);
- }
- void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) override final {
- Consumer->HandleCXXImplicitFunctionInstantiation(D);
- }
- void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override final {
- Consumer->HandleTopLevelDeclInObjCContainer(D);
- }
- void HandleImplicitImportDecl(ImportDecl *D) override final {
- Consumer->HandleImplicitImportDecl(D);
- }
- void CompleteTentativeDefinition(VarDecl *D) override final {
- Consumer->CompleteTentativeDefinition(D);
- }
- void CompleteExternalDeclaration(DeclaratorDecl *D) override final {
- Consumer->CompleteExternalDeclaration(D);
- }
- void AssignInheritanceModel(CXXRecordDecl *RD) override final {
- Consumer->AssignInheritanceModel(RD);
- }
- void HandleCXXStaticMemberVarInstantiation(VarDecl *D) override final {
- Consumer->HandleCXXStaticMemberVarInstantiation(D);
- }
- void HandleVTable(CXXRecordDecl *RD) override final {
- Consumer->HandleVTable(RD);
- }
- ASTMutationListener *GetASTMutationListener() override final {
- return Consumer->GetASTMutationListener();
- }
- ASTDeserializationListener *GetASTDeserializationListener() override final {
- return Consumer->GetASTDeserializationListener();
- }
- void PrintStats() override final { Consumer->PrintStats(); }
- bool shouldSkipFunctionBody(Decl *D) override final {
- return Consumer->shouldSkipFunctionBody(D);
- }
- static bool classof(const clang::ASTConsumer *) { return true; }
-};
-
-/// A custom action enabling the incremental processing functionality.
-///
-/// The usual \p FrontendAction expects one call to ExecuteAction and once it
-/// sees a call to \p EndSourceFile it deletes some of the important objects
-/// such as \p Preprocessor and \p Sema assuming no further input will come.
-///
-/// \p IncrementalAction ensures it keep its underlying action's objects alive
-/// as long as the \p IncrementalParser needs them.
-///
-class IncrementalAction : public WrapperFrontendAction {
-private:
- bool IsTerminating = false;
-
-public:
- IncrementalAction(CompilerInstance &CI, llvm::LLVMContext &LLVMCtx,
- llvm::Error &Err)
- : WrapperFrontendAction([&]() {
- llvm::ErrorAsOutParameter EAO(&Err);
- std::unique_ptr<FrontendAction> Act;
- switch (CI.getFrontendOpts().ProgramAction) {
- default:
- Err = llvm::createStringError(
- std::errc::state_not_recoverable,
- "Driver initialization failed. "
- "Incremental mode for action %d is not supported",
- CI.getFrontendOpts().ProgramAction);
- return Act;
- case frontend::ASTDump:
- [[fallthrough]];
- case frontend::ASTPrint:
- [[fallthrough]];
- case frontend::ParseSyntaxOnly:
- Act = CreateFrontendAction(CI);
- break;
- case frontend::PluginAction:
- [[fallthrough]];
- case frontend::EmitAssembly:
- [[fallthrough]];
- case frontend::EmitBC:
- [[fallthrough]];
- case frontend::EmitObj:
- [[fallthrough]];
- case frontend::PrintPreprocessedInput:
- [[fallthrough]];
- case frontend::EmitLLVMOnly:
- Act.reset(new EmitLLVMOnlyAction(&LLVMCtx));
- break;
- }
- return Act;
- }()) {}
- FrontendAction *getWrapped() const { return WrappedAction.get(); }
- TranslationUnitKind getTranslationUnitKind() override {
- return TU_Incremental;
- }
-
- void ExecuteAction() override {
- CompilerInstance &CI = getCompilerInstance();
- assert(CI.hasPreprocessor() && "No PP!");
-
- // Use a code completion consumer?
- CodeCompleteConsumer *CompletionConsumer = nullptr;
- if (CI.hasCodeCompletionConsumer())
- CompletionConsumer = &CI.getCodeCompletionConsumer();
-
- Preprocessor &PP = CI.getPreprocessor();
- PP.EnterMainSourceFile();
-
- if (!CI.hasSema())
- CI.createSema(getTranslationUnitKind(), CompletionConsumer);
- }
-
- // Do not terminate after processing the input. This allows us to keep various
- // clang objects alive and to incrementally grow the current TU.
- void EndSourceFile() override {
- // The WrappedAction can be nullptr if we issued an error in the ctor.
- if (IsTerminating && getWrapped())
- WrapperFrontendAction::EndSourceFile();
- }
-
- void FinalizeAction() {
- assert(!IsTerminating && "Already finalized!");
- IsTerminating = true;
- EndSourceFile();
- }
-};
-
-CodeGenerator *IncrementalParser::getCodeGen() const {
- FrontendAction *WrappedAct = Act->getWrapped();
- if (!WrappedAct->hasIRSupport())
- return nullptr;
- return static_cast<CodeGenAction *>(WrappedAct)->getCodeGenerator();
-}
-
-IncrementalParser::IncrementalParser() {}
-
-IncrementalParser::IncrementalParser(Interpreter &Interp,
- std::unique_ptr<CompilerInstance> Instance,
- llvm::LLVMContext &LLVMCtx,
+IncrementalParser::IncrementalParser(CompilerInstance &Instance,
llvm::Error &Err)
- : CI(std::move(Instance)) {
+ : S(Instance.getSema()) {
----------------
AaronBallman wrote:
For `clang-repl` alone, there is no failed assertion. For `clang-repl --cuda` we create two `IncrementalParser` objects. The first one does not assert and its call stack is:
```
> clang-repl.exe!clang::IncrementalParser::IncrementalParser(clang::CompilerInstance & Instance, llvm::Error & Err) Line 31 C++
clang-repl.exe!std::make_unique<clang::IncrementalParser,clang::CompilerInstance &,llvm::Error &,0>(clang::CompilerInstance & <_Args_0>, llvm::Error & <_Args_1>) Line 3597 C++
clang-repl.exe!clang::Interpreter::Interpreter(std::unique_ptr<clang::CompilerInstance,std::default_delete<clang::CompilerInstance>> Instance, llvm::Error & ErrOut, std::unique_ptr<llvm::orc::LLJITBuilder,std::default_delete<llvm::orc::LLJITBuilder>> JITBuilder, std::unique_ptr<clang::ASTConsumer,std::default_delete<clang::ASTConsumer>> Consumer) Line 390 C++
clang-repl.exe!clang::Interpreter::create(std::unique_ptr<clang::CompilerInstance,std::default_delete<clang::CompilerInstance>> CI) Line 461 C++
clang-repl.exe!clang::Interpreter::createWithCUDA(std::unique_ptr<clang::CompilerInstance,std::default_delete<clang::CompilerInstance>> CI, std::unique_ptr<clang::CompilerInstance,std::default_delete<clang::CompilerInstance>> DCI) Line 489 C++
clang-repl.exe!main(int argc, const char * * argv) Line 206 C++
```
and the second one is:
```
clang-repl.exe!clang::IncrementalParser::IncrementalParser(clang::CompilerInstance & Instance, llvm::Error & Err) Line 31 C++
> clang-repl.exe!clang::IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(std::unique_ptr<clang::CompilerInstance,std::default_delete<clang::CompilerInstance>> DeviceInstance, clang::CompilerInstance & HostInstance, llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS, llvm::Error & Err, const std::list<clang::PartialTranslationUnit,std::allocator<clang::PartialTranslationUnit>> & PTUs) Line 34 C++
clang-repl.exe!std::make_unique<clang::IncrementalCUDADeviceParser,std::unique_ptr<clang::CompilerInstance,std::default_delete<clang::CompilerInstance>>,clang::CompilerInstance &,llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> &,llvm::Error &,std::list<clang::PartialTranslationUnit,std::allocator<clang::PartialTranslationUnit>> &,0>(std::unique_ptr<clang::CompilerInstance,std::default_delete<clang::CompilerInstance>> && <_Args_0>, clang::CompilerInstance & <_Args_1>, llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> & <_Args_2>, llvm::Error & <_Args_3>, std::list<clang::PartialTranslationUnit,std::allocator<clang::PartialTranslationUnit>> & <_Args_4>) Line 3597 C++
clang-repl.exe!clang::Interpreter::createWithCUDA(std::unique_ptr<clang::CompilerInstance,std::default_delete<clang::CompilerInstance>> CI, std::unique_ptr<clang::CompilerInstance,std::default_delete<clang::CompilerInstance>> DCI) Line 494 C++
clang-repl.exe!main(int argc, const char * * argv) Line 206 C++
```
and this one fails because the `DeviceInstance` passed to `IncrementalCUDADeviceParser::IncrementalCUDADeviceParser()` is mostly empty, including an empty `Sema` pointer.
https://github.com/llvm/llvm-project/pull/107737
More information about the cfe-commits
mailing list