https://github.com/andykaylor updated https://github.com/llvm/llvm-project/pull/125260
>From 4801886dd4c45d32891a7337ad7430a6c5137929 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Tue, 28 Jan 2025 12:28:58 -0800 Subject: [PATCH 1/8] [CIR] Initial implementation of CIR-to-LLVM IR lowering pass This change introduces lowering from CIR to LLVM IR of global integer variables, using defaults for attributes that aren't yet implemented. --- clang/include/clang/CIR/LowerToLLVM.h | 22 ++- .../CIR/Lowering/DirectToLLVM/CMakeLists.txt | 7 + .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 130 +++++++++++++++++- clang/test/CIR/Lowering/global-var-simple.cpp | 63 +++++++++ clang/test/CIR/Lowering/hello.c | 10 +- 5 files changed, 225 insertions(+), 7 deletions(-) create mode 100644 clang/test/CIR/Lowering/global-var-simple.cpp diff --git a/clang/include/clang/CIR/LowerToLLVM.h b/clang/include/clang/CIR/LowerToLLVM.h index afa1c1923ed516..1135dbcbe0354b 100644 --- a/clang/include/clang/CIR/LowerToLLVM.h +++ b/clang/include/clang/CIR/LowerToLLVM.h @@ -12,7 +12,9 @@ #ifndef CLANG_CIR_LOWERTOLLVM_H #define CLANG_CIR_LOWERTOLLVM_H -#include "mlir/Pass/Pass.h" +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" +#include "mlir/Transforms/DialectConversion.h" +#include "clang/CIR/Dialect/IR/CIRDialect.h" #include <memory> @@ -31,6 +33,24 @@ namespace direct { std::unique_ptr<llvm::Module> lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, llvm::LLVMContext &llvmCtx); + +class CIRToLLVMGlobalOpLowering + : public mlir::OpConversionPattern<cir::GlobalOp> { + mlir::DataLayout const &dataLayout; + +public: + CIRToLLVMGlobalOpLowering(const mlir::TypeConverter &typeConverter, + mlir::MLIRContext *context, + mlir::DataLayout const &dataLayout) + : OpConversionPattern(typeConverter, context), dataLayout(dataLayout) { + setHasBoundedRewriteRecursion(); + } + + mlir::LogicalResult + matchAndRewrite(cir::GlobalOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const override; +}; + } // namespace direct } // namespace cir diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt b/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt index 0268234c3a2896..da802605676ac0 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt +++ b/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt @@ -3,6 +3,13 @@ set(LLVM_LINK_COMPONENTS Support ) +get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS) + add_clang_library(clangCIRLoweringDirectToLLVM LowerToLLVM.cpp + + LINK_LIBS + ${dialect_libs} + MLIRBuiltinToLLVMIRTranslation + MLIRLLVMToLLVMIRTranslation ) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 63d2b51b428357..b24c41a93082d4 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -12,7 +12,19 @@ #include "clang/CIR/LowerToLLVM.h" +#include "mlir/Conversion/LLVMCommon/TypeConverter.h" +#include "mlir/Dialect/DLTI/DLTI.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" +#include "mlir/IR/BuiltinDialect.h" #include "mlir/IR/BuiltinOps.h" +#include "mlir/Pass/Pass.h" +#include "mlir/Pass/PassManager.h" +#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h" +#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h" +#include "mlir/Target/LLVMIR/Export.h" +#include "mlir/Transforms/DialectConversion.h" +#include "clang/CIR/Dialect/IR/CIRDialect.h" #include "llvm/IR/Module.h" #include "llvm/Support/TimeProfiler.h" @@ -22,13 +34,127 @@ using namespace llvm; namespace cir { namespace direct { +struct ConvertCIRToLLVMPass + : public mlir::PassWrapper<ConvertCIRToLLVMPass, + mlir::OperationPass<mlir::ModuleOp>> { + void getDependentDialects(mlir::DialectRegistry ®istry) const override { + registry.insert<mlir::BuiltinDialect, mlir::DLTIDialect, + mlir::LLVM::LLVMDialect, mlir::func::FuncDialect>(); + } + void runOnOperation() final; + + StringRef getDescription() const override { + return "Convert the prepared CIR dialect module to LLVM dialect"; + } + + StringRef getArgument() const override { return "cir-flat-to-llvm"; } +}; + +mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite( + cir::GlobalOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + + // Fetch required values to create LLVM op. + const mlir::Type cirSymType = op.getSymType(); + + // This is the LLVM dialect type + const mlir::Type llvmType = getTypeConverter()->convertType(cirSymType); + // These defaults are just here until the equivalent attributes are + // available on cir.global ops. + const bool isConst = false; + const bool isDsoLocal = true; + const mlir::LLVM::Linkage linkage = mlir::LLVM::Linkage::External; + const StringRef symbol = op.getSymName(); + std::optional<mlir::Attribute> init = op.getInitialValue(); + + SmallVector<mlir::NamedAttribute> attributes; + + // Check for missing funcionalities. + if (!init.has_value()) { + rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>( + op, llvmType, isConst, linkage, symbol, mlir::Attribute(), + /*alignment*/ 0, /*addrSpace*/ 0, /*dsoLocal*/ isDsoLocal, + /*threadLocal*/ false, /*comdat*/ mlir::SymbolRefAttr(), attributes); + return mlir::success(); + } + + // Initializer is a constant array: convert it to a compatible llvm init. + if (auto intAttr = mlir::dyn_cast<cir::IntAttr>(init.value())) { + init = rewriter.getIntegerAttr(llvmType, intAttr.getValue()); + } else { + op.emitError() << "unsupported initializer '" << init.value() << "'"; + return mlir::failure(); + } + + // Rewrite op. + rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>( + op, llvmType, isConst, linkage, symbol, init.value(), /*alignment*/ 0, + /*addrSpace*/ 0, /*dsoLocal*/ isDsoLocal, /*threadLocal*/ false, + /*comdat*/ mlir::SymbolRefAttr(), attributes); + + return mlir::success(); +} + +static void prepareTypeConverter(mlir::LLVMTypeConverter &converter, + mlir::DataLayout &dataLayout) { + converter.addConversion([&](cir::IntType type) -> mlir::Type { + // LLVM doesn't work with signed types, so we drop the CIR signs here. + return mlir::IntegerType::get(type.getContext(), type.getWidth()); + }); +} + +void ConvertCIRToLLVMPass::runOnOperation() { + llvm::TimeTraceScope scope("Convert CIR to LLVM Pass"); + + mlir::ModuleOp module = getOperation(); + mlir::DataLayout dl(module); + mlir::LLVMTypeConverter converter(&getContext()); + prepareTypeConverter(converter, dl); // , lowerModule.get()); + + mlir::RewritePatternSet patterns(&getContext()); + + patterns.add<CIRToLLVMGlobalOpLowering>(converter, patterns.getContext(), dl); + + mlir::ConversionTarget target(getContext()); + target.addLegalOp<mlir::ModuleOp>(); + target.addLegalDialect<mlir::LLVM::LLVMDialect>(); + target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect, + mlir::func::FuncDialect>(); + + if (failed(applyPartialConversion(module, target, std::move(patterns)))) + signalPassFailure(); +} + +static std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() { + return std::make_unique<ConvertCIRToLLVMPass>(); +} + +static void populateCIRToLLVMPasses(mlir::OpPassManager &pm) { + pm.addPass(createConvertCIRToLLVMPass()); +} + std::unique_ptr<llvm::Module> lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, LLVMContext &llvmCtx) { llvm::TimeTraceScope scope("lower from CIR to LLVM directly"); + mlir::MLIRContext *mlirCtx = mlirModule.getContext(); + + mlir::PassManager pm(mlirCtx); + populateCIRToLLVMPasses(pm); + + bool result = !mlir::failed(pm.run(mlirModule)); + if (!result) + report_fatal_error( + "The pass manager failed to lower CIR to LLVMIR dialect!"); + + mlir::registerBuiltinDialectTranslation(*mlirCtx); + mlir::registerLLVMDialectTranslation(*mlirCtx); + + llvm::TimeTraceScope translateScope("translateModuleToLLVMIR"); + std::optional<StringRef> moduleName = mlirModule.getName(); - auto llvmModule = std::make_unique<llvm::Module>( - moduleName ? *moduleName : "CIRToLLVMModule", llvmCtx); + std::unique_ptr<llvm::Module> llvmModule = mlir::translateModuleToLLVMIR( + mlirModule, llvmCtx, moduleName ? *moduleName : "CIRToLLVMModule"); if (!llvmModule) report_fatal_error("Lowering from LLVMIR dialect to llvm IR failed!"); diff --git a/clang/test/CIR/Lowering/global-var-simple.cpp b/clang/test/CIR/Lowering/global-var-simple.cpp new file mode 100644 index 00000000000000..e8d2138de3f58b --- /dev/null +++ b/clang/test/CIR/Lowering/global-var-simple.cpp @@ -0,0 +1,63 @@ +// Global variables of intergal types +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s + +// Note: Currently unsupported features include default zero-initialization +// and alignment. The fact that "external" is only printed for globals +// without an initializer is a quirk of the LLVM AsmWriter. + +char c; +// CHECK: @c = external dso_local global i8 + +signed char sc; +// CHECK: @sc = external dso_local global i8 + +unsigned char uc; +// CHECK: @uc = external dso_local global i8 + +short ss; +// CHECK: @ss = external dso_local global i16 + +unsigned short us = 100; +// CHECK: @us = dso_local global i16 100 + +int si = 42; +// CHECK: @si = dso_local global i32 42 + +unsigned ui; +// CHECK: @ui = external dso_local global i32 + +long sl; +// CHECK: @sl = external dso_local global i64 + +unsigned long ul; +// CHECK: @ul = external dso_local global i64 + +long long sll; +// CHECK: @sll = external dso_local global i64 + +unsigned long long ull = 123456; +// CHECK: @ull = dso_local global i64 123456 + +__int128 s128; +// CHECK: @s128 = external dso_local global i128 + +unsigned __int128 u128; +// CHECK: @u128 = external dso_local global i128 + +wchar_t wc; +// CHECK: @wc = external dso_local global i32 + +char8_t c8; +// CHECK: @c8 = external dso_local global i8 + +char16_t c16; +// CHECK: @c16 = external dso_local global i16 + +char32_t c32; +// CHECK: @c32 = external dso_local global i32 + +_BitInt(20) sb20; +// CHECK: @sb20 = external dso_local global i20 + +unsigned _BitInt(48) ub48; +// CHECK: @ub48 = external dso_local global i48 diff --git a/clang/test/CIR/Lowering/hello.c b/clang/test/CIR/Lowering/hello.c index 320041f0ab7dc9..ff78b6e6f6a5e2 100644 --- a/clang/test/CIR/Lowering/hello.c +++ b/clang/test/CIR/Lowering/hello.c @@ -1,8 +1,10 @@ // Smoke test for ClangIR-to-LLVM IR code generation // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s -// TODO: Add checks when proper lowering is implemented. -// For now, we're just creating an empty module. -// CHECK: ModuleID +int a; -void foo() {} +// CHECK: @a = external dso_local global i32 + +int b = 2; + +// CHECK: @b = dso_local global i32 2 >From 6a2570cf4542ad0b7fe5c8a7a50b4b837d4c378c Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Fri, 31 Jan 2025 12:30:53 -0800 Subject: [PATCH 2/8] Address review feedback --- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index b24c41a93082d4..33ad402a8b854b 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -50,6 +50,8 @@ struct ConvertCIRToLLVMPass StringRef getArgument() const override { return "cir-flat-to-llvm"; } }; +// This pass requires the CIR to be in a "flat" state. All blocks in each +// function must belong to the parent region. mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite( cir::GlobalOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { @@ -57,40 +59,36 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite( // Fetch required values to create LLVM op. const mlir::Type cirSymType = op.getSymType(); - // This is the LLVM dialect type + // This is the LLVM dialect type. const mlir::Type llvmType = getTypeConverter()->convertType(cirSymType); - // These defaults are just here until the equivalent attributes are - // available on cir.global ops. + // FIXME: These default values are placeholders until the the equivalent + // attributes are available on cir.global ops. const bool isConst = false; + const unsigned addrSpace = 0; const bool isDsoLocal = true; + const bool isThreadLocal = false; + const uint64_t alignment = 0; const mlir::LLVM::Linkage linkage = mlir::LLVM::Linkage::External; const StringRef symbol = op.getSymName(); std::optional<mlir::Attribute> init = op.getInitialValue(); SmallVector<mlir::NamedAttribute> attributes; - // Check for missing funcionalities. - if (!init.has_value()) { - rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>( - op, llvmType, isConst, linkage, symbol, mlir::Attribute(), - /*alignment*/ 0, /*addrSpace*/ 0, /*dsoLocal*/ isDsoLocal, - /*threadLocal*/ false, /*comdat*/ mlir::SymbolRefAttr(), attributes); - return mlir::success(); - } - - // Initializer is a constant array: convert it to a compatible llvm init. - if (auto intAttr = mlir::dyn_cast<cir::IntAttr>(init.value())) { - init = rewriter.getIntegerAttr(llvmType, intAttr.getValue()); - } else { - op.emitError() << "unsupported initializer '" << init.value() << "'"; - return mlir::failure(); + if (init.has_value()) { + if (auto intAttr = mlir::dyn_cast<cir::IntAttr>(init.value())) { + // Initializer is a constant array: convert it to a compatible llvm init. + init = rewriter.getIntegerAttr(llvmType, intAttr.getValue()); + } else { + op.emitError() << "unsupported initializer '" << init.value() << "'"; + return mlir::failure(); + } } // Rewrite op. rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>( - op, llvmType, isConst, linkage, symbol, init.value(), /*alignment*/ 0, - /*addrSpace*/ 0, /*dsoLocal*/ isDsoLocal, /*threadLocal*/ false, - /*comdat*/ mlir::SymbolRefAttr(), attributes); + op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()), + alignment, addrSpace, isDsoLocal, isThreadLocal, + /*comdat=*/ mlir::SymbolRefAttr(), attributes); return mlir::success(); } @@ -109,7 +107,7 @@ void ConvertCIRToLLVMPass::runOnOperation() { mlir::ModuleOp module = getOperation(); mlir::DataLayout dl(module); mlir::LLVMTypeConverter converter(&getContext()); - prepareTypeConverter(converter, dl); // , lowerModule.get()); + prepareTypeConverter(converter, dl); mlir::RewritePatternSet patterns(&getContext()); @@ -142,22 +140,25 @@ lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, LLVMContext &llvmCtx) { mlir::PassManager pm(mlirCtx); populateCIRToLLVMPasses(pm); - bool result = !mlir::failed(pm.run(mlirModule)); - if (!result) + if (mlir::failed(pm.run(mlirModule))) { + // FIXME: Handle any errors where they occurs and return a nullptr here. report_fatal_error( "The pass manager failed to lower CIR to LLVMIR dialect!"); + } mlir::registerBuiltinDialectTranslation(*mlirCtx); mlir::registerLLVMDialectTranslation(*mlirCtx); llvm::TimeTraceScope translateScope("translateModuleToLLVMIR"); - std::optional<StringRef> moduleName = mlirModule.getName(); + StringRef moduleName = mlirModule.getName().value_or("CIRToLLVMModule"); std::unique_ptr<llvm::Module> llvmModule = mlir::translateModuleToLLVMIR( - mlirModule, llvmCtx, moduleName ? *moduleName : "CIRToLLVMModule"); + mlirModule, llvmCtx, moduleName); - if (!llvmModule) + if (!llvmModule) { + // FIXME: Handle any errors where they occurs and return a nullptr here. report_fatal_error("Lowering from LLVMIR dialect to llvm IR failed!"); + } return llvmModule; } >From ce2c8b08bf320aa5bfd2a0a6a6337a0ff14da4ef Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Fri, 31 Jan 2025 08:40:42 -0800 Subject: [PATCH 3/8] Add support for lowering floating-point globals --- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 27 ++++++++++++++++++- clang/test/CIR/Lowering/global-var-simple.cpp | 18 +++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 33ad402a8b854b..b41c7d4a5af78f 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -75,7 +75,11 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite( SmallVector<mlir::NamedAttribute> attributes; if (init.has_value()) { - if (auto intAttr = mlir::dyn_cast<cir::IntAttr>(init.value())) { + if (auto fltAttr = mlir::dyn_cast<cir::FPAttr>(init.value())) { + // Initializer is a constant floating-point number: convert to MLIR + // builtin constant. + init = rewriter.getFloatAttr(llvmType, fltAttr.getValue()); + } else if (auto intAttr = mlir::dyn_cast<cir::IntAttr>(init.value())) { // Initializer is a constant array: convert it to a compatible llvm init. init = rewriter.getIntegerAttr(llvmType, intAttr.getValue()); } else { @@ -99,6 +103,27 @@ static void prepareTypeConverter(mlir::LLVMTypeConverter &converter, // LLVM doesn't work with signed types, so we drop the CIR signs here. return mlir::IntegerType::get(type.getContext(), type.getWidth()); }); + converter.addConversion([&](cir::SingleType type) -> mlir::Type { + return mlir::Float32Type::get(type.getContext()); + }); + converter.addConversion([&](cir::DoubleType type) -> mlir::Type { + return mlir::Float64Type::get(type.getContext()); + }); + converter.addConversion([&](cir::FP80Type type) -> mlir::Type { + return mlir::Float80Type::get(type.getContext()); + }); + converter.addConversion([&](cir::FP128Type type) -> mlir::Type { + return mlir::Float128Type::get(type.getContext()); + }); + converter.addConversion([&](cir::LongDoubleType type) -> mlir::Type { + return converter.convertType(type.getUnderlying()); + }); + converter.addConversion([&](cir::FP16Type type) -> mlir::Type { + return mlir::Float16Type::get(type.getContext()); + }); + converter.addConversion([&](cir::BF16Type type) -> mlir::Type { + return mlir::BFloat16Type::get(type.getContext()); + }); } void ConvertCIRToLLVMPass::runOnOperation() { diff --git a/clang/test/CIR/Lowering/global-var-simple.cpp b/clang/test/CIR/Lowering/global-var-simple.cpp index e8d2138de3f58b..06050e409d5440 100644 --- a/clang/test/CIR/Lowering/global-var-simple.cpp +++ b/clang/test/CIR/Lowering/global-var-simple.cpp @@ -61,3 +61,21 @@ _BitInt(20) sb20; unsigned _BitInt(48) ub48; // CHECK: @ub48 = external dso_local global i48 + +_Float16 f16; +// CHECK: @f16 = external dso_local global half + +__bf16 bf16; +// CHECK: @bf16 = external dso_local global bfloat + +float f; +// CHECK: @f = external dso_local global float + +double d = 1.25; +// CHECK: @d = dso_local global double 1.250000e+00 + +long double ld; +// CHECK: @ld = external dso_local global x86_fp80 + +__float128 f128; +// CHECK: @f128 = external dso_local global fp128 >From 410665a484cdea08d90f499d450415db75a880c6 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Fri, 31 Jan 2025 13:00:34 -0800 Subject: [PATCH 4/8] Move CIRToLLVMGlobalOpLowering to the DirectToLLVM directory --- clang/include/clang/CIR/LowerToLLVM.h | 22 ---------- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 2 +- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 42 +++++++++++++++++++ 3 files changed, 43 insertions(+), 23 deletions(-) create mode 100644 clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h diff --git a/clang/include/clang/CIR/LowerToLLVM.h b/clang/include/clang/CIR/LowerToLLVM.h index 1135dbcbe0354b..6e1b0270fcd2b0 100644 --- a/clang/include/clang/CIR/LowerToLLVM.h +++ b/clang/include/clang/CIR/LowerToLLVM.h @@ -12,10 +12,6 @@ #ifndef CLANG_CIR_LOWERTOLLVM_H #define CLANG_CIR_LOWERTOLLVM_H -#include "mlir/Dialect/LLVMIR/LLVMDialect.h" -#include "mlir/Transforms/DialectConversion.h" -#include "clang/CIR/Dialect/IR/CIRDialect.h" - #include <memory> namespace llvm { @@ -33,24 +29,6 @@ namespace direct { std::unique_ptr<llvm::Module> lowerDirectlyFromCIRToLLVMIR(mlir::ModuleOp mlirModule, llvm::LLVMContext &llvmCtx); - -class CIRToLLVMGlobalOpLowering - : public mlir::OpConversionPattern<cir::GlobalOp> { - mlir::DataLayout const &dataLayout; - -public: - CIRToLLVMGlobalOpLowering(const mlir::TypeConverter &typeConverter, - mlir::MLIRContext *context, - mlir::DataLayout const &dataLayout) - : OpConversionPattern(typeConverter, context), dataLayout(dataLayout) { - setHasBoundedRewriteRecursion(); - } - - mlir::LogicalResult - matchAndRewrite(cir::GlobalOp op, OpAdaptor adaptor, - mlir::ConversionPatternRewriter &rewriter) const override; -}; - } // namespace direct } // namespace cir diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index b41c7d4a5af78f..967ac838147d8a 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -10,7 +10,7 @@ // //===----------------------------------------------------------------------===// -#include "clang/CIR/LowerToLLVM.h" +#include "LowerToLLVM.h" #include "mlir/Conversion/LLVMCommon/TypeConverter.h" #include "mlir/Dialect/DLTI/DLTI.h" diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h new file mode 100644 index 00000000000000..02fa2b39a6a4ee --- /dev/null +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -0,0 +1,42 @@ +//====- LowerToLLVM.h- Lowering from CIR to LLVM --------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares an interface for converting CIR modules to LLVM IR. +// +//===----------------------------------------------------------------------===// +#ifndef CLANG_CIR_LOWERTOLLVM_H +#define CLANG_CIR_LOWERTOLLVM_H + +#include "mlir/Transforms/DialectConversion.h" +#include "clang/CIR/Dialect/IR/CIRDialect.h" + +namespace cir { + +namespace direct { + +class CIRToLLVMGlobalOpLowering + : public mlir::OpConversionPattern<cir::GlobalOp> { + mlir::DataLayout const &dataLayout; + +public: + CIRToLLVMGlobalOpLowering(const mlir::TypeConverter &typeConverter, + mlir::MLIRContext *context, + mlir::DataLayout const &dataLayout) + : OpConversionPattern(typeConverter, context), dataLayout(dataLayout) { + setHasBoundedRewriteRecursion(); + } + + mlir::LogicalResult + matchAndRewrite(cir::GlobalOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const override; +}; + +} // namespace direct +} // namespace cir + +#endif // CLANG_CIR_LOWERTOLLVM_H >From d0c2866160c8cd1e548ab945ef94d3843914d7a2 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Fri, 31 Jan 2025 13:44:52 -0800 Subject: [PATCH 5/8] Make const DataLayout consistent with other types --- clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h index 02fa2b39a6a4ee..6167ff39b5ad6a 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -21,12 +21,12 @@ namespace direct { class CIRToLLVMGlobalOpLowering : public mlir::OpConversionPattern<cir::GlobalOp> { - mlir::DataLayout const &dataLayout; + const mlir::DataLayout &dataLayout; public: CIRToLLVMGlobalOpLowering(const mlir::TypeConverter &typeConverter, mlir::MLIRContext *context, - mlir::DataLayout const &dataLayout) + const mlir::DataLayout &dataLayout) : OpConversionPattern(typeConverter, context), dataLayout(dataLayout) { setHasBoundedRewriteRecursion(); } >From 0d207095fb0c85d743723b7edca02799f4052266 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Fri, 31 Jan 2025 14:25:20 -0800 Subject: [PATCH 6/8] Add MissingFeatures tracker --- clang/include/clang/CIR/MissingFeatures.h | 40 +++++++++++++++++++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 9 ++++- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 clang/include/clang/CIR/MissingFeatures.h diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h new file mode 100644 index 00000000000000..3c018aeea65014 --- /dev/null +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -0,0 +1,40 @@ +//===---- MissingFeatures.h - Checks for unimplemented features -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file introduces some helper classes to guard against features that +// CIR dialect supports that we do not have and also do not have great ways to +// assert against. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_CIR_MISSINGFEATURES_H +#define CLANG_CIR_MISSINGFEATURES_H + +namespace cir { + +// As a way to track features that haven't yet been implemented this class +// explicitly contains a list of static fns that will return false that you +// can guard against. If and when a feature becomes implemented simply changing +// this return to true will cause compilation to fail at all the points in which +// we noted that we needed to address. This is a much more explicit way to +// handle "TODO"s. +struct MissingFeatures { + // Address space related + static bool addressSpace() { return false; } + + // Unhandled global/linkage information. + static bool opGlobalDSOLocal() { return false; } + static bool opGlobalThreadLocal() { return false; } + static bool opGlobalConstant() { return false; } + static bool opGlobalAlignment() { return false; } + static bool opGlobalLinkage() { return false; } +}; + +} // namespace cir + +#endif // CLANG_CIR_MISSINGFEATURES_H diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 967ac838147d8a..4b223ed815bc6e 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -25,6 +25,7 @@ #include "mlir/Target/LLVMIR/Export.h" #include "mlir/Transforms/DialectConversion.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" +#include "clang/CIR/MissingFeatures.h" #include "llvm/IR/Module.h" #include "llvm/Support/TimeProfiler.h" @@ -62,12 +63,18 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite( // This is the LLVM dialect type. const mlir::Type llvmType = getTypeConverter()->convertType(cirSymType); // FIXME: These default values are placeholders until the the equivalent - // attributes are available on cir.global ops. + // attributes are available on cir.global ops. + assert(!cir::MissingFeatures::opGlobalConstant()); const bool isConst = false; + assert(!cir::MissingFeatures::addressSpace()); const unsigned addrSpace = 0; + assert(!cir::MissingFeatures::opGlobalDSOLocal()); const bool isDsoLocal = true; + assert(!cir::MissingFeatures::opGlobalThreadLocal()); const bool isThreadLocal = false; + assert(!cir::MissingFeatures::opGlobalAlignment()); const uint64_t alignment = 0; + assert(!cir::MissingFeatures::opGlobalLinkage()); const mlir::LLVM::Linkage linkage = mlir::LLVM::Linkage::External; const StringRef symbol = op.getSymName(); std::optional<mlir::Attribute> init = op.getInitialValue(); >From 71729bd5bd019bbd17b779a6a39df8eeed94e1a6 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Fri, 31 Jan 2025 15:34:07 -0800 Subject: [PATCH 7/8] Fix problems with shared library build --- clang/lib/CIR/FrontendAction/CMakeLists.txt | 1 + clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt | 2 ++ 2 files changed, 3 insertions(+) diff --git a/clang/lib/CIR/FrontendAction/CMakeLists.txt b/clang/lib/CIR/FrontendAction/CMakeLists.txt index d87ff7665987d1..ac2b857239d070 100644 --- a/clang/lib/CIR/FrontendAction/CMakeLists.txt +++ b/clang/lib/CIR/FrontendAction/CMakeLists.txt @@ -13,6 +13,7 @@ add_clang_library(clangCIRFrontendAction clangFrontend clangCIR clangCIRLoweringDirectToLLVM + clangCodeGen MLIRCIR MLIRIR ) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt b/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt index da802605676ac0..3f74c79249a272 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt +++ b/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt @@ -9,7 +9,9 @@ add_clang_library(clangCIRLoweringDirectToLLVM LowerToLLVM.cpp LINK_LIBS + MLIRIR ${dialect_libs} + MLIRCIR MLIRBuiltinToLLVMIRTranslation MLIRLLVMToLLVMIRTranslation ) >From 4558b4a9ebb0d9251eeb3c6d69e4e863b15ae32f Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Fri, 31 Jan 2025 17:20:09 -0800 Subject: [PATCH 8/8] Expand and move comment about flat cir --- clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 4b223ed815bc6e..fc082a4f5bf9b2 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -35,6 +35,10 @@ using namespace llvm; namespace cir { namespace direct { +// This pass requires the CIR to be in a "flat" state. All blocks in each +// function must belong to the parent region. Once scopes and control flow +// are implemented in CIR, a pass will be run before this one to flatten +// the CIR and get it into the state that this pass requires. struct ConvertCIRToLLVMPass : public mlir::PassWrapper<ConvertCIRToLLVMPass, mlir::OperationPass<mlir::ModuleOp>> { @@ -51,8 +55,6 @@ struct ConvertCIRToLLVMPass StringRef getArgument() const override { return "cir-flat-to-llvm"; } }; -// This pass requires the CIR to be in a "flat" state. All blocks in each -// function must belong to the parent region. mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite( cir::GlobalOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits