[clang] [CIR] Initial implementation of CIR-to-LLVM IR lowering pass (PR #125260)

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 3 10:05:45 PST 2025


================
@@ -22,16 +35,164 @@ 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>> {
+  void getDependentDialects(mlir::DialectRegistry &registry) 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);
+  // FIXME: These default values are placeholders until the the equivalent
+  //        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();
+
+  SmallVector<mlir::NamedAttribute> attributes;
+
+  if (init.has_value()) {
+    if (const auto fltAttr = mlir::dyn_cast<cir::FPAttr>(init.value())) {
----------------
erichkeane wrote:

> This is one of those things that's going to be counter-intuitive to people used to `llvm::dyn_cast` (it definitely was to me). These aren't pointers. It's related to the same thing we discussed with `ModuleOp`, where this is an object that wraps a pointer, so even though it's not a pointer, the object has `bool `and `!` operators so it works in an if-statement like this.
> 
> I was going to suggest that I could spell out the type here rather than using `auto`, but I'm not sure that makes it less confusing and it definitely goes against standard mlir practice. Since this is in the mlir-specific part of the code, I think `auto` is the way to go here.

I don't have a problem with `auto`, it makes sense here as the RHS has the 'type' being cast to.  Just you're right that `mlir::dyn_cast` not being a pointer type itself is interesting here/something I didn't know.  Thanks for clarifying!

https://github.com/llvm/llvm-project/pull/125260


More information about the cfe-commits mailing list