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/3] [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/3] 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

>From a56c7f5b00957067c2c33ad203a8c3d331b3fe36 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <akay...@nvidia.com>
Date: Wed, 5 Feb 2025 09:02:19 -0800
Subject: [PATCH 3/3] Add file header, fix typo

---
 clang/include/clang/CIR/Dialect/IR/CIRAttrVisitor.h | 12 ++++++++++++
 clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  2 +-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrVisitor.h 
b/clang/include/clang/CIR/Dialect/IR/CIRAttrVisitor.h
index 3f552c91742a04..7a4734784bf890 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrVisitor.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrVisitor.h
@@ -1,3 +1,15 @@
+//===- TypeConverter.h - Convert builtin to LLVM dialect types --*- 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 defines the CirAttrVisitor interface.
+//
+//===----------------------------------------------------------------------===//
+
 #ifndef LLVM_CLANG_CIR_DIALECT_IR_CIRATTRVISITOR_H
 #define LLVM_CLANG_CIR_DIALECT_IR_CIRATTRVISITOR_H
 
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index ed4501d1e5b1da..d60a6b38b0c128 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -123,7 +123,7 @@ struct ConvertCIRToLLVMPass
 
 bool CIRToLLVMGlobalOpLowering::attrRequiresRegionInitialization(
     mlir::Attribute attr) const {
-  // There will be more case added later.
+  // There will be more cases added later.
   return isa<cir::ConstPtrAttr>(attr);
 }
 

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to