Skip to content

Commit 38ddcb7

Browse files
authored
[CIR] Add framework for CIR to LLVM IR lowering (llvm#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.
1 parent fdfd979 commit 38ddcb7

File tree

10 files changed

+160
-19
lines changed

10 files changed

+160
-19
lines changed

clang/include/clang/CIR/FrontendAction/CIRGenAction.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class CIRGenAction : public clang::ASTFrontendAction {
2626
public:
2727
enum class OutputType {
2828
EmitCIR,
29+
EmitLLVM,
2930
};
3031

3132
private:
@@ -55,6 +56,13 @@ class EmitCIRAction : public CIRGenAction {
5556
EmitCIRAction(mlir::MLIRContext *MLIRCtx = nullptr);
5657
};
5758

59+
class EmitLLVMAction : public CIRGenAction {
60+
virtual void anchor();
61+
62+
public:
63+
EmitLLVMAction(mlir::MLIRContext *MLIRCtx = nullptr);
64+
};
65+
5866
} // namespace cir
5967

6068
#endif

clang/include/clang/CIR/LowerToLLVM.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//====- LowerToLLVM.h- Lowering from CIR to LLVM --------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file declares an interface for converting CIR modules to LLVM IR.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
#ifndef CLANG_CIR_LOWERTOLLVM_H
13+
#define CLANG_CIR_LOWERTOLLVM_H
14+
15+
#include "mlir/Pass/Pass.h"
16+
17+
#include <memory>
18+
19+
namespace llvm {
20+
class LLVMContext;
21+
class Module;
22+
} // namespace llvm
23+
24+
namespace mlir {
25+
class ModuleOp;
26+
} // namespace mlir
27+
28+
namespace cir {
29+
30+
namespace direct {
31+
std::unique_ptr<llvm::Module>
32+
lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp M, llvm::LLVMContext &Ctx);
33+
} // namespace direct
34+
} // namespace cir
35+
36+
#endif // CLANG_CIR_LOWERTOLLVM_H

clang/lib/CIR/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ add_subdirectory(Dialect)
55
add_subdirectory(CodeGen)
66
add_subdirectory(FrontendAction)
77
add_subdirectory(Interfaces)
8+
add_subdirectory(Lowering)

clang/lib/CIR/FrontendAction/CIRGenAction.cpp

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,42 +7,60 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "clang/CIR/FrontendAction/CIRGenAction.h"
10-
#include "clang/CIR/CIRGenerator.h"
11-
#include "clang/Frontend/CompilerInstance.h"
12-
1310
#include "mlir/IR/MLIRContext.h"
1411
#include "mlir/IR/OwningOpRef.h"
12+
#include "clang/CIR/CIRGenerator.h"
13+
#include "clang/CIR/LowerToLLVM.h"
14+
#include "clang/CodeGen/BackendUtil.h"
15+
#include "clang/Frontend/CompilerInstance.h"
16+
#include "llvm/IR/Module.h"
1517

1618
using namespace cir;
1719
using namespace clang;
1820

1921
namespace cir {
2022

23+
static BackendAction
24+
getBackendActionFromOutputType(CIRGenAction::OutputType Action) {
25+
switch (Action) {
26+
case CIRGenAction::OutputType::EmitCIR:
27+
assert(false &&
28+
"Unsupported output type for getBackendActionFromOutputType!");
29+
break; // Unreachable, but fall through to report that
30+
case CIRGenAction::OutputType::EmitLLVM:
31+
return BackendAction::Backend_EmitLL;
32+
}
33+
// We should only get here if a non-enum value is passed in or we went through
34+
// the assert(false) case above
35+
llvm_unreachable("Unsupported output type!");
36+
}
37+
38+
static std::unique_ptr<llvm::Module>
39+
lowerFromCIRToLLVMIR(mlir::ModuleOp MLIRModule, llvm::LLVMContext &LLVMCtx) {
40+
return direct::lowerDirectlyFromCIRToLLVMIR(MLIRModule, LLVMCtx);
41+
}
42+
2143
class CIRGenConsumer : public clang::ASTConsumer {
2244

2345
virtual void anchor();
2446

2547
CIRGenAction::OutputType Action;
2648

49+
CompilerInstance &CI;
50+
2751
std::unique_ptr<raw_pwrite_stream> OutputStream;
2852

2953
ASTContext *Context{nullptr};
3054
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
3155
std::unique_ptr<CIRGenerator> Gen;
3256

3357
public:
34-
CIRGenConsumer(CIRGenAction::OutputType Action,
35-
DiagnosticsEngine &DiagnosticsEngine,
36-
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
37-
const HeaderSearchOptions &HeaderSearchOptions,
38-
const CodeGenOptions &CodeGenOptions,
39-
const TargetOptions &TargetOptions,
40-
const LangOptions &LangOptions,
41-
const FrontendOptions &FEOptions,
58+
CIRGenConsumer(CIRGenAction::OutputType Action, CompilerInstance &CI,
4259
std::unique_ptr<raw_pwrite_stream> OS)
43-
: Action(Action), OutputStream(std::move(OS)), FS(VFS),
44-
Gen(std::make_unique<CIRGenerator>(DiagnosticsEngine, std::move(VFS),
45-
CodeGenOptions)) {}
60+
: Action(Action), CI(CI), OutputStream(std::move(OS)),
61+
FS(&CI.getVirtualFileSystem()),
62+
Gen(std::make_unique<CIRGenerator>(CI.getDiagnostics(), std::move(FS),
63+
CI.getCodeGenOpts())) {}
4664

4765
void Initialize(ASTContext &Ctx) override {
4866
assert(!Context && "initialized multiple times");
@@ -66,6 +84,17 @@ class CIRGenConsumer : public clang::ASTConsumer {
6684
MlirModule->print(*OutputStream, Flags);
6785
}
6886
break;
87+
case CIRGenAction::OutputType::EmitLLVM: {
88+
llvm::LLVMContext LLVMCtx;
89+
std::unique_ptr<llvm::Module> LLVMModule =
90+
lowerFromCIRToLLVMIR(MlirModule, LLVMCtx);
91+
92+
BackendAction BEAction = getBackendActionFromOutputType(Action);
93+
emitBackendOutput(
94+
CI, CI.getCodeGenOpts(), C.getTargetInfo().getDataLayoutString(),
95+
LLVMModule.get(), BEAction, FS, std::move(OutputStream));
96+
break;
97+
}
6998
}
7099
}
71100
};
@@ -84,6 +113,8 @@ getOutputStream(CompilerInstance &CI, StringRef InFile,
84113
switch (Action) {
85114
case CIRGenAction::OutputType::EmitCIR:
86115
return CI.createDefaultOutputFile(false, InFile, "cir");
116+
case CIRGenAction::OutputType::EmitLLVM:
117+
return CI.createDefaultOutputFile(false, InFile, "ll");
87118
}
88119
llvm_unreachable("Invalid CIRGenAction::OutputType");
89120
}
@@ -95,14 +126,16 @@ CIRGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
95126
if (!Out)
96127
Out = getOutputStream(CI, InFile, Action);
97128

98-
auto Result = std::make_unique<cir::CIRGenConsumer>(
99-
Action, CI.getDiagnostics(), &CI.getVirtualFileSystem(),
100-
CI.getHeaderSearchOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(),
101-
CI.getLangOpts(), CI.getFrontendOpts(), std::move(Out));
129+
auto Result =
130+
std::make_unique<cir::CIRGenConsumer>(Action, CI, std::move(Out));
102131

103132
return Result;
104133
}
105134

