clang 24.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;
52 Act.reset(new EmitLLVMOnlyAction(&LLVMCtx));
53 break;
54 }
55 return Act;
56 }()),
57 Interp(I), CI(Instance), Consumer(std::move(Consumer)) {}
58
59std::unique_ptr<ASTConsumer>
61 StringRef InFile) {
62 std::unique_ptr<ASTConsumer> C =
64
65 if (Consumer) {
66 std::vector<std::unique_ptr<ASTConsumer>> Cs;
67 Cs.push_back(std::move(Consumer));
68 Cs.push_back(std::move(C));
69 return std::make_unique<MultiplexConsumer>(std::move(Cs));
70 }
71
72 return std::make_unique<InProcessPrintingASTConsumer>(std::move(C), Interp);
73}
74
79
84
86 assert(!IsTerminating && "Already finalized!");
87 IsTerminating = true;
89}
90
92 CachedInCodeGenModule = GenModule();
93}
94
96 return CachedInCodeGenModule.get();
97}
98
99std::unique_ptr<llvm::Module> IncrementalAction::GenModule() {
100 static unsigned ID = 0;
101 if (CodeGenerator *CG = getCodeGen()) {
102 // Clang's CodeGen is designed to work with a single llvm::Module. In many
103 // cases for convenience various CodeGen parts have a reference to the
104 // llvm::Module (TheModule or Module) which does not change when a new
105 // module is pushed. However, the execution engine wants to take ownership
106 // of the module which does not map well to CodeGen's design. To work this
107 // around we created an empty module to make CodeGen happy. We should make
108 // sure it always stays empty.
109 assert(((!CachedInCodeGenModule ||
110 !CI.getPreprocessorOpts().Includes.empty() ||
111 !CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) ||
112 (CachedInCodeGenModule->empty() &&
113 CachedInCodeGenModule->global_empty() &&
114 CachedInCodeGenModule->alias_empty() &&
115 CachedInCodeGenModule->ifunc_empty())) &&
116 "CodeGen wrote to a readonly module");
117 std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
118 CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext());
119 return M;
120 }
121 return nullptr;
122}
123
125 FrontendAction *WrappedAct = getWrapped();
126 if (!WrappedAct || !WrappedAct->hasIRSupport())
127 return nullptr;
128 return static_cast<CodeGenAction *>(WrappedAct)->getCodeGenerator();
129}
130
132 std::unique_ptr<ASTConsumer> C, Interpreter &I)
133 : MultiplexConsumer(std::move(C)), Interp(I) {}
134
136 if (DGR.isNull())
137 return true;
138
139 CompilerInstance *CI = Interp.getCompilerInstance();
140 DiagnosticsEngine &Diags = CI->getDiagnostics();
141 if (Diags.hasErrorOccurred())
142 return true;
143
144 for (Decl *D : DGR)
145 if (auto *TLSD = llvm::dyn_cast<TopLevelStmtDecl>(D))
146 if (TLSD && TLSD->isSemiMissing()) {
147 auto ExprOrErr = Interp.convertExprToValue(cast<Expr>(TLSD->getStmt()));
148 if (llvm::Error E = ExprOrErr.takeError()) {
149 llvm::logAllUnhandledErrors(std::move(E), llvm::errs(),
150 "Value printing failed: ");
151 return false; // abort parsing
152 }
153 TLSD->setStmt(*ExprOrErr);
154 }
155
157}
158
159} // namespace clang
The primary public interface to the Clang code generator.
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
bool isNull() const
Definition DeclGroup.h:75
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:234
bool hasErrorOccurred() const
Definition Diagnostic.h:893
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:98
bool HandleTopLevelDecl(DeclGroupRef D) override
HandleTopLevelDecl - Handle the specified top-level declaration.
MultiplexConsumer(std::vector< std::unique_ptr< ASTConsumer > > C)
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition Sema.h:1444
void ExecuteAction() override
Callback to run the program action, using the initialized compiler instance.
WrapperFrontendAction(std::unique_ptr< FrontendAction > WrappedAction)
Construct a WrapperFrontendAction from an existing action, taking ownership of it.
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
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.
@ EmitLLVM
Emit a .ll 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.
Top level wrappers for InstallAPI frontend operations.
std::unique_ptr< FrontendAction > CreateFrontendAction(CompilerInstance &CI)
Construct the FrontendAction of a compiler invocation based on the options specified for the compiler...
U cast(CodeGen::Address addr)
Definition Address.h:327