[clang] [CIR] Add addition frontend actions (PR #127249)
Andy Kaylor via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 14 11:37:02 PST 2025
https://github.com/andykaylor created https://github.com/llvm/llvm-project/pull/127249
Add frontend actions to support emitting assembly, bitcode, and object files when compiling with ClangIR.
>From 62a33eb8f488bd2fcec8f155da2ec646b3562824 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <akaylor at nvidia.com>
Date: Fri, 14 Feb 2025 11:25:08 -0800
Subject: [PATCH] [CIR] Add addition frontend actions
Add frontend actions to support emitting assembly, bitcode, and
object files when compiling with ClangIR.
---
.../clang/CIR/Dialect/IR/CIRDialect.td | 2 ++
.../clang/CIR/FrontendAction/CIRGenAction.h | 24 +++++++++++++++
clang/lib/CIR/CodeGen/CIRGenModule.cpp | 3 ++
clang/lib/CIR/CodeGen/CIRGenModule.h | 4 +++
clang/lib/CIR/FrontendAction/CIRGenAction.cpp | 29 ++++++++++++++++++-
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 11 +++++++
.../ExecuteCompilerInvocation.cpp | 21 ++++++++++++--
clang/test/CIR/emit-actions.cpp | 21 ++++++++++++++
8 files changed, 111 insertions(+), 4 deletions(-)
create mode 100644 clang/test/CIR/emit-actions.cpp
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
index 305a06427ed0e..73759cfa9c3c9 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
@@ -28,6 +28,8 @@ def CIR_Dialect : Dialect {
let useDefaultTypePrinterParser = 0;
let extraClassDeclaration = [{
+ static llvm::StringRef getTripleAttrName() { return "cir.triple"; }
+
void registerAttributes();
void registerTypes();
diff --git a/clang/include/clang/CIR/FrontendAction/CIRGenAction.h b/clang/include/clang/CIR/FrontendAction/CIRGenAction.h
index 5f9110bc83b89..99495f4718c5f 100644
--- a/clang/include/clang/CIR/FrontendAction/CIRGenAction.h
+++ b/clang/include/clang/CIR/FrontendAction/CIRGenAction.h
@@ -25,8 +25,11 @@ class CIRGenConsumer;
class CIRGenAction : public clang::ASTFrontendAction {
public:
enum class OutputType {
+ EmitAssembly,
EmitCIR,
EmitLLVM,
+ EmitBC,
+ EmitObj,
};
private:
@@ -63,6 +66,27 @@ class EmitLLVMAction : public CIRGenAction {
EmitLLVMAction(mlir::MLIRContext *MLIRCtx = nullptr);
};
+class EmitBCAction : public CIRGenAction {
+ virtual void anchor();
+
+public:
+ EmitBCAction(mlir::MLIRContext *MLIRCtx = nullptr);
+};
+
+class EmitAssemblyAction : public CIRGenAction {
+ virtual void anchor();
+
+public:
+ EmitAssemblyAction(mlir::MLIRContext *MLIRCtx = nullptr);
+};
+
+class EmitObjAction : public CIRGenAction {
+ virtual void anchor();
+
+public:
+ EmitObjAction(mlir::MLIRContext *MLIRCtx = nullptr);
+};
+
} // namespace cir
#endif
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 2615ae382cb8b..cbecdf925aa5d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -52,6 +52,9 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
DoubleTy = cir::DoubleType::get(&getMLIRContext());
FP80Ty = cir::FP80Type::get(&getMLIRContext());
FP128Ty = cir::FP128Type::get(&getMLIRContext());
+
+ theModule->setAttr(cir::CIRDialect::getTripleAttrName(),
+ builder.getStringAttr(getTriple().str()));
}
mlir::Location CIRGenModule::getLoc(SourceLocation cLoc) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
index 1c7ed63773900..29bb4036218e4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -21,7 +21,9 @@
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/MLIRContext.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/TargetParser/Triple.h"
namespace clang {
class ASTContext;
@@ -88,6 +90,8 @@ class CIRGenModule : public CIRGenTypeCache {
void emitGlobalVarDefinition(const clang::VarDecl *vd,
bool isTentative = false);
+ const llvm::Triple &getTriple() const { return target.getTriple(); }
+
/// Helpers to emit "not yet implemented" error diagnostics
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef);
diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
index eab6958ac8f6d..0f686a36b982b 100644
--- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
+++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
@@ -27,8 +27,14 @@ getBackendActionFromOutputType(CIRGenAction::OutputType Action) {
assert(false &&
"Unsupported output type for getBackendActionFromOutputType!");
break; // Unreachable, but fall through to report that
+ case CIRGenAction::OutputType::EmitAssembly:
+ return BackendAction::Backend_EmitAssembly;
+ case CIRGenAction::OutputType::EmitBC:
+ return BackendAction::Backend_EmitBC;
case CIRGenAction::OutputType::EmitLLVM:
return BackendAction::Backend_EmitLL;
+ case CIRGenAction::OutputType::EmitObj:
+ return BackendAction::Backend_EmitObj;
}
// We should only get here if a non-enum value is passed in or we went through
// the assert(false) case above
@@ -84,7 +90,10 @@ class CIRGenConsumer : public clang::ASTConsumer {
MlirModule->print(*OutputStream, Flags);
}
break;
- case CIRGenAction::OutputType::EmitLLVM: {
+ case CIRGenAction::OutputType::EmitLLVM:
+ case CIRGenAction::OutputType::EmitBC:
+ case CIRGenAction::OutputType::EmitObj:
+ case CIRGenAction::OutputType::EmitAssembly: {
llvm::LLVMContext LLVMCtx;
std::unique_ptr<llvm::Module> LLVMModule =
lowerFromCIRToLLVMIR(MlirModule, LLVMCtx);
@@ -111,10 +120,16 @@ static std::unique_ptr<raw_pwrite_stream>
getOutputStream(CompilerInstance &CI, StringRef InFile,
CIRGenAction::OutputType Action) {
switch (Action) {
+ case CIRGenAction::OutputType::EmitAssembly:
+ return CI.createDefaultOutputFile(false, InFile, "s");
case CIRGenAction::OutputType::EmitCIR:
return CI.createDefaultOutputFile(false, InFile, "cir");
case CIRGenAction::OutputType::EmitLLVM:
return CI.createDefaultOutputFile(false, InFile, "ll");
+ case CIRGenAction::OutputType::EmitBC:
+ return CI.createDefaultOutputFile(true, InFile, "bc");
+ case CIRGenAction::OutputType::EmitObj:
+ return CI.createDefaultOutputFile(true, InFile, "o");
}
llvm_unreachable("Invalid CIRGenAction::OutputType");
}
@@ -132,6 +147,10 @@ CIRGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
return Result;
}
+void EmitAssemblyAction::anchor() {}
+EmitAssemblyAction::EmitAssemblyAction(mlir::MLIRContext *MLIRCtx)
+ : CIRGenAction(OutputType::EmitAssembly, MLIRCtx) {}
+
void EmitCIRAction::anchor() {}
EmitCIRAction::EmitCIRAction(mlir::MLIRContext *MLIRCtx)
: CIRGenAction(OutputType::EmitCIR, MLIRCtx) {}
@@ -139,3 +158,11 @@ EmitCIRAction::EmitCIRAction(mlir::MLIRContext *MLIRCtx)
void EmitLLVMAction::anchor() {}
EmitLLVMAction::EmitLLVMAction(mlir::MLIRContext *MLIRCtx)
: CIRGenAction(OutputType::EmitLLVM, MLIRCtx) {}
+
+void EmitBCAction::anchor() {}
+EmitBCAction::EmitBCAction(mlir::MLIRContext *MLIRCtx)
+ : CIRGenAction(OutputType::EmitBC, MLIRCtx) {}
+
+void EmitObjAction::anchor() {}
+EmitObjAction::EmitObjAction(mlir::MLIRContext *MLIRCtx)
+ : CIRGenAction(OutputType::EmitObj, MLIRCtx) {}
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index d60a6b38b0c12..5915a9517b028 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -114,6 +114,8 @@ struct ConvertCIRToLLVMPass
}
void runOnOperation() final;
+ void processCIRAttrs(mlir::ModuleOp module);
+
StringRef getDescription() const override {
return "Convert the prepared CIR dialect module to LLVM dialect";
}
@@ -271,6 +273,13 @@ static void prepareTypeConverter(mlir::LLVMTypeConverter &converter,
});
}
+void ConvertCIRToLLVMPass::processCIRAttrs(mlir::ModuleOp module) {
+ // Lower the module attributes to LLVM equivalents.
+ if (auto tripleAttr = module->getAttr(cir::CIRDialect::getTripleAttrName()))
+ module->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
+ tripleAttr);
+}
+
void ConvertCIRToLLVMPass::runOnOperation() {
llvm::TimeTraceScope scope("Convert CIR to LLVM Pass");
@@ -283,6 +292,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
patterns.add<CIRToLLVMGlobalOpLowering>(converter, patterns.getContext(), dl);
+ processCIRAttrs(module);
+
mlir::ConversionTarget target(getContext());
target.addLegalOp<mlir::ModuleOp>();
target.addLegalDialect<mlir::LLVM::LLVMDialect>();
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index c8d004163b96d..bb3bb0aac78bf 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -62,8 +62,18 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
return std::make_unique<DumpCompilerOptionsAction>();
case DumpRawTokens: return std::make_unique<DumpRawTokensAction>();
case DumpTokens: return std::make_unique<DumpTokensAction>();
- case EmitAssembly: return std::make_unique<EmitAssemblyAction>();
- case EmitBC: return std::make_unique<EmitBCAction>();
+ case EmitAssembly:
+#if CLANG_ENABLE_CIR
+ if (UseCIR)
+ return std::make_unique<cir::EmitAssemblyAction>();
+#endif
+ return std::make_unique<EmitAssemblyAction>();
+ case EmitBC:
+#if CLANG_ENABLE_CIR
+ if (UseCIR)
+ return std::make_unique<cir::EmitBCAction>();
+#endif
+ return std::make_unique<EmitBCAction>();
case EmitCIR:
#if CLANG_ENABLE_CIR
return std::make_unique<cir::EmitCIRAction>();
@@ -80,7 +90,12 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
}
case EmitLLVMOnly: return std::make_unique<EmitLLVMOnlyAction>();
case EmitCodeGenOnly: return std::make_unique<EmitCodeGenOnlyAction>();
- case EmitObj: return std::make_unique<EmitObjAction>();
+ case EmitObj:
+#if CLANG_ENABLE_CIR
+ if (UseCIR)
+ return std::make_unique<cir::EmitObjAction>();
+#endif
+ return std::make_unique<EmitObjAction>();
case ExtractAPI:
return std::make_unique<ExtractAPIAction>();
case FixIt: return std::make_unique<FixItAction>();
diff --git a/clang/test/CIR/emit-actions.cpp b/clang/test/CIR/emit-actions.cpp
new file mode 100644
index 0000000000000..94ddf23b34753
--- /dev/null
+++ b/clang/test/CIR/emit-actions.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -S %s -o - | FileCheck %s -check-prefix=ASM
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm-bc %s -o %t.bc
+// RUN: llvm-dis %t.bc -o - | FileCheck %s -check-prefix=BC
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-obj %s -o %t.o
+// RUN: llvm-objdump -t %t.o | FileCheck %s -check-prefix=OBJ
+
+// TODO: Make this test target-independent
+// REQUIRES: x86-registered-target
+
+int x = 1;
+
+// BC: @x = dso_local global i32 1
+
+// ASM: x:
+// ASM: .long 1
+// ASM: .size x, 4
+
+// OBJ: .data
+// OBJ-SAME: x
More information about the cfe-commits
mailing list