| //===--- CIRGenAction.cpp - LLVM Code generation Frontend Action ---------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "clang/CIR/FrontendAction/CIRGenAction.h" |
| #include "mlir/IR/MLIRContext.h" |
| #include "mlir/IR/OwningOpRef.h" |
| #include "clang/CIR/CIRGenerator.h" |
| #include "clang/CIR/LowerToLLVM.h" |
| #include "clang/CodeGen/BackendUtil.h" |
| #include "clang/Frontend/CompilerInstance.h" |
| #include "llvm/IR/Module.h" |
| |
| using namespace cir; |
| using namespace clang; |
| |
| namespace cir { |
| |
| static BackendAction |
| getBackendActionFromOutputType(CIRGenAction::OutputType Action) { |
| switch (Action) { |
| case CIRGenAction::OutputType::EmitCIR: |
| assert(false && |
| "Unsupported output type for getBackendActionFromOutputType!"); |
| break; // Unreachable, but fall through to report that |
| case CIRGenAction::OutputType::EmitLLVM: |
| return BackendAction::Backend_EmitLL; |
| } |
| // We should only get here if a non-enum value is passed in or we went through |
| // the assert(false) case above |
| llvm_unreachable("Unsupported output type!"); |
| } |
| |
| static std::unique_ptr<llvm::Module> |
| lowerFromCIRToLLVMIR(mlir::ModuleOp MLIRModule, llvm::LLVMContext &LLVMCtx) { |
| return direct::lowerDirectlyFromCIRToLLVMIR(MLIRModule, LLVMCtx); |
| } |
| |
| class CIRGenConsumer : public clang::ASTConsumer { |
| |
| virtual void anchor(); |
| |
| CIRGenAction::OutputType Action; |
| |
| CompilerInstance &CI; |
| |
| std::unique_ptr<raw_pwrite_stream> OutputStream; |
| |
| ASTContext *Context{nullptr}; |
| IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS; |
| std::unique_ptr<CIRGenerator> Gen; |
| |
| public: |
| CIRGenConsumer(CIRGenAction::OutputType Action, CompilerInstance &CI, |
| std::unique_ptr<raw_pwrite_stream> OS) |
| : Action(Action), CI(CI), OutputStream(std::move(OS)), |
| FS(&CI.getVirtualFileSystem()), |
| Gen(std::make_unique<CIRGenerator>(CI.getDiagnostics(), std::move(FS), |
| CI.getCodeGenOpts())) {} |
| |
| void Initialize(ASTContext &Ctx) override { |
| assert(!Context && "initialized multiple times"); |
| Context = &Ctx; |
| Gen->Initialize(Ctx); |
| } |
| |
| bool HandleTopLevelDecl(DeclGroupRef D) override { |
| Gen->HandleTopLevelDecl(D); |
| return true; |
| } |
| |
| void HandleTranslationUnit(ASTContext &C) override { |
| Gen->HandleTranslationUnit(C); |
| mlir::ModuleOp MlirModule = Gen->getModule(); |
| switch (Action) { |
| case CIRGenAction::OutputType::EmitCIR: |
| if (OutputStream && MlirModule) { |
| mlir::OpPrintingFlags Flags; |
| Flags.enableDebugInfo(/*enable=*/true, /*prettyForm=*/false); |
| MlirModule->print(*OutputStream, Flags); |
| } |
| break; |
| case CIRGenAction::OutputType::EmitLLVM: { |
| llvm::LLVMContext LLVMCtx; |
| std::unique_ptr<llvm::Module> LLVMModule = |
| lowerFromCIRToLLVMIR(MlirModule, LLVMCtx); |
| |
| BackendAction BEAction = getBackendActionFromOutputType(Action); |
| emitBackendOutput( |
| CI, CI.getCodeGenOpts(), C.getTargetInfo().getDataLayoutString(), |
| LLVMModule.get(), BEAction, FS, std::move(OutputStream)); |
| break; |
| } |
| } |
| } |
| }; |
| } // namespace cir |
| |
| void CIRGenConsumer::anchor() {} |
| |
| CIRGenAction::CIRGenAction(OutputType Act, mlir::MLIRContext *MLIRCtx) |
| : MLIRCtx(MLIRCtx ? MLIRCtx : new mlir::MLIRContext), Action(Act) {} |
| |
| CIRGenAction::~CIRGenAction() { MLIRMod.release(); } |
| |
| static std::unique_ptr<raw_pwrite_stream> |
| getOutputStream(CompilerInstance &CI, StringRef InFile, |
| CIRGenAction::OutputType Action) { |
| switch (Action) { |
| case CIRGenAction::OutputType::EmitCIR: |
| return CI.createDefaultOutputFile(false, InFile, "cir"); |
| case CIRGenAction::OutputType::EmitLLVM: |
| return CI.createDefaultOutputFile(false, InFile, "ll"); |
| } |
| llvm_unreachable("Invalid CIRGenAction::OutputType"); |
| } |
| |
| std::unique_ptr<ASTConsumer> |
| CIRGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { |
| std::unique_ptr<llvm::raw_pwrite_stream> Out = CI.takeOutputStream(); |
| |
| if (!Out) |
| Out = getOutputStream(CI, InFile, Action); |
| |
| auto Result = |
| std::make_unique<cir::CIRGenConsumer>(Action, CI, std::move(Out)); |
| |
| return Result; |
| } |
| |
| void EmitCIRAction::anchor() {} |
| EmitCIRAction::EmitCIRAction(mlir::MLIRContext *MLIRCtx) |
| : CIRGenAction(OutputType::EmitCIR, MLIRCtx) {} |
| |
| void EmitLLVMAction::anchor() {} |
| EmitLLVMAction::EmitLLVMAction(mlir::MLIRContext *MLIRCtx) |
| : CIRGenAction(OutputType::EmitLLVM, MLIRCtx) {} |