1 | /* |
2 | * Copyright 2016-present Facebook, Inc. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | #pragma once |
18 | |
19 | #if defined(_WIN32) && !defined(__clang__) |
20 | #include <assert.h> |
21 | #include <folly/Portability.h> |
22 | #include <intrin.h> |
23 | #include <stdint.h> |
24 | |
25 | namespace folly { |
26 | namespace portability { |
27 | namespace detail { |
28 | void call_flush_instruction_cache_self_pid(void* begin, size_t size); |
29 | } |
30 | } // namespace portability |
31 | } // namespace folly |
32 | |
33 | FOLLY_ALWAYS_INLINE void __builtin___clear_cache(char* begin, char* end) { |
34 | if (folly::kIsArchAmd64) { |
35 | // x86_64 doesn't require the instruction cache to be flushed after |
36 | // modification. |
37 | } else { |
38 | // Default to flushing it for everything else, such as ARM. |
39 | folly::portability::detail::call_flush_instruction_cache_self_pid( |
40 | static_cast<void*>(begin), static_cast<size_t>(end - begin)); |
41 | } |
42 | } |
43 | |
44 | FOLLY_ALWAYS_INLINE int __builtin_clz(unsigned int x) { |
45 | unsigned long index; |
46 | return int(_BitScanReverse(&index, (unsigned long)x) ? 31 - index : 32); |
47 | } |
48 | |
49 | FOLLY_ALWAYS_INLINE int __builtin_clzl(unsigned long x) { |
50 | return __builtin_clz((unsigned int)x); |
51 | } |
52 | |
53 | FOLLY_ALWAYS_INLINE int __builtin_clzll(unsigned long long x) { |
54 | unsigned long index; |
55 | return int(_BitScanReverse64(&index, x) ? 63 - index : 64); |
56 | } |
57 | |
58 | FOLLY_ALWAYS_INLINE int __builtin_ctz(unsigned int x) { |
59 | unsigned long index; |
60 | return int(_BitScanForward(&index, (unsigned long)x) ? index : 32); |
61 | } |
62 | |
63 | FOLLY_ALWAYS_INLINE int __builtin_ctzl(unsigned long x) { |
64 | return __builtin_ctz((unsigned int)x); |
65 | } |
66 | |
67 | FOLLY_ALWAYS_INLINE int __builtin_ctzll(unsigned long long x) { |
68 | unsigned long index; |
69 | return int(_BitScanForward64(&index, x) ? index : 64); |
70 | } |
71 | |
72 | FOLLY_ALWAYS_INLINE int __builtin_ffs(int x) { |
73 | unsigned long index; |
74 | return int(_BitScanForward(&index, (unsigned long)x) ? index + 1 : 0); |
75 | } |
76 | |
77 | FOLLY_ALWAYS_INLINE int __builtin_ffsl(long x) { |
78 | return __builtin_ffs(int(x)); |
79 | } |
80 | |
81 | FOLLY_ALWAYS_INLINE int __builtin_ffsll(long long x) { |
82 | unsigned long index; |
83 | return int(_BitScanForward64(&index, (unsigned long long)x) ? index + 1 : 0); |
84 | } |
85 | |
86 | FOLLY_ALWAYS_INLINE int __builtin_popcount(unsigned int x) { |
87 | return int(__popcnt(x)); |
88 | } |
89 | |
90 | FOLLY_ALWAYS_INLINE int __builtin_popcountl(unsigned long x) { |
91 | static_assert(sizeof(x) == 4, "" ); |
92 | return int(__popcnt(x)); |
93 | } |
94 | |
95 | FOLLY_ALWAYS_INLINE int __builtin_popcountll(unsigned long long x) { |
96 | return int(__popcnt64(x)); |
97 | } |
98 | |
99 | FOLLY_ALWAYS_INLINE void* __builtin_return_address(unsigned int frame) { |
100 | // I really hope frame is zero... |
101 | (void)frame; |
102 | assert(frame == 0); |
103 | return _ReturnAddress(); |
104 | } |
105 | #endif |
106 | |