https://github.com/skc7 updated https://github.com/llvm/llvm-project/pull/204190

>From 6604679ad19e92cf843046e209367d07b365e9e2 Mon Sep 17 00:00:00 2001
From: skc7 <[email protected]>
Date: Tue, 16 Jun 2026 21:42:07 +0530
Subject: [PATCH 1/2] [CIR] Add metadata type, attributes, and
 metadata_as_value op.

---
 .../include/clang/CIR/Dialect/IR/CIRAttrs.td  | 41 +++++++++++++++++++
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 30 ++++++++++++++
 .../include/clang/CIR/Dialect/IR/CIRTypes.td  | 15 ++++++-
 clang/lib/CIR/CodeGen/CIRGenBuilder.h         | 15 +++++++
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp       | 13 ++++++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 40 ++++++++++++++++++
 clang/test/CIR/Lowering/metadata-as-value.cir | 37 +++++++++++++++++
 7 files changed, 190 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/CIR/Lowering/metadata-as-value.cir

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td 
b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index e3c992ed327ac..bdd1e2394939e 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -1692,6 +1692,47 @@ def CIR_AnnotationArrayAttr
     : CIR_TypedArrayAttrBase<CIR_AnnotationAttr,
                              "array of cir.annotation attributes">;
 
+//===----------------------------------------------------------------------===//
+// Metadata attributes
+//===----------------------------------------------------------------------===//
+
+def CIR_MDStringAttr : CIR_Attr<"MDString", "md_string"> {
+  let summary = "CIR metadata string";
+  let description = [{
+    Wraps a string as a metadata node, mirroring the LLVM dialect's
+    `#llvm.md_string`.
+
+    Example:
+    ```mlir
+    #cir.md_string<"agent-one-as">
+    ```
+  }];
+  let parameters = (ins "::mlir::StringAttr":$value);
+  let assemblyFormat = "`<` $value `>`";
+  let canHaveIllegalCXXABIType = 0;
+}
+
+def CIR_MDNodeAttr : CIR_Attr<"MDNode", "md_node"> {
+  let summary = "CIR metadata node";
+  let description = [{
+    Represents a metadata node, mirroring the LLVM dialect's `#llvm.md_node`.
+    Its operands can be any combination of metadata attributes, including
+    nested `#cir.md_node`.
+
+    Example:
+    ```mlir
+    #cir.md_node<#cir.md_string<"agent-one-as">>
+    #cir.md_node<>
+    ```
+  }];
+  let parameters = (ins 
OptionalArrayRefParameter<"mlir::Attribute">:$operands);
+  let assemblyFormat = "`<` (`>`) : ($operands^ `>`)?";
+  let canHaveIllegalCXXABIType = 0;
+}
+
+def CIR_AnyMDAttr : AnyAttrOf<[CIR_MDStringAttr, CIR_MDNodeAttr],
+    "CIR metadata attribute (md_string or md_node)">;
+
 include "clang/CIR/Dialect/IR/CIROpenCLAttrs.td"
 include "clang/CIR/Dialect/IR/CIRCUDAAttrs.td"
 
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 9dae3534991e5..f429e3efeb1e7 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4092,6 +4092,36 @@ def CIR_LocalInitOp : CIR_Op<"local_init", [
   let hasLLVMLowering = false;
 }
 
+//===----------------------------------------------------------------------===//
+// MetadataAsValueOp
+//===----------------------------------------------------------------------===//
+
+def CIR_MetadataAsValueOp
+    : CIR_Op<"metadata_as_value", [Pure, ConstantLike]> {
+  let summary = "Wrap a metadata node so it can be used as an SSA value";
+  let description = [{
+    Materializes a `!cir.metadata` SSA value from a metadata attribute,
+    mirroring the LLVM dialect's `llvm.mlir.metadata_as_value`. This lifts a
+    metadata node into the value domain so it can be passed as an operand to
+    intrinsic calls that take `metadata` arguments.
+
+    The wrapped metadata is described by the `metadata` attribute, which must
+    be one of the CIR metadata attributes.
+
+    ```mlir
+    %0 = cir.metadata_as_value #cir.md_string<"agent-one-as">
+    %1 = cir.metadata_as_value #cir.md_node<#cir.md_string<"sp">>
+    ```
+  }];
+
+  let arguments = (ins CIR_AnyMDAttr:$metadata);
+  let results = (outs CIR_MetadataType:$result);
+
+  let assemblyFormat = "$metadata attr-dict";
+
+  let hasFolder = 1;
+}
+
 
