llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Andy Kaylor (andykaylor) <details> <summary>Changes</summary> 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. --- Full diff: https://github.com/llvm/llvm-project/pull/124650.diff 11 Files Affected: - (modified) clang/include/clang/CIR/CIRGenerator.h (+3) - (modified) clang/include/clang/CIR/FrontendAction/CIRGenAction.h (+8) - (added) clang/include/clang/CIR/LowerToLLVM.h (+36) - (modified) clang/lib/CIR/CMakeLists.txt (+1) - (modified) clang/lib/CIR/FrontendAction/CIRGenAction.cpp (+46-14) - (modified) clang/lib/CIR/FrontendAction/CMakeLists.txt (+1) - (added) clang/lib/CIR/Lowering/CMakeLists.txt (+1) - (added) clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt (+8) - (added) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+41) - (modified) clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp (+7-1) - (added) clang/test/CIR/Lowering/hello.c (+8) ``````````diff 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() {} `````````` </details> https://github.com/llvm/llvm-project/pull/124650 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits