@@ -34,3 +34,53 @@ void fn1() { F f1; }
3434// OGCG: define {{.*}} ptr @_ZN1F1bEv
3535// OGCG: %[[VAR_H:.*]] = load i32, ptr @h
3636// OGCG: %[[RET:.*]] = call noundef ptr @_ZN1A1bEi(i32 noundef %[[VAR_H]])
37+
38+ class B {
39+ public:
40+ B ();
41+ int (&indirect_callee_int_ref)(int );
42+ };
43+
44+ class C {
45+ public:
46+ int call_indirect (int v) { return inner.indirect_callee_int_ref (v); };
47+ B inner;
48+ };
49+
50+ void fn2 () { C c1; c1.call_indirect (2 ); }
51+
52+ // CIR: cir.func {{.*}} @_ZN1C13call_indirectEi(%[[THIS_ARG:.*]]: !cir.ptr<!rec_C> {{.*}}, %[[V_ARG:.*]]: !s32i {{.*}}) -> !s32i
53+ // CIR: %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<!rec_C>, !cir.ptr<!cir.ptr<!rec_C>>, ["this", init]
54+ // CIR: %[[V_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["v", init]
55+ // CIR: cir.store %[[THIS_ARG]], %[[THIS_ADDR]]
56+ // CIR: cir.store %[[V_ARG]], %[[V_ADDR]]
57+ // CIR: %[[THIS:.*]] = cir.load %[[THIS_ADDR]]
58+ // CIR: %[[INNER:.*]] = cir.get_member %[[THIS]][0] {name = "inner"} : !cir.ptr<!rec_C> -> !cir.ptr<!rec_B>
59+ // CIR: %[[INDIRECT_CALLEE_PTR:.*]] = cir.get_member %[[INNER]][0] {name = "indirect_callee_int_ref"}
60+ // CIR: %[[INDIRECT_CALLEE:.*]] = cir.load %[[INDIRECT_CALLEE_PTR]]
61+ // CIR: %[[V:.*]] = cir.load{{.*}} %[[V_ADDR]] : !cir.ptr<!s32i>, !s32i
62+ // CIR: %[[RET:.*]] = cir.call %[[INDIRECT_CALLEE]](%[[V]])
63+
64+ // LLVM: define {{.*}} i32 @_ZN1C13call_indirectEi(ptr %[[THIS_ARG:.*]], i32 %[[V_ARG:.*]])
65+ // LLVM: %[[THIS_ADDR:.*]] = alloca ptr
66+ // LLVM: %[[V_ADDR:.*]] = alloca i32
67+ // LLVM: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
68+ // LLVM: store i32 %[[V_ARG]], ptr %[[V_ADDR]]
69+ // LLVM: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
70+ // LLVM: %[[INNER:.*]] = getelementptr %class.C, ptr %[[THIS]], i32 0, i32 0
71+ // LLVM: %[[INDIRECT_CALLEE_PTR:.*]] = getelementptr %class.B, ptr %[[INNER]], i32 0, i32 0
72+ // LLVM: %[[INDIRECT_CALLEE:.*]] = load ptr, ptr %[[INDIRECT_CALLEE_PTR]]
73+ // LLVM: %[[V:.*]] = load i32, ptr %[[V_ADDR]]
74+ // LLVM: %[[RET:.*]] = call i32 %[[INDIRECT_CALLEE]](i32 %[[V]])
75+
76+ // OGCG: define {{.*}} i32 @_ZN1C13call_indirectEi(ptr {{.*}} %[[THIS_ARG:.*]], i32 {{.*}} %[[V_ARG:.*]])
77+ // OGCG: %[[THIS_ADDR:.*]] = alloca ptr
78+ // OGCG: %[[V_ADDR:.*]] = alloca i32
79+ // OGCG: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
80+ // OGCG: store i32 %[[V_ARG]], ptr %[[V_ADDR]]
81+ // OGCG: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
82+ // OGCG: %[[INNER:.*]] = getelementptr inbounds nuw %class.C, ptr %[[THIS]], i32 0, i32 0
83+ // OGCG: %[[INDIRECT_CALLEE_PTR:.*]] = getelementptr inbounds nuw %class.B, ptr %[[INNER]], i32 0, i32 0
84+ // OGCG: %[[INDIRECT_CALLEE:.*]] = load ptr, ptr %[[INDIRECT_CALLEE_PTR]]
85+ // OGCG: %[[V:.*]] = load i32, ptr %[[V_ADDR]]
86+ // OGCG: %[[RET:.*]] = call noundef i32 %[[INDIRECT_CALLEE]](i32 noundef %[[V]])
0 commit comments