https://github.com/andykaylor updated https://github.com/llvm/llvm-project/pull/124650
>From 41546e2d096310d8a1474539b5036152c7df3d11 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Mon, 27 Jan 2025 14:54:10 -0800 Subject: [PATCH 1/2] [CIR] Add framework for CIR to LLVM IR lowering Create the skeleton framework for lowering from ClangIR to LLVM IR. This initial implementation just creates an empty LLVM IR module. Actual lowering of even minimal ClangIR is deferred to a later patch. --- clang/include/clang/CIR/CIRGenerator.h | 3 + .../clang/CIR/FrontendAction/CIRGenAction.h | 8 +++ clang/include/clang/CIR/LowerToLLVM.h | 36 +++++++++++ clang/lib/CIR/CMakeLists.txt | 1 + clang/lib/CIR/FrontendAction/CIRGenAction.cpp | 60 ++++++++++++++----- clang/lib/CIR/FrontendAction/CMakeLists.txt | 1 + clang/lib/CIR/Lowering/CMakeLists.txt | 1 + .../CIR/Lowering/DirectToLLVM/CMakeLists.txt | 8 +++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 41 +++++++++++++ .../ExecuteCompilerInvocation.cpp | 8 ++- clang/test/CIR/Lowering/hello.c | 8 +++ 11 files changed, 160 insertions(+), 15 deletions(-) create mode 100644 clang/include/clang/CIR/LowerToLLVM.h create mode 100644 clang/lib/CIR/Lowering/CMakeLists.txt create mode 100644 clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt create mode 100644 clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp create mode 100644 clang/test/CIR/Lowering/hello.c diff --git a/clang/include/clang/CIR/CIRGenerator.h b/clang/include/clang/CIR/CIRGenerator.h index 414eba80b88b8f..58ed15041015af 100644 --- a/clang/include/clang/CIR/CIRGenerator.h +++ b/clang/include/clang/CIR/CIRGenerator.h @@ -55,6 +55,9 @@ class CIRGenerator : public clang::ASTConsumer { void Initialize(clang::ASTContext &astContext) override; bool HandleTopLevelDecl(clang::DeclGroupRef group) override; mlir::ModuleOp getModule() const; + std::unique_ptr<mlir::MLIRContext> takeContext() { + return std::move(mlirContext); + }; }; } // namespace cir diff --git a/clang/include/clang/CIR/FrontendAction/CIRGenAction.h b/clang/include/clang/CIR/FrontendAction/CIRGenAction.h index 2ab612613b73da..5f9110bc83b89f 100644 --- a/clang/include/clang/CIR/FrontendAction/CIRGenAction.h +++ b/clang/include/clang/CIR/FrontendAction/CIRGenAction.h @@ -26,6 +26,7 @@ class CIRGenAction : public clang::ASTFrontendAction { public: enum class OutputType { EmitCIR, + EmitLLVM, }; private: @@ -55,6 +56,13 @@ class EmitCIRAction : public CIRGenAction { EmitCIRAction(mlir::MLIRContext *MLIRCtx = nullptr); }; +class EmitLLVMAction : public CIRGenAction { + virtual void anchor(); + +public: + EmitLLVMAction(mlir::MLIRContext *MLIRCtx = nullptr); +}; + } // namespace cir #endif diff --git a/clang/include/clang/CIR/LowerToLLVM.h b/clang/include/clang/CIR/LowerToLLVM.h new file mode 100644 index 00000000000000..82a28270cc1538 --- /dev/null +++ b/clang/include/clang/CIR/LowerToLLVM.h @@ -0,0 +1,36 @@ +//====- LowerToLLVM.h- Lowering from CIR to LLVM --------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file declares an interface for converting CIR modules to LLVM IR. +// +//===----------------------------------------------------------------------===// +#ifndef CLANG_CIR_LOWERTOLLVM_H +#define CLANG_CIR_LOWERTOLLVM_H + +#include "mlir/Pass/Pass.h" + +#include <memory> + +namespace llvm { +class LLVMContext; +class Module; +} // namespace llvm + +namespace mlir { +class ModuleOp; +} // namespace mlir + +namespace cir { + +namespace direct { +std::unique_ptr<llvm::Module> lowerDirectlyFromCIRToLLVMIR( + mlir::ModuleOp M, llvm::LLVMContext &Ctx); +} // namespace direct +} // namespace cir + +#endif // CLANG_CIR_LOWERTOLLVM_H \ No newline at end of file diff --git a/clang/lib/CIR/CMakeLists.txt b/clang/lib/CIR/CMakeLists.txt index f3ef8525e15c26..4a99ecb33dfb23 100644 --- a/clang/lib/CIR/CMakeLists.txt +++ b/clang/lib/CIR/CMakeLists.txt @@ -5,3 +5,4 @@ add_subdirectory(Dialect) add_subdirectory(CodeGen) add_subdirectory(FrontendAction) add_subdirectory(Interfaces) +add_subdirectory(Lowering) diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp index 21b6bc56ed0503..583fd8126e9518 100644 --- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp +++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp @@ -8,8 +8,10 @@ #include "clang/CIR/FrontendAction/CIRGenAction.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" #include "mlir/IR/MLIRContext.h" #include "mlir/IR/OwningOpRef.h" @@ -18,12 +20,30 @@ using namespace clang; namespace cir { +static BackendAction +getBackendActionFromOutputType(CIRGenAction::OutputType Action) { + switch (Action) { + case CIRGenAction::OutputType::EmitLLVM: + return BackendAction::Backend_EmitLL; + default: + llvm_unreachable("Unsupported action"); + } +} + +static std::unique_ptr<llvm::Module> lowerFromCIRToLLVMIR( + const clang::FrontendOptions &FEOpts, mlir::ModuleOp MLIRModule, + std::unique_ptr<mlir::MLIRContext> MLIRCtx, 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}; @@ -32,17 +52,12 @@ class CIRGenConsumer : public clang::ASTConsumer { public: CIRGenConsumer(CIRGenAction::OutputType Action, - DiagnosticsEngine &DiagnosticsEngine, - IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, - const HeaderSearchOptions &HeaderSearchOptions, - const CodeGenOptions &CodeGenOptions, - const TargetOptions &TargetOptions, - const LangOptions &LangOptions, - const FrontendOptions &FEOptions, + CompilerInstance &CI, std::unique_ptr<raw_pwrite_stream> OS) - : Action(Action), OutputStream(std::move(OS)), FS(VFS), - Gen(std::make_unique<CIRGenerator>(DiagnosticsEngine, std::move(VFS), - CodeGenOptions)) {} + : 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"); @@ -58,6 +73,7 @@ class CIRGenConsumer : public clang::ASTConsumer { void HandleTranslationUnit(ASTContext &C) override { Gen->HandleTranslationUnit(C); mlir::ModuleOp MlirModule = Gen->getModule(); + auto MLIRCtx = Gen->takeContext(); switch (Action) { case CIRGenAction::OutputType::EmitCIR: if (OutputStream && MlirModule) { @@ -66,6 +82,18 @@ class CIRGenConsumer : public clang::ASTConsumer { MlirModule->print(*OutputStream, Flags); } break; + case CIRGenAction::OutputType::EmitLLVM: { + llvm::LLVMContext LLVMCtx; + auto LLVMModule = lowerFromCIRToLLVMIR(CI.getFrontendOpts(), MlirModule, + std::move(MLIRCtx), LLVMCtx); + + BackendAction BEAction = getBackendActionFromOutputType(Action); + emitBackendOutput(CI, CI.getCodeGenOpts(), + C.getTargetInfo().getDataLayoutString(), + LLVMModule.get(), BEAction, FS, + std::move(OutputStream)); + break; + } } } }; @@ -84,6 +112,8 @@ getOutputStream(CompilerInstance &CI, StringRef InFile, 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"); } @@ -96,9 +126,7 @@ CIRGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { Out = getOutputStream(CI, InFile, Action); auto Result = std::make_unique<cir::CIRGenConsumer>( - Action, CI.getDiagnostics(), &CI.getVirtualFileSystem(), - CI.getHeaderSearchOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(), - CI.getLangOpts(), CI.getFrontendOpts(), std::move(Out)); + Action, CI, std::move(Out)); return Result; } @@ -106,3 +134,7 @@ CIRGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { void EmitCIRAction::anchor() {} EmitCIRAction::EmitCIRAction(mlir::MLIRContext *MLIRCtx) : CIRGenAction(OutputType::EmitCIR, MLIRCtx) {} + +void EmitLLVMAction::anchor() {} +EmitLLVMAction::EmitLLVMAction(mlir::MLIRContext *MLIRCtx) + : CIRGenAction(OutputType::EmitLLVM, MLIRCtx) {} \ No newline at end of file diff --git a/clang/lib/CIR/FrontendAction/CMakeLists.txt b/clang/lib/CIR/FrontendAction/CMakeLists.txt index b0616ab5d64b09..d87ff7665987d1 100644 --- a/clang/lib/CIR/FrontendAction/CMakeLists.txt +++ b/clang/lib/CIR/FrontendAction/CMakeLists.txt @@ -12,6 +12,7 @@ add_clang_library(clangCIRFrontendAction clangAST clangFrontend clangCIR + clangCIRLoweringDirectToLLVM MLIRCIR MLIRIR ) diff --git a/clang/lib/CIR/Lowering/CMakeLists.txt b/clang/lib/CIR/Lowering/CMakeLists.txt new file mode 100644 index 00000000000000..44ec87c28d65e3 --- /dev/null +++ b/clang/lib/CIR/Lowering/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(DirectToLLVM) \ No newline at end of file diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt b/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt new file mode 100644 index 00000000000000..0268234c3a2896 --- /dev/null +++ b/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt @@ -0,0 +1,8 @@ +set(LLVM_LINK_COMPONENTS + Core + Support + ) + +add_clang_library(clangCIRLoweringDirectToLLVM + LowerToLLVM.cpp + ) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp new file mode 100644 index 00000000000000..4bf0f3ab78c53d --- /dev/null +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -0,0 +1,41 @@ +//====- LowerToLLVM.cpp - Lowering from CIR to LLVMIR ---------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file implements lowering of CIR operations to LLVMIR. +// +//===----------------------------------------------------------------------===// + +#include "clang/CIR/LowerToLLVM.h" + +#include "mlir/IR/BuiltinOps.h" +#include "mlir/Pass/Pass.h" +#include "mlir/Pass/PassManager.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/TimeProfiler.h" + + +using namespace cir; +using namespace llvm; + +namespace cir { +namespace direct { + +std::unique_ptr<llvm::Module> +lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp theModule, LLVMContext &llvmCtx) { + llvm::TimeTraceScope scope("lower from CIR to LLVM directly"); + + auto ModuleName = theModule.getName(); + auto llvmModule = std::make_unique<llvm::Module>(ModuleName ? *ModuleName : "CIRToLLVMModule", llvmCtx); + + if (!llvmModule) + report_fatal_error("Lowering from LLVMIR dialect to llvm IR failed!"); + + return llvmModule; +} +} // namespace direct +} // namespace cir diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 3f95a1efb2eed7..f947299292a36d 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -72,7 +72,13 @@ CreateFrontendBaseAction(CompilerInstance &CI) { llvm_unreachable("CIR suppport not built into clang"); #endif case EmitHTML: return std::make_unique<HTMLPrintAction>(); - case EmitLLVM: return std::make_unique<EmitLLVMAction>(); + case EmitLLVM: { +#if CLANG_ENABLE_CIR + if (UseCIR) + return std::make_unique<cir::EmitLLVMAction>(); +#endif + return std::make_unique<EmitLLVMAction>(); + } case EmitLLVMOnly: return std::make_unique<EmitLLVMOnlyAction>(); case EmitCodeGenOnly: return std::make_unique<EmitCodeGenOnlyAction>(); case EmitObj: return std::make_unique<EmitObjAction>(); diff --git a/clang/test/CIR/Lowering/hello.c b/clang/test/CIR/Lowering/hello.c new file mode 100644 index 00000000000000..320041f0ab7dc9 --- /dev/null +++ b/clang/test/CIR/Lowering/hello.c @@ -0,0 +1,8 @@ +// Smoke test for ClangIR-to-LLVM IR code generation +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s + +// TODO: Add checks when proper lowering is implemented. +// For now, we're just creating an empty module. +// CHECK: ModuleID + +void foo() {} >From a9ea2d885d7fd4e8cfcc23d37dbb70f04b3750d8 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Mon, 27 Jan 2025 16:44:47 -0800 Subject: [PATCH 2/2] Formatting and style changes --- clang/include/clang/CIR/LowerToLLVM.h | 4 ++-- clang/lib/CIR/FrontendAction/CIRGenAction.cpp | 18 ++++++++---------- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 12 ++++++------ 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/clang/include/clang/CIR/LowerToLLVM.h b/clang/include/clang/CIR/LowerToLLVM.h index 82a28270cc1538..ee9f70495e986c 100644 --- a/clang/include/clang/CIR/LowerToLLVM.h +++ b/clang/include/clang/CIR/LowerToLLVM.h @@ -28,8 +28,8 @@ class ModuleOp; namespace cir { namespace direct { -std::unique_ptr<llvm::Module> lowerDirectlyFromCIRToLLVMIR( - mlir::ModuleOp M, llvm::LLVMContext &Ctx); +std::unique_ptr<llvm::Module> +lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp M, llvm::LLVMContext &Ctx); } // namespace direct } // namespace cir diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp index 583fd8126e9518..9101f3cc38441e 100644 --- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp +++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp @@ -7,13 +7,13 @@ //===----------------------------------------------------------------------===// #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" -#include "mlir/IR/MLIRContext.h" -#include "mlir/IR/OwningOpRef.h" using namespace cir; using namespace clang; @@ -51,8 +51,7 @@ class CIRGenConsumer : public clang::ASTConsumer { std::unique_ptr<CIRGenerator> Gen; public: - CIRGenConsumer(CIRGenAction::OutputType Action, - CompilerInstance &CI, + CIRGenConsumer(CIRGenAction::OutputType Action, CompilerInstance &CI, std::unique_ptr<raw_pwrite_stream> OS) : Action(Action), CI(CI), OutputStream(std::move(OS)), FS(&CI.getVirtualFileSystem()), @@ -88,10 +87,9 @@ class CIRGenConsumer : public clang::ASTConsumer { std::move(MLIRCtx), LLVMCtx); BackendAction BEAction = getBackendActionFromOutputType(Action); - emitBackendOutput(CI, CI.getCodeGenOpts(), - C.getTargetInfo().getDataLayoutString(), - LLVMModule.get(), BEAction, FS, - std::move(OutputStream)); + emitBackendOutput( + CI, CI.getCodeGenOpts(), C.getTargetInfo().getDataLayoutString(), + LLVMModule.get(), BEAction, FS, std::move(OutputStream)); break; } } @@ -125,8 +123,8 @@ CIRGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { if (!Out) Out = getOutputStream(CI, InFile, Action); - auto Result = std::make_unique<cir::CIRGenConsumer>( - Action, CI, std::move(Out)); + auto Result = + std::make_unique<cir::CIRGenConsumer>(Action, CI, std::move(Out)); return Result; } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 4bf0f3ab78c53d..349a99c36d2736 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -18,7 +18,6 @@ #include "llvm/IR/Module.h" #include "llvm/Support/TimeProfiler.h" - using namespace cir; using namespace llvm; @@ -26,16 +25,17 @@ namespace cir { namespace direct { std::unique_ptr<llvm::Module> -lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp theModule, LLVMContext &llvmCtx) { +lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp MOp, LLVMContext &LLVMCtx) { llvm::TimeTraceScope scope("lower from CIR to LLVM directly"); - auto ModuleName = theModule.getName(); - auto llvmModule = std::make_unique<llvm::Module>(ModuleName ? *ModuleName : "CIRToLLVMModule", llvmCtx); + std::optional<StringRef> ModuleName = MOp.getName(); + auto M = std::make_unique<llvm::Module>( + ModuleName ? *ModuleName : "CIRToLLVMModule", LLVMCtx); - if (!llvmModule) + if (!M) report_fatal_error("Lowering from LLVMIR dialect to llvm IR failed!"); - return llvmModule; + return M; } } // namespace direct } // namespace cir _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits