1//===-- assembly.h - compiler-rt assembler support macros -----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines macros for use in compiler-rt assembler source.
10// This file is not part of the interface of this library.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef COMPILERRT_ASSEMBLY_H
15#define COMPILERRT_ASSEMBLY_H
16
17#if defined(__APPLE__) && defined(__aarch64__)
18#define SEPARATOR %%
19#else
20#define SEPARATOR ;
21#endif
22
23#if defined(__APPLE__)
24#define HIDDEN(name) .private_extern name
25#define LOCAL_LABEL(name) L_##name
26// tell linker it can break up file at label boundaries
27#define FILE_LEVEL_DIRECTIVE .subsections_via_symbols
28#define SYMBOL_IS_FUNC(name)
29#define CONST_SECTION .const
30
31#define NO_EXEC_STACK_DIRECTIVE
32
33#elif defined(__ELF__)
34
35#define HIDDEN(name) .hidden name
36#define LOCAL_LABEL(name) .L_##name
37#define FILE_LEVEL_DIRECTIVE
38#if defined(__arm__) || defined(__aarch64__)
39#define SYMBOL_IS_FUNC(name) .type name,%function
40#else
41#define SYMBOL_IS_FUNC(name) .type name,@function
42#endif
43#define CONST_SECTION .section .rodata
44
45#if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) ||        \
46    defined(__linux__)
47#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits
48#else
49#define NO_EXEC_STACK_DIRECTIVE
50#endif
51
52#else // !__APPLE__ && !__ELF__
53
54#define HIDDEN(name)
55#define LOCAL_LABEL(name) .L ## name
56#define FILE_LEVEL_DIRECTIVE
57#define SYMBOL_IS_FUNC(name)                                                   \
58  .def name SEPARATOR                                                          \
59    .scl 2 SEPARATOR                                                           \
60    .type 32 SEPARATOR                                                         \
61  .endef
62#define CONST_SECTION .section .rdata,"rd"
63
64#define NO_EXEC_STACK_DIRECTIVE
65
66#endif
67
68#if defined(__arm__) || defined(__aarch64__)
69#define FUNC_ALIGN                                                             \
70  .text SEPARATOR                                                              \
71  .balign 16 SEPARATOR
72#else
73#define FUNC_ALIGN
74#endif
75
76// BTI and PAC gnu property note
77#define NT_GNU_PROPERTY_TYPE_0 5
78#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
79#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI 1
80#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC 2
81
82#if defined(__ARM_FEATURE_BTI_DEFAULT)
83#define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI
84#else
85#define BTI_FLAG 0
86#endif
87
88#if __ARM_FEATURE_PAC_DEFAULT & 3
89#define PAC_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_PAC
90#else
91#define PAC_FLAG 0
92#endif
93
94#define GNU_PROPERTY(type, value)                                              \
95  .pushsection .note.gnu.property, "a" SEPARATOR                               \
96  .p2align 3 SEPARATOR                                                         \
97  .word 4 SEPARATOR                                                            \
98  .word 16 SEPARATOR                                                           \
99  .word NT_GNU_PROPERTY_TYPE_0 SEPARATOR                                       \
100  .asciz "GNU" SEPARATOR                                                       \
101  .word type SEPARATOR                                                         \
102  .word 4 SEPARATOR                                                            \
103  .word value SEPARATOR                                                        \
104  .word 0 SEPARATOR                                                            \
105  .popsection
106
107#if BTI_FLAG != 0
108#define BTI_C hint #34
109#define BTI_J hint #36
110#else
111#define BTI_C
112#define BTI_J
113#endif
114
115#if (BTI_FLAG | PAC_FLAG) != 0
116#define GNU_PROPERTY_BTI_PAC                                                   \
117  GNU_PROPERTY(GNU_PROPERTY_AARCH64_FEATURE_1_AND, BTI_FLAG | PAC_FLAG)
118#else
119#define GNU_PROPERTY_BTI_PAC
120#endif
121
122#if defined(__clang__) || defined(__GCC_HAVE_DWARF2_CFI_ASM)
123#define CFI_START .cfi_startproc
124#define CFI_END .cfi_endproc
125#else
126#define CFI_START
127#define CFI_END
128#endif
129
130#if defined(__arm__)
131
132// Determine actual [ARM][THUMB[1][2]] ISA using compiler predefined macros:
133// - for '-mthumb -march=armv6' compiler defines '__thumb__'
134// - for '-mthumb -march=armv7' compiler defines '__thumb__' and '__thumb2__'
135#if defined(__thumb2__) || defined(__thumb__)
136#define DEFINE_CODE_STATE .thumb SEPARATOR
137#define DECLARE_FUNC_ENCODING    .thumb_func SEPARATOR
138#if defined(__thumb2__)
139#define USE_THUMB_2
140#define IT(cond)  it cond
141#define ITT(cond) itt cond
142#define ITE(cond) ite cond
143#else
144#define USE_THUMB_1
145#define IT(cond)
146#define ITT(cond)
147#define ITE(cond)
148#endif // defined(__thumb__2)
149#else // !defined(__thumb2__) && !defined(__thumb__)
150#define DEFINE_CODE_STATE .arm SEPARATOR
151#define DECLARE_FUNC_ENCODING
152#define IT(cond)
153#define ITT(cond)
154#define ITE(cond)
155#endif
156
157#if defined(USE_THUMB_1) && defined(USE_THUMB_2)
158#error "USE_THUMB_1 and USE_THUMB_2 can't be defined together."
159#endif
160
161#if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5
162#define ARM_HAS_BX
163#endif
164#if !defined(__ARM_FEATURE_CLZ) && !defined(USE_THUMB_1) &&  \
165    (__ARM_ARCH >= 6 || (__ARM_ARCH == 5 && !defined(__ARM_ARCH_5__)))
166#define __ARM_FEATURE_CLZ
167#endif
168
169#ifdef ARM_HAS_BX
170#define JMP(r) bx r
171#define JMPc(r, c) bx##c r
172#else
173#define JMP(r) mov pc, r
174#define JMPc(r, c) mov##c pc, r
175#endif
176
177// pop {pc} can't switch Thumb mode on ARMv4T
178#if __ARM_ARCH >= 5
179#define POP_PC() pop {pc}
180#else
181#define POP_PC()                                                               \
182  pop {ip};                                                                    \
183  JMP(ip)
184#endif
185
186#if defined(USE_THUMB_2)
187#define WIDE(op) op.w
188#else
189#define WIDE(op) op
190#endif
191#else // !defined(__arm)
192#define DECLARE_FUNC_ENCODING
193#define DEFINE_CODE_STATE
194#endif
195
196#define GLUE2_(a, b) a##b
197#define GLUE(a, b) GLUE2_(a, b)
198#define GLUE2(a, b) GLUE2_(a, b)
199#define GLUE3_(a, b, c) a##b##c
200#define GLUE3(a, b, c) GLUE3_(a, b, c)
201#define GLUE4_(a, b, c, d) a##b##c##d
202#define GLUE4(a, b, c, d) GLUE4_(a, b, c, d)
203
204#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
205
206#ifdef VISIBILITY_HIDDEN
207#define DECLARE_SYMBOL_VISIBILITY(name)                                        \
208  HIDDEN(SYMBOL_NAME(name)) SEPARATOR
209#define DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) \
210  HIDDEN(name) SEPARATOR
211#else
212#define DECLARE_SYMBOL_VISIBILITY(name)
213#define DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name)
214#endif
215
216#define DEFINE_COMPILERRT_FUNCTION(name)                                       \
217  DEFINE_CODE_STATE                                                            \
218  FILE_LEVEL_DIRECTIVE SEPARATOR                                               \
219  .globl SYMBOL_NAME(name) SEPARATOR                                           \
220  SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR                                  \
221  DECLARE_SYMBOL_VISIBILITY(name)                                              \
222  DECLARE_FUNC_ENCODING                                                        \
223  SYMBOL_NAME(name):
224
225#define DEFINE_COMPILERRT_THUMB_FUNCTION(name)                                 \
226  DEFINE_CODE_STATE                                                            \
227  FILE_LEVEL_DIRECTIVE SEPARATOR                                               \
228  .globl SYMBOL_NAME(name) SEPARATOR                                           \
229  SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR                                  \
230  DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR                                    \
231  .thumb_func SEPARATOR                                                        \
232  SYMBOL_NAME(name):
233
234#define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name)                               \
235  DEFINE_CODE_STATE                                                            \
236  FILE_LEVEL_DIRECTIVE SEPARATOR                                               \
237  .globl SYMBOL_NAME(name) SEPARATOR                                           \
238  SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR                                  \
239  HIDDEN(SYMBOL_NAME(name)) SEPARATOR                                          \
240  DECLARE_FUNC_ENCODING                                                        \
241  SYMBOL_NAME(name):
242
243#define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name)                     \
244  DEFINE_CODE_STATE                                                            \
245  .globl name SEPARATOR                                                        \
246  SYMBOL_IS_FUNC(name) SEPARATOR                                               \
247  HIDDEN(name) SEPARATOR                                                       \
248  DECLARE_FUNC_ENCODING                                                        \
249  name:
250
251#define DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(name)                     \
252  DEFINE_CODE_STATE                                                            \
253  FUNC_ALIGN                                                                   \
254  .globl name SEPARATOR                                                        \
255  SYMBOL_IS_FUNC(name) SEPARATOR                                               \
256  DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) SEPARATOR                          \
257  CFI_START SEPARATOR                                                          \
258  DECLARE_FUNC_ENCODING                                                        \
259  name: SEPARATOR BTI_C
260
261#define DEFINE_COMPILERRT_FUNCTION_ALIAS(name, target)                         \
262  .globl SYMBOL_NAME(name) SEPARATOR                                           \
263  SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR                                  \
264  DECLARE_SYMBOL_VISIBILITY(SYMBOL_NAME(name)) SEPARATOR                       \
265  .set SYMBOL_NAME(name), SYMBOL_NAME(target) SEPARATOR
266
267#if defined(__ARM_EABI__)
268#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name)                          \
269  DEFINE_COMPILERRT_FUNCTION_ALIAS(aeabi_name, name)
270#else
271#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name)
272#endif
273
274#ifdef __ELF__
275#define END_COMPILERRT_FUNCTION(name)                                          \
276  .size SYMBOL_NAME(name), . - SYMBOL_NAME(name)
277#define END_COMPILERRT_OUTLINE_FUNCTION(name)                                  \
278  CFI_END SEPARATOR                                                            \
279  .size SYMBOL_NAME(name), . - SYMBOL_NAME(name)
280#else
281#define END_COMPILERRT_FUNCTION(name)
282#define END_COMPILERRT_OUTLINE_FUNCTION(name)                                  \
283  CFI_END
284#endif
285
286#endif // COMPILERRT_ASSEMBLY_H
287