https://github.com/andykaylor updated https://github.com/llvm/llvm-project/pull/125619
>From dc7f71d511d2e13e527e0c8cd242a3ece82bcdfd Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Mon, 3 Feb 2025 13:20:51 -0800 Subject: [PATCH 1/2] [CIR] Lowering to LLVM for global pointers Add support for lowering global variables of any pointer type to LLVM IR. --- .../clang/CIR/Dialect/IR/CIRAttrVisitor.h | 51 +++++++++++ clang/include/clang/CIR/MissingFeatures.h | 3 + .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 84 +++++++++++++++++++ clang/test/CIR/Lowering/global-var-simple.cpp | 21 +++++ 4 files changed, 159 insertions(+) create mode 100644 clang/include/clang/CIR/Dialect/IR/CIRAttrVisitor.h diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrVisitor.h b/clang/include/clang/CIR/Dialect/IR/CIRAttrVisitor.h new file mode 100644 index 00000000000000..4babccc48038e6 --- /dev/null +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrVisitor.h @@ -0,0 +1,51 @@ +#ifndef LLVM_CLANG_CIR_DIALECT_IR_CIRATTRVISITOR_H +#define LLVM_CLANG_CIR_DIALECT_IR_CIRATTRVISITOR_H + +#include "clang/CIR/Dialect/IR/CIRAttrs.h" + +namespace cir { + +template <typename ImplClass, typename RetTy> class CirAttrVisitor { +public: + // FIXME: Create a TableGen list to automatically handle new attributes + template <typename... Args> + RetTy visit(mlir::Attribute attr, Args &&...args) { + if (const auto intAttr = mlir::dyn_cast<cir::IntAttr>(attr)) + return static_cast<ImplClass *>(this)->visitCirIntAttr( + intAttr, std::forward<Args>(args)...); + if (const auto fltAttr = mlir::dyn_cast<cir::FPAttr>(attr)) + return static_cast<ImplClass *>(this)->visitCirFPAttr( + fltAttr, std::forward<Args>(args)...); + if (const auto ptrAttr = mlir::dyn_cast<cir::ConstPtrAttr>(attr)) + return static_cast<ImplClass *>(this)->visitCirConstPtrAttr( + ptrAttr, std::forward<Args>(args)...); + llvm_unreachable("unhandled attribute type"); + } + + // If the implementation chooses not to implement a certain visit + // method, fall back to the parent. + template <typename... Args> + RetTy visitCirIntAttr(cir::IntAttr attr, Args &&...args) { + return static_cast<ImplClass *>(this)->visitCirAttr( + attr, std::forward<Args>(args)...); + } + template <typename... Args> + RetTy visitCirFPAttr(cir::FPAttr attr, Args &&...args) { + return static_cast<ImplClass *>(this)->visitCirAttr( + attr, std::forward<Args>(args)...); + } + template <typename... Args> + RetTy visitCirConstPtrAttr(cir::ConstPtrAttr attr, Args &&...args) { + return static_cast<ImplClass *>(this)->visitCirAttr( + attr, std::forward<Args>(args)...); + } + + template <typename... Args> + RetTy visitCirAttr(mlir::Attribute attr, Args &&...args) { + return RetTy(); + } +}; + +} // namespace cir + +#endif // LLVM_CLANG_CIR_DIALECT_IR_CIRATTRVISITOR_H diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index 3c018aeea65014..d4fcd52e7e6e3b 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -27,6 +27,9 @@ struct MissingFeatures { // Address space related static bool addressSpace() { return false; } + // This isn't needed until we add support for bools. + static bool convertTypeForMemory() { return false; } + // Unhandled global/linkage information. static bool opGlobalDSOLocal() { return false; } static bool opGlobalThreadLocal() { return false; } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index af8ca7d0b89e68..66f6ee328e55e5 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -24,6 +24,7 @@ #include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h" #include "mlir/Target/LLVMIR/Export.h" #include "mlir/Transforms/DialectConversion.h" +#include "clang/CIR/Dialect/IR/CIRAttrVisitor.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" #include "clang/CIR/MissingFeatures.h" #include "llvm/IR/Module.h" @@ -35,6 +36,54 @@ using namespace llvm; namespace cir { namespace direct { +class CIRAttrToValue : public CirAttrVisitor<CIRAttrToValue, mlir::Value> { +public: + mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, + mlir::Attribute attr, + mlir::ConversionPatternRewriter &rewriter, + const mlir::TypeConverter *converter, + mlir::DataLayout const &dataLayout) { + return visit(attr, parentOp, rewriter, converter, dataLayout); + } + + mlir::Value visitCirIntAttr(cir::IntAttr intAttr, mlir::Operation *parentOp, + mlir::ConversionPatternRewriter &rewriter, + const mlir::TypeConverter *converter, + mlir::DataLayout const &dataLayout) { + auto loc = parentOp->getLoc(); + return rewriter.create<mlir::LLVM::ConstantOp>( + loc, converter->convertType(intAttr.getType()), intAttr.getValue()); + } + + mlir::Value visitCirFPAttr(cir::FPAttr fltAttr, mlir::Operation *parentOp, + mlir::ConversionPatternRewriter &rewriter, + const mlir::TypeConverter *converter, + mlir::DataLayout const &dataLayout) { + auto loc = parentOp->getLoc(); + return rewriter.create<mlir::LLVM::ConstantOp>( + loc, converter->convertType(fltAttr.getType()), fltAttr.getValue()); + } + + mlir::Value visitCirConstPtrAttr(cir::ConstPtrAttr ptrAttr, + mlir::Operation *parentOp, + mlir::ConversionPatternRewriter &rewriter, + const mlir::TypeConverter *converter, + mlir::DataLayout const &dataLayout) { + auto loc = parentOp->getLoc(); + if (ptrAttr.isNullValue()) { + return rewriter.create<mlir::LLVM::ZeroOp>( + loc, converter->convertType(ptrAttr.getType())); + } + mlir::DataLayout layout(parentOp->getParentOfType<mlir::ModuleOp>()); + mlir::Value ptrVal = rewriter.create<mlir::LLVM::ConstantOp>( + loc, + rewriter.getIntegerType(layout.getTypeSizeInBits(ptrAttr.getType())), + ptrAttr.getValue().getInt()); + return rewriter.create<mlir::LLVM::IntToPtrOp>( + loc, converter->convertType(ptrAttr.getType()), ptrVal); + } +}; + // 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 @@ -55,14 +104,19 @@ struct ConvertCIRToLLVMPass StringRef getArgument() const override { return "cir-flat-to-llvm"; } }; +/// Replace CIR global with a region initialized LLVM global and update +/// insertion point to the end of the initializer block. + 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(); + const auto loc = op.getLoc(); // This is the LLVM dialect type. + assert(!cir::MissingFeatures::convertTypeForMemory()); const mlir::Type llvmType = getTypeConverter()->convertType(cirSymType); // FIXME: These default values are placeholders until the the equivalent // attributes are available on cir.global ops. @@ -84,6 +138,19 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite( SmallVector<mlir::NamedAttribute> attributes; if (init.has_value()) { + auto setupRegionInitializedLLVMGlobalOp = [&]() { + assert(!cir::MissingFeatures::convertTypeForMemory()); + const mlir::Type llvmType = + getTypeConverter()->convertType(op.getSymType()); + SmallVector<mlir::NamedAttribute> attributes; + auto newGlobalOp = rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>( + op, llvmType, isConst, linkage, op.getSymName(), nullptr, alignment, + addrSpace, isDsoLocal, isThreadLocal, + /*comdat=*/mlir::SymbolRefAttr(), attributes); + newGlobalOp.getRegion().push_back(new mlir::Block()); + rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock()); + }; + if (const auto fltAttr = mlir::dyn_cast<cir::FPAttr>(init.value())) { // Initializer is a constant floating-point number: convert to MLIR // builtin constant. @@ -92,6 +159,16 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite( 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 if (isa<cir::ConstPtrAttr>(init.value())) { + // TODO(cir): once LLVM's dialect has proper equivalent attributes this + // should be updated. For now, we use a custom op to initialize globals + // to the appropriate value. + setupRegionInitializedLLVMGlobalOp(); + CIRAttrToValue attrVisitor; + mlir::Value value = attrVisitor.lowerCirAttrAsValue( + op, init.value(), rewriter, typeConverter, dataLayout); + rewriter.create<mlir::LLVM::ReturnOp>(loc, value); + return mlir::success(); } else { op.emitError() << "unsupported initializer '" << init.value() << "'"; return mlir::failure(); @@ -109,6 +186,13 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite( static void prepareTypeConverter(mlir::LLVMTypeConverter &converter, mlir::DataLayout &dataLayout) { + converter.addConversion([&](cir::PointerType type) -> mlir::Type { + // Drop pointee type since LLVM dialect only allows opaque pointers. + assert(!cir::MissingFeatures::addressSpace()); + unsigned targetAS = 0; + + return mlir::LLVM::LLVMPointerType::get(type.getContext(), targetAS); + }); 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()); diff --git a/clang/test/CIR/Lowering/global-var-simple.cpp b/clang/test/CIR/Lowering/global-var-simple.cpp index 06050e409d5440..a5adb4011931af 100644 --- a/clang/test/CIR/Lowering/global-var-simple.cpp +++ b/clang/test/CIR/Lowering/global-var-simple.cpp @@ -79,3 +79,24 @@ long double ld; __float128 f128; // CHECK: @f128 = external dso_local global fp128 + +void *vp; +// CHECK: @vp = external dso_local global ptr{{$}} + +int *ip = 0; +// CHECK: @ip = dso_local global ptr null + +double *dp; +// CHECK: @dp = external dso_local global ptr{{$}} + +char **cpp; +// CHECK: @cpp = external dso_local global ptr{{$}} + +void (*fp)(); +// CHECK: @fp = external dso_local global ptr{{$}} + +int (*fpii)(int) = 0; +// CHECK: @fpii = dso_local global ptr null + +void (*fpvar)(int, ...); +// CHECK: @fpvar = external dso_local global ptr{{$}} >From eee630f582711a38c96ec2d13a9bef426cb4aa88 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <akay...@nvidia.com> Date: Tue, 4 Feb 2025 17:10:10 -0800 Subject: [PATCH 2/2] Refactoring based on review feedback --- .../clang/CIR/Dialect/IR/CIRAttrVisitor.h | 37 ++-- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 167 ++++++++++++------ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 10 ++ 3 files changed, 132 insertions(+), 82 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrVisitor.h b/clang/include/clang/CIR/Dialect/IR/CIRAttrVisitor.h index 4babccc48038e6..3f552c91742a04 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrVisitor.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrVisitor.h @@ -8,42 +8,31 @@ namespace cir { template <typename ImplClass, typename RetTy> class CirAttrVisitor { public: // FIXME: Create a TableGen list to automatically handle new attributes - template <typename... Args> - RetTy visit(mlir::Attribute attr, Args &&...args) { + RetTy visit(mlir::Attribute attr) { if (const auto intAttr = mlir::dyn_cast<cir::IntAttr>(attr)) - return static_cast<ImplClass *>(this)->visitCirIntAttr( - intAttr, std::forward<Args>(args)...); + return getImpl().visitCirIntAttr(intAttr); if (const auto fltAttr = mlir::dyn_cast<cir::FPAttr>(attr)) - return static_cast<ImplClass *>(this)->visitCirFPAttr( - fltAttr, std::forward<Args>(args)...); + return getImpl().visitCirFPAttr(fltAttr); if (const auto ptrAttr = mlir::dyn_cast<cir::ConstPtrAttr>(attr)) - return static_cast<ImplClass *>(this)->visitCirConstPtrAttr( - ptrAttr, std::forward<Args>(args)...); + return getImpl().visitCirConstPtrAttr(ptrAttr); llvm_unreachable("unhandled attribute type"); } // If the implementation chooses not to implement a certain visit // method, fall back to the parent. - template <typename... Args> - RetTy visitCirIntAttr(cir::IntAttr attr, Args &&...args) { - return static_cast<ImplClass *>(this)->visitCirAttr( - attr, std::forward<Args>(args)...); + RetTy visitCirIntAttr(cir::IntAttr attr) { + return getImpl().visitCirAttr(attr); } - template <typename... Args> - RetTy visitCirFPAttr(cir::FPAttr attr, Args &&...args) { - return static_cast<ImplClass *>(this)->visitCirAttr( - attr, std::forward<Args>(args)...); + RetTy visitCirFPAttr(cir::FPAttr attr) { + return getImpl().visitCirAttr(attr); } - template <typename... Args> - RetTy visitCirConstPtrAttr(cir::ConstPtrAttr attr, Args &&...args) { - return static_cast<ImplClass *>(this)->visitCirAttr( - attr, std::forward<Args>(args)...); + RetTy visitCirConstPtrAttr(cir::ConstPtrAttr attr) { + return getImpl().visitCirAttr(attr); } - template <typename... Args> - RetTy visitCirAttr(mlir::Attribute attr, Args &&...args) { - return RetTy(); - } + RetTy visitCirAttr(mlir::Attribute attr) { return RetTy(); } + + ImplClass &getImpl() { return *static_cast<ImplClass *>(this); } }; } // namespace cir diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 66f6ee328e55e5..ed4501d1e5b1da 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -38,38 +38,27 @@ namespace direct { class CIRAttrToValue : public CirAttrVisitor<CIRAttrToValue, mlir::Value> { public: - mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, - mlir::Attribute attr, - mlir::ConversionPatternRewriter &rewriter, - const mlir::TypeConverter *converter, - mlir::DataLayout const &dataLayout) { - return visit(attr, parentOp, rewriter, converter, dataLayout); - } + CIRAttrToValue(mlir::Operation *parentOp, + mlir::ConversionPatternRewriter &rewriter, + const mlir::TypeConverter *converter) + : parentOp(parentOp), rewriter(rewriter), converter(converter) {} + + mlir::Value lowerCirAttrAsValue(mlir::Attribute attr) { return visit(attr); } - mlir::Value visitCirIntAttr(cir::IntAttr intAttr, mlir::Operation *parentOp, - mlir::ConversionPatternRewriter &rewriter, - const mlir::TypeConverter *converter, - mlir::DataLayout const &dataLayout) { - auto loc = parentOp->getLoc(); + mlir::Value visitCirIntAttr(cir::IntAttr intAttr) { + mlir::Location loc = parentOp->getLoc(); return rewriter.create<mlir::LLVM::ConstantOp>( loc, converter->convertType(intAttr.getType()), intAttr.getValue()); } - mlir::Value visitCirFPAttr(cir::FPAttr fltAttr, mlir::Operation *parentOp, - mlir::ConversionPatternRewriter &rewriter, - const mlir::TypeConverter *converter, - mlir::DataLayout const &dataLayout) { - auto loc = parentOp->getLoc(); + mlir::Value visitCirFPAttr(cir::FPAttr fltAttr) { + mlir::Location loc = parentOp->getLoc(); return rewriter.create<mlir::LLVM::ConstantOp>( loc, converter->convertType(fltAttr.getType()), fltAttr.getValue()); } - mlir::Value visitCirConstPtrAttr(cir::ConstPtrAttr ptrAttr, - mlir::Operation *parentOp, - mlir::ConversionPatternRewriter &rewriter, - const mlir::TypeConverter *converter, - mlir::DataLayout const &dataLayout) { - auto loc = parentOp->getLoc(); + mlir::Value visitCirConstPtrAttr(cir::ConstPtrAttr ptrAttr) { + mlir::Location loc = parentOp->getLoc(); if (ptrAttr.isNullValue()) { return rewriter.create<mlir::LLVM::ZeroOp>( loc, converter->convertType(ptrAttr.getType())); @@ -82,6 +71,34 @@ class CIRAttrToValue : public CirAttrVisitor<CIRAttrToValue, mlir::Value> { return rewriter.create<mlir::LLVM::IntToPtrOp>( loc, converter->convertType(ptrAttr.getType()), ptrVal); } + +private: + mlir::Operation *parentOp; + mlir::ConversionPatternRewriter &rewriter; + const mlir::TypeConverter *converter; +}; + +// This class handles rewriting initializer attributes for types that do not +// require region initialization. +class GlobalInitAttrRewriter + : public CirAttrVisitor<GlobalInitAttrRewriter, mlir::Attribute> { +public: + GlobalInitAttrRewriter(mlir::Type type, + mlir::ConversionPatternRewriter &rewriter) + : llvmType(type), rewriter(rewriter) {} + + mlir::Attribute rewriteInitAttr(mlir::Attribute attr) { return visit(attr); } + + mlir::Attribute visitCirIntAttr(cir::IntAttr attr) { + return rewriter.getIntegerAttr(llvmType, attr.getValue()); + } + mlir::Attribute visitCirFPAttr(cir::FPAttr attr) { + return rewriter.getFloatAttr(llvmType, attr.getValue()); + } + +private: + mlir::Type llvmType; + mlir::ConversionPatternRewriter &rewriter; }; // This pass requires the CIR to be in a "flat" state. All blocks in each @@ -104,16 +121,78 @@ struct ConvertCIRToLLVMPass StringRef getArgument() const override { return "cir-flat-to-llvm"; } }; +bool CIRToLLVMGlobalOpLowering::attrRequiresRegionInitialization( + mlir::Attribute attr) const { + // There will be more case added later. + return isa<cir::ConstPtrAttr>(attr); +} + /// Replace CIR global with a region initialized LLVM global and update /// insertion point to the end of the initializer block. +void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp( + cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter) const { + assert(!cir::MissingFeatures::convertTypeForMemory()); + const mlir::Type llvmType = getTypeConverter()->convertType(op.getSymType()); + + // FIXME: These default values are placeholders until the the equivalent + // attributes are available on cir.global ops. This duplicates code + // in CIRToLLVMGlobalOpLowering::matchAndRewrite() but that will go + // away when the placeholders are no longer needed. + 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(); + + SmallVector<mlir::NamedAttribute> attributes; + auto newGlobalOp = rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>( + op, llvmType, isConst, linkage, symbol, nullptr, alignment, addrSpace, + isDsoLocal, isThreadLocal, + /*comdat=*/mlir::SymbolRefAttr(), attributes); + newGlobalOp.getRegion().push_back(new mlir::Block()); + rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock()); +}; + +mlir::LogicalResult +CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal( + cir::GlobalOp op, mlir::Attribute init, + mlir::ConversionPatternRewriter &rewriter) const { + // TODO: Generalize this handling when more types are needed here. + assert(isa<cir::ConstPtrAttr>(init)); + + // TODO(cir): once LLVM's dialect has proper equivalent attributes this + // should be updated. For now, we use a custom op to initialize globals + // to the appropriate value. + const mlir::Location loc = op.getLoc(); + setupRegionInitializedLLVMGlobalOp(op, rewriter); + CIRAttrToValue attrVisitor(op, rewriter, typeConverter); + mlir::Value value = attrVisitor.lowerCirAttrAsValue(init); + rewriter.create<mlir::LLVM::ReturnOp>(loc, value); + return mlir::success(); +} mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite( cir::GlobalOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { + std::optional<mlir::Attribute> init = op.getInitialValue(); + + // If we have an initializer and it requires region initialization, handle + // that separately + if (init.has_value() && attrRequiresRegionInitialization(init.value())) { + return matchAndRewriteRegionInitializedGlobal(op, init.value(), rewriter); + } + // Fetch required values to create LLVM op. const mlir::Type cirSymType = op.getSymType(); - const auto loc = op.getLoc(); // This is the LLVM dialect type. assert(!cir::MissingFeatures::convertTypeForMemory()); @@ -133,43 +212,15 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite( 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(); - SmallVector<mlir::NamedAttribute> attributes; if (init.has_value()) { - auto setupRegionInitializedLLVMGlobalOp = [&]() { - assert(!cir::MissingFeatures::convertTypeForMemory()); - const mlir::Type llvmType = - getTypeConverter()->convertType(op.getSymType()); - SmallVector<mlir::NamedAttribute> attributes; - auto newGlobalOp = rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>( - op, llvmType, isConst, linkage, op.getSymName(), nullptr, alignment, - addrSpace, isDsoLocal, isThreadLocal, - /*comdat=*/mlir::SymbolRefAttr(), attributes); - newGlobalOp.getRegion().push_back(new mlir::Block()); - rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock()); - }; - - if (const 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 (const 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 if (isa<cir::ConstPtrAttr>(init.value())) { - // TODO(cir): once LLVM's dialect has proper equivalent attributes this - // should be updated. For now, we use a custom op to initialize globals - // to the appropriate value. - setupRegionInitializedLLVMGlobalOp(); - CIRAttrToValue attrVisitor; - mlir::Value value = attrVisitor.lowerCirAttrAsValue( - op, init.value(), rewriter, typeConverter, dataLayout); - rewriter.create<mlir::LLVM::ReturnOp>(loc, value); - return mlir::success(); - } else { + GlobalInitAttrRewriter initRewriter(llvmType, rewriter); + init = initRewriter.rewriteInitAttr(init.value()); + // If initRewriter returned a null attribute, init will have a value but + // the value will be null. If that happens, initRewriter didn't handle the + // attribute type. It probably needs to be added to GlobalInitAttrRewriter. + if (!init.value()) { op.emitError() << "unsupported initializer '" << init.value() << "'"; return mlir::failure(); } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h index 6167ff39b5ad6a..b3366c1fb93378 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -34,6 +34,16 @@ class CIRToLLVMGlobalOpLowering mlir::LogicalResult matchAndRewrite(cir::GlobalOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const override; + +private: + bool attrRequiresRegionInitialization(mlir::Attribute attr) const; + + mlir::LogicalResult matchAndRewriteRegionInitializedGlobal( + cir::GlobalOp op, mlir::Attribute init, + mlir::ConversionPatternRewriter &rewriter) const; + + void setupRegionInitializedLLVMGlobalOp( + cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter) const; }; } // namespace direct _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits