llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangir

Author: Aman Maurya (amanmaurya92)

<details>
<summary>Changes</summary>

Implement support for pointer-to-data-member binary operators (`.*` and 
`-&gt;*`) when the result is an aggregate type.

Issue #<!-- -->221783

---
Full diff: https://github.com/llvm/llvm-project/pull/221784.diff


2 Files Affected:

- (modified) clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp (+7-4) 
- (modified) clang/test/CIR/CodeGen/pointer-to-data-member.cpp (+123) 


``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index 16bfdae8cb0f1..4f59b3004094e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -427,12 +427,15 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> 
{
 
   void VisitPredefinedExpr(const PredefinedExpr *e) { emitAggLoadOfLValue(e); }
   void VisitBinaryOperator(const BinaryOperator *e) {
-    cgf.cgm.errorNYI(e->getSourceRange(),
-                     "AggExprEmitter: VisitBinaryOperator");
+    if (e->getOpcode() == BO_PtrMemD || e->getOpcode() == BO_PtrMemI)
+      VisitPointerToDataMemberBinaryOperator(e);
+    else
+      cgf.cgm.errorNYI(e->getSourceRange(),
+                       "AggExprEmitter: VisitBinaryOperator");
   }
   void VisitPointerToDataMemberBinaryOperator(const BinaryOperator *e) {
-    cgf.cgm.errorNYI(e->getSourceRange(),
-                     "AggExprEmitter: VisitPointerToDataMemberBinaryOperator");
+    LValue lv = cgf.emitPointerToDataMemberBinaryExpr(e);
+    emitFinalDestCopy(e->getType(), lv);
   }
   void VisitBinComma(const BinaryOperator *e) {
     cgf.emitIgnoredExpr(e->getLHS());
diff --git a/clang/test/CIR/CodeGen/pointer-to-data-member.cpp 
b/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
index 9ad8a6fe58cc5..16d16c45fca70 100644
--- a/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
+++ b/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
@@ -480,3 +480,126 @@ void useHasField() {
 // LLVM: %[[GET_MEM:.*]] = getelementptr i8, ptr %[[LOAD_ARG]], i64 0
 // LLVM: store i32 1, ptr %[[GET_MEM]]
 
+struct Inner {
+  int x;
+  int y;
+};
+
+struct Outer {
+  int a;
+  Inner inner;
+};
+
+Inner test_agg_dot(const Outer &o, Inner Outer::*p) {
+  return o.*p;
+}
+
+// CIR-BEFORE-LABEL: cir.func {{.*}} @_Z12test_agg_dotRK5OuterMS_5Inner(
+// CIR-BEFORE-SAME:         %[[O_ARG:.*]]: !cir.ptr<!rec_Outer>
+// CIR-BEFORE-SAME:         %[[P_ARG:.*]]: !cir.data_member<!rec_Inner in 
!rec_Outer>
+// CIR-BEFORE:         %[[O_ADDR:.*]] = cir.alloca "o" {{.*}} init const : 
!cir.ptr<!cir.ptr<!rec_Outer>>
+// CIR-BEFORE:         %[[P_ADDR:.*]] = cir.alloca "p" {{.*}} init : 
!cir.ptr<!cir.data_member<!rec_Inner in !rec_Outer>>
+// CIR-BEFORE:         %[[RETVAL_ADDR:.*]] = cir.alloca "__retval" {{.*}} : 
!cir.ptr<!rec_Inner>
+// CIR-BEFORE:         cir.store %[[O_ARG]], %[[O_ADDR]]
+// CIR-BEFORE:         cir.store %[[P_ARG]], %[[P_ADDR]]
+// CIR-BEFORE:         %[[O:.*]] = cir.load %[[O_ADDR]]
+// CIR-BEFORE:         %[[P:.*]] = cir.load{{.*}} %[[P_ADDR]]
+// CIR-BEFORE:         %[[RT_MEMBER:.*]] = cir.get_runtime_member 
%[[O]][%[[P]] : !cir.data_member<!rec_Inner in !rec_Outer>] : 
!cir.ptr<!rec_Outer> -> !cir.ptr<!rec_Inner>
+// CIR-BEFORE:         cir.copy %[[RT_MEMBER]] to %[[RETVAL_ADDR]] : 
!cir.ptr<!rec_Inner>
+// CIR-BEFORE:         cir.return
+
+// CIR-AFTER-LABEL: cir.func {{.*}} @_Z12test_agg_dotRK5OuterMS_5Inner(
+// CIR-AFTER-SAME:        %[[O_ARG:.*]]: !cir.ptr<!rec_Outer>
+// CIR-AFTER-SAME:        %[[P_ARG:.*]]: !s64i
+// CIR-AFTER:        %[[O_ADDR:.*]] = cir.alloca "o" {{.*}} init const : 
!cir.ptr<!cir.ptr<!rec_Outer>>
+// CIR-AFTER:        %[[P_ADDR:.*]] = cir.alloca "p" {{.*}} init : 
!cir.ptr<!s64i>
+// CIR-AFTER:        %[[RETVAL_ADDR:.*]] = cir.alloca "__retval" {{.*}} : 
!cir.ptr<!rec_Inner>
+// CIR-AFTER:        cir.store %[[O_ARG]], %[[O_ADDR]] : !cir.ptr<!rec_Outer>, 
!cir.ptr<!cir.ptr<!rec_Outer>>
+// CIR-AFTER:        cir.store %[[P_ARG]], %[[P_ADDR]] : !s64i, !cir.ptr<!s64i>
+// CIR-AFTER:        %[[O:.*]] = cir.load %[[O_ADDR]] : 
!cir.ptr<!cir.ptr<!rec_Outer>>, !cir.ptr<!rec_Outer>
+// CIR-AFTER:        %[[P:.*]] = cir.load{{.*}} %[[P_ADDR]] : !cir.ptr<!s64i>, 
!s64i
+// CIR-AFTER:        %[[BYTE_PTR:.*]] = cir.cast bitcast %[[O]] : 
!cir.ptr<!rec_Outer> -> !cir.ptr<!s8i>
+// CIR-AFTER:        %[[BYTE_PTR_STRIDE:.*]] = cir.ptr_stride %[[BYTE_PTR]], 
%[[P]] : (!cir.ptr<!s8i>, !s64i) -> !cir.ptr<!s8i>
+// CIR-AFTER:        %[[MEMBER_ADDR:.*]] = cir.cast bitcast 
%[[BYTE_PTR_STRIDE]] : !cir.ptr<!s8i> -> !cir.ptr<!rec_Inner>
+// CIR-AFTER:        cir.copy %[[MEMBER_ADDR]] to %[[RETVAL_ADDR]] : 
!cir.ptr<!rec_Inner>
+// CIR-AFTER:        cir.return
+
+// LLVM-LABEL: define {{.*}} @_Z12test_agg_dotRK5OuterMS_5Inner(
+// LLVM:   %[[RETVAL_ADDR:.*]] = alloca %struct.Inner
+// LLVM:   %[[O_ADDR:.*]] = alloca ptr
+// LLVM:   %[[P_ADDR:.*]] = alloca i64
+// LLVM:   store ptr %[[O_ARG:.*]], ptr %[[O_ADDR]]
+// LLVM:   store i64 %[[P_ARG:.*]], ptr %[[P_ADDR]]
+// LLVM:   %[[O:.*]] = load ptr, ptr %[[O_ADDR]]
+// LLVM:   %[[P:.*]] = load i64, ptr %[[P_ADDR]]
+// LLVM:   %[[RT_MEMBER:.*]] = getelementptr i8, ptr %[[O]], i64 %[[P]]
+// LLVM:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[RETVAL_ADDR]], ptr 
align 4 %[[RT_MEMBER]], i64 8, i1 false)
+
+// OGCG-LABEL: define {{.*}} @_Z12test_agg_dotRK5OuterMS_5Inner(
+// OGCG:   %[[RETVAL_ADDR:.*]] = alloca %struct.Inner
+// OGCG:   %[[O_ADDR:.*]] = alloca ptr
+// OGCG:   %[[P_ADDR:.*]] = alloca i64
+// OGCG:   store ptr %[[O_ARG:.*]], ptr %[[O_ADDR]]
+// OGCG:   store i64 %[[P_ARG:.*]], ptr %[[P_ADDR]]
+// OGCG:   %[[O:.*]] = load ptr, ptr %[[O_ADDR]]
+// OGCG:   %[[P:.*]] = load i64, ptr %[[P_ADDR]]
+// OGCG:   %[[RT_MEMBER:.*]] = getelementptr inbounds i8, ptr %[[O]], i64 
%[[P]]
+// OGCG:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[RETVAL_ADDR]], ptr 
align 4 %[[RT_MEMBER]], i64 8, i1 false)
+
+Inner test_agg_arrow(const Outer *o, Inner Outer::*p) {
+  return o->*p;
+}
+
+// CIR-BEFORE-LABEL: cir.func {{.*}} @_Z14test_agg_arrowPK5OuterMS_5Inner(
+// CIR-BEFORE-SAME:         %[[O_ARG:.*]]: !cir.ptr<!rec_Outer>
+// CIR-BEFORE-SAME:         %[[P_ARG:.*]]: !cir.data_member<!rec_Inner in 
!rec_Outer>
+// CIR-BEFORE:         %[[O_ADDR:.*]] = cir.alloca "o" {{.*}} init const : 
!cir.ptr<!cir.ptr<!rec_Outer>>
+// CIR-BEFORE:         %[[P_ADDR:.*]] = cir.alloca "p" {{.*}} init : 
!cir.ptr<!cir.data_member<!rec_Inner in !rec_Outer>>
+// CIR-BEFORE:         %[[RETVAL_ADDR:.*]] = cir.alloca "__retval" {{.*}} : 
!cir.ptr<!rec_Inner>
+// CIR-BEFORE:         cir.store %[[O_ARG]], %[[O_ADDR]]
+// CIR-BEFORE:         cir.store %[[P_ARG]], %[[P_ADDR]]
+// CIR-BEFORE:         %[[O:.*]] = cir.load{{.*}} %[[O_ADDR]]
+// CIR-BEFORE:         %[[P:.*]] = cir.load{{.*}} %[[P_ADDR]]
+// CIR-BEFORE:         %[[RT_MEMBER:.*]] = cir.get_runtime_member 
%[[O]][%[[P]] : !cir.data_member<!rec_Inner in !rec_Outer>] : 
!cir.ptr<!rec_Outer> -> !cir.ptr<!rec_Inner>
+// CIR-BEFORE:         cir.copy %[[RT_MEMBER]] to %[[RETVAL_ADDR]] : 
!cir.ptr<!rec_Inner>
+// CIR-BEFORE:         cir.return
+
+// CIR-AFTER-LABEL: cir.func {{.*}} @_Z14test_agg_arrowPK5OuterMS_5Inner(
+// CIR-AFTER-SAME:        %[[O_ARG:.*]]: !cir.ptr<!rec_Outer>
+// CIR-AFTER-SAME:        %[[P_ARG:.*]]: !s64i
+// CIR-AFTER:        %[[O_ADDR:.*]] = cir.alloca "o" {{.*}} init const : 
!cir.ptr<!cir.ptr<!rec_Outer>>
+// CIR-AFTER:        %[[P_ADDR:.*]] = cir.alloca "p" {{.*}} init : 
!cir.ptr<!s64i>
+// CIR-AFTER:        %[[RETVAL_ADDR:.*]] = cir.alloca "__retval" {{.*}} : 
!cir.ptr<!rec_Inner>
+// CIR-AFTER:        cir.store %[[O_ARG]], %[[O_ADDR]] : !cir.ptr<!rec_Outer>, 
!cir.ptr<!cir.ptr<!rec_Outer>>
+// CIR-AFTER:        cir.store %[[P_ARG]], %[[P_ADDR]] : !s64i, !cir.ptr<!s64i>
+// CIR-AFTER:        %[[O:.*]] = cir.load{{.*}} %[[O_ADDR]] : 
!cir.ptr<!cir.ptr<!rec_Outer>>, !cir.ptr<!rec_Outer>
+// CIR-AFTER:        %[[P:.*]] = cir.load{{.*}} %[[P_ADDR]] : !cir.ptr<!s64i>, 
!s64i
+// CIR-AFTER:        %[[BYTE_PTR:.*]] = cir.cast bitcast %[[O]] : 
!cir.ptr<!rec_Outer> -> !cir.ptr<!s8i>
+// CIR-AFTER:        %[[BYTE_PTR_STRIDE:.*]] = cir.ptr_stride %[[BYTE_PTR]], 
%[[P]] : (!cir.ptr<!s8i>, !s64i) -> !cir.ptr<!s8i>
+// CIR-AFTER:        %[[MEMBER_ADDR:.*]] = cir.cast bitcast 
%[[BYTE_PTR_STRIDE]] : !cir.ptr<!s8i> -> !cir.ptr<!rec_Inner>
+// CIR-AFTER:        cir.copy %[[MEMBER_ADDR]] to %[[RETVAL_ADDR]] : 
!cir.ptr<!rec_Inner>
+// CIR-AFTER:        cir.return
+
+// LLVM-LABEL: define {{.*}} @_Z14test_agg_arrowPK5OuterMS_5Inner(
+// LLVM:   %[[RETVAL_ADDR:.*]] = alloca %struct.Inner
+// LLVM:   %[[O_ADDR:.*]] = alloca ptr
+// LLVM:   %[[P_ADDR:.*]] = alloca i64
+// LLVM:   store ptr %[[O_ARG:.*]], ptr %[[O_ADDR]]
+// LLVM:   store i64 %[[P_ARG:.*]], ptr %[[P_ADDR]]
+// LLVM:   %[[O:.*]] = load ptr, ptr %[[O_ADDR]]
+// LLVM:   %[[P:.*]] = load i64, ptr %[[P_ADDR]]
+// LLVM:   %[[RT_MEMBER:.*]] = getelementptr i8, ptr %[[O]], i64 %[[P]]
+// LLVM:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[RETVAL_ADDR]], ptr 
align 4 %[[RT_MEMBER]], i64 8, i1 false)
+
+// OGCG-LABEL: define {{.*}} @_Z14test_agg_arrowPK5OuterMS_5Inner(
+// OGCG:   %[[RETVAL_ADDR:.*]] = alloca %struct.Inner
+// OGCG:   %[[O_ADDR:.*]] = alloca ptr
+// OGCG:   %[[P_ADDR:.*]] = alloca i64
+// OGCG:   store ptr %[[O_ARG:.*]], ptr %[[O_ADDR]]
+// OGCG:   store i64 %[[P_ARG:.*]], ptr %[[P_ADDR]]
+// OGCG:   %[[O:.*]] = load ptr, ptr %[[O_ADDR]]
+// OGCG:   %[[P:.*]] = load i64, ptr %[[P_ADDR]]
+// OGCG:   %[[RT_MEMBER:.*]] = getelementptr inbounds i8, ptr %[[O]], i64 
%[[P]]
+// OGCG:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[RETVAL_ADDR]], ptr 
align 4 %[[RT_MEMBER]], i64 8, i1 false)
+
+

``````````

</details>


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

Reply via email to