106135
void EmitCIRAction::anchor() {}
107136
EmitCIRAction::EmitCIRAction(mlir::MLIRContext *MLIRCtx)
108137
: CIRGenAction(OutputType::EmitCIR, MLIRCtx) {}
138+
139+
void EmitLLVMAction::anchor() {}
140+
EmitLLVMAction::EmitLLVMAction(mlir::MLIRContext *MLIRCtx)
141+
: CIRGenAction(OutputType::EmitLLVM, MLIRCtx) {}

clang/lib/CIR/FrontendAction/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ add_clang_library(clangCIRFrontendAction
1212
clangAST
1313
clangFrontend
1414
clangCIR
15+
clangCIRLoweringDirectToLLVM
1516
MLIRCIR
1617
MLIRIR
1718
)

clang/lib/CIR/Lowering/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
add_subdirectory(DirectToLLVM)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
set(LLVM_LINK_COMPONENTS
2+
Core
3+
Support
4+
)
5+
6+
add_clang_library(clangCIRLoweringDirectToLLVM
7+
LowerToLLVM.cpp
8+
)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//====- LowerToLLVM.cpp - Lowering from CIR to LLVMIR ---------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file implements lowering of CIR operations to LLVMIR.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "clang/CIR/LowerToLLVM.h"
14+
15+
#include "mlir/IR/BuiltinOps.h"
16+
#include "llvm/IR/Module.h"
17+
#include "llvm/Support/TimeProfiler.h"
18+
19+
using namespace cir;
20+
using namespace llvm;
21+
22+
namespace cir {
23+
namespace direct {
24+
25+
std::unique_ptr<llvm::Module>
26+
lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp MOp, LLVMContext &LLVMCtx) {
27+
llvm::TimeTraceScope scope("lower from CIR to LLVM directly");
28+
29+
std::optional<StringRef> ModuleName = MOp.getName();
30+
auto M = std::make_unique<llvm::Module>(
31+
ModuleName ? *ModuleName : "CIRToLLVMModule", LLVMCtx);
32+
33+
if (!M)
34+
report_fatal_error("Lowering from LLVMIR dialect to llvm IR failed!");
35+
36+
return M;
37+
}
38+
} // namespace direct
39+
} // namespace cir

clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,13 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
7171
llvm_unreachable("CIR suppport not built into clang");
7272
#endif
7373
case EmitHTML: return std::make_unique<HTMLPrintAction>();
74-
case EmitLLVM: return std::make_unique<EmitLLVMAction>();
74+
case EmitLLVM: {
75+
#if CLANG_ENABLE_CIR
76+
if (UseCIR)
77+
return std::make_unique<cir::EmitLLVMAction>();
78+
#endif
79+
return std::make_unique<EmitLLVMAction>();
80+
}
7581
case EmitLLVMOnly: return std::make_unique<EmitLLVMOnlyAction>();
7682
case EmitCodeGenOnly: return std::make_unique<EmitCodeGenOnlyAction>();
7783
case EmitObj: return std::make_unique<EmitObjAction>();

clang/test/CIR/Lowering/hello.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Smoke test for ClangIR-to-LLVM IR code generation
2+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s
3+
4+
// TODO: Add checks when proper lowering is implemented.
5+
// For now, we're just creating an empty module.
6+
// CHECK: ModuleID
7+
8+
void foo() {}

0 commit comments

Comments
 (0)