//===----------------------------------------------------------------------===//
 // LLVMIntrinsicCallOp
 
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td 
b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index 95be236854338..c44487b570415 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -619,6 +619,19 @@ def CIR_VoidType : CIR_Type<"Void", "void"> {
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// MetadataType
+//===----------------------------------------------------------------------===//
+
+def CIR_MetadataType : CIR_Type<"Metadata", "metadata"> {
+  let summary = "CIR metadata type";
+  let description = [{
+    The `!cir.metadata` type mirrors the LLVM dialect's `!llvm.metadata`. It
+    wraps a metadata node so it can be used as an operand of intrinsic calls
+    that take `metadata` arguments.
+  }];
+}
+
 
//===----------------------------------------------------------------------===//
 // StructType
 //
@@ -957,7 +970,7 @@ def CIR_AnyType : AnyTypeOf<[
   CIR_AnyFloatType, CIR_PointerType, CIR_FuncType, CIR_StructType,
   CIR_UnionType,
   CIR_ComplexType, CIR_VPtrType, CIR_DataMemberType, CIR_MethodType,
-  CIR_EhTokenType, CIR_CleanupTokenType, CIR_CatchTokenType
+  CIR_EhTokenType, CIR_CleanupTokenType, CIR_CatchTokenType, CIR_MetadataType
 ]>;
 
 #endif // CLANG_CIR_DIALECT_IR_CIRTYPES_TD
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h 
b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 3188b096579be..a4345598aa45e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -464,6 +464,21 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
     return cir::ConstantOp::create(*this, loc, cir::ZeroAttr::get(ty));
   }
 
+  
//===--------------------------------------------------------------------===//
+  // Metadata creation helpers
+  
//===--------------------------------------------------------------------===//
+  cir::MDStringAttr getMDStringAttr(llvm::StringRef str) {
+    return cir::MDStringAttr::get(getContext(), getStringAttr(str));
+  }
+
+  cir::MDNodeAttr getMDNodeAttr(llvm::ArrayRef<mlir::Attribute> operands) {
+    return cir::MDNodeAttr::get(getContext(), operands);
+  }
+
+  mlir::Value createMetadataAsValue(mlir::Location loc, mlir::Attribute md) {
+    return cir::MetadataAsValueOp::create(*this, loc, md);
+  }
+
   
//===--------------------------------------------------------------------===//
   // UnaryOp creation helpers
   
//===--------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index f374e9beb2068..9135bdc69052a 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -105,6 +105,11 @@ Operation 
*cir::CIRDialect::materializeConstant(mlir::OpBuilder &builder,
                                                 mlir::Attribute value,
                                                 mlir::Type type,
                                                 mlir::Location loc) {
+  // Metadata folds to its wrapped attribute, so rematerialize the wrapper
+  // rather than a cir.const (the attribute is not a TypedAttr).
+  if (mlir::isa<cir::MDStringAttr, cir::MDNodeAttr>(value) &&
+      mlir::isa<cir::MetadataType>(type))
+    return cir::MetadataAsValueOp::create(builder, loc, type, value);
   return cir::ConstantOp::create(builder, loc, type,
                                  mlir::cast<mlir::TypedAttr>(value));
 }
@@ -604,6 +609,14 @@ OpFoldResult cir::ConstantOp::fold(FoldAdaptor 
/*adaptor*/) {
   return getValue();
 }
 
+//===----------------------------------------------------------------------===//
+// MetadataAsValueOp
+//===----------------------------------------------------------------------===//
+
+OpFoldResult cir::MetadataAsValueOp::fold(FoldAdaptor /*adaptor*/) {
+  return getMetadataAttr();
+}
+
 
