clang 22.0.0git
IncrementalAction.cpp
Go to the documentation of this file.
1//===--- IncrementalAction.h - Incremental Frontend Action -*- 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#include "IncrementalAction.h"
10
19#include "clang/Sema/Sema.h"
20#include "llvm/IR/Module.h"
21#include "llvm/Support/Error.h"
22#include "llvm/Support/ErrorHandling.h"
23
24namespace clang {
26 llvm::LLVMContext &LLVMCtx,
27 llvm::Error &Err, Interpreter &I,
28 std::unique_ptr<ASTConsumer> Consumer)
29 : WrapperFrontendAction([&]() {
30 llvm::ErrorAsOutParameter EAO(&Err);
31 std::unique_ptr<FrontendAction> Act;
32 switch (Instance.getFrontendOpts().ProgramAction) {
33 default:
34 Err = llvm::createStringError(
35 std::errc::state_not_recoverable,
36 "Driver initialization failed. "
37 "Incremental mode for action %d is not supported",
38 Instance.getFrontendOpts().ProgramAction);
39 return Act;
43 Act = CreateFrontendAction(Instance);
44 break;
51 Act.reset(new EmitLLVMOnlyAction(&LLVMCtx));
52 break;
53 }
54 return Act;
55 }()),
56 Interp(I), CI(Instance), Consumer(std::move(Consumer)) {}
57
58std::unique_ptr<ASTConsumer>
60 StringRef InFile) {
61 std::unique_ptr<ASTConsumer> C =
63
64 if (Consumer) {
65 std::vector<std::unique_ptr<ASTConsumer>> Cs;
66 Cs.push_back(std::move(Consumer));
67 Cs.push_back(std::move(C));
68 return std::make_unique<MultiplexConsumer>(std::move(Cs));
69 }
70
71 return std::make_unique<InProcessPrintingASTConsumer>(std::move(C), Interp);
72}
73
77}
78
80 if (IsTerminating && getWrapped())
82}
83
85 assert(!IsTerminating && "Already finalized!");
86 IsTerminating = true;
88}
89
91 CachedInCodeGenModule = GenModule();
92}
93
95 return CachedInCodeGenModule.get();
96}
97
98std::unique_ptr<llvm::Module> IncrementalAction::GenModule() {
99 static unsigned ID = 0;
100 if (CodeGenerator *CG = getCodeGen()) {
101 // Clang's CodeGen is designed to work with a single llvm::Module. In many
102 // cases for convenience various CodeGen parts have a reference to the
103 // llvm::Module (TheModule or Module) which does not change when a new
104 // module is pushed. However, the execution engine wants to take ownership
105 // of the module which does not map well to CodeGen's design. To work this
106 // around we created an empty module to make CodeGen happy. We should make
107 // sure it always stays empty.
108 assert(((!CachedInCodeGenModule ||
109 !CI.getPreprocessorOpts().Includes.empty()) ||
110 (CachedInCodeGenModule->empty() &&
111 CachedInCodeGenModule->global_empty() &&
112 CachedInCodeGenModule->alias_empty() &&
113 CachedInCodeGenModule->ifunc_empty())) &&
114 "CodeGen wrote to a readonly module");
115 std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
116 CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext());
117 return M;
118 }
119 return nullptr;
120}
121
123 FrontendAction *WrappedAct = getWrapped();
124 if (!WrappedAct || !WrappedAct->hasIRSupport())
125 return nullptr;
126 return static_cast<CodeGenAction *>(WrappedAct)->getCodeGenerator();
127}
128
130 std::unique_ptr<ASTConsumer> C, Interpreter &I)
131 : MultiplexConsumer(std::move(C)), Interp(I) {}
132
134 if (DGR.isNull())
135 return true;
136
137 for (Decl *D : DGR)
138 if (auto *TLSD = llvm::dyn_cast<TopLevelStmtDecl>(D))
139 if (TLSD && TLSD->isSemiMissing()) {
140 auto ExprOrErr = Interp.convertExprToValue(cast<Expr>(TLSD->getStmt()));
141 if (llvm::Error E = ExprOrErr.takeError()) {
142 llvm::logAllUnhandledErrors(std::move(E), llvm::errs(),
143 "Value printing failed: ");
144 return false; // abort parsing
145 }
146 TLSD->setStmt(*ExprOrErr);
147 }
148
150}
151
152} // namespace clang
static char ID
Definition: Arena.cpp:183
const Decl * D
Expr * E
The primary public interface to the Clang code generator.
Definition: ModuleBuilder.h:52
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
PreprocessorOptions & getPreprocessorOpts()
bool isNull() const
Definition: DeclGroup.h:75
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
Abstract base class for actions which can be performed by the frontend.
virtual bool hasIRSupport() const
Does this action support use with IR files?
CompilerInstance & getCompilerInstance() const
InProcessPrintingASTConsumer(std::unique_ptr< ASTConsumer > C, Interpreter &I)
bool HandleTopLevelDecl(DeclGroupRef DGR) override
HandleTopLevelDecl - Handle the specified top-level declaration.
llvm::Module * getCachedCodeGenModule() const
Access the cached CodeGen module.
void ExecuteAction() override
Callback to run the program action, using the initialized compiler instance.
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
CodeGenerator * getCodeGen() const
Access the current code generator.
void CacheCodeGenModule()
Cache the current CodeGen module to preserve internal references.
IncrementalAction(CompilerInstance &Instance, llvm::LLVMContext &LLVMCtx, llvm::Error &Err, Interpreter &I, std::unique_ptr< ASTConsumer > Consumer=nullptr)
FrontendAction * getWrapped() const
void EndSourceFile() override
Perform any per-file post processing, deallocate per-file objects, and run statistics and output file...
std::unique_ptr< llvm::Module > GenModule()
Generate an LLVM module for the most recent parsed input.
Provides top-level interfaces for incremental compilation and execution.
Definition: Interpreter.h:86
bool HandleTopLevelDecl(DeclGroupRef D) override
HandleTopLevelDecl - Handle the specified top-level declaration.
std::vector< std::string > Includes
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition: Sema.h:1411
A frontend action which simply wraps some other runtime-specified frontend action.
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
void ExecuteAction() override
Callback to run the program action, using the initialized compiler instance.
void EndSourceFile() override
Perform any per-file post processing, deallocate per-file objects, and run statistics and output file...
@ PrintPreprocessedInput
-E mode.
@ ParseSyntaxOnly
Parse and perform semantic analysis.
@ EmitBC
Emit a .bc file.
@ PluginAction
Run a plugin action,.
@ EmitObj
Emit a .o file.
@ ASTPrint
Parse ASTs and print them.
@ ASTDump
Parse ASTs and dump them.
@ EmitAssembly
Emit a .s file.
@ EmitLLVMOnly
Generate LLVM IR, but do not emit anything.
The JSON file list parser is used to communicate input to InstallAPI.
std::unique_ptr< FrontendAction > CreateFrontendAction(CompilerInstance &CI)
Construct the FrontendAction of a compiler invocation based on the options specified for the compiler...