117 lines · cpp
1// RUN: %clang_cc1 %s -triple=arm64-apple-ios -emit-llvm -o - | FileCheck %s2// RUN: %clang_cc1 %s -triple=arm64-apple-ios -emit-llvm -o - | FileCheck -check-prefix=CHECK-GLOBALS %s3 4// __cxa_guard_acquire argument is 64-bit5struct A {6 A();7};8 9void f() {10 // CHECK: call i32 @__cxa_guard_acquire(ptr11 static A a;12}13 14// ARM64 uses the C++11 definition of POD.15namespace test1 {16 // This class is POD in C++11 and cannot have objects allocated in17 // its tail-padding.18 struct ABase {};19 struct A : ABase {20 int x;21 char c;22 };23 24 struct B : A {25 char d;26 };27 28 int test() {29 return sizeof(B);30 }31 // CHECK: define{{.*}} i32 @_ZN5test14testEv()32 // CHECK: ret i32 1233}34 35namespace std {36 class type_info;37}38 39// ARM64 uses string comparisons for what would otherwise be40// default-visibility weak RTTI.41namespace test2 {42 struct A {43 virtual void foo();44 };45 void A::foo() {}46 // CHECK-GLOBALS-DAG: @_ZTSN5test21AE ={{.*}} constant [11 x i8]47 // CHECK-GLOBALS-DAG: @_ZTIN5test21AE ={{.*}} constant { {{.*}}, ptr @_ZTSN5test21AE }48 49 struct __attribute__((visibility("hidden"))) B {};50 const std::type_info &b0 = typeid(B);51 // CHECK-GLOBALS-DAG: @_ZTSN5test21BE = linkonce_odr hidden constant52 // CHECK-GLOBALS-DAG: @_ZTIN5test21BE = linkonce_odr hidden constant { {{.*}}, ptr @_ZTSN5test21BE }53 54 const std::type_info &b1 = typeid(B*);55 // CHECK-GLOBALS-DAG: @_ZTSPN5test21BE = linkonce_odr hidden constant56 // CHECK-GLOBALS-DAG: @_ZTIPN5test21BE = linkonce_odr hidden constant { {{.*}}, ptr @_ZTSPN5test21BE, i32 0, ptr @_ZTIN5test21BE57 58 struct C {};59 const std::type_info &c0 = typeid(C);60 // CHECK-GLOBALS-DAG: @_ZTSN5test21CE = linkonce_odr hidden constant61 // CHECK-GLOBALS-DAG: @_ZTIN5test21CE = linkonce_odr hidden constant { {{.*}}, ptr inttoptr (i64 add (i64 ptrtoint (ptr @_ZTSN5test21CE to i64), i64 -9223372036854775808) to ptr) }62 63 const std::type_info &c1 = typeid(C*);64 // CHECK-GLOBALS-DAG: @_ZTSPN5test21CE = linkonce_odr hidden constant65 // CHECK-GLOBALS-DAG: @_ZTIPN5test21CE = linkonce_odr hidden constant { {{.*}}, ptr inttoptr (i64 add (i64 ptrtoint (ptr @_ZTSPN5test21CE to i64), i64 -9223372036854775808) to ptr), i32 0, ptr @_ZTIN5test21CE66 67 // This class is explicitly-instantiated, but that instantiation68 // doesn't guarantee to emit RTTI, so we can still demote the visibility.69 template <class T> class D {};70 template class D<int>;71 const std::type_info &d0 = typeid(D<int>);72 // CHECK-GLOBALS-DAG: @_ZTSN5test21DIiEE = linkonce_odr hidden constant73 // CHECK-GLOBALS-DAG: @_ZTIN5test21DIiEE = linkonce_odr hidden constant { {{.*}}, ptr inttoptr (i64 add (i64 ptrtoint (ptr @_ZTSN5test21DIiEE to i64), i64 -9223372036854775808) to ptr) }74 75 // This class is explicitly-instantiated and *does* guarantee to76 // emit RTTI, so we're stuck with having to use default visibility.77 template <class T> class E {78 virtual void foo() {}79 };80 template class E<int>;81 // CHECK-GLOBALS-DAG: @_ZTSN5test21EIiEE = weak_odr constant [14 x i8]82 // CHECK-GLOBALS-DAG: @_ZTIN5test21EIiEE = weak_odr constant { {{.*}}, ptr inttoptr (i64 add (i64 ptrtoint (ptr @_ZTSN5test21EIiEE to i64), i64 -9223372036854775808) to ptr) }83 84}85 86// ARM64 reserves the top half of the vtable offset in virtual87// member pointers.88namespace test3 {89 struct A {90 virtual void foo();91 virtual void bar();92 };93 94 // The offset half of the pointer is still initialized to zero.95 // CHECK-GLOBALS-DAG: @_ZN5test34mptrE ={{.*}} global { i64, i64 } { i64 0, i64 1 }96 void (A::*mptr)() = &A::foo;97 98 // CHECK-LABEL: define{{.*}} void @_ZN5test34testEv()99 // CHECK: [[TEMP:%.*]] = alloca [[A:.*]], align 8100 // CHECK: [[MEMPTR:%.*]] = load { i64, i64 }, ptr @_ZN5test34mptrE, align 8101 // CHECK: [[ADJUST_AND_IS_VIRTUAL:%.*]] = extractvalue { i64, i64 } [[MEMPTR]], 1102 // CHECK: [[ADJUST:%.*]] = ashr i64 [[ADJUST_AND_IS_VIRTUAL]], 1103 // CHECK: [[T1:%.*]] = getelementptr inbounds i8, ptr [[TEMP]], i64 [[ADJUST]]104 // CHECK: [[MEMBER:%.*]] = extractvalue { i64, i64 } [[MEMPTR]], 0105 // CHECK: [[T0:%.*]] = and i64 [[ADJUST_AND_IS_VIRTUAL]], 1106 // CHECK: [[IS_VIRTUAL:%.*]] = icmp ne i64 [[T0]], 0107 // CHECK: br i1 [[IS_VIRTUAL]],108 // CHECK: [[VPTR:%.*]] = load ptr, ptr [[T1]], align 8109 // CHECK: [[TRUNC:%.*]] = trunc i64 [[MEMBER]] to i32110 // CHECK: [[ZEXT:%.*]] = zext i32 [[TRUNC]] to i64111 // CHECK: [[T0:%.*]] = getelementptr i8, ptr [[VPTR]], i64 [[ZEXT]]112 // CHECK: load ptr, ptr [[T0]],113 void test() {114 (A().*mptr)();115 }116}117