Author: Andy Kaylor Date: 2025-01-30T13:11:25-08:00 New Revision: 38ddcb7e3639438dd925229bbbfb20fbcfb23f7f
URL: https://github.com/llvm/llvm-project/commit/38ddcb7e3639438dd925229bbbfb20fbcfb23f7f DIFF: https://github.com/llvm/llvm-project/commit/38ddcb7e3639438dd925229bbbfb20fbcfb23f7f.diff LOG: [CIR] Add framework for CIR to LLVM IR lowering (#124650) 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. Added: clang/include/clang/CIR/LowerToLLVM.h clang/lib/CIR/Lowering/CMakeLists.txt clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp clang/test/CIR/Lowering/hello.c Modified: clang/include/clang/CIR/FrontendAction/CIRGenAction.h clang/lib/CIR/CMakeLists.txt clang/lib/CIR/FrontendAction/CIRGenAction.cpp clang/lib/CIR/FrontendAction/CMakeLists.txt clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp Removed: ################################################################################ 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..9fd0706a91a5a0 --- /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 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..eab6958ac8f6df 100644 --- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp +++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp @@ -7,23 +7,47 @@ //===----------------------------------------------------------------------===// #include "clang/CIR/FrontendAction/CIRGenAction.h" -#include "clang/CIR/CIRGenerator.h" -#include "clang/Frontend/CompilerInstance.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}; @@ -31,18 +55,12 @@ class CIRGenConsumer : public clang::ASTConsumer { std::unique_ptr<CIRGenerator> Gen; 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, + CIRGenConsumer(CIRGenAction::OutputType Action, 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"); @@ -66,6 +84,17 @@ class CIRGenConsumer : public clang::ASTConsumer { 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; + } } } }; @@ -84,6 +113,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"); } @@ -95,10 +126,8 @@ CIRGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { if (!Out) 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)); + auto Result = + std::make_unique<cir::CIRGenConsumer>(Action, CI, std::move(Out)); return Result; } @@ -106,3 +135,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) {} 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..95c304ded91837 --- /dev/null +++ b/clang/lib/CIR/Lowering/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(DirectToLLVM) 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..3687e482fa9bbc --- /dev/null +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -0,0 +1,39 @@ +//====- 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 "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 MOp, LLVMContext &LLVMCtx) { + llvm::TimeTraceScope scope("lower from CIR to LLVM directly"); + + std::optional<StringRef> ModuleName = MOp.getName(); + auto M = std::make_unique<llvm::Module>( + ModuleName ? *ModuleName : "CIRToLLVMModule", LLVMCtx); + + if (!M) + report_fatal_error("Lowering from LLVMIR dialect to llvm IR failed!"); + + return M; +} +} // namespace direct +} // namespace cir diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 079bcd93d6162a..c8d004163b96d8 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -71,7 +71,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() {} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits