11#include "mlir/IR/MLIRContext.h"
12#include "mlir/IR/OwningOpRef.h"
23#include "llvm/ADT/ScopeExit.h"
24#include "llvm/ADT/SmallString.h"
25#include "llvm/ADT/StringSet.h"
26#include "llvm/Frontend/Offloading/OffloadWrapper.h"
27#include "llvm/IR/DiagnosticHandler.h"
28#include "llvm/IR/Function.h"
29#include "llvm/IR/GlobalValue.h"
30#include "llvm/IR/LLVMContext.h"
31#include "llvm/IR/Module.h"
32#include "llvm/Linker/Linker.h"
33#include "llvm/Support/MemoryBuffer.h"
34#include "llvm/Support/Path.h"
35#include "llvm/Support/raw_ostream.h"
36#include "llvm/Transforms/IPO/Internalize.h"
48 "Unsupported output type for getBackendActionFromOutputType!");
61 llvm_unreachable(
"Unsupported output type!");
64static std::unique_ptr<llvm::Module>
67 llvm::StringRef mlirSaveTempsOutFile = {},
68 llvm::vfs::FileSystem *fs =
nullptr) {
70 mlirSaveTempsOutFile, fs);
75 virtual void anchor();
81 std::unique_ptr<raw_pwrite_stream> OutputStream;
85 std::unique_ptr<CIRGenerator> Gen;
89 llvm::LLVMContext &LLVMCtx;
92 std::optional<CIRDiagnosticHandler> MLIRDiagHandler;
102 llvm::LLVMContext &LLVMCtx,
104 : Action(Action), CI(CI), OutputStream(
std::move(OS)),
105 FS(&CI.getVirtualFileSystem()),
107 CI.getCodeGenOpts())),
108 FEOptions(CI.getFrontendOpts()), CGO(CGO), LLVMCtx(LLVMCtx),
109 LinkModules(LinkModules),
110 DiagConsumer(CI.getDiagnostics(), CI.getCodeGenOpts()) {}
113 assert(!Context &&
"initialized multiple times");
116 Gen->Initialize(Ctx);
120 MLIRDiagHandler.emplace(&Gen->getMLIRContext(), CI.getDiagnostics(),
121 CI.getSourceManager(), CI.getFileManager());
125 Gen->HandleTopLevelDecl(D);
130 Gen->HandleCXXStaticMemberVarInstantiation(VD);
135 Gen->HandleOpenACCRoutineReference(FD, RD);
139 Gen->HandleInlineFunctionDefinition(D);
143 Gen->HandleTranslationUnit(
C);
145 if (!FEOptions.ClangIRDisableCIRVerifier) {
146 if (!Gen->verifyModule()) {
149 if (!CI.getDiagnostics().hasErrorOccurred())
150 CI.getDiagnostics().Report(
151 diag::err_cir_verification_failed_pre_passes);
152 llvm::report_fatal_error(
153 "CIR codegen: module verification error before running CIR passes");
158 mlir::ModuleOp MlirModule = Gen->getModule();
159 mlir::MLIRContext &MlirCtx = Gen->getMLIRContext();
161 if (!FEOptions.ClangIRDisablePasses) {
162 std::string LibOptOptions = FEOptions.ClangIRLibOptOptions;
165 const bool EnableLibOpt =
166 FEOptions.ClangIRLibOptEnabled && (CGO.OptimizationLevel > 0);
168 MlirModule, MlirCtx, !FEOptions.ClangIRDisableCIRVerifier,
169 FEOptions.ClangIREnableIdiomRecognizer, CGO.OptimizationLevel > 0,
170 EnableLibOpt, LibOptOptions, FEOptions.ClangIRCallConvLowering)
174 if (!CI.getDiagnostics().hasErrorOccurred())
175 CI.getDiagnostics().Report(diag::err_cir_to_cir_transform_failed);
182 if (OutputStream && MlirModule) {
183 mlir::OpPrintingFlags Flags;
184 Flags.enableDebugInfo(
true,
false);
185 MlirModule->print(*OutputStream, Flags);
192 StringRef saveTempsPrefix = CGO.SaveTempsFilePrefix;
193 std::string cirSaveTempsOutFile, mlirSaveTempsOutFile;
194 if (!saveTempsPrefix.empty()) {
196 llvm::sys::path::replace_extension(stem,
"cir");
197 cirSaveTempsOutFile = std::string(stem);
198 llvm::sys::path::replace_extension(stem,
"mlir");
199 mlirSaveTempsOutFile = std::string(stem);
202 if (!cirSaveTempsOutFile.empty()) {
204 llvm::raw_fd_ostream
out(cirSaveTempsOutFile, ec);
206 MlirModule->print(
out);
210 if (CI.getDiagnostics().hasErrorOccurred())
216 std::unique_ptr<llvm::DiagnosticHandler> OldDiagnosticHandler =
217 LLVMCtx.getDiagnosticHandler();
218 llvm::scope_exit RestoreDiagnosticHandler([&]() {
219 LLVMCtx.setDiagnosticHandler(std::move(OldDiagnosticHandler));
221 LLVMCtx.setDiagnosticHandler(DiagConsumer.createDiagnosticHandler());
224 MlirModule, LLVMCtx,
C.getLangOpts().OpenMP, mlirSaveTempsOutFile,
225 &CI.getVirtualFileSystem());
227 LLVMModule->setDataLayout(
C.getTargetInfo().getDataLayoutString());
229 for (llvm::Function &F : LLVMModule->functions())
230 if (
const Decl *FD = Gen->getDeclForMangledName(F.getName()))
231 DiagConsumer.addFunctionSourceLocation(
232 F.getName(), FD->getASTContext().getFullLoc(FD->getLocation()));
238 if (
C.getLangOpts().SYCLIsHost && !CGO.OffloadBinaryToEmbedFile.empty())
245 if (!CGO.OffloadObjects.empty() &&
250 "ClangIR code gen Not Yet Implemented: embedding offload objects "
251 "for CUDA, HIP or OpenMP offloading"));
256 EmbedObject(LLVMModule.get(), CGO, CI.getVirtualFileSystem(),
257 CI.getDiagnostics());
261 std::move(OutputStream));
270 for (
auto &LM : LinkModules) {
271 assert(LM.Module &&
"LinkModule does not actually have a module");
273 if (LM.PropagateAttrs)
274 for (llvm::Function &F : *LM.Module) {
278 F, CGO, CI.getLangOpts(), CI.getTargetOpts(), LM.Internalize);
281 DiagConsumer.setCurLinkModule(LM.Module.get());
283 if (LM.Internalize) {
284 Err = llvm::Linker::linkModules(
285 M, std::move(LM.Module), LM.LinkFlags,
286 [](llvm::Module &M,
const llvm::StringSet<> &GVS) {
287 llvm::internalizeModule(M, [&GVS](const llvm::GlobalValue &GV) {
288 return !GV.hasName() || (GVS.count(GV.getName()) == 0);
292 Err = llvm::Linker::linkModules(M, std::move(LM.Module), LM.LinkFlags);
307 StringRef fileName = CGO.OffloadBinaryToEmbedFile;
308 auto bufferOrErr = CI.getVirtualFileSystem().getBufferForFile(fileName);
309 if (std::error_code ec = bufferOrErr.getError()) {
310 CI.getDiagnostics().Report(diag::err_cannot_open_file)
311 << fileName << ec.message();
314 std::unique_ptr<llvm::MemoryBuffer> buffer = std::move(bufferOrErr.get());
315 if (llvm::Error err = llvm::offloading::wrapSYCLBinaries(
317 ArrayRef<char>(buffer->getBufferStart(), buffer->getBufferSize()),
318 llvm::offloading::SYCLJITOptions(),
true)) {
319 CI.getDiagnostics().Report(diag::err_fe_error_backend)
320 << llvm::toString(std::move(err));
327 Context->getSourceManager(),
328 "CIR generation of declaration");
329 Gen->HandleTagDeclDefinition(D);
333 Gen->HandleTagDeclRequiredDefinition(D);
337 Gen->CompleteTentativeDefinition(D);
344void CIRGenConsumer::anchor() {}
347 : MLIRCtx(MLIRCtx ? MLIRCtx : new
mlir::MLIRContext),
366 diag::err_fe_cir_input_unsupported);
369static std::unique_ptr<raw_pwrite_stream>
384 llvm_unreachable(
"Invalid CIRGenAction::OutputType");
387std::unique_ptr<ASTConsumer>
394 auto Result = std::make_unique<cir::CIRGenConsumer>(
400void EmitAssemblyAction::anchor() {}
404void EmitCIRAction::anchor() {}
408void EmitLLVMAction::anchor() {}
412void EmitBCAction::anchor() {}
416void EmitObjAction::anchor() {}
Defines the clang::ASTContext interface.
static std::unique_ptr< raw_pwrite_stream > getOutputStream(CompilerInstance &CI, StringRef InFile, CIRGenAction::OutputType Action)
CIRGenAction(OutputType Action, mlir::MLIRContext *MLIRCtx=nullptr)
void ExecuteAction() override
Implement the ExecuteAction interface by running Sema on the already-initialized AST consumer.
bool BeginSourceFileAction(clang::CompilerInstance &CI) override
Callback at the start of processing a single input.
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...
bool linkInModules(llvm::Module &M)
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.
CIRGenConsumer(CIRGenAction::OutputType Action, CompilerInstance &CI, CodeGenOptions &CGO, std::unique_ptr< raw_pwrite_stream > OS, llvm::LLVMContext &LLVMCtx, SmallVectorImpl<::clang::LinkModule > &LinkModules)
void embedSYCLDeviceBinary(llvm::Module &M)
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.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
void ExecuteAction() override
Implement the ExecuteAction interface by running Sema on the already-initialized AST consumer.
Owns the state needed to translate LLVM backend diagnostics into clang diagnostics,...
Represents a C++ struct/union/class.
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, bool SetOnlyIfDifferent=false)
Create the default output file (from the invocation's options) and add it to the list of tracked outp...
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
std::unique_ptr< llvm::raw_pwrite_stream > takeOutputStream()
CodeGenOptions & getCodeGenOpts()
Decl - This represents one declaration (or definition), e.g.
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
InputKind getCurrentFileKind() const
virtual bool BeginSourceFileAction(CompilerInstance &CI)
Callback at the start of processing a single input.
CompilerInstance & getCompilerInstance() const
FrontendOptions - Options for controlling the behavior of the frontend.
Represents a function declaration or definition.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
std::vector< llvm::Triple > OMPTargetTriples
Triples of the OpenMP targets that the host code codegen should take into account in order to generat...
PrettyStackTraceDecl - If a crash occurs, indicate that it happened when doing something to a specifi...
Encodes a location in the source.
Represents the declaration of a struct/union/class/enum.
Represents a variable declaration or definition.
std::unique_ptr< llvm::Module > lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, llvm::LLVMContext &llvmCtx, bool enableOpenMP, llvm::StringRef mlirSaveTempsOutFile={}, llvm::vfs::FileSystem *fs=nullptr)
static BackendAction getBackendActionFromOutputType(CIRGenAction::OutputType Action)
mlir::LogicalResult runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirCtx, bool enableVerifier, bool enableIdiomRecognizer, bool enableCIRSimplify, bool enableLibOpt, llvm::StringRef libOptOptions, bool enableCallConvLowering)
static std::unique_ptr< llvm::Module > lowerFromCIRToLLVMIR(mlir::ModuleOp MLIRModule, llvm::LLVMContext &LLVMCtx, bool EnableOpenMP, llvm::StringRef mlirSaveTempsOutFile={}, llvm::vfs::FileSystem *fs=nullptr)
void mergeDefaultFunctionDefinitionAttributes(llvm::Function &F, const CodeGenOptions &CodeGenOpts, const LangOptions &LangOpts, const TargetOptions &TargetOpts, bool WillInternalize)
Adds attributes to F according to our CodeGenOpts and LangOpts, as though we had emitted it ourselves...
Top level wrappers for InstallAPI frontend operations.
@ CIR
LLVM IR & CIR: we accept these so that we can run the optimizer on them, and compile them to assembly...
void EmbedObject(llvm::Module *M, const CodeGenOptions &CGOpts, llvm::vfs::FileSystem &VFS, DiagnosticsEngine &Diags)
void emitBackendOutput(CompilerInstance &CI, CodeGenOptions &CGOpts, llvm::Module *M, BackendAction Action, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, std::unique_ptr< raw_pwrite_stream > OS, BackendConsumer *BC=nullptr)
@ Backend_EmitAssembly
Emit native assembly files.
@ Backend_EmitLL
Emit human-readable LLVM assembly.
@ Backend_EmitBC
Emit LLVM bitcode files.
@ Backend_EmitObj
Emit native object files.
bool loadLinkModules(CompilerInstance &CI, llvm::LLVMContext &Ctx, llvm::SmallVectorImpl< LinkModule > &LinkModules)
Load every bitcode file listed in CodeGenOpts.LinkBitcodeFiles into LinkModules.
Diagnostic wrappers for TextAPI types for error reporting.