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