Skip to content

Commit 75ea7ae

Browse files
authored
[CIR] Add additional frontend actions (#127249)
Add frontend actions to support emitting assembly, bitcode, and object files when compiling with ClangIR. This change also correctly sets and propagates the target triple in the MLIR and LLVM modules, which was a necessary prerequisite for emitting assembly and object files.
1 parent ddf2408 commit 75ea7ae

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)