Skip to content

Commit 62a33eb

Browse files
committed
[CIR] Add addition frontend actions
Add frontend actions to support emitting assembly, bitcode, and object files when compiling with ClangIR.
1 parent 1ff5f32 commit 62a33eb

File tree

8 files changed

+111
-4
lines changed

8 files changed

+111
-4
lines changed

clang/include/clang/CIR/Dialect/IR/CIRDialect.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ def CIR_Dialect : Dialect {
2828
let useDefaultTypePrinterParser = 0;
2929

3030
let extraClassDeclaration = [{
31+
static llvm::StringRef getTripleAttrName() { return "cir.triple"; }
32+
3133
void registerAttributes();
3234
void registerTypes();
3335

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ class CIRGenConsumer;
2525
class CIRGenAction : public clang::ASTFrontendAction {
2626
public:
2727
enum class OutputType {
28+
EmitAssembly,
2829
EmitCIR,
2930
EmitLLVM,
31+
EmitBC,
32+
EmitObj,
3033
};
3134

3235
private:
@@ -63,6 +66,27 @@ class EmitLLVMAction : public CIRGenAction {
6366
EmitLLVMAction(mlir::MLIRContext *MLIRCtx = nullptr);
6467
};
6568

69+
class EmitBCAction : public CIRGenAction {
70+
virtual void anchor();
71+
72+
public:
73+
EmitBCAction(mlir::MLIRContext *MLIRCtx = nullptr);
74+
};
75+
76+
class EmitAssemblyAction : public CIRGenAction {
77+
virtual void anchor();
78+
79+
public:
80+
EmitAssemblyAction(mlir::MLIRContext *MLIRCtx = nullptr);
81+
};
82+
83+
class EmitObjAction : public CIRGenAction {
84+
virtual void anchor();
85+
86+
public:
87+
EmitObjAction(mlir::MLIRContext *MLIRCtx = nullptr);
88+
};
89+
6690
} // namespace cir
6791

6892
#endif

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
5252
DoubleTy = cir::DoubleType::get(&getMLIRContext());
5353
FP80Ty = cir::FP80Type::get(&getMLIRContext());
5454
FP128Ty = cir::FP128Type::get(&getMLIRContext());
55+
56+
theModule->setAttr(cir::CIRDialect::getTripleAttrName(),
57+
builder.getStringAttr(getTriple().str()));
5558
}
5659

5760
mlir::Location CIRGenModule::getLoc(SourceLocation cLoc) {

clang/lib/CIR/CodeGen/CIRGenModule.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
#include "mlir/IR/BuiltinOps.h"
2222
#include "mlir/IR/MLIRContext.h"
2323
#include "clang/Basic/SourceManager.h"
24+
#include "clang/Basic/TargetInfo.h"
2425
#include "llvm/ADT/StringRef.h"
26+
#include "llvm/TargetParser/Triple.h"
2527

2628
namespace clang {
2729
class ASTContext;
@@ -88,6 +90,8 @@ class CIRGenModule : public CIRGenTypeCache {
8890
void emitGlobalVarDefinition(const clang::VarDecl *vd,
8991
bool isTentative = false);
9092

93+
const llvm::Triple &getTriple() const { return target.getTriple(); }
94+
9195
/// Helpers to emit "not yet implemented" error diagnostics
9296
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef);
9397

clang/lib/CIR/FrontendAction/CIRGenAction.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,14 @@ getBackendActionFromOutputType(CIRGenAction::OutputType Action) {
2727
assert(false &&
2828
"Unsupported output type for getBackendActionFromOutputType!");
2929
break; // Unreachable, but fall through to report that
30+
case CIRGenAction::OutputType::EmitAssembly:
31+
return BackendAction::Backend_EmitAssembly;
32+
case CIRGenAction::OutputType::EmitBC:
33+
return BackendAction::Backend_EmitBC;
3034
case CIRGenAction::OutputType::EmitLLVM:
3135
return BackendAction::Backend_EmitLL;
36+
case CIRGenAction::OutputType::EmitObj:
37+
return BackendAction::Backend_EmitObj;
3238
}
3339
// We should only get here if a non-enum value is passed in or we went through
3440
// the assert(false) case above
@@ -84,7 +90,10 @@ class CIRGenConsumer : public clang::ASTConsumer {
8490
MlirModule->print(*OutputStream, Flags);
8591
}
8692
break;
87-
case CIRGenAction::OutputType::EmitLLVM: {
93+
case CIRGenAction::OutputType::EmitLLVM:
94+
case CIRGenAction::OutputType::EmitBC:
95+
case CIRGenAction::OutputType::EmitObj:
96+
case CIRGenAction::OutputType::EmitAssembly: {
8897
llvm::LLVMContext LLVMCtx;
8998
std::unique_ptr<llvm::Module> LLVMModule =
9099
lowerFromCIRToLLVMIR(MlirModule, LLVMCtx);
@@ -111,10 +120,16 @@ static std::unique_ptr<raw_pwrite_stream>
111120
getOutputStream(CompilerInstance &CI, StringRef InFile,
112121
CIRGenAction::OutputType Action) {
113122
switch (Action) {
123+
case CIRGenAction::OutputType::EmitAssembly:
124+
return CI.createDefaultOutputFile(false, InFile, "s");
114125
case CIRGenAction::OutputType::EmitCIR:
115126
return CI.createDefaultOutputFile(false, InFile, "cir");
116127
case CIRGenAction::OutputType::EmitLLVM:
117128
return CI.createDefaultOutputFile(false, InFile, "ll");
129+
case CIRGenAction::OutputType::EmitBC:
130+
return CI.createDefaultOutputFile(true, InFile, "bc");
131+
case CIRGenAction::OutputType::EmitObj:
132+
return CI.createDefaultOutputFile(true, InFile, "o");
118133
}
119134
llvm_unreachable("Invalid CIRGenAction::OutputType");
120135
}
@@ -132,10 +147,22 @@ CIRGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
132147
return Result;
133148
}
134149

150+
void EmitAssemblyAction::anchor() {}
151+
EmitAssemblyAction::EmitAssemblyAction(mlir::MLIRContext *MLIRCtx)
152+
: CIRGenAction(OutputType::EmitAssembly, MLIRCtx) {}
153+
135154
void EmitCIRAction::anchor() {}
136155
EmitCIRAction::EmitCIRAction(mlir::MLIRContext *MLIRCtx)
137156
: CIRGenAction(OutputType::EmitCIR, MLIRCtx) {}
138157

139158
void EmitLLVMAction::anchor() {}
140159
EmitLLVMAction::EmitLLVMAction(mlir::MLIRContext *MLIRCtx)
141160
: CIRGenAction(OutputType::EmitLLVM, MLIRCtx) {}
161+
162+
void EmitBCAction::anchor() {}
163+
EmitBCAction::EmitBCAction(mlir::MLIRContext *MLIRCtx)
164+
: CIRGenAction(OutputType::EmitBC, MLIRCtx) {}
165+
166+
void EmitObjAction::anchor() {}
167+
EmitObjAction::EmitObjAction(mlir::MLIRContext *MLIRCtx)
168+
: CIRGenAction(OutputType::EmitObj, MLIRCtx) {}

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ struct ConvertCIRToLLVMPass
114114
}
115115
void runOnOperation() final;
116116

117+
void processCIRAttrs(mlir::ModuleOp module);
118+
117119
StringRef getDescription() const override {
118120
return "Convert the prepared CIR dialect module to LLVM dialect";
119121
}
@@ -271,6 +273,13 @@ static void prepareTypeConverter(mlir::LLVMTypeConverter &converter,
271273
});
272274
}
273275

276+
void ConvertCIRToLLVMPass::processCIRAttrs(mlir::ModuleOp module) {
277+
// Lower the module attributes to LLVM equivalents.
278+
if (auto tripleAttr = module->getAttr(cir::CIRDialect::getTripleAttrName()))
279+
module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
280+
tripleAttr);
281+
}
282+
274283
void ConvertCIRToLLVMPass::runOnOperation() {
275284
llvm::TimeTraceScope scope("Convert CIR to LLVM Pass");
276285

@@ -283,6 +292,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
283292

284293
patterns.add<CIRToLLVMGlobalOpLowering>(converter, patterns.getContext(), dl);
285294

295+
processCIRAttrs(module);
296+
286297
mlir::ConversionTarget target(getContext());
287298
target.addLegalOp<mlir::ModuleOp>();
288299
target.addLegalDialect<mlir::LLVM::LLVMDialect>();

clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,18 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
6262
return std::make_unique<DumpCompilerOptionsAction>();
6363
case DumpRawTokens: return std::make_unique<DumpRawTokensAction>();
6464
case DumpTokens: return std::make_unique<DumpTokensAction>();
65-
case EmitAssembly: return std::make_unique<EmitAssemblyAction>();
66-
case EmitBC: return std::make_unique<EmitBCAction>();
65+
case EmitAssembly:
66+
#if CLANG_ENABLE_CIR
67+
if (UseCIR)
68+
return std::make_unique<cir::EmitAssemblyAction>();
69+
#endif
70+
return std::make_unique<EmitAssemblyAction>();
71+
case EmitBC:
72+
#if CLANG_ENABLE_CIR
73+
if (UseCIR)
74+
return std::make_unique<cir::EmitBCAction>();
75+
#endif
76+
return std::make_unique<EmitBCAction>();
6777
case EmitCIR:
6878
#if CLANG_ENABLE_CIR
6979
return std::make_unique<cir::EmitCIRAction>();
@@ -80,7 +90,12 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
8090
}
8191
case EmitLLVMOnly: return std::make_unique<EmitLLVMOnlyAction>();
8292
case EmitCodeGenOnly: return std::make_unique<EmitCodeGenOnlyAction>();
83-
case EmitObj: return std::make_unique<EmitObjAction>();
93+
case EmitObj:
94+
#if CLANG_ENABLE_CIR
95+
if (UseCIR)
96+
return std::make_unique<cir::EmitObjAction>();
97+
#endif
98+
return std::make_unique<EmitObjAction>();
8499
case ExtractAPI:
85100
return std::make_unique<ExtractAPIAction>();
86101
case FixIt: return std::make_unique<FixItAction>();

clang/test/CIR/emit-actions.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -S %s -o - | FileCheck %s -check-prefix=ASM
2+
3+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm-bc %s -o %t.bc
4+
// RUN: llvm-dis %t.bc -o - | FileCheck %s -check-prefix=BC
5+
6+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-obj %s -o %t.o
7+
// RUN: llvm-objdump -t %t.o | FileCheck %s -check-prefix=OBJ
8+
9+
// TODO: Make this test target-independent
10+
// REQUIRES: x86-registered-target
11+
12+
int x = 1;
13+
14+
// BC: @x = dso_local global i32 1
15+
16+
// ASM: x:
17+
// ASM: .long 1
18+
// ASM: .size x, 4
19+
20+
// OBJ: .data
21+
// OBJ-SAME: x

0 commit comments

Comments
 (0)