1 //===- bolt/runtime/common.h ------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
20 #elif defined(__APPLE__)
22 typedef __SIZE_TYPE__
size_t;
23 #define __SSIZE_TYPE__ \
24 __typeof__(_Generic((__SIZE_TYPE__)0, unsigned long long int \
25 : (long long int)0, unsigned long int \
26 : (long int)0, unsigned int \
27 : (int)0, unsigned short \
28 : (short)0, unsigned char \
30 typedef __SSIZE_TYPE__ ssize_t
;
32 typedef unsigned long long uint64_t;
33 typedef unsigned uint32_t;
34 typedef unsigned char uint8_t;
36 typedef long long int64_t;
40 #error "For Linux or MacOS only"
43 #define PROT_READ 0x1 /* Page can be read. */
44 #define PROT_WRITE 0x2 /* Page can be written. */
45 #define PROT_EXEC 0x4 /* Page can be executed. */
46 #define PROT_NONE 0x0 /* Page can not be accessed. */
47 #define PROT_GROWSDOWN \
48 0x01000000 /* Extend change to start of \
49 growsdown vma (mprotect only). */
50 #define PROT_GROWSUP \
51 0x02000000 /* Extend change to start of \
52 growsup vma (mprotect only). */
54 /* Sharing types (must choose one and only one of these). */
55 #define MAP_SHARED 0x01 /* Share changes. */
56 #define MAP_PRIVATE 0x02 /* Changes are private. */
57 #define MAP_FIXED 0x10 /* Interpret addr exactly. */
59 #if defined(__APPLE__)
60 #define MAP_ANONYMOUS 0x1000
62 #define MAP_ANONYMOUS 0x20
65 #define MAP_FAILED ((void *)-1)
67 #define SEEK_SET 0 /* Seek from beginning of file. */
68 #define SEEK_CUR 1 /* Seek from current position. */
69 #define SEEK_END 2 /* Seek from end of file. */
78 // Functions that are required by freestanding environment. Compiler may
79 // generate calls to these implicitly.
81 void *memcpy(void *Dest
, const void *Src
, size_t Len
) {
82 uint8_t *d
= static_cast<uint8_t *>(Dest
);
83 const uint8_t *s
= static_cast<const uint8_t *>(Src
);
89 void *memmove(void *Dest
, const void *Src
, size_t Len
) {
90 uint8_t *d
= static_cast<uint8_t *>(Dest
);
91 const uint8_t *s
= static_cast<const uint8_t *>(Src
);
105 void *memset(void *Buf
, int C
, size_t Size
) {
106 char *S
= (char *)Buf
;
107 for (size_t I
= 0; I
< Size
; ++I
)
112 int memcmp(const void *s1
, const void *s2
, size_t n
) {
113 const uint8_t *c1
= static_cast<const uint8_t *>(s1
);
114 const uint8_t *c2
= static_cast<const uint8_t *>(s2
);
115 for (; n
--; c1
++, c2
++) {
117 return *c1
< *c2
? -1 : 1;
123 // Anonymous namespace covering everything but our library entry point
127 uint64_t d_ino
; /* Inode number */
128 int64_t d_off
; /* Offset to next linux_dirent */
129 unsigned short d_reclen
; /* Length of this linux_dirent */
130 unsigned char d_type
;
131 char d_name
[]; /* Filename (null-terminated) */
132 /* length is actually (d_reclen - 2 -
133 offsetof(struct linux_dirent, d_name)) */
136 /* Length of the entries in `struct utsname' is 65. */
137 #define _UTSNAME_LENGTH 65
140 char sysname
[_UTSNAME_LENGTH
]; /* Operating system name (e.g., "Linux") */
141 char nodename
[_UTSNAME_LENGTH
]; /* Name within "some implementation-defined
143 char release
[_UTSNAME_LENGTH
]; /* Operating system release (e.g., "2.6.28") */
144 char version
[_UTSNAME_LENGTH
]; /* Operating system version */
145 char machine
[_UTSNAME_LENGTH
]; /* Hardware identifier */
146 char domainname
[_UTSNAME_LENGTH
]; /* NIS or YP domain name */
150 uint64_t tv_sec
; /* seconds */
151 uint64_t tv_nsec
; /* nanoseconds */
154 #if defined(__aarch64__)
155 #include "sys_aarch64.h"
157 #include "sys_x86_64.h"
160 constexpr uint32_t BufSize
= 10240;
162 // Helper functions for writing strings to the .fdata file. We intentionally
163 // avoid using libc names to make it clear it is our impl.
165 /// Write number Num using Base to the buffer in OutBuf, returns a pointer to
166 /// the end of the string.
167 char *intToStr(char *OutBuf
, uint64_t Num
, uint32_t Base
) {
168 const char *Chars
= "0123456789abcdef";
172 *Ptr
++ = *(Chars
+ (Num
% Base
));
185 /// Copy Str to OutBuf, returns a pointer to the end of the copied string
186 char *strCopy(char *OutBuf
, const char *Str
, int32_t Size
= BufSize
) {
195 /// Compare two strings, at most Num bytes.
196 int strnCmp(const char *Str1
, const char *Str2
, size_t Num
) {
197 while (Num
&& *Str1
&& (*Str1
== *Str2
)) {
204 return *(unsigned char *)Str1
- *(unsigned char *)Str2
;
207 uint32_t strLen(const char *Str
) {
214 void *strStr(const char *const Haystack
, const char *const Needle
) {
217 for (int i
= 0; i
< strLen(Haystack
); i
++) {
218 if (Haystack
[i
] == Needle
[0]) {
219 for (j
= 1; j
< strLen(Needle
); j
++) {
220 if (Haystack
[i
+ j
] != Needle
[j
])
223 if (j
== strLen(Needle
))
224 return (void *)&Haystack
[i
];
230 void reportNumber(const char *Msg
, uint64_t Num
, uint32_t Base
) {
233 Ptr
= strCopy(Ptr
, Msg
, BufSize
- 23);
234 Ptr
= intToStr(Ptr
, Num
, Base
);
235 Ptr
= strCopy(Ptr
, "\n");
236 __write(2, Buf
, Ptr
- Buf
);
239 void report(const char *Msg
) { __write(2, Msg
, strLen(Msg
)); }
241 unsigned long hexToLong(const char *Str
, char Terminator
= '\0') {
242 unsigned long Res
= 0;
243 while (*Str
!= Terminator
) {
245 if ('0' <= *Str
&& *Str
<= '9')
247 else if ('a' <= *Str
&& *Str
<= 'f')
248 Res
+= *Str
++ - 'a' + 10;
249 else if ('A' <= *Str
&& *Str
<= 'F')
250 Res
+= *Str
++ - 'A' + 10;
257 /// Starting from character at \p buf, find the longest consecutive sequence
258 /// of digits (0-9) and convert it to uint32_t. The converted value
259 /// is put into \p ret. \p end marks the end of the buffer to avoid buffer
260 /// overflow. The function \returns whether a valid uint32_t value is found.
261 /// \p buf will be updated to the next character right after the digits.
262 static bool scanUInt32(const char *&Buf
, const char *End
, uint32_t &Ret
) {
264 const char *OldBuf
= Buf
;
265 while (Buf
< End
&& ((*Buf
) >= '0' && (*Buf
) <= '9')) {
266 Result
= Result
* 10 + (*Buf
) - '0';
269 if (OldBuf
!= Buf
&& Result
<= 0xFFFFFFFFu
) {
270 Ret
= static_cast<uint32_t>(Result
);
276 void reportError(const char *Msg
, uint64_t Size
) {
277 __write(2, Msg
, Size
);
281 void assert(bool Assertion
, const char *Msg
) {
286 Ptr
= strCopy(Ptr
, "Assertion failed: ");
287 Ptr
= strCopy(Ptr
, Msg
, BufSize
- 40);
288 Ptr
= strCopy(Ptr
, "\n");
289 reportError(Buf
, Ptr
- Buf
);
293 #define SIG_UNBLOCK 1
294 #define SIG_SETMASK 2
296 static const uint64_t MaskAllSignals
[] = {-1ULL};
299 volatile bool InUse
{false};
302 bool acquire() { return !__atomic_test_and_set(&InUse
, __ATOMIC_ACQUIRE
); }
303 void release() { __atomic_clear(&InUse
, __ATOMIC_RELEASE
); }
306 /// RAII wrapper for Mutex
309 uint64_t SignalMask
[1] = {};
312 Lock(Mutex
&M
) : M(M
) {
313 __sigprocmask(SIG_BLOCK
, MaskAllSignals
, SignalMask
);
314 while (!M
.acquire()) {
320 __sigprocmask(SIG_SETMASK
, SignalMask
, nullptr);
324 /// RAII wrapper for Mutex
330 TryLock(Mutex
&M
) : M(M
) {
332 while (--Retry
&& !M
.acquire())
337 bool isLocked() { return Locked
; }
345 inline uint64_t alignTo(uint64_t Value
, uint64_t Align
) {
346 return (Value
+ Align
- 1) / Align
* Align
;
349 } // anonymous namespace