1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 // REQUIRES: linux && target={{aarch64-.+}} 11 12 // Basic test for float registers number are accepted. 13 14 #include <dlfcn.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <unwind.h> 18 19 _Unwind_Reason_Code frame_handler(struct _Unwind_Context *ctx, void *arg) { 20 (void)arg; 21 Dl_info info = {0, 0, 0, 0}; 22 23 // Unwind util the main is reached, above frames depend on the platform and 24 // architecture. 25 if (dladdr(reinterpret_cast<void *>(_Unwind_GetIP(ctx)), &info) && 26 info.dli_sname && !strcmp("main", info.dli_sname)) 27 _Exit(0); 28 29 return _URC_NO_REASON; 30 } 31 32 __attribute__((noinline)) void foo() { 33 // Provide some CFI directives that instructs the unwinder where given 34 // float register is. 35 #if defined(__aarch64__) 36 // DWARF register number for V0-V31 registers are 64-95. 37 // Previous value of V0 is saved at offset 0 from CFA. 38 asm volatile(".cfi_offset 64, 0"); 39 // From now on the previous value of register can't be restored anymore. 40 asm volatile(".cfi_undefined 65"); 41 asm volatile(".cfi_undefined 95"); 42 // Previous value of V2 is in V30. 43 asm volatile(".cfi_register 66, 94"); 44 #endif 45 _Unwind_Backtrace(frame_handler, NULL); 46 } 47 48 int main() { 49 foo(); 50 return -2; 51 } 52