clang 23.0.0git
CIRGenAction.cpp
Go to the documentation of this file.
1//===--- CIRGenAction.cpp - LLVM Code generation Frontend Action ---------===//
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
10#include "mlir/IR/MLIRContext.h"
11#include "mlir/IR/OwningOpRef.h"
18#include "llvm/ADT/SmallString.h"
19#include "llvm/IR/Module.h"
20#include "llvm/Support/Path.h"
21#include "llvm/Support/raw_ostream.h"
22
23using namespace cir;
24using namespace clang;
25
26namespace cir {
27
28static BackendAction
30 switch (Action) {
32 assert(false &&
33 "Unsupported output type for getBackendActionFromOutputType!");
34 break; // Unreachable, but fall through to report that
43 }
44 // We should only get here if a non-enum value is passed in or we went through
45 // the assert(false) case above
46 llvm_unreachable("Unsupported output type!");
47}
48
49static std::unique_ptr<llvm::Module>
50lowerFromCIRToLLVMIR(mlir::ModuleOp MLIRModule, llvm::LLVMContext &LLVMCtx,
51 llvm::StringRef mlirSaveTempsOutFile = {}) {
52 return direct::lowerDirectlyFromCIRToLLVMIR(MLIRModule, LLVMCtx,
53 mlirSaveTempsOutFile);
54}
55
57
58 virtual void anchor();
59
61
63
64 std::unique_ptr<raw_pwrite_stream> OutputStream;
65
66 ASTContext *Context{nullptr};
68 std::unique_ptr<CIRGenerator> Gen;
69 const FrontendOptions &FEOptions;
70 CodeGenOptions &CGO;
71
72public:
74 CodeGenOptions &CGO, std::unique_ptr<raw_pwrite_stream> OS)
75 : Action(Action), CI(CI), OutputStream(std::move(OS)),
76 FS(&CI.getVirtualFileSystem()),
77 Gen(std::make_unique<CIRGenerator>(CI.getDiagnostics(), std::move(FS),
78 CI.getCodeGenOpts())),
79 FEOptions(CI.getFrontendOpts()), CGO(CGO) {}
80
81 void Initialize(ASTContext &Ctx) override {
82 assert(!Context && "initialized multiple times");
83 Context = &Ctx;
84 Gen->Initialize(Ctx);
85 }
86
88 Gen->HandleTopLevelDecl(D);
89 return true;
90 }
91
93 Gen->HandleCXXStaticMemberVarInstantiation(VD);
94 }
95
97 const OpenACCRoutineDecl *RD) override {
98 Gen->HandleOpenACCRoutineReference(FD, RD);
99 }
100
102 Gen->HandleInlineFunctionDefinition(D);
103 }
104
106 Gen->HandleTranslationUnit(C);
107
108 if (!FEOptions.ClangIRDisableCIRVerifier) {
109 if (!Gen->verifyModule()) {
110 CI.getDiagnostics().Report(
111 diag::err_cir_verification_failed_pre_passes);
112 llvm::report_fatal_error(
113 "CIR codegen: module verification error before running CIR passes");
114 return;
115 }
116 }
117
118 mlir::ModuleOp MlirModule = Gen->getModule();
119 mlir::MLIRContext &MlirCtx = Gen->getMLIRContext();
120
121 if (!FEOptions.ClangIRDisablePasses) {
122 // Setup and run CIR pipeline.
124 MlirModule, MlirCtx, C, !FEOptions.ClangIRDisableCIRVerifier,
125 FEOptions.ClangIREnableIdiomRecognizer, CGO.OptimizationLevel > 0)
126 .failed()) {
127 CI.getDiagnostics().Report(diag::err_cir_to_cir_transform_failed);
128 return;
129 }
130 }
131
132 switch (Action) {
134 if (OutputStream && MlirModule) {
135 mlir::OpPrintingFlags Flags;
136 Flags.enableDebugInfo(/*enable=*/true, /*prettyForm=*/false);
137 MlirModule->print(*OutputStream, Flags);
138 }
139 break;
144 StringRef saveTempsPrefix = CGO.SaveTempsFilePrefix;
145 std::string cirSaveTempsOutFile, mlirSaveTempsOutFile;
146 if (!saveTempsPrefix.empty()) {
147 SmallString<128> stem(saveTempsPrefix);
148 llvm::sys::path::replace_extension(stem, "cir");
149 cirSaveTempsOutFile = std::string(stem);
150 llvm::sys::path::replace_extension(stem, "mlir");
151 mlirSaveTempsOutFile = std::string(stem);
152 }
153
154 if (!cirSaveTempsOutFile.empty()) {
155 std::error_code ec;
156 llvm::raw_fd_ostream out(cirSaveTempsOutFile, ec);
157 if (!ec)
158 MlirModule->print(out);
159 }
160
161 llvm::LLVMContext LLVMCtx;
162 std::unique_ptr<llvm::Module> LLVMModule =
163 lowerFromCIRToLLVMIR(MlirModule, LLVMCtx, mlirSaveTempsOutFile);
164
167 CI, CI.getCodeGenOpts(), C.getTargetInfo().getDataLayoutString(),
168 LLVMModule.get(), BEAction, FS, std::move(OutputStream));
169 break;
170 }
171 }
172 }
173
176 Context->getSourceManager(),
177 "CIR generation of declaration");
178 Gen->HandleTagDeclDefinition(D);
179 }
180
181 void HandleTagDeclRequiredDefinition(const TagDecl *D) override {
182 Gen->HandleTagDeclRequiredDefinition(D);
183 }
184
186 Gen->CompleteTentativeDefinition(D);
187 }
188
189 void HandleVTable(CXXRecordDecl *RD) override { Gen->HandleVTable(RD); }
190};
191} // namespace cir
192
193void CIRGenConsumer::anchor() {}
194
195CIRGenAction::CIRGenAction(OutputType Act, mlir::MLIRContext *MLIRCtx)
196 : MLIRCtx(MLIRCtx ? MLIRCtx : new mlir::MLIRContext), Action(Act) {}
197
198CIRGenAction::~CIRGenAction() { MLIRMod.release(); }
199
200static std::unique_ptr<raw_pwrite_stream>
201getOutputStream(CompilerInstance &CI, StringRef InFile,
203 switch (Action) {
205 return CI.createDefaultOutputFile(false, InFile, "s");
207 return CI.createDefaultOutputFile(false, InFile, "cir");
209 return CI.createDefaultOutputFile(false, InFile, "ll");
211 return CI.createDefaultOutputFile(true, InFile, "bc");
213 return CI.createDefaultOutputFile(true, InFile, "o");
214 }
215 llvm_unreachable("Invalid CIRGenAction::OutputType");
216}
217
218std::unique_ptr<ASTConsumer>
220 std::unique_ptr<llvm::raw_pwrite_stream> Out = CI.takeOutputStream();
221
222 if (!Out)
223 Out = getOutputStream(CI, InFile, Action);
224
225 auto Result = std::make_unique<cir::CIRGenConsumer>(
226 Action, CI, CI.getCodeGenOpts(), std::move(Out));
227
228 return Result;
229}
230
231void EmitAssemblyAction::anchor() {}
232EmitAssemblyAction::EmitAssemblyAction(mlir::MLIRContext *MLIRCtx)
233 : CIRGenAction(OutputType::EmitAssembly, MLIRCtx) {}
234
235void EmitCIRAction::anchor() {}
236EmitCIRAction::EmitCIRAction(mlir::MLIRContext *MLIRCtx)
237 : CIRGenAction(OutputType::EmitCIR, MLIRCtx) {}
238
239void EmitLLVMAction::anchor() {}
240EmitLLVMAction::EmitLLVMAction(mlir::MLIRContext *MLIRCtx)
241 : CIRGenAction(OutputType::EmitLLVM, MLIRCtx) {}
242
243void EmitBCAction::anchor() {}
244EmitBCAction::EmitBCAction(mlir::MLIRContext *MLIRCtx)
245 : CIRGenAction(OutputType::EmitBC, MLIRCtx) {}
246
247void EmitObjAction::anchor() {}
248EmitObjAction::EmitObjAction(mlir::MLIRContext *MLIRCtx)
249 : CIRGenAction(OutputType::EmitObj, MLIRCtx) {}
static std::unique_ptr< raw_pwrite_stream > getOutputStream(CompilerInstance &CI, StringRef InFile, CIRGenAction::OutputType Action)
CIRGenAction(OutputType Action, mlir::MLIRContext *MLIRCtx=nullptr)
OutputType Action
~CIRGenAction() override
std::unique_ptr< clang::ASTConsumer > CreateASTConsumer(clang::CompilerInstance &CI, llvm::StringRef InFile) override
void Initialize(ASTContext &Ctx) override
Initialize - This is called to initialize the consumer, providing the ASTContext.
bool HandleTopLevelDecl(DeclGroupRef D) override
HandleTopLevelDecl - Handle the specified top-level declaration.
void HandleTranslationUnit(ASTContext &C) override
HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...
CIRGenConsumer(CIRGenAction::OutputType Action, CompilerInstance &CI, CodeGenOptions &CGO, std::unique_ptr< raw_pwrite_stream > OS)
void HandleInlineFunctionDefinition(FunctionDecl *D) override
This callback is invoked each time an inline (method or friend) function definition in a class is com...
void CompleteTentativeDefinition(VarDecl *D) override
CompleteTentativeDefinition - Callback invoked at the end of a translation unit to notify the consume...
void HandleTagDeclRequiredDefinition(const TagDecl *D) override
This callback is invoked the first time each TagDecl is required to be complete.
void HandleVTable(CXXRecordDecl *RD) override
Callback involved at the end of a translation unit to notify the consumer that a vtable for the given...
void HandleCXXStaticMemberVarInstantiation(clang::VarDecl *VD) override
HandleCXXStaticMemberVarInstantiation - Tell the consumer that this.
void HandleOpenACCRoutineReference(const FunctionDecl *FD, const OpenACCRoutineDecl *RD) override
Callback to handle the end-of-translation unit attachment of OpenACC routine declaration information.
void HandleTagDeclDefinition(TagDecl *D) override
HandleTagDeclDefinition - This callback is invoked each time a TagDecl (e.g.
EmitAssemblyAction(mlir::MLIRContext *MLIRCtx=nullptr)
EmitBCAction(mlir::MLIRContext *MLIRCtx=nullptr)
EmitCIRAction(mlir::MLIRContext *MLIRCtx=nullptr)
EmitLLVMAction(mlir::MLIRContext *MLIRCtx=nullptr)
EmitObjAction(mlir::MLIRContext *MLIRCtx=nullptr)
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs.
Definition ASTConsumer.h:35
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:226
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
std::unique_ptr< raw_pwrite_stream > createDefaultOutputFile(bool Binary=true, StringRef BaseInput="", StringRef Extension="", bool RemoveFileOnSignal=true, bool CreateMissingDirectories=false, bool ForceUseTemporary=false)
Create the default output file (from the invocation's options) and add it to the list of tracked outp...
std::unique_ptr< llvm::raw_pwrite_stream > takeOutputStream()
CodeGenOptions & getCodeGenOpts()
FrontendOptions - Options for controlling the behavior of the frontend.
Represents a function declaration or definition.
Definition Decl.h:2015
PrettyStackTraceDecl - If a crash occurs, indicate that it happened when doing something to a specifi...
Definition DeclBase.h:1300
Encodes a location in the source.
Represents the declaration of a struct/union/class/enum.
Definition Decl.h:3732
Represents a variable declaration or definition.
Definition Decl.h:926
std::unique_ptr< llvm::Module > lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, llvm::LLVMContext &llvmCtx, llvm::StringRef mlirSaveTempsOutFile={})
static BackendAction getBackendActionFromOutputType(CIRGenAction::OutputType Action)
mlir::LogicalResult runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirCtx, clang::ASTContext &astCtx, bool enableVerifier, bool enableIdiomRecognizer, bool enableCIRSimplify)
Definition CIRPasses.cpp:21
static std::unique_ptr< llvm::Module > lowerFromCIRToLLVMIR(mlir::ModuleOp MLIRModule, llvm::LLVMContext &LLVMCtx, llvm::StringRef mlirSaveTempsOutFile={})
The JSON file list parser is used to communicate input to InstallAPI.
void emitBackendOutput(CompilerInstance &CI, CodeGenOptions &CGOpts, StringRef TDesc, llvm::Module *M, BackendAction Action, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, std::unique_ptr< raw_pwrite_stream > OS, BackendConsumer *BC=nullptr)
BackendAction
Definition BackendUtil.h:33
@ Backend_EmitAssembly
Emit native assembly files.
Definition BackendUtil.h:34
@ Backend_EmitLL
Emit human-readable LLVM assembly.
Definition BackendUtil.h:36
@ Backend_EmitBC
Emit LLVM bitcode files.
Definition BackendUtil.h:35
@ Backend_EmitObj
Emit native object files.
Definition BackendUtil.h:39