184 lines · cpp
1// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -fno-rtti -fclangir -emit-cir %s -o %t.cir2// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s3// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -fno-rtti -fclangir -emit-llvm %s -o %t-cir.ll4// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s5// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -fno-rtti -emit-llvm %s -o %t.ll6// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s7 8// Note: This test is using -fno-rtti so that we can delay implemntation of that handling.9// When rtti handling for vtables is implemented, that option should be removed.10 11class Mother {12public:13 virtual void MotherKey();14 void simple() { }15 virtual void MotherNonKey() {}16};17 18class Father {19public:20 virtual void FatherKey();21};22 23class Child : public Mother, public Father {24public:25 Child();26 void MotherKey() override;27};28 29void Mother::MotherKey() {}30void Father::FatherKey() {}31void Child::MotherKey() {}32 33// CIR-DAG: [[MOTHER_VTABLE_TYPE:.*]] = !cir.record<struct {!cir.array<!cir.ptr<!u8i> x 4>}>34// CIR-DAG: [[FATHER_VTABLE_TYPE:.*]] = !cir.record<struct {!cir.array<!cir.ptr<!u8i> x 3>}>35// CIR-DAG: [[CHILD_VTABLE_TYPE:.*]] = !cir.record<struct {!cir.array<!cir.ptr<!u8i> x 4>, !cir.array<!cir.ptr<!u8i> x 3>}>36// CIR-DAG: !rec_Father = !cir.record<class "Father" {!cir.vptr}37// CIR-DAG: !rec_Mother = !cir.record<class "Mother" {!cir.vptr}38// CIR-DAG: !rec_Child = !cir.record<class "Child" {!rec_Mother, !rec_Father}39 40// Child vtable41 42// CIR: cir.global "private" external @_ZTV5Child = #cir.vtable<{43// CIR-SAME: #cir.const_array<[44// CIR-SAME: #cir.ptr<null> : !cir.ptr<!u8i>,45// CIR-SAME: #cir.ptr<null> : !cir.ptr<!u8i>,46// CIR-SAME: #cir.global_view<@_ZN5Child9MotherKeyEv> : !cir.ptr<!u8i>,47// CIR-SAME: #cir.global_view<@_ZN6Mother12MotherNonKeyEv> : !cir.ptr<!u8i>48// CIR-SAME: ]> : !cir.array<!cir.ptr<!u8i> x 4>,49// CIR-SAME: #cir.const_array<[50// CIR-SAME: #cir.ptr<-8 : i64> : !cir.ptr<!u8i>,51// CIR-SAME: #cir.ptr<null> : !cir.ptr<!u8i>,52// CIR-SAME: #cir.global_view<@_ZN6Father9FatherKeyEv> : !cir.ptr<!u8i>53// CIR-SAME: ]> : !cir.array<!cir.ptr<!u8i> x 3>54// CIR-SAME: }> : [[CHILD_VTABLE_TYPE]]55 56// LLVM: @_ZTV5Child = global { [4 x ptr], [3 x ptr] } {57// LLVM-SAME: [4 x ptr] [58// LLVM-SAME: ptr null,59// LLVM-SAME: ptr null,60// LLVM-SAME: ptr @_ZN5Child9MotherKeyEv,61// LLVM-SAME: ptr @_ZN6Mother12MotherNonKeyEv62// LLVM-SAME: ],63// LLVM-SAME: [3 x ptr] [64// LLVM-SAME: ptr inttoptr (i64 -8 to ptr),65// LLVM-SAME: ptr null,66// LLVM-SAME: ptr @_ZN6Father9FatherKeyEv67// LLVM-SAME: ]68// LLVM-SAME: }69 70// OGCG: @_ZTV5Child = unnamed_addr constant { [4 x ptr], [3 x ptr] } {71// OGCG-SAME: [4 x ptr] [72// OGCG-SAME: ptr null,73// OGCG-SAME: ptr null,74// OGCG-SAME: ptr @_ZN5Child9MotherKeyEv,75// OGCG-SAME: ptr @_ZN6Mother12MotherNonKeyEv76// OGCG-SAME: ],77// OGCG-SAME: [3 x ptr] [78// OGCG-SAME: ptr inttoptr (i64 -8 to ptr),79// OGCG-SAME: ptr null,80// OGCG-SAME: ptr @_ZN6Father9FatherKeyEv81// OGCG-SAME: ]82// OGCG-SAME: }83 84// Mother vtable85 86// CIR: cir.global "private" external @_ZTV6Mother = #cir.vtable<{87// CIR-SAME: #cir.const_array<[88// CIR-SAME: #cir.ptr<null> : !cir.ptr<!u8i>,89// CIR-SAME: #cir.ptr<null> : !cir.ptr<!u8i>,90// CIR-SAME: #cir.global_view<@_ZN6Mother9MotherKeyEv> : !cir.ptr<!u8i>,91// CIR-SAME: #cir.global_view<@_ZN6Mother12MotherNonKeyEv> : !cir.ptr<!u8i>92// CIR-SAME: ]> : !cir.array<!cir.ptr<!u8i> x 4>93// CIR-SAME: }> : [[MOTHER_VTABLE_TYPE]]94 95// LLVM: @_ZTV6Mother = global { [4 x ptr] } {96// LLVM-SAME: [4 x ptr] [97// LLVM-SAME: ptr null,98// LLVM-SAME: ptr null,99// LLVM-SAME: ptr @_ZN6Mother9MotherKeyEv,100// LLVM-SAME: ptr @_ZN6Mother12MotherNonKeyEv101// LLVM-SAME: ]102// LLVM-SAME: }103 104// OGCG: @_ZTV6Mother = unnamed_addr constant { [4 x ptr] } {105// OGCG-SAME: [4 x ptr] [106// OGCG-SAME: ptr null,107// OGCG-SAME: ptr null,108// OGCG-SAME: ptr @_ZN6Mother9MotherKeyEv,109// OGCG-SAME: ptr @_ZN6Mother12MotherNonKeyEv110// OGCG-SAME: ]111// OGCG-SAME: }112 113// Father vtable114 115// CIR: cir.global "private" external @_ZTV6Father = #cir.vtable<{116// CIR-SAME: #cir.const_array<[117// CIR-SAME: #cir.ptr<null> : !cir.ptr<!u8i>,118// CIR-SAME: #cir.ptr<null> : !cir.ptr<!u8i>,119// CIR-SAME: #cir.global_view<@_ZN6Father9FatherKeyEv> : !cir.ptr<!u8i>120// CIR-SAME: ]> : !cir.array<!cir.ptr<!u8i> x 3>121// CIR-SAME: }> : [[FATHER_VTABLE_TYPE]]122 123// LLVM: @_ZTV6Father = global { [3 x ptr] } {124// LLVM-SAME: [3 x ptr] [125// LLVM-SAME: ptr null,126// LLVM-SAME: ptr null,127// LLVM-SAME: ptr @_ZN6Father9FatherKeyEv128// LLVM-SAME: ]129// LLVM-SAME: }130 131// OGCG: @_ZTV6Father = unnamed_addr constant { [3 x ptr] } {132// OGCG-SAME: [3 x ptr] [133// OGCG-SAME: ptr null,134// OGCG-SAME: ptr null,135// OGCG-SAME: ptr @_ZN6Father9FatherKeyEv136// OGCG-SAME: ]137// OGCG-SAME: }138 139 140Child::Child() {}141 142// CIR: cir.func {{.*}} @_ZN5ChildC2Ev(%[[THIS_ARG:.*]]: !cir.ptr<!rec_Child>143// CIR: %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]144// CIR: cir.store %[[THIS_ARG]], %[[THIS_ADDR]]145// CIR: %[[THIS:.*]] = cir.load %[[THIS_ADDR]]146// CIR: %[[MOTHER_BASE:.*]] = cir.base_class_addr %[[THIS]] : !cir.ptr<!rec_Child> nonnull [0] -> !cir.ptr<!rec_Mother>147// CIR: cir.call @_ZN6MotherC2Ev(%[[MOTHER_BASE]]) nothrow : (!cir.ptr<!rec_Mother>) -> ()148// CIR: %[[FATHER_BASE:.*]] = cir.base_class_addr %[[THIS]] : !cir.ptr<!rec_Child> nonnull [8] -> !cir.ptr<!rec_Father>149// CIR: cir.call @_ZN6FatherC2Ev(%[[FATHER_BASE]]) nothrow : (!cir.ptr<!rec_Father>) -> ()150// CIR: %[[CHILD_VPTR:.*]] = cir.vtable.address_point(@_ZTV5Child, address_point = <index = 0, offset = 2>) : !cir.vptr151// CIR: %[[CHILD_VPTR_ADDR:.*]] = cir.vtable.get_vptr %[[THIS]] : !cir.ptr<!rec_Child> -> !cir.ptr<!cir.vptr>152// CIR: cir.store{{.*}} %[[CHILD_VPTR]], %[[CHILD_VPTR_ADDR]] : !cir.vptr, !cir.ptr<!cir.vptr>153// CIR: %[[FATHER_IN_CHILD_VPTR:.*]] = cir.vtable.address_point(@_ZTV5Child, address_point = <index = 1, offset = 2>) : !cir.vptr154// CIR: %[[FATHER_BASE:.*]] = cir.base_class_addr %[[THIS]] : !cir.ptr<!rec_Child> nonnull [8] -> !cir.ptr<!rec_Father>155// CIR: %[[FATHER_IN_CHILD_VPTR_ADDR:.*]] = cir.vtable.get_vptr %[[FATHER_BASE]] : !cir.ptr<!rec_Father> -> !cir.ptr<!cir.vptr>156// CIR: cir.store{{.*}} %[[FATHER_IN_CHILD_VPTR]], %[[FATHER_IN_CHILD_VPTR_ADDR]] : !cir.vptr, !cir.ptr<!cir.vptr>157// CIR: cir.return158 159// The GEP instructions are different between LLVM and OGCG, but they calculate the same addresses.160 161// LLVM: define{{.*}} void @_ZN5ChildC2Ev(ptr{{.*}} %[[THIS_ARG:.*]])162// LLVM: %[[THIS_ADDR:.*]] = alloca ptr163// LLVM: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]164// LLVM: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]165// LLVM: call void @_ZN6MotherC2Ev(ptr{{.*}} %[[THIS]])166// LLVM: %[[FATHER_BASE:.*]] = getelementptr{{.*}} i8, ptr %[[THIS]], i32 8167// LLVM: call void @_ZN6FatherC2Ev(ptr{{.*}} %[[FATHER_BASE]])168// LLVM: store ptr getelementptr inbounds nuw (i8, ptr @_ZTV5Child, i64 16), ptr %[[THIS]]169// LLVM: %[[FATHER_BASE:.*]] = getelementptr{{.*}} i8, ptr %[[THIS]], i32 8170// LLVM: store ptr getelementptr inbounds nuw (i8, ptr @_ZTV5Child, i64 48), ptr %[[FATHER_BASE]]171// LLVM: ret void172 173// OGCG: define{{.*}} void @_ZN5ChildC2Ev(ptr{{.*}} %[[THIS_ARG:.*]])174// OGCG: %[[THIS_ADDR:.*]] = alloca ptr175// OGCG: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]176// OGCG: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]177// OGCG: call void @_ZN6MotherC2Ev(ptr {{.*}} %[[THIS]])178// OGCG: %[[FATHER_BASE:.*]] = getelementptr{{.*}} i8, ptr %[[THIS]], i64 8179// OGCG: call void @_ZN6FatherC2Ev(ptr{{.*}} %[[FATHER_BASE]])180// OGCG: store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [3 x ptr] }, ptr @_ZTV5Child, i32 0, i32 0, i32 2), ptr %[[THIS]]181// OGCG: %[[FATHER_BASE:.*]] = getelementptr{{.*}} i8, ptr %[[THIS]], i64 8182// OGCG: store ptr getelementptr inbounds inrange(-16, 8) ({ [4 x ptr], [3 x ptr] }, ptr @_ZTV5Child, i32 0, i32 1, i32 2), ptr %[[FATHER_BASE]]183// OGCG: ret void184