/* Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) */ #pragma once #include #include #include #include #include "asserts.h" #include "globals.h" namespace py { class Utils { public: template static bool isAligned(T x, int n) { DCHECK(isPowerOfTwo(n), "must be power of 2"); return (x & (n - 1)) == 0; } template static bool isPowerOfTwo(T x) { return (x & (x - 1)) == 0; } template static bool fits(word value) { return static_cast(static_cast(value)) == value; } template static T roundDown(T x, int n) { DCHECK(isPowerOfTwo(n), "must be power of 2"); return (x & -n); } template static T roundUp(T x, int n) { return roundDown(x + n - 1, n); } template static T roundUpDiv(T denominator, int divisor) { if (isPowerOfTwo(divisor)) { return roundUp(denominator, divisor) >> (highestBit(divisor) - 1); } return (denominator + (divisor - 1)) / divisor; } template static T nextPowerOfTwo(T x) { // Turn off all but msb. while ((x & (x - 1u)) != 0) { x &= x - 1u; } return x << 1u; } template static T rotateLeft(T x, int n) { return (x << n) | (x >> (-n & (sizeof(T) * kBitsPerByte - 1))); } template static T maximum(T x, T y) { return x > y ? x : y; } // Search forwards through `haystack` looking for `needle`. Return the byte // offset, or -1 if not found. static word memoryFind(const byte* haystack, word haystack_len, const byte* needle, word needle_len); // Search forwards through `haystack` looking for `needle`. Return the byte // offset, or -1 if not found. static word memoryFindChar(const byte* haystack, word haystack_len, byte needle); // Search backwards through `haystack` looking for `needle`. Return the byte // offset, or -1 if not found. static word memoryFindCharReverse(const byte* haystack, word haystack_len, byte needle); // Search backwards through `haystack` looking for `needle`. Return the byte // offset, or -1 if not found. static word memoryFindReverse(const byte* haystack, word haystack_len, const byte* needle, word needle_len); template static T minimum(T x, T y) { return x < y ? x : y; } static int highestBit(word x) { return x == 0 ? 0 : kBitsPerWord - __builtin_clzl(x); } // Returns the number of leading redundant sign bits. // This is equivalent to gccs __builtin_clrsbl but works for any compiler. static int numRedundantSignBits(word x) { #if __has_builtin(__builtin_clrsbl) || \ (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) static_assert(sizeof(x) == sizeof(long), "Need to choose matching clrsbX builtin"); return __builtin_clrsbl(x); #else if (x < 0) x = ~x; if (x == 0) return sizeof(x) * kBitsPerByte - 1; return __builtin_clzl(x) - 1; #endif } template static T readBytes(void* addr) { T dest; std::memcpy(&dest, addr, sizeof(dest)); return dest; } // Print the current traceback, information about the pending exception, if // one is set, and call std::abort(). [[noreturn]] static void printDebugInfoAndAbort(); private: DISALLOW_IMPLICIT_CONSTRUCTORS(Utils); }; // Convenience wrappers to enable templates based on signed or unsigned integral // types. template using if_signed_t = typename std::enable_if::value, R>::type; template using if_unsigned_t = typename std::enable_if::value, R>::type; // std::unique_ptr for objects created with std::malloc() rather than new. struct FreeDeleter { void operator()(void* ptr) const { std::free(ptr); } }; template using unique_c_ptr = std::unique_ptr; } // namespace py