xref: /minix3/external/bsd/llvm/dist/clang/test/CodeGenCXX/aarch64-cxxabi.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc // RUN: %clang_cc1 -triple arm64-none-linux-gnu -emit-llvm -w -o - %s | FileCheck %s
2f4a2713aSLionel Sambuc 
3f4a2713aSLionel Sambuc // Check differences between the generic Itanium ABI, the AArch32 version and
4f4a2713aSLionel Sambuc // the AArch64 version.
5f4a2713aSLionel Sambuc 
6f4a2713aSLionel Sambuc ////////////////////////////////////////////////////////////////////////////////
7f4a2713aSLionel Sambuc 
8f4a2713aSLionel Sambuc // The ABI says that the key function is the "textually first, non-inline,
9f4a2713aSLionel Sambuc // non-pure, virtual member function". The generic version decides this after
10f4a2713aSLionel Sambuc // the completion of the class definition; the AArch32 version decides this at
11f4a2713aSLionel Sambuc // the end of the translation unit.
12f4a2713aSLionel Sambuc 
13f4a2713aSLionel Sambuc // We construct a class which needs a VTable here under generic ABI, but not
14f4a2713aSLionel Sambuc // AArch32.
15f4a2713aSLionel Sambuc 
16f4a2713aSLionel Sambuc // (see next section for explanation of guard)
17f4a2713aSLionel Sambuc // CHECK: @_ZGVZ15guard_variablesiE4mine = internal global i64 0
18f4a2713aSLionel Sambuc 
19f4a2713aSLionel Sambuc // CHECK: @_ZTV16CheckKeyFunction =
20f4a2713aSLionel Sambuc struct CheckKeyFunction {
21f4a2713aSLionel Sambuc   virtual void foo();
22f4a2713aSLionel Sambuc };
23f4a2713aSLionel Sambuc 
24f4a2713aSLionel Sambuc // This is not inline when CheckKeyFunction is completed, so
25f4a2713aSLionel Sambuc // CheckKeyFunction::foo is the key function. VTables should be emitted.
foo()26f4a2713aSLionel Sambuc inline void CheckKeyFunction::foo() {
27f4a2713aSLionel Sambuc }
28f4a2713aSLionel Sambuc 
29f4a2713aSLionel Sambuc ////////////////////////////////////////////////////////////////////////////////
30f4a2713aSLionel Sambuc 
31f4a2713aSLionel Sambuc // Guard variables only specify and use the low bit to determine status, rather
32f4a2713aSLionel Sambuc // than the low byte as in the generic Itanium ABI. However, unlike 32-bit ARM,
33f4a2713aSLionel Sambuc // they *are* 64-bits wide so check that in case confusion has occurred.
34f4a2713aSLionel Sambuc 
35f4a2713aSLionel Sambuc class Guarded {
36f4a2713aSLionel Sambuc public:
37f4a2713aSLionel Sambuc   Guarded(int i);
38f4a2713aSLionel Sambuc   ~Guarded();
39f4a2713aSLionel Sambuc };
40f4a2713aSLionel Sambuc 
guard_variables(int a)41f4a2713aSLionel Sambuc void guard_variables(int a) {
42f4a2713aSLionel Sambuc   static Guarded mine(a);
43*0a6a1f1dSLionel Sambuc // CHECK: [[GUARDBIT:%[0-9]+]] = and i8 {{%[0-9]+}}, 1
44*0a6a1f1dSLionel Sambuc // CHECK: icmp eq i8 [[GUARDBIT]], 0
45f4a2713aSLionel Sambuc 
46f4a2713aSLionel Sambuc   // As guards are 64-bit, these helpers should take 64-bit pointers.
47f4a2713aSLionel Sambuc // CHECK: call i32 @__cxa_guard_acquire(i64*
48f4a2713aSLionel Sambuc // CHECK: call void @__cxa_guard_release(i64*
49f4a2713aSLionel Sambuc }
50f4a2713aSLionel Sambuc 
51f4a2713aSLionel Sambuc ////////////////////////////////////////////////////////////////////////////////
52f4a2713aSLionel Sambuc 
53f4a2713aSLionel Sambuc // Member function pointers use the adj field to distinguish between virtual and
54f4a2713aSLionel Sambuc // nonvirtual members. As a result the adjustment is shifted (if ptr was used, a
55f4a2713aSLionel Sambuc // mask would be expected instead).
56f4a2713aSLionel Sambuc 
57f4a2713aSLionel Sambuc class C {
58f4a2713aSLionel Sambuc   int a();
59f4a2713aSLionel Sambuc   virtual int b();
60f4a2713aSLionel Sambuc };
61f4a2713aSLionel Sambuc 
62f4a2713aSLionel Sambuc 
member_pointer(C & c,int (C::* func)())63f4a2713aSLionel Sambuc int member_pointer(C &c, int (C::*func)()) {
64f4a2713aSLionel Sambuc // CHECK: ashr i64 %[[MEMPTRADJ:[0-9a-z.]+]], 1
65f4a2713aSLionel Sambuc // CHECK: %[[ISVIRTUAL:[0-9]+]] = and i64 %[[MEMPTRADJ]], 1
66f4a2713aSLionel Sambuc // CHECK: icmp ne i64 %[[ISVIRTUAL]], 0
67f4a2713aSLionel Sambuc   return (c.*func)();
68f4a2713aSLionel Sambuc }
69f4a2713aSLionel Sambuc 
70f4a2713aSLionel Sambuc ////////////////////////////////////////////////////////////////////////////////
71f4a2713aSLionel Sambuc 
72f4a2713aSLionel Sambuc // AArch64 PCS says that va_list type is based on "struct __va_list ..." in the
73f4a2713aSLionel Sambuc // std namespace, which means it should mangle as "St9__va_list".
74f4a2713aSLionel Sambuc 
75f4a2713aSLionel Sambuc // CHECK: @_Z7va_funcSt9__va_list
va_func(__builtin_va_list l)76f4a2713aSLionel Sambuc void va_func(__builtin_va_list l) {
77f4a2713aSLionel Sambuc }
78f4a2713aSLionel Sambuc 
79f4a2713aSLionel Sambuc ////////////////////////////////////////////////////////////////////////////////
80f4a2713aSLionel Sambuc 
81f4a2713aSLionel Sambuc // AArch64 constructors (like generic Itanium, but unlike AArch32) do not return
82f4a2713aSLionel Sambuc // "this".
83f4a2713aSLionel Sambuc 
test_constructor()84f4a2713aSLionel Sambuc void test_constructor() {
85f4a2713aSLionel Sambuc   Guarded g(42);
86f4a2713aSLionel Sambuc // CHECK: call void @_ZN7GuardedC1Ei
87f4a2713aSLionel Sambuc }
88f4a2713aSLionel Sambuc 
89f4a2713aSLionel Sambuc ////////////////////////////////////////////////////////////////////////////////
90f4a2713aSLionel Sambuc 
91f4a2713aSLionel Sambuc // In principle the AArch32 ABI allows this to be accomplished via a call to
92f4a2713aSLionel Sambuc // __aeabi_atexit instead of __cxa_atexit. Clang doesn't make use of this at the
93f4a2713aSLionel Sambuc // moment, but it's definitely not allowed for AArch64.
94f4a2713aSLionel Sambuc 
95f4a2713aSLionel Sambuc // CHECK: call i32 @__cxa_atexit
96f4a2713aSLionel Sambuc Guarded g(42);
97