| //===-- Implementation of apply_irelative_relocs test ---------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "test/IntegrationTest/test.h" |
| |
| #ifndef __has_attribute |
| #define __has_attribute(x) 0 |
| #endif |
| |
| #if __has_attribute(ifunc) |
| |
| // Two trivial implementations that return different constants. |
| static int impl_a() { return 42; } |
| static int impl_b() { return 84; } |
| |
| // The resolver function. On x86_64 this takes no arguments; on AArch64 it |
| // receives (hwcap, hwcap2). We use extern "C" to ensure C linkage for the |
| // ifunc attribute. |
| extern "C" { |
| // Declare the resolver to return a generic function pointer. |
| // For testing, unconditionally select impl_a. |
| void *my_ifunc_resolver() { |
| (void)impl_b; // Suppress unused warning. |
| return reinterpret_cast<void *>(impl_a); |
| } |
| } |
| |
| // Declare the ifunc. The compiler and linker will generate an IRELATIVE |
| // relocation that calls my_ifunc_resolver at startup. |
| extern "C" int my_ifunc() __attribute__((ifunc("my_ifunc_resolver"))); |
| |
| TEST_MAIN() { |
| // If IRELATIVE processing works correctly, my_ifunc() should call impl_a |
| // and return 42. |
| ASSERT_EQ(my_ifunc(), 42); |
| return 0; |
| } |
| |
| #else |
| |
| TEST_MAIN() { return 0; } |
| |
| #endif |