12f09f445SMaksim Panchenko //===- bolt/runtime/common.h ------------------------------------*- C++ -*-===//
276d346caSVladislav Khmelevsky //
376d346caSVladislav Khmelevsky // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
476d346caSVladislav Khmelevsky // See https://llvm.org/LICENSE.txt for license information.
576d346caSVladislav Khmelevsky // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
676d346caSVladislav Khmelevsky //
776d346caSVladislav Khmelevsky //===----------------------------------------------------------------------===//
876d346caSVladislav Khmelevsky
91c3653dfSNathan Sidwell #if defined(__linux__)
101cf23e5eSAlexander Shaposhnikov
119bd71615SXun Li #include <cstddef>
129bd71615SXun Li #include <cstdint>
131cf23e5eSAlexander Shaposhnikov
14823ebcc7SVladislav Khmelevsky #include "config.h"
15823ebcc7SVladislav Khmelevsky
16823ebcc7SVladislav Khmelevsky #ifdef HAVE_ELF_H
17823ebcc7SVladislav Khmelevsky #include <elf.h>
18823ebcc7SVladislav Khmelevsky #endif
19823ebcc7SVladislav Khmelevsky
201c3653dfSNathan Sidwell #elif defined(__APPLE__)
211cf23e5eSAlexander Shaposhnikov
221cf23e5eSAlexander Shaposhnikov typedef __SIZE_TYPE__ size_t;
231cf23e5eSAlexander Shaposhnikov #define __SSIZE_TYPE__ \
241cf23e5eSAlexander Shaposhnikov __typeof__(_Generic((__SIZE_TYPE__)0, unsigned long long int \
251cf23e5eSAlexander Shaposhnikov : (long long int)0, unsigned long int \
261cf23e5eSAlexander Shaposhnikov : (long int)0, unsigned int \
271cf23e5eSAlexander Shaposhnikov : (int)0, unsigned short \
281cf23e5eSAlexander Shaposhnikov : (short)0, unsigned char \
291cf23e5eSAlexander Shaposhnikov : (signed char)0))
301cf23e5eSAlexander Shaposhnikov typedef __SSIZE_TYPE__ ssize_t;
311cf23e5eSAlexander Shaposhnikov
321cf23e5eSAlexander Shaposhnikov typedef unsigned long long uint64_t;
33d6e60c5bSAlexander Shaposhnikov typedef unsigned uint32_t;
34a0dd5b05SAlexander Shaposhnikov typedef unsigned char uint8_t;
35d6e60c5bSAlexander Shaposhnikov
36d6e60c5bSAlexander Shaposhnikov typedef long long int64_t;
37d6e60c5bSAlexander Shaposhnikov typedef int int32_t;
381cf23e5eSAlexander Shaposhnikov
391c3653dfSNathan Sidwell #else
401c3653dfSNathan Sidwell #error "For Linux or MacOS only"
41bbd9d610SAlexander Shaposhnikov #endif
429bd71615SXun Li
438b23a853SDenis Revunov #define PROT_READ 0x1 /* Page can be read. */
448b23a853SDenis Revunov #define PROT_WRITE 0x2 /* Page can be written. */
458b23a853SDenis Revunov #define PROT_EXEC 0x4 /* Page can be executed. */
468b23a853SDenis Revunov #define PROT_NONE 0x0 /* Page can not be accessed. */
478b23a853SDenis Revunov #define PROT_GROWSDOWN \
488b23a853SDenis Revunov 0x01000000 /* Extend change to start of \
498b23a853SDenis Revunov growsdown vma (mprotect only). */
508b23a853SDenis Revunov #define PROT_GROWSUP \
518b23a853SDenis Revunov 0x02000000 /* Extend change to start of \
528b23a853SDenis Revunov growsup vma (mprotect only). */
538b23a853SDenis Revunov
548b23a853SDenis Revunov /* Sharing types (must choose one and only one of these). */
558b23a853SDenis Revunov #define MAP_SHARED 0x01 /* Share changes. */
568b23a853SDenis Revunov #define MAP_PRIVATE 0x02 /* Changes are private. */
578b23a853SDenis Revunov #define MAP_FIXED 0x10 /* Interpret addr exactly. */
588b23a853SDenis Revunov
598b23a853SDenis Revunov #if defined(__APPLE__)
608b23a853SDenis Revunov #define MAP_ANONYMOUS 0x1000
618b23a853SDenis Revunov #else
628b23a853SDenis Revunov #define MAP_ANONYMOUS 0x20
638b23a853SDenis Revunov #endif
648b23a853SDenis Revunov
658b23a853SDenis Revunov #define MAP_FAILED ((void *)-1)
668b23a853SDenis Revunov
6760bbddf3SDenis Revunov #define SEEK_SET 0 /* Seek from beginning of file. */
6860bbddf3SDenis Revunov #define SEEK_CUR 1 /* Seek from current position. */
6960bbddf3SDenis Revunov #define SEEK_END 2 /* Seek from end of file. */
7060bbddf3SDenis Revunov
7160bbddf3SDenis Revunov #define O_RDONLY 0
7260bbddf3SDenis Revunov #define O_WRONLY 1
7360bbddf3SDenis Revunov #define O_RDWR 2
7460bbddf3SDenis Revunov #define O_CREAT 64
7560bbddf3SDenis Revunov #define O_TRUNC 512
7660bbddf3SDenis Revunov #define O_APPEND 1024
7760bbddf3SDenis Revunov
78ea2182feSMaksim Panchenko // Functions that are required by freestanding environment. Compiler may
79ea2182feSMaksim Panchenko // generate calls to these implicitly.
80ea2182feSMaksim Panchenko extern "C" {
memcpy(void * Dest,const void * Src,size_t Len)81ea2182feSMaksim Panchenko void *memcpy(void *Dest, const void *Src, size_t Len) {
82ea2182feSMaksim Panchenko uint8_t *d = static_cast<uint8_t *>(Dest);
83ea2182feSMaksim Panchenko const uint8_t *s = static_cast<const uint8_t *>(Src);
84ea2182feSMaksim Panchenko while (Len--)
85ea2182feSMaksim Panchenko *d++ = *s++;
86ea2182feSMaksim Panchenko return Dest;
87ea2182feSMaksim Panchenko }
88ea2182feSMaksim Panchenko
memmove(void * Dest,const void * Src,size_t Len)89ea2182feSMaksim Panchenko void *memmove(void *Dest, const void *Src, size_t Len) {
90ea2182feSMaksim Panchenko uint8_t *d = static_cast<uint8_t *>(Dest);
91ea2182feSMaksim Panchenko const uint8_t *s = static_cast<const uint8_t *>(Src);
92ea2182feSMaksim Panchenko if (d < s) {
93ea2182feSMaksim Panchenko while (Len--)
94ea2182feSMaksim Panchenko *d++ = *s++;
95ea2182feSMaksim Panchenko } else {
96ea2182feSMaksim Panchenko s += Len - 1;
97ea2182feSMaksim Panchenko d += Len - 1;
98ea2182feSMaksim Panchenko while (Len--)
99ea2182feSMaksim Panchenko *d-- = *s--;
100ea2182feSMaksim Panchenko }
101ea2182feSMaksim Panchenko
102ea2182feSMaksim Panchenko return Dest;
103ea2182feSMaksim Panchenko }
104ea2182feSMaksim Panchenko
memset(void * Buf,int C,size_t Size)105e10e120cSVladislav Khmelevsky void *memset(void *Buf, int C, size_t Size) {
106e10e120cSVladislav Khmelevsky char *S = (char *)Buf;
107e10e120cSVladislav Khmelevsky for (size_t I = 0; I < Size; ++I)
108e10e120cSVladislav Khmelevsky *S++ = C;
109e10e120cSVladislav Khmelevsky return Buf;
110ea2182feSMaksim Panchenko }
111ea2182feSMaksim Panchenko
memcmp(const void * s1,const void * s2,size_t n)112ea2182feSMaksim Panchenko int memcmp(const void *s1, const void *s2, size_t n) {
113ea2182feSMaksim Panchenko const uint8_t *c1 = static_cast<const uint8_t *>(s1);
114ea2182feSMaksim Panchenko const uint8_t *c2 = static_cast<const uint8_t *>(s2);
115ea2182feSMaksim Panchenko for (; n--; c1++, c2++) {
116ea2182feSMaksim Panchenko if (*c1 != *c2)
117ea2182feSMaksim Panchenko return *c1 < *c2 ? -1 : 1;
118ea2182feSMaksim Panchenko }
119ea2182feSMaksim Panchenko return 0;
120ea2182feSMaksim Panchenko }
121ea2182feSMaksim Panchenko } // extern "C"
122ea2182feSMaksim Panchenko
1239bd71615SXun Li // Anonymous namespace covering everything but our library entry point
1249bd71615SXun Li namespace {
1259bd71615SXun Li
126*87e9c424SElvina Yakubova struct dirent64 {
127*87e9c424SElvina Yakubova uint64_t d_ino; /* Inode number */
128*87e9c424SElvina Yakubova int64_t d_off; /* Offset to next linux_dirent */
129*87e9c424SElvina Yakubova unsigned short d_reclen; /* Length of this linux_dirent */
130*87e9c424SElvina Yakubova unsigned char d_type;
131*87e9c424SElvina Yakubova char d_name[]; /* Filename (null-terminated) */
132*87e9c424SElvina Yakubova /* length is actually (d_reclen - 2 -
133*87e9c424SElvina Yakubova offsetof(struct linux_dirent, d_name)) */
134*87e9c424SElvina Yakubova };
135*87e9c424SElvina Yakubova
136*87e9c424SElvina Yakubova /* Length of the entries in `struct utsname' is 65. */
137*87e9c424SElvina Yakubova #define _UTSNAME_LENGTH 65
138*87e9c424SElvina Yakubova
139*87e9c424SElvina Yakubova struct UtsNameTy {
140*87e9c424SElvina Yakubova char sysname[_UTSNAME_LENGTH]; /* Operating system name (e.g., "Linux") */
141*87e9c424SElvina Yakubova char nodename[_UTSNAME_LENGTH]; /* Name within "some implementation-defined
142*87e9c424SElvina Yakubova network" */
143*87e9c424SElvina Yakubova char release[_UTSNAME_LENGTH]; /* Operating system release (e.g., "2.6.28") */
144*87e9c424SElvina Yakubova char version[_UTSNAME_LENGTH]; /* Operating system version */
145*87e9c424SElvina Yakubova char machine[_UTSNAME_LENGTH]; /* Hardware identifier */
146*87e9c424SElvina Yakubova char domainname[_UTSNAME_LENGTH]; /* NIS or YP domain name */
147*87e9c424SElvina Yakubova };
148*87e9c424SElvina Yakubova
149*87e9c424SElvina Yakubova struct timespec {
150*87e9c424SElvina Yakubova uint64_t tv_sec; /* seconds */
151*87e9c424SElvina Yakubova uint64_t tv_nsec; /* nanoseconds */
152*87e9c424SElvina Yakubova };
153*87e9c424SElvina Yakubova
154*87e9c424SElvina Yakubova #if defined(__aarch64__)
155*87e9c424SElvina Yakubova #include "sys_aarch64.h"
156*87e9c424SElvina Yakubova #else
157*87e9c424SElvina Yakubova #include "sys_x86_64.h"
158*87e9c424SElvina Yakubova #endif
159a86dd9aeSDenis Revunov
160d6e60c5bSAlexander Shaposhnikov constexpr uint32_t BufSize = 10240;
161d6e60c5bSAlexander Shaposhnikov
162d6e60c5bSAlexander Shaposhnikov // Helper functions for writing strings to the .fdata file. We intentionally
163ea2182feSMaksim Panchenko // avoid using libc names to make it clear it is our impl.
164d6e60c5bSAlexander Shaposhnikov
165d6e60c5bSAlexander Shaposhnikov /// Write number Num using Base to the buffer in OutBuf, returns a pointer to
166d6e60c5bSAlexander Shaposhnikov /// the end of the string.
intToStr(char * OutBuf,uint64_t Num,uint32_t Base)167d6e60c5bSAlexander Shaposhnikov char *intToStr(char *OutBuf, uint64_t Num, uint32_t Base) {
168d6e60c5bSAlexander Shaposhnikov const char *Chars = "0123456789abcdef";
169d6e60c5bSAlexander Shaposhnikov char Buf[21];
170d6e60c5bSAlexander Shaposhnikov char *Ptr = Buf;
171d6e60c5bSAlexander Shaposhnikov while (Num) {
172d6e60c5bSAlexander Shaposhnikov *Ptr++ = *(Chars + (Num % Base));
173d6e60c5bSAlexander Shaposhnikov Num /= Base;
174d6e60c5bSAlexander Shaposhnikov }
175d6e60c5bSAlexander Shaposhnikov if (Ptr == Buf) {
176d6e60c5bSAlexander Shaposhnikov *OutBuf++ = '0';
177d6e60c5bSAlexander Shaposhnikov return OutBuf;
178d6e60c5bSAlexander Shaposhnikov }
179883bf0e8SAmir Ayupov while (Ptr != Buf)
180d6e60c5bSAlexander Shaposhnikov *OutBuf++ = *--Ptr;
181883bf0e8SAmir Ayupov
182d6e60c5bSAlexander Shaposhnikov return OutBuf;
183d6e60c5bSAlexander Shaposhnikov }
184d6e60c5bSAlexander Shaposhnikov
185d6e60c5bSAlexander Shaposhnikov /// Copy Str to OutBuf, returns a pointer to the end of the copied string
186d6e60c5bSAlexander Shaposhnikov char *strCopy(char *OutBuf, const char *Str, int32_t Size = BufSize) {
187d6e60c5bSAlexander Shaposhnikov while (*Str) {
188d6e60c5bSAlexander Shaposhnikov *OutBuf++ = *Str++;
189d6e60c5bSAlexander Shaposhnikov if (--Size <= 0)
190d6e60c5bSAlexander Shaposhnikov return OutBuf;
191d6e60c5bSAlexander Shaposhnikov }
192d6e60c5bSAlexander Shaposhnikov return OutBuf;
193d6e60c5bSAlexander Shaposhnikov }
194d6e60c5bSAlexander Shaposhnikov
1952da5b12aSAmir Ayupov /// Compare two strings, at most Num bytes.
strnCmp(const char * Str1,const char * Str2,size_t Num)1962da5b12aSAmir Ayupov int strnCmp(const char *Str1, const char *Str2, size_t Num) {
1972da5b12aSAmir Ayupov while (Num && *Str1 && (*Str1 == *Str2)) {
1982da5b12aSAmir Ayupov Num--;
1992da5b12aSAmir Ayupov Str1++;
2002da5b12aSAmir Ayupov Str2++;
2012da5b12aSAmir Ayupov }
2022da5b12aSAmir Ayupov if (Num == 0)
2032da5b12aSAmir Ayupov return 0;
2042da5b12aSAmir Ayupov return *(unsigned char *)Str1 - *(unsigned char *)Str2;
2052da5b12aSAmir Ayupov }
2062da5b12aSAmir Ayupov
strLen(const char * Str)207d6e60c5bSAlexander Shaposhnikov uint32_t strLen(const char *Str) {
208d6e60c5bSAlexander Shaposhnikov uint32_t Size = 0;
209d6e60c5bSAlexander Shaposhnikov while (*Str++)
210d6e60c5bSAlexander Shaposhnikov ++Size;
211d6e60c5bSAlexander Shaposhnikov return Size;
212d6e60c5bSAlexander Shaposhnikov }
213d6e60c5bSAlexander Shaposhnikov
strStr(const char * const Haystack,const char * const Needle)2141fb18619SAlexey Moksyakov void *strStr(const char *const Haystack, const char *const Needle) {
2151fb18619SAlexey Moksyakov int j = 0;
2161fb18619SAlexey Moksyakov
2171fb18619SAlexey Moksyakov for (int i = 0; i < strLen(Haystack); i++) {
2181fb18619SAlexey Moksyakov if (Haystack[i] == Needle[0]) {
2191fb18619SAlexey Moksyakov for (j = 1; j < strLen(Needle); j++) {
2201fb18619SAlexey Moksyakov if (Haystack[i + j] != Needle[j])
2211fb18619SAlexey Moksyakov break;
2221fb18619SAlexey Moksyakov }
2231fb18619SAlexey Moksyakov if (j == strLen(Needle))
2241fb18619SAlexey Moksyakov return (void *)&Haystack[i];
2251fb18619SAlexey Moksyakov }
2261fb18619SAlexey Moksyakov }
2271fb18619SAlexey Moksyakov return nullptr;
2281fb18619SAlexey Moksyakov }
2291fb18619SAlexey Moksyakov
reportNumber(const char * Msg,uint64_t Num,uint32_t Base)2303b876cc3SAlexander Shaposhnikov void reportNumber(const char *Msg, uint64_t Num, uint32_t Base) {
2313b876cc3SAlexander Shaposhnikov char Buf[BufSize];
2323b876cc3SAlexander Shaposhnikov char *Ptr = Buf;
2333b876cc3SAlexander Shaposhnikov Ptr = strCopy(Ptr, Msg, BufSize - 23);
2343b876cc3SAlexander Shaposhnikov Ptr = intToStr(Ptr, Num, Base);
2353b876cc3SAlexander Shaposhnikov Ptr = strCopy(Ptr, "\n");
2363b876cc3SAlexander Shaposhnikov __write(2, Buf, Ptr - Buf);
2373b876cc3SAlexander Shaposhnikov }
2383b876cc3SAlexander Shaposhnikov
report(const char * Msg)2393b876cc3SAlexander Shaposhnikov void report(const char *Msg) { __write(2, Msg, strLen(Msg)); }
2403b876cc3SAlexander Shaposhnikov
2412ffd6e2bSElvina Yakubova unsigned long hexToLong(const char *Str, char Terminator = '\0') {
2422ffd6e2bSElvina Yakubova unsigned long Res = 0;
2432ffd6e2bSElvina Yakubova while (*Str != Terminator) {
2442ffd6e2bSElvina Yakubova Res <<= 4;
2452ffd6e2bSElvina Yakubova if ('0' <= *Str && *Str <= '9')
2462ffd6e2bSElvina Yakubova Res += *Str++ - '0';
2472ffd6e2bSElvina Yakubova else if ('a' <= *Str && *Str <= 'f')
2482ffd6e2bSElvina Yakubova Res += *Str++ - 'a' + 10;
2492ffd6e2bSElvina Yakubova else if ('A' <= *Str && *Str <= 'F')
2502ffd6e2bSElvina Yakubova Res += *Str++ - 'A' + 10;
251883bf0e8SAmir Ayupov else
2522ffd6e2bSElvina Yakubova return 0;
2532ffd6e2bSElvina Yakubova }
2542ffd6e2bSElvina Yakubova return Res;
2552ffd6e2bSElvina Yakubova }
2562ffd6e2bSElvina Yakubova
2571fb18619SAlexey Moksyakov /// Starting from character at \p buf, find the longest consecutive sequence
2581fb18619SAlexey Moksyakov /// of digits (0-9) and convert it to uint32_t. The converted value
2591fb18619SAlexey Moksyakov /// is put into \p ret. \p end marks the end of the buffer to avoid buffer
2601fb18619SAlexey Moksyakov /// overflow. The function \returns whether a valid uint32_t value is found.
2611fb18619SAlexey Moksyakov /// \p buf will be updated to the next character right after the digits.
scanUInt32(const char * & Buf,const char * End,uint32_t & Ret)2621fb18619SAlexey Moksyakov static bool scanUInt32(const char *&Buf, const char *End, uint32_t &Ret) {
2631fb18619SAlexey Moksyakov uint64_t Result = 0;
2641fb18619SAlexey Moksyakov const char *OldBuf = Buf;
2651fb18619SAlexey Moksyakov while (Buf < End && ((*Buf) >= '0' && (*Buf) <= '9')) {
2661fb18619SAlexey Moksyakov Result = Result * 10 + (*Buf) - '0';
2671fb18619SAlexey Moksyakov ++Buf;
2681fb18619SAlexey Moksyakov }
2691fb18619SAlexey Moksyakov if (OldBuf != Buf && Result <= 0xFFFFFFFFu) {
2701fb18619SAlexey Moksyakov Ret = static_cast<uint32_t>(Result);
2711fb18619SAlexey Moksyakov return true;
2721fb18619SAlexey Moksyakov }
2731fb18619SAlexey Moksyakov return false;
2741fb18619SAlexey Moksyakov }
2751fb18619SAlexey Moksyakov
reportError(const char * Msg,uint64_t Size)2769bd71615SXun Li void reportError(const char *Msg, uint64_t Size) {
2779bd71615SXun Li __write(2, Msg, Size);
2789bd71615SXun Li __exit(1);
2799bd71615SXun Li }
2809bd71615SXun Li
assert(bool Assertion,const char * Msg)2819bd71615SXun Li void assert(bool Assertion, const char *Msg) {
2829bd71615SXun Li if (Assertion)
2839bd71615SXun Li return;
2849bd71615SXun Li char Buf[BufSize];
2859bd71615SXun Li char *Ptr = Buf;
2869bd71615SXun Li Ptr = strCopy(Ptr, "Assertion failed: ");
2879bd71615SXun Li Ptr = strCopy(Ptr, Msg, BufSize - 40);
2889bd71615SXun Li Ptr = strCopy(Ptr, "\n");
2899bd71615SXun Li reportError(Buf, Ptr - Buf);
2909bd71615SXun Li }
2919bd71615SXun Li
292*87e9c424SElvina Yakubova #define SIG_BLOCK 0
293*87e9c424SElvina Yakubova #define SIG_UNBLOCK 1
294*87e9c424SElvina Yakubova #define SIG_SETMASK 2
295*87e9c424SElvina Yakubova
296*87e9c424SElvina Yakubova static const uint64_t MaskAllSignals[] = {-1ULL};
297*87e9c424SElvina Yakubova
2989bd71615SXun Li class Mutex {
2999bd71615SXun Li volatile bool InUse{false};
3009bd71615SXun Li
3019bd71615SXun Li public:
acquire()30235155a07SElvina Yakubova bool acquire() { return !__atomic_test_and_set(&InUse, __ATOMIC_ACQUIRE); }
release()30335155a07SElvina Yakubova void release() { __atomic_clear(&InUse, __ATOMIC_RELEASE); }
3049bd71615SXun Li };
3059bd71615SXun Li
3069bd71615SXun Li /// RAII wrapper for Mutex
3079bd71615SXun Li class Lock {
3089bd71615SXun Li Mutex &M;
3092cf9008aSVladislav Khmelevsky uint64_t SignalMask[1] = {};
3109bd71615SXun Li
3119bd71615SXun Li public:
Lock(Mutex & M)3129bd71615SXun Li Lock(Mutex &M) : M(M) {
3132cf9008aSVladislav Khmelevsky __sigprocmask(SIG_BLOCK, MaskAllSignals, SignalMask);
3149bd71615SXun Li while (!M.acquire()) {
3159bd71615SXun Li }
3169bd71615SXun Li }
3172cf9008aSVladislav Khmelevsky
~Lock()3182cf9008aSVladislav Khmelevsky ~Lock() {
3192cf9008aSVladislav Khmelevsky M.release();
3202cf9008aSVladislav Khmelevsky __sigprocmask(SIG_SETMASK, SignalMask, nullptr);
3212cf9008aSVladislav Khmelevsky }
3229bd71615SXun Li };
3239bd71615SXun Li
3249aa134dcSVasily Leonenko /// RAII wrapper for Mutex
3259aa134dcSVasily Leonenko class TryLock {
3269aa134dcSVasily Leonenko Mutex &M;
3279aa134dcSVasily Leonenko bool Locked = false;
3289aa134dcSVasily Leonenko
3299aa134dcSVasily Leonenko public:
TryLock(Mutex & M)3309aa134dcSVasily Leonenko TryLock(Mutex &M) : M(M) {
3319aa134dcSVasily Leonenko int Retry = 100;
3329aa134dcSVasily Leonenko while (--Retry && !M.acquire())
3339aa134dcSVasily Leonenko ;
3349aa134dcSVasily Leonenko if (Retry)
3359aa134dcSVasily Leonenko Locked = true;
3369aa134dcSVasily Leonenko }
isLocked()3379aa134dcSVasily Leonenko bool isLocked() { return Locked; }
3389aa134dcSVasily Leonenko
~TryLock()3399aa134dcSVasily Leonenko ~TryLock() {
3409aa134dcSVasily Leonenko if (isLocked())
3419aa134dcSVasily Leonenko M.release();
3429aa134dcSVasily Leonenko }
3439aa134dcSVasily Leonenko };
3449aa134dcSVasily Leonenko
alignTo(uint64_t Value,uint64_t Align)3459bd71615SXun Li inline uint64_t alignTo(uint64_t Value, uint64_t Align) {
3469bd71615SXun Li return (Value + Align - 1) / Align * Align;
3479bd71615SXun Li }
348bbd9d610SAlexander Shaposhnikov
3491cf23e5eSAlexander Shaposhnikov } // anonymous namespace
350