|
| 1 | +// RUN: %clang_cc1 -std=c++20 -triple aarch64-none-linux-android21 -fclangir -emit-cir %s -o %t.cir |
| 2 | +// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR |
| 3 | +// RUN: %clang_cc1 -std=c++20 -triple aarch64-none-linux-android21 -fclangir -emit-llvm %s -o %t-cir.ll |
| 4 | +// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM |
| 5 | +// RUN: %clang_cc1 -std=c++20 -triple aarch64-none-linux-android21 -emit-llvm %s -o %t.ll |
| 6 | +// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG |
| 7 | + |
| 8 | +class A { |
| 9 | +public: |
| 10 | + static char *b(int); |
| 11 | +}; |
| 12 | + |
| 13 | +int h=0; |
| 14 | + |
| 15 | +class F { |
| 16 | +public: |
| 17 | + const char *b(); |
| 18 | + A g; |
| 19 | +}; |
| 20 | + |
| 21 | +const char *F::b() { return g.b(h); } |
| 22 | + |
| 23 | +void fn1() { F f1; } |
| 24 | + |
| 25 | +// CIR: cir.func {{.*}} @_ZN1F1bEv |
| 26 | +// CIR: %[[H_PTR:.*]] = cir.get_global @h : !cir.ptr<!s32i> |
| 27 | +// CIR: %[[H_VAL:.*]] = cir.load{{.*}} %[[H_PTR]] : !cir.ptr<!s32i>, !s32i |
| 28 | +// CIR: %[[RET:.*]] = cir.call @_ZN1A1bEi(%[[H_VAL]]) : (!s32i) -> !cir.ptr<!s8i> |
| 29 | + |
| 30 | +// LLVM: define {{.*}} ptr @_ZN1F1bEv |
| 31 | +// LLVM: %[[VAR_H:.*]] = load i32, ptr @h |
| 32 | +// LLVM: %[[RET:.*]] = call ptr @_ZN1A1bEi(i32 %[[VAR_H]]) |
| 33 | + |
| 34 | +// OGCG: define {{.*}} ptr @_ZN1F1bEv |
| 35 | +// OGCG: %[[VAR_H:.*]] = load i32, ptr @h |
| 36 | +// 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