Skip to content

Commit 41546e2

Browse files
committed
[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.
1 parent 3861b9d commit 41546e2

File tree

11 files changed

+160
-15
lines changed

11 files changed

+160
-15
lines changed

clang/include/clang/CIR/CIRGenerator.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ class CIRGenerator : public clang::ASTConsumer {
5555
void Initialize(clang::ASTContext &astContext) override;
5656
bool HandleTopLevelDecl(clang::DeclGroupRef group) override;
5757
mlir::ModuleOp getModule() const;
58+
std::unique_ptr<mlir::MLIRContext> takeContext() {
59+
return std::move(mlirContext);
60+
};
5861
};
5962

6063
} // namespace cir

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
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> lowerDirectlyFromCIRToLLVMIR(
32+
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: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88

99
#include "clang/CIR/FrontendAction/CIRGenAction.h"
1010
#include "clang/CIR/CIRGenerator.h"
11+
#include "clang/CIR/LowerToLLVM.h"
12+
#include "clang/CodeGen/BackendUtil.h"
1113
#include "clang/Frontend/CompilerInstance.h"
12-
14+
#include "llvm/IR/Module.h"
1315
#include "mlir/IR/MLIRContext.h"
1416
#include "mlir/IR/OwningOpRef.h"
1517

@@ -18,12 +20,30 @@ using namespace clang;
1820

1921
namespace cir {
2022

23+
static BackendAction
24+
getBackendActionFromOutputType(CIRGenAction::OutputType Action) {
25+
switch (Action) {
26+
case CIRGenAction::OutputType::EmitLLVM:
27+
return BackendAction::Backend_EmitLL;
28+
default:
29+
llvm_unreachable("Unsupported action");
30+
}
31+
}
32+
33+
static std::unique_ptr<llvm::Module> lowerFromCIRToLLVMIR(
34+
const clang::FrontendOptions &FEOpts, mlir::ModuleOp MLIRModule,
35+
std::unique_ptr<mlir::MLIRContext> MLIRCtx, llvm::LLVMContext &LLVMCtx) {
36+
return direct::lowerDirectlyFromCIRToLLVMIR(MLIRModule, LLVMCtx);
37+
}
38+
2139
class CIRGenConsumer : public clang::ASTConsumer {
2240

2341
virtual void anchor();
2442

2543
CIRGenAction::OutputType Action;
2644

45+
CompilerInstance &CI;
46+
2747
std::unique_ptr<raw_pwrite_stream> OutputStream;
2848

2949
ASTContext *Context{nullptr};
@@ -32,17 +52,12 @@ class CIRGenConsumer : public clang::ASTConsumer {
3252

3353
public:
3454
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,
55+
CompilerInstance &CI,
4256
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)) {}
57+
: Action(Action), CI(CI), OutputStream(std::move(OS)),
58+
FS(&CI.getVirtualFileSystem()),
59+
Gen(std::make_unique<CIRGenerator>(CI.getDiagnostics(), std::move(FS),
60+
CI.getCodeGenOpts())) {}
4661

4762
void Initialize(ASTContext &Ctx) override {
4863
assert(!Context && "initialized multiple times");
@@ -58,6 +73,7 @@ class CIRGenConsumer : public clang::ASTConsumer {
5873
void HandleTranslationUnit(ASTContext &C) override {
5974
Gen->HandleTranslationUnit(C);
6075
mlir::ModuleOp MlirModule = Gen->getModule();
76+
auto MLIRCtx = Gen->takeContext();
6177
switch (Action) {
6278
case CIRGenAction::OutputType::EmitCIR:
6379
if (OutputStream && MlirModule) {
@@ -66,6 +82,18 @@ class CIRGenConsumer : public clang::ASTConsumer {
6682
MlirModule->print(*OutputStream, Flags);
6783
}
6884
break;
85+
case CIRGenAction::OutputType::EmitLLVM: {
86+
llvm::LLVMContext LLVMCtx;
87+
auto LLVMModule = lowerFromCIRToLLVMIR(CI.getFrontendOpts(), MlirModule,
88+
std::move(MLIRCtx), LLVMCtx);
89+
90+
BackendAction BEAction = getBackendActionFromOutputType(Action);
91+
emitBackendOutput(CI, CI.getCodeGenOpts(),
92+
C.getTargetInfo().getDataLayoutString(),
93+
LLVMModule.get(), BEAction, FS,
94+
std::move(OutputStream));
95+
break;
96+
}
6997
}
7098
}
7199
};
@@ -84,6 +112,8 @@ getOutputStream(CompilerInstance &CI, StringRef InFile,
84112
switch (Action) {
85113
case CIRGenAction::OutputType::EmitCIR:
86114
return CI.createDefaultOutputFile(false, InFile, "cir");
115+
case CIRGenAction::OutputType::EmitLLVM:
116+
return CI.createDefaultOutputFile(false, InFile, "ll");
87117
}
88118
llvm_unreachable("Invalid CIRGenAction::OutputType");
89119
}
@@ -96,13 +126,15 @@ CIRGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
96126
Out = getOutputStream(CI, InFile, Action);
97127

98128
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+
Action, CI, std::move(Out));
102130

103131
return Result;
104132
}
105133

106134
void EmitCIRAction::anchor() {}
107135
EmitCIRAction::EmitCIRAction(mlir::MLIRContext *MLIRCtx)
108136
: CIRGenAction(OutputType::EmitCIR, MLIRCtx) {}
137+
138+
void EmitLLVMAction::anchor() {}
139+
EmitLLVMAction::EmitLLVMAction(mlir::MLIRContext *MLIRCtx)
140+
: 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
)
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: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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 "mlir/Pass/Pass.h"
17+
#include "mlir/Pass/PassManager.h"
18+
#include "llvm/IR/Module.h"
19+
#include "llvm/Support/TimeProfiler.h"
20+
21+
22+
using namespace cir;
23+
using namespace llvm;
24+
25+
namespace cir {
26+
namespace direct {
27+
28+
std::unique_ptr<llvm::Module>
29+
lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp theModule, LLVMContext &llvmCtx) {
30+
llvm::TimeTraceScope scope("lower from CIR to LLVM directly");
31+
32+
auto ModuleName = theModule.getName();
33+
auto llvmModule = std::make_unique<llvm::Module>(ModuleName ? *ModuleName : "CIRToLLVMModule", llvmCtx);
34+
35+
if (!llvmModule)
36+
report_fatal_error("Lowering from LLVMIR dialect to llvm IR failed!");
37+
38+
return llvmModule;
39+
}
40+
} // namespace direct
41+
} // namespace cir

clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp

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

0 commit comments

Comments
 (0)