1 // RUN: %clang_cc1 -no-opaque-pointers -triple powerpc-ibm-aix-xcoff -emit-llvm \ 2 // RUN: -fno-use-cxa-atexit < %s | \ 3 // RUN: FileCheck --check-prefix=NO-REGISTER %s 4 // RUN: %clang_cc1 -no-opaque-pointers -triple powerpc64-ibm-aix-xcoff -emit-llvm \ 5 // RUN: -fno-use-cxa-atexit < %s | \ 6 // RUN: FileCheck --check-prefix=NO-REGISTER %s 7 8 // RUN: %clang_cc1 -no-opaque-pointers -triple powerpc-ibm-aix-xcoff -emit-llvm \ 9 // RUN: -fno-use-cxa-atexit -fregister-global-dtors-with-atexit < %s | \ 10 // RUN: FileCheck --check-prefix=REGISTER %s 11 // RUN: %clang_cc1 -no-opaque-pointers -triple powerpc64-ibm-aix-xcoff -emit-llvm \ 12 // RUN: -fno-use-cxa-atexit -fregister-global-dtors-with-atexit < %s | \ 13 // RUN: FileCheck --check-prefix=REGISTER %s 14 15 int bar(void) __attribute__((destructor(100))); 16 int bar2(void) __attribute__((destructor(65535))); 17 int bar3(int) __attribute__((destructor(65535))); 18 19 int bar(void) { 20 return 1; 21 } 22 23 int bar2(void) { 24 return 2; 25 } 26 27 int bar3(int a) { 28 return a; 29 } 30 31 // NO-REGISTER: @llvm.global_dtors = appending global [3 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 100, void ()* bitcast (i32 ()* @bar to void ()*), i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* bitcast (i32 ()* @bar2 to void ()*), i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* bitcast (i32 (i32)* @bar3 to void ()*), i8* null }] 32 33 // REGISTER: @llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 100, void ()* @__GLOBAL_init_100, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @__GLOBAL_init_65535, i8* null }] 34 // REGISTER: @llvm.global_dtors = appending global [2 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 100, void ()* @__GLOBAL_cleanup_100, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @__GLOBAL_cleanup_65535, i8* null }] 35 36 // REGISTER: define internal void @__GLOBAL_init_100() [[ATTR:#[0-9]+]] { 37 // REGISTER: entry: 38 // REGISTER: %0 = call i32 @atexit(void ()* bitcast (i32 ()* @bar to void ()*)) 39 // REGISTER: ret void 40 // REGISTER: } 41 42 // REGISTER: define internal void @__GLOBAL_init_65535() [[ATTR:#[0-9]+]] { 43 // REGISTER: entry: 44 // REGISTER: %0 = call i32 @atexit(void ()* bitcast (i32 ()* @bar2 to void ()*)) 45 // REGISTER: %1 = call i32 @atexit(void ()* bitcast (i32 (i32)* @bar3 to void ()*)) 46 // REGISTER: ret void 47 // REGISTER: } 48 49 // REGISTER: define internal void @__GLOBAL_cleanup_100() [[ATTR:#[0-9]+]] { 50 // REGISTER: entry: 51 // REGISTER: %0 = call i32 @unatexit(void ()* bitcast (i32 ()* @bar to void ()*)) 52 // REGISTER: %needs_destruct = icmp eq i32 %0, 0 53 // REGISTER: br i1 %needs_destruct, label %destruct.call, label %destruct.end 54 55 // REGISTER: destruct.call: 56 // REGISTER: call void bitcast (i32 ()* @bar to void ()*)() 57 // REGISTER: br label %destruct.end 58 59 // REGISTER: destruct.end: 60 // REGISTER: ret void 61 // REGISTER: } 62 63 // REGISTER: define internal void @__GLOBAL_cleanup_65535() [[ATTR:#[0-9]+]] { 64 // REGISTER: entry: 65 // REGISTER: %0 = call i32 @unatexit(void ()* bitcast (i32 (i32)* @bar3 to void ()*)) 66 // REGISTER: %needs_destruct = icmp eq i32 %0, 0 67 // REGISTER: br i1 %needs_destruct, label %destruct.call, label %unatexit.call 68 69 // REGISTER: destruct.call: 70 // REGISTER: call void bitcast (i32 (i32)* @bar3 to void ()*)() 71 // REGISTER: br label %unatexit.call 72 73 // REGISTER: unatexit.call: 74 // REGISTER: %1 = call i32 @unatexit(void ()* bitcast (i32 ()* @bar2 to void ()*)) 75 // REGISTER: %needs_destruct1 = icmp eq i32 %1, 0 76 // REGISTER: br i1 %needs_destruct1, label %destruct.call2, label %destruct.end 77 78 // REGISTER: destruct.call2: 79 // REGISTER: call void bitcast (i32 ()* @bar2 to void ()*)() 80 // REGISTER: br label %destruct.end 81 82 // REGISTER: destruct.end: 83 // REGISTER: ret void 84 // REGISTER: } 85