https://github.com/vishruth-thimmaiah updated 
https://github.com/llvm/llvm-project/pull/173512

>From 410ec8eee9e1643fef3a405b03687846cd1329e1 Mon Sep 17 00:00:00 2001
From: vishruth-thimmaiah <[email protected]>
Date: Thu, 25 Dec 2025 03:34:24 +0530
Subject: [PATCH 1/2] [CIR] Upstream ExtractMemberOp

This PR upstreams `ExtractMemberOp`.

Signed-off-by: vishruth-thimmaiah <[email protected]>
---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 49 +++++++++++++++++++
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp       | 17 +++++++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 29 +++++++++++
 clang/test/CIR/Lowering/struct.cir            | 23 +++++++++
 4 files changed, 118 insertions(+)
 create mode 100644 clang/test/CIR/Lowering/struct.cir

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 8358b076ee7b6..9e1be13476a16 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2727,6 +2727,55 @@ def CIR_GetMemberOp : CIR_Op<"get_member"> {
   let hasVerifier = 1;
 }
 
+//===----------------------------------------------------------------------===//
+// ExtractMemberOp
+//===----------------------------------------------------------------------===//
+
+def CIR_ExtractMemberOp : CIR_Op<"extract_member", [Pure]> {
+  let summary = "Extract the value of a member of a record value";
+  let description = [{
+    The `cir.extract_member` operation extracts the value of a particular 
member
+    from the input record. Unlike `cir.get_member` which derives pointers, this
+    operation operates on values. It takes a value of record type, and extract
+    the value of the specified record member from the input record value.
+
+    Currently `cir.extract_member` does not work on unions.
+
+    Example:
+
+    ```mlir
+    // Suppose we have a record with multiple members.
+    !s32i = !cir.int<s, 32>
+    !s8i = !cir.int<s, 32>
+    !record_ty = !cir.record<"struct.Bar" {!s32i, !s8i}>
+
+    // And suppose we have a value of the record type.
+    %0 = cir.const #cir.const_record<{#cir.int<1> : !s32i, #cir.int<2> : 
!s8i}> : !record_ty
+
+    // Extract the value of the second member of the record.
+    %1 = cir.extract_member %0[1] : !record_ty -> !s8i
+    ```
+  }];
+
+  let arguments = (ins CIRRecordType:$record, I64Attr:$index);
+  let results = (outs CIR_AnyType:$result);
+
+  let assemblyFormat = [{
+    $record `[` $index `]` attr-dict
+    `:` qualified(type($record)) `->` qualified(type($result))
+  }];
+
+  let builders = [
+    OpBuilder<(ins "mlir::Value":$record, "uint64_t":$index), [{
+      auto recordTy = mlir::cast<cir::RecordType>(record.getType());
+      mlir::Type memberTy = recordTy.getMembers()[index];
+      build($_builder, $_state, memberTy, record, index);
+    }]>
+  ];
+
+  let hasVerifier = 1;
+}
+
 
//===----------------------------------------------------------------------===//
 // GetElementOp
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 8f0dc705181e6..48893318c977b 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -2557,6 +2557,23 @@ LogicalResult cir::GetMemberOp::verify() {
 
   return mlir::success();
 }
+
+//===----------------------------------------------------------------------===//
+// ExtractMemberOp Definitions
+//===----------------------------------------------------------------------===//
+
+LogicalResult cir::ExtractMemberOp::verify() {
+  auto recordTy = mlir::cast<cir::RecordType>(getRecord().getType());
+  if (recordTy.getKind() == cir::RecordType::Union)
+    return emitError()
+           << "cir.extract_member currently does not work on unions";
+  if (recordTy.getMembers().size() <= getIndex())
+    return emitError() << "member index out of bounds";
+  if (recordTy.getMembers()[getIndex()] != getType())
+    return emitError() << "member type mismatch";
+  return mlir::success();
+}
+
 
//===----------------------------------------------------------------------===//
 // VecCreateOp
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 998c93efb768a..ce63cc2823525 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -3289,6 +3289,35 @@ mlir::LogicalResult 
CIRToLLVMGetMemberOpLowering::matchAndRewrite(
   }
 }
 
+mlir::LogicalResult CIRToLLVMExtractMemberOpLowering::matchAndRewrite(
+    cir::ExtractMemberOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  std::int64_t indecies[1] = {static_cast<std::int64_t>(op.getIndex())};
+
+  mlir::Type recordTy = op.getRecord().getType();
+  if (auto llvmStructTy =
+          mlir::dyn_cast<mlir::LLVM::LLVMStructType>(recordTy)) {
+    rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
+        op, adaptor.getRecord(), indecies);
+    return mlir::success();
+  }
+
+  auto cirRecordTy = mlir::cast<cir::RecordType>(recordTy);
+  switch (cirRecordTy.getKind()) {
+  case cir::RecordType::Struct:
+  case cir::RecordType::Class: {
+    rewriter.replaceOpWithNewOp<mlir::LLVM::ExtractValueOp>(
+        op, adaptor.getRecord(), indecies);
+    return mlir::success();
+  }
+
+  case cir::RecordType::Union: {
+    op.emitError("cir.extract_member cannot extract member from a union");
+    return mlir::failure();
+  }
+  }
+}
+
 mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
     cir::UnreachableOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
