[clang] [CIR] Add framework for CIR to LLVM IR lowering (PR #124650)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 27 15:02:25 PST 2025
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
More information about the cfe-commits
mailing list