10b57cec5SDimitry Andric //===-- assembly.h - compiler-rt assembler support macros -----------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines macros for use in compiler-rt assembler source.
100b57cec5SDimitry Andric // This file is not part of the interface of this library.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef COMPILERRT_ASSEMBLY_H
150b57cec5SDimitry Andric #define COMPILERRT_ASSEMBLY_H
160b57cec5SDimitry Andric 
1704eeddc0SDimitry Andric #if defined(__linux__) && defined(__CET__)
1804eeddc0SDimitry Andric #if __has_include(<cet.h>)
1904eeddc0SDimitry Andric #include <cet.h>
2004eeddc0SDimitry Andric #endif
2104eeddc0SDimitry Andric #endif
2204eeddc0SDimitry Andric 
23e8d8bef9SDimitry Andric #if defined(__APPLE__) && defined(__aarch64__)
24e8d8bef9SDimitry Andric #define SEPARATOR %%
250b57cec5SDimitry Andric #else
260b57cec5SDimitry Andric #define SEPARATOR ;
270b57cec5SDimitry Andric #endif
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric #if defined(__APPLE__)
300b57cec5SDimitry Andric #define HIDDEN(name) .private_extern name
310b57cec5SDimitry Andric #define LOCAL_LABEL(name) L_##name
320b57cec5SDimitry Andric // tell linker it can break up file at label boundaries
330b57cec5SDimitry Andric #define FILE_LEVEL_DIRECTIVE .subsections_via_symbols
340b57cec5SDimitry Andric #define SYMBOL_IS_FUNC(name)
350b57cec5SDimitry Andric #define CONST_SECTION .const
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric #define NO_EXEC_STACK_DIRECTIVE
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric #elif defined(__ELF__)
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric #define HIDDEN(name) .hidden name
420b57cec5SDimitry Andric #define LOCAL_LABEL(name) .L_##name
430b57cec5SDimitry Andric #define FILE_LEVEL_DIRECTIVE
44e8d8bef9SDimitry Andric #if defined(__arm__) || defined(__aarch64__)
450b57cec5SDimitry Andric #define SYMBOL_IS_FUNC(name) .type name,%function
460b57cec5SDimitry Andric #else
470b57cec5SDimitry Andric #define SYMBOL_IS_FUNC(name) .type name,@function
480b57cec5SDimitry Andric #endif
490b57cec5SDimitry Andric #define CONST_SECTION .section .rodata
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric #if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) ||        \
520b57cec5SDimitry Andric     defined(__linux__)
530b57cec5SDimitry Andric #define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits
540b57cec5SDimitry Andric #else
550b57cec5SDimitry Andric #define NO_EXEC_STACK_DIRECTIVE
560b57cec5SDimitry Andric #endif
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric #else // !__APPLE__ && !__ELF__
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric #define HIDDEN(name)
610b57cec5SDimitry Andric #define LOCAL_LABEL(name) .L ## name
620b57cec5SDimitry Andric #define FILE_LEVEL_DIRECTIVE
630b57cec5SDimitry Andric #define SYMBOL_IS_FUNC(name)                                                   \
640b57cec5SDimitry Andric   .def name SEPARATOR                                                          \
650b57cec5SDimitry Andric     .scl 2 SEPARATOR                                                           \
660b57cec5SDimitry Andric     .type 32 SEPARATOR                                                         \
670b57cec5SDimitry Andric   .endef
680b57cec5SDimitry Andric #define CONST_SECTION .section .rdata,"rd"
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric #define NO_EXEC_STACK_DIRECTIVE
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric #endif
730b57cec5SDimitry Andric 
74e8d8bef9SDimitry Andric #if defined(__arm__) || defined(__aarch64__)
75e8d8bef9SDimitry Andric #define FUNC_ALIGN                                                             \
76e8d8bef9SDimitry Andric   .text SEPARATOR                                                              \
77e8d8bef9SDimitry Andric   .balign 16 SEPARATOR
78e8d8bef9SDimitry Andric #else
79e8d8bef9SDimitry Andric #define FUNC_ALIGN
80e8d8bef9SDimitry Andric #endif
81e8d8bef9SDimitry Andric 
82e8d8bef9SDimitry Andric // BTI and PAC gnu property note
83e8d8bef9SDimitry Andric #define NT_GNU_PROPERTY_TYPE_0 5
84e8d8bef9SDimitry Andric #define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
85e8d8bef9SDimitry Andric #define GNU_PROPERTY_AARCH64_FEATURE_1_BTI 1
86e8d8bef9SDimitry Andric #define GNU_PROPERTY_AARCH64_FEATURE_1_PAC 2
87e8d8bef9SDimitry Andric 
88e8d8bef9SDimitry Andric #if defined(__ARM_FEATURE_BTI_DEFAULT)
89e8d8bef9SDimitry Andric #define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI
90e8d8bef9SDimitry Andric #else
91e8d8bef9SDimitry Andric #define BTI_FLAG 0
92e8d8bef9SDimitry Andric #endif
93e8d8bef9SDimitry Andric 
94e8d8bef9SDimitry Andric #if __ARM_FEATURE_PAC_DEFAULT & 3
95e8d8bef9SDimitry Andric #define PAC_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_PAC
96e8d8bef9SDimitry Andric #else
97e8d8bef9SDimitry Andric #define PAC_FLAG 0
98e8d8bef9SDimitry Andric #endif
99e8d8bef9SDimitry Andric 
100e8d8bef9SDimitry Andric #define GNU_PROPERTY(type, value)                                              \
101e8d8bef9SDimitry Andric   .pushsection .note.gnu.property, "a" SEPARATOR                               \
102e8d8bef9SDimitry Andric   .p2align 3 SEPARATOR                                                         \
103e8d8bef9SDimitry Andric   .word 4 SEPARATOR                                                            \
104e8d8bef9SDimitry Andric   .word 16 SEPARATOR                                                           \
105e8d8bef9SDimitry Andric   .word NT_GNU_PROPERTY_TYPE_0 SEPARATOR                                       \
106e8d8bef9SDimitry Andric   .asciz "GNU" SEPARATOR                                                       \
107e8d8bef9SDimitry Andric   .word type SEPARATOR                                                         \
108e8d8bef9SDimitry Andric   .word 4 SEPARATOR                                                            \
109e8d8bef9SDimitry Andric   .word value SEPARATOR                                                        \
110e8d8bef9SDimitry Andric   .word 0 SEPARATOR                                                            \
111e8d8bef9SDimitry Andric   .popsection
112e8d8bef9SDimitry Andric 
113e8d8bef9SDimitry Andric #if BTI_FLAG != 0
114fe6060f1SDimitry Andric #define BTI_C hint #34
115fe6060f1SDimitry Andric #define BTI_J hint #36
116e8d8bef9SDimitry Andric #else
117e8d8bef9SDimitry Andric #define BTI_C
118fe6060f1SDimitry Andric #define BTI_J
119e8d8bef9SDimitry Andric #endif
120e8d8bef9SDimitry Andric 
121e8d8bef9SDimitry Andric #if (BTI_FLAG | PAC_FLAG) != 0
122e8d8bef9SDimitry Andric #define GNU_PROPERTY_BTI_PAC                                                   \
123e8d8bef9SDimitry Andric   GNU_PROPERTY(GNU_PROPERTY_AARCH64_FEATURE_1_AND, BTI_FLAG | PAC_FLAG)
124e8d8bef9SDimitry Andric #else
125e8d8bef9SDimitry Andric #define GNU_PROPERTY_BTI_PAC
126e8d8bef9SDimitry Andric #endif
127e8d8bef9SDimitry Andric 
128e8d8bef9SDimitry Andric #if defined(__clang__) || defined(__GCC_HAVE_DWARF2_CFI_ASM)
129e8d8bef9SDimitry Andric #define CFI_START .cfi_startproc
130e8d8bef9SDimitry Andric #define CFI_END .cfi_endproc
131e8d8bef9SDimitry Andric #else
132e8d8bef9SDimitry Andric #define CFI_START
133e8d8bef9SDimitry Andric #define CFI_END
134e8d8bef9SDimitry Andric #endif
135e8d8bef9SDimitry Andric 
1360b57cec5SDimitry Andric #if defined(__arm__)
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric // Determine actual [ARM][THUMB[1][2]] ISA using compiler predefined macros:
1390b57cec5SDimitry Andric // - for '-mthumb -march=armv6' compiler defines '__thumb__'
1400b57cec5SDimitry Andric // - for '-mthumb -march=armv7' compiler defines '__thumb__' and '__thumb2__'
1410b57cec5SDimitry Andric #if defined(__thumb2__) || defined(__thumb__)
1420b57cec5SDimitry Andric #define DEFINE_CODE_STATE .thumb SEPARATOR
1430b57cec5SDimitry Andric #define DECLARE_FUNC_ENCODING    .thumb_func SEPARATOR
1440b57cec5SDimitry Andric #if defined(__thumb2__)
1450b57cec5SDimitry Andric #define USE_THUMB_2
1460b57cec5SDimitry Andric #define IT(cond)  it cond
1470b57cec5SDimitry Andric #define ITT(cond) itt cond
1480b57cec5SDimitry Andric #define ITE(cond) ite cond
1490b57cec5SDimitry Andric #else
1500b57cec5SDimitry Andric #define USE_THUMB_1
1510b57cec5SDimitry Andric #define IT(cond)
1520b57cec5SDimitry Andric #define ITT(cond)
1530b57cec5SDimitry Andric #define ITE(cond)
1540b57cec5SDimitry Andric #endif // defined(__thumb__2)
1550b57cec5SDimitry Andric #else // !defined(__thumb2__) && !defined(__thumb__)
1560b57cec5SDimitry Andric #define DEFINE_CODE_STATE .arm SEPARATOR
1570b57cec5SDimitry Andric #define DECLARE_FUNC_ENCODING
1580b57cec5SDimitry Andric #define IT(cond)
1590b57cec5SDimitry Andric #define ITT(cond)
1600b57cec5SDimitry Andric #define ITE(cond)
1610b57cec5SDimitry Andric #endif
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric #if defined(USE_THUMB_1) && defined(USE_THUMB_2)
1640b57cec5SDimitry Andric #error "USE_THUMB_1 and USE_THUMB_2 can't be defined together."
1650b57cec5SDimitry Andric #endif
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric #if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5
1680b57cec5SDimitry Andric #define ARM_HAS_BX
1690b57cec5SDimitry Andric #endif
1700b57cec5SDimitry Andric #if !defined(__ARM_FEATURE_CLZ) && !defined(USE_THUMB_1) &&  \
1710b57cec5SDimitry Andric     (__ARM_ARCH >= 6 || (__ARM_ARCH == 5 && !defined(__ARM_ARCH_5__)))
1720b57cec5SDimitry Andric #define __ARM_FEATURE_CLZ
1730b57cec5SDimitry Andric #endif
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric #ifdef ARM_HAS_BX
1760b57cec5SDimitry Andric #define JMP(r) bx r
1770b57cec5SDimitry Andric #define JMPc(r, c) bx##c r
1780b57cec5SDimitry Andric #else
1790b57cec5SDimitry Andric #define JMP(r) mov pc, r
1800b57cec5SDimitry Andric #define JMPc(r, c) mov##c pc, r
1810b57cec5SDimitry Andric #endif
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric // pop {pc} can't switch Thumb mode on ARMv4T
1840b57cec5SDimitry Andric #if __ARM_ARCH >= 5
1850b57cec5SDimitry Andric #define POP_PC() pop {pc}
1860b57cec5SDimitry Andric #else
1870b57cec5SDimitry Andric #define POP_PC()                                                               \
1880b57cec5SDimitry Andric   pop {ip};                                                                    \
1890b57cec5SDimitry Andric   JMP(ip)
1900b57cec5SDimitry Andric #endif
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric #if defined(USE_THUMB_2)
1930b57cec5SDimitry Andric #define WIDE(op) op.w
1940b57cec5SDimitry Andric #else
1950b57cec5SDimitry Andric #define WIDE(op) op
1960b57cec5SDimitry Andric #endif
1970b57cec5SDimitry Andric #else // !defined(__arm)
1980b57cec5SDimitry Andric #define DECLARE_FUNC_ENCODING
1990b57cec5SDimitry Andric #define DEFINE_CODE_STATE
2000b57cec5SDimitry Andric #endif
2010b57cec5SDimitry Andric 
202e8d8bef9SDimitry Andric #define GLUE2_(a, b) a##b
203e8d8bef9SDimitry Andric #define GLUE(a, b) GLUE2_(a, b)
204e8d8bef9SDimitry Andric #define GLUE2(a, b) GLUE2_(a, b)
205e8d8bef9SDimitry Andric #define GLUE3_(a, b, c) a##b##c
206e8d8bef9SDimitry Andric #define GLUE3(a, b, c) GLUE3_(a, b, c)
207e8d8bef9SDimitry Andric #define GLUE4_(a, b, c, d) a##b##c##d
208e8d8bef9SDimitry Andric #define GLUE4(a, b, c, d) GLUE4_(a, b, c, d)
209e8d8bef9SDimitry Andric 
2100b57cec5SDimitry Andric #define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric #ifdef VISIBILITY_HIDDEN
2130b57cec5SDimitry Andric #define DECLARE_SYMBOL_VISIBILITY(name)                                        \
2140b57cec5SDimitry Andric   HIDDEN(SYMBOL_NAME(name)) SEPARATOR
215fe6060f1SDimitry Andric #define DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) \
216fe6060f1SDimitry Andric   HIDDEN(name) SEPARATOR
2170b57cec5SDimitry Andric #else
2180b57cec5SDimitry Andric #define DECLARE_SYMBOL_VISIBILITY(name)
219fe6060f1SDimitry Andric #define DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name)
2200b57cec5SDimitry Andric #endif
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric #define DEFINE_COMPILERRT_FUNCTION(name)                                       \
2230b57cec5SDimitry Andric   DEFINE_CODE_STATE                                                            \
2240b57cec5SDimitry Andric   FILE_LEVEL_DIRECTIVE SEPARATOR                                               \
2250b57cec5SDimitry Andric   .globl SYMBOL_NAME(name) SEPARATOR                                           \
2260b57cec5SDimitry Andric   SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR                                  \
2270b57cec5SDimitry Andric   DECLARE_SYMBOL_VISIBILITY(name)                                              \
2280b57cec5SDimitry Andric   DECLARE_FUNC_ENCODING                                                        \
2290b57cec5SDimitry Andric   SYMBOL_NAME(name):
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric #define DEFINE_COMPILERRT_THUMB_FUNCTION(name)                                 \
2320b57cec5SDimitry Andric   DEFINE_CODE_STATE                                                            \
2330b57cec5SDimitry Andric   FILE_LEVEL_DIRECTIVE SEPARATOR                                               \
2340b57cec5SDimitry Andric   .globl SYMBOL_NAME(name) SEPARATOR                                           \
2350b57cec5SDimitry Andric   SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR                                  \
2360b57cec5SDimitry Andric   DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR                                    \
2370b57cec5SDimitry Andric   .thumb_func SEPARATOR                                                        \
2380b57cec5SDimitry Andric   SYMBOL_NAME(name):
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric #define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name)                               \
2410b57cec5SDimitry Andric   DEFINE_CODE_STATE                                                            \
2420b57cec5SDimitry Andric   FILE_LEVEL_DIRECTIVE SEPARATOR                                               \
2430b57cec5SDimitry Andric   .globl SYMBOL_NAME(name) SEPARATOR                                           \
2440b57cec5SDimitry Andric   SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR                                  \
2450b57cec5SDimitry Andric   HIDDEN(SYMBOL_NAME(name)) SEPARATOR                                          \
2460b57cec5SDimitry Andric   DECLARE_FUNC_ENCODING                                                        \
2470b57cec5SDimitry Andric   SYMBOL_NAME(name):
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric #define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name)                     \
2500b57cec5SDimitry Andric   DEFINE_CODE_STATE                                                            \
2510b57cec5SDimitry Andric   .globl name SEPARATOR                                                        \
2520b57cec5SDimitry Andric   SYMBOL_IS_FUNC(name) SEPARATOR                                               \
2530b57cec5SDimitry Andric   HIDDEN(name) SEPARATOR                                                       \
2540b57cec5SDimitry Andric   DECLARE_FUNC_ENCODING                                                        \
2550b57cec5SDimitry Andric   name:
2560b57cec5SDimitry Andric 
257e8d8bef9SDimitry Andric #define DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(name)                     \
258e8d8bef9SDimitry Andric   DEFINE_CODE_STATE                                                            \
259e8d8bef9SDimitry Andric   FUNC_ALIGN                                                                   \
260e8d8bef9SDimitry Andric   .globl name SEPARATOR                                                        \
261e8d8bef9SDimitry Andric   SYMBOL_IS_FUNC(name) SEPARATOR                                               \
262fe6060f1SDimitry Andric   DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) SEPARATOR                          \
263e8d8bef9SDimitry Andric   DECLARE_FUNC_ENCODING                                                        \
2645f757f3fSDimitry Andric   name:                                                                        \
2655f757f3fSDimitry Andric   SEPARATOR CFI_START                                                          \
2665f757f3fSDimitry Andric   SEPARATOR BTI_C
267e8d8bef9SDimitry Andric 
2680b57cec5SDimitry Andric #define DEFINE_COMPILERRT_FUNCTION_ALIAS(name, target)                         \
2690b57cec5SDimitry Andric   .globl SYMBOL_NAME(name) SEPARATOR                                           \
2700b57cec5SDimitry Andric   SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR                                  \
27106c3fb27SDimitry Andric   DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR                                    \
2720b57cec5SDimitry Andric   .set SYMBOL_NAME(name), SYMBOL_NAME(target) SEPARATOR
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric #if defined(__ARM_EABI__)
2750b57cec5SDimitry Andric #define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name)                          \
2760b57cec5SDimitry Andric   DEFINE_COMPILERRT_FUNCTION_ALIAS(aeabi_name, name)
2770b57cec5SDimitry Andric #else
2780b57cec5SDimitry Andric #define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name)
2790b57cec5SDimitry Andric #endif
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric #ifdef __ELF__
2820b57cec5SDimitry Andric #define END_COMPILERRT_FUNCTION(name)                                          \
2830b57cec5SDimitry Andric   .size SYMBOL_NAME(name), . - SYMBOL_NAME(name)
284e8d8bef9SDimitry Andric #define END_COMPILERRT_OUTLINE_FUNCTION(name)                                  \
285e8d8bef9SDimitry Andric   CFI_END SEPARATOR                                                            \
286e8d8bef9SDimitry Andric   .size SYMBOL_NAME(name), . - SYMBOL_NAME(name)
2870b57cec5SDimitry Andric #else
2880b57cec5SDimitry Andric #define END_COMPILERRT_FUNCTION(name)
289e8d8bef9SDimitry Andric #define END_COMPILERRT_OUTLINE_FUNCTION(name)                                  \
290e8d8bef9SDimitry Andric   CFI_END
2910b57cec5SDimitry Andric #endif
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric #endif // COMPILERRT_ASSEMBLY_H
294