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#ifdef __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 FUNC_SYMBOL(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(__aarch64__) && defined(__ELF__) && \
75 defined(COMPILER_RT_EXECUTE_ONLY_CODE)
76// The assembler always creates an implicit '.text' section with default flags
77// (SHF_ALLOC | SHF_EXECINSTR), which is incompatible with the execute-only
78// '.text' section we want to create here because of the missing
79// SHF_AARCH64_PURECODE section flag. To solve this, we use 'unique,0' to
80// differentiate the two sections. The output will therefore have two separate
81// sections named '.text', where code will be placed into the execute-only
82// '.text' section, and the implicitly-created one will be empty.
83#define TEXT_SECTION \
84 .section .text,"axy",@progbits,unique,0
85#else
86#define TEXT_SECTION \
87 .text
88#endif
89
90#if defined(__arm__) || defined(__aarch64__) || defined(__arm64ec__)
91#define FUNC_ALIGN \
92 .balign 16 SEPARATOR
93#else
94#define FUNC_ALIGN
95#endif
96
97// BTI, PAC, and GCS gnu property note
98#define NT_GNU_PROPERTY_TYPE_0 5
99#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
100#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI 1
101#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC 2
102#define GNU_PROPERTY_AARCH64_FEATURE_1_GCS 4
103
104#if defined(__ARM_FEATURE_BTI_DEFAULT)
105#define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI
106#else
107#define BTI_FLAG 0
108#endif
109
110#if __ARM_FEATURE_PAC_DEFAULT & 3
111#define PAC_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_PAC
112#else
113#define PAC_FLAG 0
114#endif
115
116#if defined(__ARM_FEATURE_GCS_DEFAULT)
117#define GCS_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_GCS
118#else
119#define GCS_FLAG 0
120#endif
121
122#define GNU_PROPERTY(type, value) \
123 .pushsection .note.gnu.property, "a" SEPARATOR \
124 .p2align 3 SEPARATOR \
125 .word 4 SEPARATOR \
126 .word 16 SEPARATOR \
127 .word NT_GNU_PROPERTY_TYPE_0 SEPARATOR \
128 .asciz "GNU" SEPARATOR \
129 .word type SEPARATOR \
130 .word 4 SEPARATOR \
131 .word value SEPARATOR \
132 .word 0 SEPARATOR \
133 .popsection
134
135#if BTI_FLAG != 0
136#define BTI_C hint #34
137#define BTI_J hint #36
138#else
139#define BTI_C
140#define BTI_J
141#endif
142
143#if (BTI_FLAG | PAC_FLAG | GCS_FLAG) != 0
144#define GNU_PROPERTY_BTI_PAC_GCS \
145 GNU_PROPERTY(GNU_PROPERTY_AARCH64_FEATURE_1_AND, \
146 BTI_FLAG | PAC_FLAG | GCS_FLAG)
147#else
148#define GNU_PROPERTY_BTI_PAC_GCS
149#endif
150
151#if defined(__clang__) || defined(__GCC_HAVE_DWARF2_CFI_ASM)
152#define CFI_START .cfi_startproc
153#define CFI_END .cfi_endproc
154#else
155#define CFI_START
156#define CFI_END
157#endif
158
159#if defined(__arm__)
160
161// Determine actual [ARM][THUMB[1][2]] ISA using compiler predefined macros:
162// - for '-mthumb -march=armv6' compiler defines '__thumb__'
163// - for '-mthumb -march=armv7' compiler defines '__thumb__' and '__thumb2__'
164#if defined(__thumb2__) || defined(__thumb__)
165#define DEFINE_CODE_STATE .thumb SEPARATOR
166#define DECLARE_FUNC_ENCODING .thumb_func SEPARATOR
167#if defined(__thumb2__)
168#define USE_THUMB_2
169#define IT(cond) it cond
170#define ITT(cond) itt cond
171#define ITE(cond) ite cond
172#else
173#define USE_THUMB_1
174#define IT(cond)
175#define ITT(cond)
176#define ITE(cond)
177#endif // defined(__thumb__2)
178#else // !defined(__thumb2__) && !defined(__thumb__)
179#define DEFINE_CODE_STATE .arm SEPARATOR
180#define DECLARE_FUNC_ENCODING
181#define IT(cond)
182#define ITT(cond)
183#define ITE(cond)
184#endif
185
186#if defined(USE_THUMB_1) && defined(USE_THUMB_2)
187#error "USE_THUMB_1 and USE_THUMB_2 can't be defined together."
188#endif
189
190#if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5
191#define ARM_HAS_BX
192#endif
193#if !defined(__ARM_FEATURE_CLZ) && !defined(USE_THUMB_1) && \
194 (__ARM_ARCH >= 6 || (__ARM_ARCH == 5 && !defined(__ARM_ARCH_5__)))
195#define __ARM_FEATURE_CLZ
196#endif
197
198#ifdef ARM_HAS_BX
199#define JMP(r) bx r
200#define JMPc(r, c) bx##c r
201#else
202#define JMP(r) mov pc, r
203#define JMPc(r, c) mov##c pc, r
204#endif
205
206// pop {pc} can't switch Thumb mode on ARMv4T
207#if __ARM_ARCH >= 5
208#define POP_PC() pop {pc}
209#else
210#define POP_PC() \
211 pop {ip}; \
212 JMP(ip)
213#endif
214
215#if defined(USE_THUMB_2)
216#define WIDE(op) op.w
217#else
218#define WIDE(op) op
219#endif
220
221#if defined(__ARM_FEATURE_PAC_DEFAULT) && defined(__ARM_FEATURE_BTI_DEFAULT)
222#define PACBTI_LANDING pacbti r12, lr, sp
223#elif defined(__ARM_FEATURE_PAC_DEFAULT)
224#define PACBTI_LANDING pac r12, lr, sp
225#elif defined(__ARM_FEATURE_BTI_DEFAULT)
226#define PACBTI_LANDING bti
227#else
228#define PACBTI_LANDING
229#endif
230
231#if defined(__ARM_FEATURE_PAUTH)
232#define PAC_RETURN bxaut r12, lr, sp
233#else
234#define PAC_RETURN aut r12, lr, sp SEPARATOR bx lr
235#endif
236
237#else // !defined(__arm)
238#define DECLARE_FUNC_ENCODING
239#define DEFINE_CODE_STATE
240#endif
241
242#define GLUE2_(a, b) a##b
243#define GLUE(a, b) GLUE2_(a, b)
244#define GLUE2(a, b) GLUE2_(a, b)
245#define GLUE3_(a, b, c) a##b##c
246#define GLUE3(a, b, c) GLUE3_(a, b, c)
247#define GLUE4_(a, b, c, d) a##b##c##d
248#define GLUE4(a, b, c, d) GLUE4_(a, b, c, d)
249
250#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
251#ifndef __arm64ec__
252#define FUNC_SYMBOL(name) name
253#else
254// On ARM64EC, function names and calls (but not address-taking or data symbol
255// references) use symbols prefixed with "#".
256#define QUOTE(a) #a
257#define STR(a) QUOTE(a)
258#define HASH #
259#define FUNC_SYMBOL(name) STR(GLUE2(HASH, name))
260#endif
261
262#ifdef VISIBILITY_HIDDEN
263#define DECLARE_SYMBOL_VISIBILITY(name) \
264 HIDDEN(SYMBOL_NAME(name)) SEPARATOR
265#define DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) \
266 HIDDEN(name) SEPARATOR
267#else
268#define DECLARE_SYMBOL_VISIBILITY(name)
269#define DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name)
270#endif
271
272#define DEFINE_COMPILERRT_FUNCTION(name) \
273 TEXT_SECTION SEPARATOR \
274 DEFINE_CODE_STATE \
275 FILE_LEVEL_DIRECTIVE SEPARATOR \
276 .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
277 SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
278 DECLARE_SYMBOL_VISIBILITY(name) \
279 DECLARE_FUNC_ENCODING \
280 FUNC_SYMBOL(SYMBOL_NAME(name)):
281
282#define DEFINE_COMPILERRT_THUMB_FUNCTION(name) \
283 TEXT_SECTION SEPARATOR \
284 DEFINE_CODE_STATE \
285 FILE_LEVEL_DIRECTIVE SEPARATOR \
286 .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
287 SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
288 DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \
289 .thumb_func SEPARATOR \
290 FUNC_SYMBOL(SYMBOL_NAME(name)):
291
292#define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name) \
293 TEXT_SECTION SEPARATOR \
294 DEFINE_CODE_STATE \
295 FILE_LEVEL_DIRECTIVE SEPARATOR \
296 .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
297 SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
298 HIDDEN(SYMBOL_NAME(name)) SEPARATOR \
299 DECLARE_FUNC_ENCODING \
300 FUNC_SYMBOL(SYMBOL_NAME(name)):
301
302#define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name) \
303 TEXT_SECTION SEPARATOR \
304 DEFINE_CODE_STATE \
305 .globl FUNC_SYMBOL(name) SEPARATOR \
306 SYMBOL_IS_FUNC(name) SEPARATOR \
307 HIDDEN(name) SEPARATOR \
308 DECLARE_FUNC_ENCODING \
309 FUNC_SYMBOL(name):
310
311#define DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(name) \
312 TEXT_SECTION SEPARATOR \
313 DEFINE_CODE_STATE \
314 FUNC_ALIGN \
315 .globl FUNC_SYMBOL(name) SEPARATOR \
316 SYMBOL_IS_FUNC(name) SEPARATOR \
317 DECLARE_SYMBOL_VISIBILITY_UNMANGLED(FUNC_SYMBOL(name)) SEPARATOR \
318 DECLARE_FUNC_ENCODING \
319 FUNC_SYMBOL(name): \
320 SEPARATOR CFI_START \
321 SEPARATOR BTI_C
322
323#define DEFINE_COMPILERRT_FUNCTION_ALIAS(name, target) \
324 .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
325 SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
326 DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \
327 .set FUNC_SYMBOL(SYMBOL_NAME(name)), FUNC_SYMBOL(SYMBOL_NAME(target)) SEPARATOR
328
329#if defined(__ARM_EABI__)
330#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) \
331 DEFINE_COMPILERRT_FUNCTION_ALIAS(aeabi_name, name)
332#else
333#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name)
334#endif
335
336#ifdef __ELF__
337#define END_COMPILERRT_FUNCTION(name) \
338 .size SYMBOL_NAME(name), . - SYMBOL_NAME(name)
339#define END_COMPILERRT_OUTLINE_FUNCTION(name) \
340 CFI_END SEPARATOR \
341 .size SYMBOL_NAME(name), . - SYMBOL_NAME(name)
342#else
343#define END_COMPILERRT_FUNCTION(name)
344#define END_COMPILERRT_OUTLINE_FUNCTION(name) \
345 CFI_END
346#endif
347
348#ifdef __arm__
349#include "int_endianness.h"
350
351#if _YUGA_BIG_ENDIAN
352#define VMOV_TO_DOUBLE(dst, src0, src1) vmov dst, src1, src0 SEPARATOR
353#define VMOV_FROM_DOUBLE(dst0, dst1, src) vmov dst1, dst0, src SEPARATOR
354#else
355#define VMOV_TO_DOUBLE(dst, src0, src1) vmov dst, src0, src1 SEPARATOR
356#define VMOV_FROM_DOUBLE(dst0, dst1, src) vmov dst0, dst1, src SEPARATOR
357#endif
358#endif
359
360#if defined(__ASSEMBLER__) && (defined(__i386__) || defined(__amd64__)) && \
361 !defined(__arm64ec__)
362.att_syntax
363#endif
364
365#endif // COMPILERRT_ASSEMBLY_H
366