diff --git a/clang/test/CIR/Lowering/struct.cir 
b/clang/test/CIR/Lowering/struct.cir
new file mode 100644
index 0000000000000..5ebd0d80afc30
--- /dev/null
+++ b/clang/test/CIR/Lowering/struct.cir
@@ -0,0 +1,23 @@
+// RUN: cir-opt %s -cir-to-llvm -o %t.mlir
+// RUN: FileCheck --input-file=%t.mlir %s
+
+!s32i = !cir.int<s, 32>
+!u8i = !cir.int<u, 8>
+!ty_S = !cir.record<struct "S" {!u8i, !s32i}>
+
+module {
+  // CHECK-LABEL: @test_value
+  cir.func @test_value() {
+    %0 = cir.const #cir.const_record<{#cir.int<1> : !u8i, #cir.int<2> : 
!s32i}> : !ty_S
+    //      CHECK: %[[#v0:]] = llvm.mlir.undef : !llvm.struct<"struct.S", (i8, 
i32)>
+    // CHECK-NEXT: %[[#v1:]] = llvm.mlir.constant(1 : i8) : i8
+    // CHECK-NEXT: %[[#v2:]] = llvm.insertvalue %[[#v1]], %[[#v0]][0] : 
!llvm.struct<"struct.S", (i8, i32)>
+    // CHECK-NEXT: %[[#v3:]] = llvm.mlir.constant(2 : i32) : i32
+    // CHECK-NEXT: %[[#v4:]] = llvm.insertvalue %[[#v3]], %[[#v2]][1] : 
!llvm.struct<"struct.S", (i8, i32)>
+    %1 = cir.extract_member %0[0] : !ty_S -> !u8i
+    // CHECK-NEXT: %{{.+}} = llvm.extractvalue %[[#v4]][0] : 
!llvm.struct<"struct.S", (i8, i32)>
+    %2 = cir.extract_member %0[1] : !ty_S -> !s32i
+    // CHECK-NEXT: %{{.+}} = llvm.extractvalue %[[#v4]][1] : 
!llvm.struct<"struct.S", (i8, i32)>
+    cir.return
+  }
+}

>From 4403653f9f1d5ecf148d20c1bd74713dcf1cc00d Mon Sep 17 00:00:00 2001
From: vishruth-thimmaiah <[email protected]>
Date: Fri, 26 Dec 2025 01:35:10 +0530
Subject: [PATCH 2/2] Add more tests

Signed-off-by: vishruth-thimmaiah <[email protected]>
---
 clang/test/CIR/IR/invalid-struct.cir | 43 ++++++++++++++++++++++++++++
 clang/test/CIR/IR/struct.cir         | 13 +++++++++
 2 files changed, 56 insertions(+)
 create mode 100644 clang/test/CIR/IR/invalid-struct.cir

diff --git a/clang/test/CIR/IR/invalid-struct.cir 
b/clang/test/CIR/IR/invalid-struct.cir
new file mode 100644
index 0000000000000..d34534c79eb44
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-struct.cir
@@ -0,0 +1,43 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+!u8i = !cir.int<u, 8>
+!u32i = !cir.int<u, 32>
+!rec_S = !cir.record<struct "S" {!u8i, !u32i}>
+
+module  {
+  cir.func @struct_extract_member_invalid_element_type() {
+    %0 = cir.const #cir.const_record<{#cir.int<1> : !u8i, #cir.int<3> : 
!u32i}> : !rec_S
+       // expected-error @below {{member type mismatch}}
+    %1 = cir.extract_member %0[1] : !rec_S -> !u8i
+    cir.return
+  }
+}
+
+// -----
+
+!u8i = !cir.int<u, 8>
+!u32i = !cir.int<u, 32>
+!rec_S = !cir.record<struct "S" {!u8i, !u32i}>
+
+module  {
+  cir.func @struct_extract_member_invalid_index_value() {
+    %0 = cir.const #cir.const_record<{#cir.int<1> : !u8i, #cir.int<3> : 
!u32i}> : !rec_S
+       // expected-error @below {{member index out of bounds}}
+    %1 = cir.extract_member %0[2] : !rec_S -> !u8i
+    cir.return
+  }
+}
+
+// -----
+
+!u32i = !cir.int<u, 32>
+!rec_U = !cir.record<union "U" {!u32i}>
+
+module  {
+  cir.func @extract_member_invalid_for_union() {
+    %0 = cir.const #cir.const_record<{#cir.int<1> : !u32i}> : !rec_U
+       // expected-error @below {{cir.extract_member currently does not work 
on unions}}
+    %1 = cir.extract_member %0[2] : !rec_U -> !u32i
+    cir.return
+  }
+}
diff --git a/clang/test/CIR/IR/struct.cir b/clang/test/CIR/IR/struct.cir
index 2e011fba36b26..0f36e1a418ca4 100644
--- a/clang/test/CIR/IR/struct.cir
+++ b/clang/test/CIR/IR/struct.cir
@@ -76,4 +76,17 @@ module  {
 // CHECK: cir.func @structs() {
 // CHECK:     %0 = cir.alloca !cir.ptr<!rec_Sc>, !cir.ptr<!cir.ptr<!rec_Sc>>, 
["sc", init]
 // CHECK:     %1 = cir.alloca !cir.ptr<!rec_U>, !cir.ptr<!cir.ptr<!rec_U>>, 
["u", init]
+
+cir.func @struct_extract_member_test() {
+    %0 = cir.const #cir.const_record<{#cir.int<1> : !u8i, #cir.int<2> : !u16i, 
#cir.int<3> : !u32i}> : !rec_Sc
+    %1 = cir.extract_member %0[0] : !rec_Sc -> !u8i
+    cir.return
+}
+
+// CHECK: cir.func{{.*}} @struct_extract_member_test() {
+// CHECK: %0 = cir.const #cir.const_record<{#cir.int<1> : !u8i, #cir.int<2> : 
!u16i, #cir.int<3> : !u32i}> : !rec_Sc
+// CHECK: %1 = cir.extract_member %0[0] : !rec_Sc -> !u8i
+// CHECK: cir.return
+// CHECK: }
+
 }

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

Reply via email to