diff --git a/compiler-rt/test/orc/TestCases/Linux/aarch64/ehframe-default.cpp b/compiler-rt/test/orc/TestCases/Linux/aarch64/ehframe-default.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/aarch64/ehframe-default.cpp @@ -0,0 +1,14 @@ +// RUN: %clangxx -fexceptions -fPIC -c -o %t %s +// RUN: %llvm_jitlink %t + +extern "C" void llvm_jitlink_setTestResultOverride(long Value); + +int main(int argc, char *argv[]) { + llvm_jitlink_setTestResultOverride(1); + try { + throw 0; + } catch (int X) { + llvm_jitlink_setTestResultOverride(X); + } + return 0; +} diff --git a/compiler-rt/test/orc/TestCases/Linux/aarch64/ehframe-libunwind.cpp b/compiler-rt/test/orc/TestCases/Linux/aarch64/ehframe-libunwind.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/aarch64/ehframe-libunwind.cpp @@ -0,0 +1,15 @@ +// REQUIRES: libunwind-available +// RUN: %clangxx -fexceptions -fPIC -c -o %t %s +// RUN: env LD_PRELOAD=%shared_libunwind %llvm_jitlink %t + +extern "C" void llvm_jitlink_setTestResultOverride(long Value); + +int main(int argc, char *argv[]) { + llvm_jitlink_setTestResultOverride(1); + try { + throw 0; + } catch (int X) { + llvm_jitlink_setTestResultOverride(X); + } + return 0; +} diff --git a/compiler-rt/test/orc/TestCases/Linux/aarch64/lit.local.cfg.py b/compiler-rt/test/orc/TestCases/Linux/aarch64/lit.local.cfg.py new file mode 100644 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/aarch64/lit.local.cfg.py @@ -0,0 +1,5 @@ +if config.root.host_arch != 'aarch64': + config.unsupported = True + +if config.target_arch != 'aarch64': + config.unsupported = True diff --git a/compiler-rt/test/orc/TestCases/Linux/aarch64/lljit-ehframe.cpp b/compiler-rt/test/orc/TestCases/Linux/aarch64/lljit-ehframe.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/aarch64/lljit-ehframe.cpp @@ -0,0 +1,15 @@ +// RUN: %clangxx -fPIC -emit-llvm -c -o %t %s +// RUN: %lli_orc_jitlink -relocation-model=pic %t | FileCheck %s + +// CHECK: catch + +#include + +int main(int argc, char *argv[]) { + try { + throw 0; + } catch (int X) { + puts("catch"); + } + return 0; +} diff --git a/compiler-rt/test/orc/TestCases/Linux/aarch64/lljit-initialize-deinitialize.ll b/compiler-rt/test/orc/TestCases/Linux/aarch64/lljit-initialize-deinitialize.ll new file mode 100644 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/aarch64/lljit-initialize-deinitialize.ll @@ -0,0 +1,32 @@ +; RUN: %lli_orc_jitlink %s | FileCheck %s + +; CHECK: constructor +; CHECK-NEXT: main +; CHECK-NEXT: destructor + +@__dso_handle = external hidden global i8 +@.str = private unnamed_addr constant [5 x i8] c"main\00", align 1 +@.str.1 = private unnamed_addr constant [12 x i8] c"constructor\00", align 1 +@.str.2 = private unnamed_addr constant [11 x i8] c"destructor\00", align 1 +@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @constructor, i8* null }] + +define dso_local void @destructor(i8* %0) { + %2 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i64 0, i64 0)) + ret void +} + +declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*) + +; Function Attrs: nofree norecurse nounwind uwtable +define dso_local i32 @main(i32 %0, i8** nocapture readnone %1) local_unnamed_addr #2 { + %3 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0)) + ret i32 0 +} + +declare i32 @puts(i8* nocapture readonly) + +define internal void @constructor() { + %1 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @.str.1, i64 0, i64 0)) #5 + %2 = tail call i32 @__cxa_atexit(void (i8*)* @destructor, i8* null, i8* nonnull @__dso_handle) #5 + ret void +} diff --git a/compiler-rt/test/orc/TestCases/Linux/aarch64/priority-static-initializer.S b/compiler-rt/test/orc/TestCases/Linux/aarch64/priority-static-initializer.S new file mode 100644 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/aarch64/priority-static-initializer.S @@ -0,0 +1,111 @@ +// Test that ELF static initializers with different constructor priorities work +// and are executed in the proper order. +// +// RUN: %clang -c -o %t %s +// RUN: %llvm_jitlink %t | FileCheck %s + +// CHECK: constructor 100 +// CHECK-NEXT: constructor 200 +// CHECK-NEXT: constructor 65535 +// CHECK-NEXT: main +// CHECK-NEXT: destructor + + .text + .globl destructor + .p2align 2 + .type destructor,@function +destructor: +.Ldestructor$local: + + adrp x0, .L.str.2 + add x0, x0, :lo12:.L.str.2 + b puts + + .globl main + .p2align 2 + .type main,@function +main: + + str x30, [sp, #-16]! + adrp x0, .L.str + add x0, x0, :lo12:.L.str + bl puts + mov w0, wzr + ldr x30, [sp], #16 + ret + + .p2align 2 + .type constructor.65535,@function +constructor.65535: + + str x30, [sp, #-16]! + adrp x0, .L.str.65535 + add x0, x0, :lo12:.L.str.65535 + bl puts + adrp x0, .Ldestructor$local + add x0, x0, :lo12:.Ldestructor$local + adrp x2, __dso_handle + add x2, x2, :lo12:__dso_handle + mov x1, xzr + ldr x30, [sp], #16 + b __cxa_atexit + + .p2align 2 + .type constructor.100,@function +constructor.100: + + str x30, [sp, #-16]! + adrp x0, .L.str.100 + add x0, x0, :lo12:.L.str.100 + bl puts + ldr x30, [sp], #16 + ret + + .p2align 2 + .type constructor.200,@function +constructor.200: + + str x30, [sp, #-16]! + adrp x0, .L.str.200 + add x0, x0, :lo12:.L.str.200 + bl puts + ldr x30, [sp], #16 + ret + + .hidden __dso_handle + .type .L.str,@object + .section .rodata.str1.1,"aMS",@progbits,1 +.L.str: + .asciz "main" + .size .L.str, 5 + + .type .L.str.100,@object +.L.str.100: + .asciz "constructor 100" + .size .L.str.100, 16 + + .type .L.str.200,@object +.L.str.200: + .asciz "constructor 200" + .size .L.str.200, 16 + + .type .L.str.65535,@object +.L.str.65535: + .asciz "constructor 65535" + .size .L.str.65535, 18 + + + .type .L.str.2,@object +.L.str.2: + .asciz "destructor" + .size .L.str.2, 11 + + .section .init_array.100,"aw",@init_array + .p2align 3 + .xword constructor.100 + .section .init_array.200,"aw",@init_array + .p2align 3 + .xword constructor.200 + .section .init_array,"aw",@init_array + .p2align 3 + .xword constructor.65535 diff --git a/compiler-rt/test/orc/TestCases/Linux/aarch64/trivial-atexit.S b/compiler-rt/test/orc/TestCases/Linux/aarch64/trivial-atexit.S new file mode 100644 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/aarch64/trivial-atexit.S @@ -0,0 +1,33 @@ +// Test that the runtime correctly interposes atexit. +// +// RUN: %clang -c -o %t %s +// RUN: %llvm_jitlink %t + + .text +// OnExit destructor resets the test result override to zero. + .globl on_exit + .p2align 2 + .type on_exit,@function +on_exit: + + mov w0, wzr + b llvm_jitlink_setTestResultOverride +.Lfunc_end0: + .size on_exit, .Lfunc_end0-on_exit + +// main registers the atexit and sets the test result to one. + .globl main + .p2align 2 + .type main,@function +main: + + stp x29, x30, [sp, #-16]! + mov x29, sp + adrp x0, :got:on_exit + ldr x0, [x0, :got_lo12:on_exit] + bl atexit + mov w0, wzr + ldp x29, x30, [sp], #16 + ret +.Lfunc_end1: + .size main, .Lfunc_end1-main diff --git a/compiler-rt/test/orc/TestCases/Linux/aarch64/trivial-cxa-atexit.S b/compiler-rt/test/orc/TestCases/Linux/aarch64/trivial-cxa-atexit.S new file mode 100644 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/aarch64/trivial-cxa-atexit.S @@ -0,0 +1,39 @@ +// Test that the runtime correctly interposes ___cxa_atexit. +// +// RUN: %clang -c -o %t %s +// RUN: %llvm_jitlink %t + + .text +// Destructor resets the test result override to zero. + .globl on_exit + .p2align 2 + .type on_exit,@function +on_exit: + + mov w0, wzr + b llvm_jitlink_setTestResultOverride +.Lfunc_end0: + .size on_exit, .Lfunc_end0-on_exit + +// main registers the atexit and sets the test result to one. + .globl main + .p2align 2 + .type main,@function +main: + + stp x29, x30, [sp, #-16]! + mov x29, sp + adrp x8, :got:__dso_handle + adrp x0, :got:on_exit + mov x1, xzr + ldr x8, [x8, :got_lo12:__dso_handle] + ldr x2, [x8] + ldr x0, [x0, :got_lo12:on_exit] + bl __cxa_atexit + mov w0, #1 + bl llvm_jitlink_setTestResultOverride + mov w0, wzr + ldp x29, x30, [sp], #16 + ret +.Lfunc_end1: + .size main, .Lfunc_end1-main diff --git a/compiler-rt/test/orc/TestCases/Linux/aarch64/trivial-static-initializer.S b/compiler-rt/test/orc/TestCases/Linux/aarch64/trivial-static-initializer.S new file mode 100644 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Linux/aarch64/trivial-static-initializer.S @@ -0,0 +1,47 @@ +// Test that basic ELF static initializers work. The main function in this +// test returns the value of 'x', which is initially 1 in the data section, +// and reset to 0 if the _static_init function is run. If the static initializer +// does not run then main will return 1, causing the test to be treated as a +// failure. +// +// RUN: %clang -c -o %t %s +// RUN: %llvm_jitlink %t + + .text + .globl main + .p2align 2 + .type main,@function +main: + + adrp x8, :got:x + ldr x8, [x8, :got_lo12:x] + ldr w0, [x8] + ret +.Lfunc_end0: + .size main, .Lfunc_end0-main + +// static initializer sets the value of 'x' to zero. + + .section .text.startup,"ax",@progbits + .p2align 2 + .type static_init,@function +static_init: + + adrp x8, :got:x + ldr x8, [x8, :got_lo12:x] + str wzr, [x8] + ret +.Lfunc_end1: + .size static_init, .Lfunc_end1-static_init + + .type x,@object + .data + .globl x + .p2align 2 +x: + .word 1 + .size x, 4 + + .section .init_array,"aw",@init_array + .p2align 3 + .xword static_init