brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.9 KiB · 8fcb2a4 Raw
156 lines · cpp
1// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir2// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR3// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll4// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM5// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll6// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG7 8// Test the record layout for a class with a primary virtual base.9class Base {10public:11  virtual void f();12};13 14class Derived : public virtual Base {};15 16void f() {17  Derived d;18  d.f();19}20 21class DerivedFinal final : public virtual Base {};22 23void g() {24  DerivedFinal df;25  df.f();26}27 28// CIR: !rec_Base = !cir.record<class "Base" {!cir.vptr}>29// CIR: !rec_Derived = !cir.record<class "Derived" {!rec_Base}>30// CIR: !rec_DerivedFinal = !cir.record<class "DerivedFinal" {!rec_Base}>31 32// LLVM: %class.Derived = type { %class.Base }33// LLVM: %class.Base = type { ptr }34// LLVM: %class.DerivedFinal = type { %class.Base }35 36// OGCG: %class.Derived = type { %class.Base }37// OGCG: %class.Base = type { ptr }38// OGCG: %class.DerivedFinal = type { %class.Base }39 40// Test the constructor handling for a class with a virtual base.41struct A {42  int a;43};44 45struct B:  virtual A {46  int b;47};48 49void ppp() { B b; }50 51// Note: OGCG speculatively emits the VTT and VTables. This is not yet implemented in CIR.52 53// Vtable definition for B54// CIR:  cir.global "private" external @_ZTV1B55 56// LLVM: @_ZTV1B = external global { [3 x ptr] }57 58// OGCG: @_ZTV1B = linkonce_odr unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr inttoptr (i64 12 to ptr), ptr null, ptr @_ZTI1B] }, comdat, align 859 60// CIR: cir.func {{.*}}@_Z1fv()61// CIR:   %[[D:.+]] = cir.alloca !rec_Derived, !cir.ptr<!rec_Derived>, ["d", init]62// CIR:   cir.call @_ZN7DerivedC1Ev(%[[D]]) nothrow : (!cir.ptr<!rec_Derived>) -> ()63// CIR:   %[[VPTR_PTR:.+]] = cir.vtable.get_vptr %[[D]] : !cir.ptr<!rec_Derived> -> !cir.ptr<!cir.vptr>64// CIR:   %[[VPTR:.+]] = cir.load {{.*}} %[[VPTR_PTR]] : !cir.ptr<!cir.vptr>, !cir.vptr65// CIR:   %[[VPTR_I8:.+]] = cir.cast bitcast %[[VPTR]] : !cir.vptr -> !cir.ptr<!u8i>66// CIR:   %[[NEG32:.+]] = cir.const #cir.int<-32> : !s64i67// CIR:   %[[ADJ_VPTR_I8:.+]] = cir.ptr_stride %[[VPTR_I8]], %[[NEG32]] : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i>68// CIR:   %[[OFFSET_PTR:.+]] = cir.cast bitcast %[[ADJ_VPTR_I8]] : !cir.ptr<!u8i> -> !cir.ptr<!s64i>69// CIR:   %[[OFFSET:.+]] = cir.load {{.*}} %[[OFFSET_PTR]] : !cir.ptr<!s64i>, !s64i70// CIR:   %[[D_I8:.+]] = cir.cast bitcast %[[D]] : !cir.ptr<!rec_Derived> -> !cir.ptr<!u8i>71// CIR:   %[[ADJ_THIS_I8:.+]] = cir.ptr_stride %[[D_I8]], %[[OFFSET]] : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i>72// CIR:   %[[ADJ_THIS_D:.+]] = cir.cast bitcast %[[ADJ_THIS_I8]] : !cir.ptr<!u8i> -> !cir.ptr<!rec_Derived>73// CIR:   %[[BASE_THIS:.+]] = cir.cast bitcast %[[ADJ_THIS_D]] : !cir.ptr<!rec_Derived> -> !cir.ptr<!rec_Base>74// CIR:   %[[BASE_VPTR_PTR:.+]] = cir.vtable.get_vptr %[[BASE_THIS]] : !cir.ptr<!rec_Base> -> !cir.ptr<!cir.vptr>75// CIR:   %[[BASE_VPTR:.+]] = cir.load {{.*}} %[[BASE_VPTR_PTR]] : !cir.ptr<!cir.vptr>, !cir.vptr76// CIR:   %[[SLOT_PTR:.+]] = cir.vtable.get_virtual_fn_addr %[[BASE_VPTR]][0] : !cir.vptr -> !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>>77// CIR:   %[[FN:.+]] = cir.load {{.*}} %[[SLOT_PTR]] : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>>, !cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>78// CIR:   cir.call %[[FN]](%[[BASE_THIS]]) : (!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>, !cir.ptr<!rec_Base>) -> ()79// CIR:   cir.return80 81// CIR: cir.func {{.*}}@_Z1gv()82// CIR:   %[[DF:.+]] = cir.alloca !rec_DerivedFinal, !cir.ptr<!rec_DerivedFinal>, ["df", init]83// CIR:   cir.call @_ZN12DerivedFinalC1Ev(%[[DF]]) nothrow : (!cir.ptr<!rec_DerivedFinal>) -> ()84// CIR:   %[[BASE_THIS_2:.+]] = cir.base_class_addr %[[DF]] : !cir.ptr<!rec_DerivedFinal> nonnull [0] -> !cir.ptr<!rec_Base>85// CIR:   %[[BASE_VPTR_PTR_2:.+]] = cir.vtable.get_vptr %[[BASE_THIS_2]] : !cir.ptr<!rec_Base> -> !cir.ptr<!cir.vptr>86// CIR:   %[[BASE_VPTR_2:.+]] = cir.load {{.*}} %[[BASE_VPTR_PTR_2]] : !cir.ptr<!cir.vptr>, !cir.vptr87// CIR:   %[[SLOT_PTR_2:.+]] = cir.vtable.get_virtual_fn_addr %[[BASE_VPTR_2]][0] : !cir.vptr -> !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>>88// CIR:   %[[FN_2:.+]] = cir.load {{.*}} %[[SLOT_PTR_2]] : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>>, !cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>89// CIR:   cir.call %[[FN_2]](%[[BASE_THIS_2]]) : (!cir.ptr<!cir.func<(!cir.ptr<!rec_Base>)>>, !cir.ptr<!rec_Base>) -> ()90// CIR:   cir.return91 92// LLVM: define {{.*}}void @_Z1fv(){{.*}}93// LLVM:   %[[D:.+]] = alloca {{.*}}94// LLVM:   call void @_ZN7DerivedC1Ev(ptr %[[D]])95// LLVM:   %[[VPTR_ADDR:.+]] = load ptr, ptr %[[D]]96// LLVM:   %[[NEG32_PTR:.+]] = getelementptr i8, ptr %[[VPTR_ADDR]], i64 -3297// LLVM:   %[[OFF:.+]] = load i64, ptr %[[NEG32_PTR]]98// LLVM:   %[[ADJ_THIS:.+]] = getelementptr i8, ptr %[[D]], i64 %[[OFF]]99// LLVM:   %[[VFN_TAB:.+]] = load ptr, ptr %[[ADJ_THIS]]100// LLVM:   %[[SLOT0:.+]] = getelementptr inbounds ptr, ptr %[[VFN_TAB]], i32 0101// LLVM:   %[[VFN:.+]] = load ptr, ptr %[[SLOT0]]102// LLVM:   call void %[[VFN]](ptr %[[ADJ_THIS]])103// LLVM:   ret void104 105// LLVM: define {{.*}}void @_Z1gv(){{.*}}106// LLVM:   %[[DF:.+]] = alloca {{.*}}107// LLVM:   call void @_ZN12DerivedFinalC1Ev(ptr %[[DF]])108// LLVM:   %[[VPTR2:.+]] = load ptr, ptr %[[DF]]109// LLVM:   %[[SLOT0_2:.+]] = getelementptr inbounds ptr, ptr %[[VPTR2]], i32 0110// LLVM:   %[[VFN2:.+]] = load ptr, ptr %[[SLOT0_2]]111// LLVM:   call void %[[VFN2]](ptr %[[DF]])112// LLVM:   ret void113 114// OGCG: define {{.*}}void @_Z1fv()115// OGCG:   %[[D:.+]] = alloca {{.*}}116// OGCG:   call void @_ZN7DerivedC1Ev(ptr {{.*}} %[[D]])117// OGCG:   %[[VTABLE:.+]] = load ptr, ptr %[[D]]118// OGCG:   %[[NEG32_PTR:.+]] = getelementptr i8, ptr %[[VTABLE]], i64 -32119// OGCG:   %[[OFF:.+]] = load i64, ptr %[[NEG32_PTR]]120// OGCG:   %[[ADJ_THIS:.+]] = getelementptr inbounds i8, ptr %[[D]], i64 %[[OFF]]121// OGCG:   call void @_ZN4Base1fEv(ptr {{.*}} %[[ADJ_THIS]])122// OGCG:   ret void123 124// OGCG: define {{.*}}void @_Z1gv()125// OGCG:   %[[DF:.+]] = alloca {{.*}}126// OGCG:   call void @_ZN12DerivedFinalC1Ev(ptr {{.*}} %[[DF]])127// OGCG:   call void @_ZN4Base1fEv(ptr {{.*}} %[[DF]])128// OGCG:   ret void129 130// Constructor for B131// CIR: cir.func comdat linkonce_odr @_ZN1BC1Ev(%arg0: !cir.ptr<!rec_B>132// CIR:   %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<!rec_B>, !cir.ptr<!cir.ptr<!rec_B>>, ["this", init]133// CIR:   cir.store %arg0, %[[THIS_ADDR]] : !cir.ptr<!rec_B>, !cir.ptr<!cir.ptr<!rec_B>>134// CIR:   %[[THIS:.*]] = cir.load %[[THIS_ADDR]] : !cir.ptr<!cir.ptr<!rec_B>>, !cir.ptr<!rec_B>135// CIR:   %[[BASE_A_ADDR:.*]] = cir.base_class_addr %[[THIS]] : !cir.ptr<!rec_B> nonnull [12] -> !cir.ptr<!rec_A>136// CIR:   %[[VTABLE:.*]] = cir.vtable.address_point(@_ZTV1B, address_point = <index = 0, offset = 3>) : !cir.vptr137// CIR:   %[[B_VPTR:.*]] = cir.vtable.get_vptr %[[THIS]] : !cir.ptr<!rec_B> -> !cir.ptr<!cir.vptr>138// CIR:   cir.store align(8) %[[VTABLE]], %[[B_VPTR]] : !cir.vptr, !cir.ptr<!cir.vptr>139// CIR:   cir.return140 141// LLVM: define{{.*}} void @_ZN1BC1Ev(ptr %[[THIS_ARG:.*]]){{.*}} {142// LLVM:   %[[THIS_ADDR:.*]] = alloca ptr143// LLVM:   store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]144// LLVM:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]145// LLVM:   %[[BASE_A_ADDR:.*]] = getelementptr i8, ptr %[[THIS]], i32 12146// LLVM:   store ptr getelementptr inbounds nuw (i8, ptr @_ZTV1B, i64 24), ptr %[[THIS]]147// LLVM:   ret void148 149// OGCG: define{{.*}} void @_ZN1BC1Ev(ptr {{.*}} %[[THIS_ARG:.*]])150// OGCG:   %[[THIS_ADDR:.*]] = alloca ptr151// OGCG:   store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]152// OGCG:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]153// OGCG:   %[[BASE_A_ADDR:.*]] = getelementptr inbounds i8, ptr %[[THIS]], i64 12154// OGCG:   store ptr getelementptr inbounds inrange(-24, 0) ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 3), ptr %[[THIS]]155// OGCG:   ret void156