//===----------------------------------------------------------------------===//
 // CastOp
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index c844375a000e0..5d6cc8c4e6d4e 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -404,6 +404,43 @@ mlir::LogicalResult 
CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+/// Translate a CIR metadata attribute into the matching LLVM dialect metadata
+/// attribute, recursing through md_node operands. Returns null on an
+/// unsupported attribute.
+static mlir::Attribute convertCirMetadataAttr(mlir::Attribute attr) {
+  mlir::MLIRContext *ctx = attr.getContext();
+  if (auto str = mlir::dyn_cast<cir::MDStringAttr>(attr))
+    return mlir::LLVM::MDStringAttr::get(ctx, str.getValue());
+  if (auto node = mlir::dyn_cast<cir::MDNodeAttr>(attr)) {
+    llvm::SmallVector<mlir::Attribute> operands;
+    operands.reserve(node.getOperands().size());
+    for (mlir::Attribute operand : node.getOperands()) {
+      mlir::Attribute converted = convertCirMetadataAttr(operand);
+      if (!converted)
+        return {};
+      operands.push_back(converted);
+    }
+    return mlir::LLVM::MDNodeAttr::get(ctx, operands);
+  }
+  return {};
+}
+
+mlir::LogicalResult CIRToLLVMMetadataAsValueOpLowering::matchAndRewrite(
+    cir::MetadataAsValueOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  mlir::Attribute llvmMetadata = convertCirMetadataAttr(op.getMetadata());
+  if (!llvmMetadata)
+    return op.emitError("unsupported CIR metadata attribute");
+
+  mlir::Type resTy = typeConverter->convertType(op.getType());
+  if (!resTy)
+    return op.emitError("expected LLVM metadata result type");
+
+  rewriter.replaceOpWithNewOp<mlir::LLVM::MetadataAsValueOp>(op, resTy,
+                                                             llvmMetadata);
+  return mlir::success();
+}
+
 /// BoolAttr visitor.
 mlir::Value CIRAttrToValue::visitCirAttr(cir::BoolAttr boolAttr) {
   mlir::Location loc = parentOp->getLoc();
@@ -3292,6 +3329,9 @@ static void prepareTypeConverter(mlir::LLVMTypeConverter 
&converter,
   converter.addConversion([&](cir::VoidType type) -> mlir::Type {
     return mlir::LLVM::LLVMVoidType::get(type.getContext());
   });
+  converter.addConversion([&](cir::MetadataType type) -> mlir::Type {
+    return mlir::LLVM::LLVMMetadataType::get(type.getContext());
+  });
 }
 
 static void buildCtorDtorList(
diff --git a/clang/test/CIR/Lowering/metadata-as-value.cir 
b/clang/test/CIR/Lowering/metadata-as-value.cir
new file mode 100644
index 0000000000000..d994b6f5bb2e6
--- /dev/null
+++ b/clang/test/CIR/Lowering/metadata-as-value.cir
@@ -0,0 +1,37 @@
+// RUN: cir-opt %s -cir-to-llvm -o - | FileCheck %s
+
+// Lowering test for CIRToLLVMMetadataAsValueOpLowering and the
+// !cir.metadata -> !llvm.metadata type conversion.
+
+module {
+  // md_string operand.
+  // CHECK-LABEL: llvm.func @md_string
+  // CHECK:         %[[MD:.*]] = llvm.mlir.metadata_as_value 
#llvm.md_string<"foo">
+  // CHECK:         llvm.call_intrinsic "llvm.test.md.string"(%[[MD]]) : 
(!llvm.metadata) -> ()
+  // CHECK:         llvm.return
+  cir.func @md_string() {
+    %0 = cir.metadata_as_value #cir.md_string<"foo">
+    cir.call_llvm_intrinsic "test.md.string" %0 : (!cir.metadata) -> ()
+    cir.return
+  }
+
+  // Nested md_node<md_string>.
+  // CHECK-LABEL: llvm.func @md_node_nested
+  // CHECK:         %[[MD:.*]] = llvm.mlir.metadata_as_value 
#llvm.md_node<#llvm.md_string<"bar">>
+  // CHECK:         llvm.call_intrinsic "llvm.test.md.node"(%[[MD]]) : 
(!llvm.metadata) -> ()
+  cir.func @md_node_nested() {
+    %0 = cir.metadata_as_value #cir.md_node<#cir.md_string<"bar">>
+    cir.call_llvm_intrinsic "test.md.node" %0 : (!cir.metadata) -> ()
+    cir.return
+  }
+
+  // Empty md_node.
+  // CHECK-LABEL: llvm.func @md_node_empty
+  // CHECK:         %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_node<>
+  // CHECK:         llvm.call_intrinsic "llvm.test.md.empty"(%[[MD]]) : 
(!llvm.metadata) -> ()
+  cir.func @md_node_empty() {
+    %0 = cir.metadata_as_value #cir.md_node<>
+    cir.call_llvm_intrinsic "test.md.empty" %0 : (!cir.metadata) -> ()
+    cir.return
+  }
+}

>From ad725233be20b8d53c31b8ffd8033c754647d73e Mon Sep 17 00:00:00 2001
From: skc7 <[email protected]>
Date: Tue, 23 Jun 2026 10:27:02 +0530
Subject: [PATCH 2/2] add metadata verify-roundtrip test

---
 clang/test/CIR/IR/metadata.cir | 43 ++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)
 create mode 100644 clang/test/CIR/IR/metadata.cir

diff --git a/clang/test/CIR/IR/metadata.cir b/clang/test/CIR/IR/metadata.cir
new file mode 100644
index 0000000000000..c988d810d3230
--- /dev/null
+++ b/clang/test/CIR/IR/metadata.cir
@@ -0,0 +1,43 @@
+// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
+
+// Round-trip test for the !cir.metadata type, the #cir.md_string / 
#cir.md_node
+// attributes, and the cir.metadata_as_value op.
+
+module {
+  // CHECK-LABEL: cir.func @md_string
+  cir.func @md_string() {
+    // CHECK: %{{.*}} = cir.metadata_as_value #cir.md_string<"agent-one-as">
+    %0 = cir.metadata_as_value #cir.md_string<"agent-one-as">
+    cir.return
+  }
+
+  // CHECK-LABEL: cir.func @md_node_nested
+  cir.func @md_node_nested() {
+    // CHECK: %{{.*}} = cir.metadata_as_value 
#cir.md_node<#cir.md_string<"sp">>
+    %0 = cir.metadata_as_value #cir.md_node<#cir.md_string<"sp">>
+    cir.return
+  }
+
+  // CHECK-LABEL: cir.func @md_node_multi
+  cir.func @md_node_multi() {
+    // CHECK: %{{.*}} = cir.metadata_as_value 
#cir.md_node<#cir.md_string<"a">, #cir.md_string<"b">>
+    %0 = cir.metadata_as_value #cir.md_node<#cir.md_string<"a">, 
#cir.md_string<"b">>
+    cir.return
+  }
+
+  // CHECK-LABEL: cir.func @md_node_empty
+  cir.func @md_node_empty() {
+    // CHECK: %{{.*}} = cir.metadata_as_value #cir.md_node<>
+    %0 = cir.metadata_as_value #cir.md_node<>
+    cir.return
+  }
+
+  // CHECK-LABEL: cir.func @md_as_intrinsic_arg
+  cir.func @md_as_intrinsic_arg() {
+    // CHECK: %[[MD:.*]] = cir.metadata_as_value #cir.md_string<"foo">
+    // CHECK: cir.call_llvm_intrinsic "test.md.string" %[[MD]] : 
(!cir.metadata) -> ()
+    %0 = cir.metadata_as_value #cir.md_string<"foo">
+    cir.call_llvm_intrinsic "test.md.string" %0 : (!cir.metadata) -> ()
+    cir.return
+  }
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to