a0e78563592113a66754326a85698148fd6ef0e8
[WebKit-https.git] / Source / WTF / wtf / PtrTag.h
1 /*
2  * Copyright (C) 2018-2019 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #include <wtf/Assertions.h>
29 #include <wtf/DataLog.h>
30
31 namespace WTF {
32
33 #define FOR_EACH_BASE_WTF_PTRTAG(v) \
34     v(NoPtrTag) \
35     v(CFunctionPtrTag) \
36
37 #define FOR_EACH_ADDITIONAL_WTF_PTRTAG(v) \
38     v(FreeSpacePtrTag) \
39     v(HandleMemoryPtrTag) \
40     v(PlatformRegistersLRPtrTag) \
41     v(PlatformRegistersPCPtrTag) \
42
43 #define FOR_EACH_WTF_PTRTAG(v) \
44     FOR_EACH_BASE_WTF_PTRTAG(v) \
45     FOR_EACH_ADDITIONAL_WTF_PTRTAG(v) \
46
47 enum PtrTag : uintptr_t {
48     NoPtrTag,
49     CFunctionPtrTag,
50 };
51
52 #if CPU(ARM64E)
53 #define WTF_PTRTAG_HASH(tag) ptrauth_string_discriminator(#tag)
54
55 #else // not CPU(ARM64E)
56
57 template<size_t N>
58 constexpr uintptr_t makePtrTagHash(const char (&str)[N])
59 {
60     uintptr_t result = 134775813;
61     for (size_t i = 0; i < N; ++i)
62         result += ((result * str[i]) ^ (result >> 16));
63     return result & 0xffff;
64 }
65
66 #define WTF_PTRTAG_HASH(tag) WTF::makePtrTagHash(#tag)
67 #endif // not CPU(ARM64E)
68
69 #define WTF_DECLARE_PTRTAG(tag) \
70     constexpr PtrTag tag = static_cast<PtrTag>(WTF_PTRTAG_HASH(#tag)); \
71     static_assert(tag != NoPtrTag && tag != CFunctionPtrTag, "");
72
73 static_assert(static_cast<uintptr_t>(NoPtrTag) == static_cast<uintptr_t>(0), "");
74 static_assert(static_cast<uintptr_t>(CFunctionPtrTag) == static_cast<uintptr_t>(1), "");
75
76 #if COMPILER(MSVC)
77 #pragma warning(push)
78 #pragma warning(disable:4307)
79 #endif
80
81 FOR_EACH_ADDITIONAL_WTF_PTRTAG(WTF_DECLARE_PTRTAG)
82
83 #if COMPILER(MSVC)
84 #pragma warning(pop)
85 #endif
86
87 struct PtrTagLookup {
88     const char* (*tagForPtr)(const void*);
89     const char* (*ptrTagName)(PtrTag);
90     PtrTagLookup* next { nullptr };
91 };
92
93 #if CPU(ARM64E)
94
95 enum class PtrTagAction {
96     ReleaseAssert,
97     DebugAssert,
98     NoAssert,
99 };
100
101 constexpr PtrTag AnyPtrTag = static_cast<PtrTag>(-1); // Only used for assertion messages.
102
103 WTF_EXPORT_PRIVATE void registerPtrTagLookup(PtrTagLookup*);
104 WTF_EXPORT_PRIVATE void reportBadTag(const void*, PtrTag expectedTag);
105
106 #if ASSERT_DISABLED
107 constexpr bool enablePtrTagDebugAssert = false;
108 #else
109 constexpr bool enablePtrTagDebugAssert = true;
110 #endif
111
112 #define WTF_PTRTAG_ASSERT(action, ptr, expectedTag, assertion) \
113     do { \
114         if (action == PtrTagAction::ReleaseAssert \
115             || (WTF::enablePtrTagDebugAssert && action == PtrTagAction::DebugAssert)) { \
116             bool passed = (assertion); \
117             if (UNLIKELY(!passed)) { \
118                 reportBadTag(reinterpret_cast<const void*>(ptr), expectedTag); \
119             } \
120             RELEASE_ASSERT(passed && #assertion); \
121         } \
122     } while (false)
123
124
125 template<typename T>
126 inline T* tagArrayPtr(nullptr_t ptr, size_t length)
127 {
128     ASSERT(!length);
129     return ptrauth_sign_unauthenticated(static_cast<T*>(ptr), ptrauth_key_process_dependent_data, length);
130 }
131
132
133 template<typename T>
134 inline T* tagArrayPtr(T* ptr, size_t length)
135 {
136     return ptrauth_sign_unauthenticated(ptr, ptrauth_key_process_dependent_data, length);
137 }
138
139 template<typename T>
140 inline T* untagArrayPtr(T* ptr, size_t length)
141 {
142     return ptrauth_auth_data(ptr, ptrauth_key_process_dependent_data, length);
143 }
144
145 template<typename T>
146 inline T* removeArrayPtrTag(T* ptr)
147 {
148     return ptrauth_strip(ptr, ptrauth_key_process_dependent_data);
149 }
150
151 template<typename T>
152 inline T* retagArrayPtr(T* ptr, size_t oldLength, size_t newLength)
153 {
154     return ptrauth_auth_and_resign(ptr, ptrauth_key_process_dependent_data, oldLength, ptrauth_key_process_dependent_data, newLength);
155 }
156
157 template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
158 inline constexpr T removeCodePtrTag(PtrType ptr)
159 {
160     return bitwise_cast<T>(ptrauth_strip(ptr, ptrauth_key_process_dependent_code));
161 }
162
163 template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
164 inline constexpr PtrType removeCodePtrTag(PtrType ptr)
165 {
166     return ptrauth_strip(ptr, ptrauth_key_process_dependent_code);
167 }
168
169 template<PtrTagAction tagAction, typename PtrType>
170 inline PtrType tagCodePtrImpl(PtrType ptr, PtrTag tag)
171 {
172     if (!ptr)
173         return nullptr;
174     WTF_PTRTAG_ASSERT(tagAction, ptr, NoPtrTag, removeCodePtrTag(ptr) == ptr);
175     if (tag == NoPtrTag)
176         return ptr;
177     if (tag == CFunctionPtrTag)
178         return ptrauth_sign_unauthenticated(ptr, ptrauth_key_function_pointer, 0);
179     return ptrauth_sign_unauthenticated(ptr, ptrauth_key_process_dependent_code, tag);
180 }
181
182 template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
183 inline T tagCodePtr(PtrType ptr, PtrTag tag)
184 {
185     return bitwise_cast<T>(tagCodePtrImpl<PtrTagAction::DebugAssert>(ptr, tag));
186 }
187
188 template<typename T, PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
189 inline T tagCodePtr(PtrType ptr)
190 {
191     return bitwise_cast<T>(tagCodePtrImpl<PtrTagAction::DebugAssert>(ptr, tag));
192 }
193
194 template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
195 inline PtrType tagCodePtr(PtrType ptr, PtrTag tag)
196 {
197     return tagCodePtrImpl<PtrTagAction::DebugAssert>(ptr, tag);
198 }
199
200 template<PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
201 inline PtrType tagCodePtr(PtrType ptr) { return tagCodePtr(ptr, tag); }
202
203 template<typename PtrType>
204 inline PtrType untagCodePtrImplHelper(PtrType ptr, PtrTag tag)
205 {
206     if (tag == NoPtrTag)
207         return ptr;
208     if (tag == CFunctionPtrTag)
209         return __builtin_ptrauth_auth(ptr, ptrauth_key_function_pointer, 0);
210     return __builtin_ptrauth_auth(ptr, ptrauth_key_process_dependent_code, tag);
211 }
212
213 template<PtrTagAction tagAction, typename PtrType>
214 inline PtrType untagCodePtrImpl(PtrType ptr, PtrTag tag)
215 {
216     if (!ptr)
217         return nullptr;
218     PtrType result = untagCodePtrImplHelper(ptr, tag);
219     WTF_PTRTAG_ASSERT(tagAction, ptr, tag, removeCodePtrTag(ptr) == result);
220     return result;
221 }
222
223 template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
224 inline T untagCodePtr(PtrType ptr, PtrTag tag)
225 {
226     return bitwise_cast<T>(untagCodePtrImpl<PtrTagAction::ReleaseAssert>(ptr, tag));
227 }
228
229 template<typename T, PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
230 inline T untagCodePtr(PtrType ptr)
231 {
232     return bitwise_cast<T>(untagCodePtrImpl<PtrTagAction::ReleaseAssert>(ptr, tag));
233 }
234
235 template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
236 inline PtrType untagCodePtr(PtrType ptr, PtrTag tag)
237 {
238     return untagCodePtrImpl<PtrTagAction::ReleaseAssert>(ptr, tag);
239 }
240
241 template<PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
242 inline PtrType untagCodePtr(PtrType ptr) { return untagCodePtr(ptr, tag); }
243
244 template<PtrTagAction tagAction, typename PtrType>
245 inline PtrType retagCodePtrImplHelper(PtrType ptr, PtrTag oldTag, PtrTag newTag)
246 {
247     if (oldTag == newTag || (oldTag == NoPtrTag && newTag == NoPtrTag))
248         return ptr;
249     if (newTag == NoPtrTag)
250         return untagCodePtrImpl<tagAction>(ptr, oldTag);
251     if (oldTag == NoPtrTag)
252         return tagCodePtrImpl<tagAction>(ptr, newTag);
253     if (oldTag == CFunctionPtrTag)
254         return ptrauth_auth_and_resign(ptr, ptrauth_key_function_pointer, 0, ptrauth_key_process_dependent_code, newTag);
255     if (newTag == CFunctionPtrTag)
256         return ptrauth_auth_and_resign(ptr, ptrauth_key_process_dependent_code, oldTag, ptrauth_key_function_pointer, 0);
257     return ptrauth_auth_and_resign(ptr, ptrauth_key_process_dependent_code, oldTag, ptrauth_key_process_dependent_code, newTag);
258 }
259
260 template<PtrTagAction tagAction, typename PtrType>
261 inline PtrType retagCodePtrImpl(PtrType ptr, PtrTag oldTag, PtrTag newTag)
262 {
263     if (!ptr)
264         return nullptr;
265     PtrTagAction untagAction = (tagAction == PtrTagAction::NoAssert) ? PtrTagAction::NoAssert : PtrTagAction::ReleaseAssert;
266     WTF_PTRTAG_ASSERT(untagAction, ptr, oldTag, removeCodePtrTag(ptr) == untagCodePtrImpl<PtrTagAction::NoAssert>(ptr, oldTag));
267     PtrType result = retagCodePtrImplHelper<tagAction>(ptr, oldTag, newTag);
268     WTF_PTRTAG_ASSERT(tagAction, ptr, newTag, result == tagCodePtrImpl<PtrTagAction::NoAssert>(removeCodePtrTag(ptr), newTag));
269     return result;
270 }
271
272 template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
273 inline T retagCodePtr(PtrType ptr, PtrTag oldTag, PtrTag newTag)
274 {
275     return bitwise_cast<T>(retagCodePtrImpl<PtrTagAction::DebugAssert>(ptr, oldTag, newTag));
276 }
277
278 template<typename T, PtrTag oldTag, PtrTag newTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
279 inline T retagCodePtr(PtrType ptr)
280 {
281     return bitwise_cast<T>(retagCodePtrImpl<PtrTagAction::DebugAssert>(ptr, oldTag, newTag));
282 }
283
284 template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
285 inline PtrType retagCodePtr(PtrType ptr, PtrTag oldTag, PtrTag newTag)
286 {
287     return retagCodePtrImpl<PtrTagAction::DebugAssert>(ptr, oldTag, newTag);
288 }
289
290 template<PtrTag oldTag, PtrTag newTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
291 inline PtrType retagCodePtr(PtrType ptr) { return retagCodePtr(ptr, oldTag, newTag); }
292
293 template<PtrTagAction tagAction, typename PtrType>
294 inline PtrType tagCFunctionPtrImpl(PtrType ptr, PtrTag tag)
295 {
296     if (!ptr)
297         return nullptr;
298     WTF_PTRTAG_ASSERT(tagAction, ptr, CFunctionPtrTag, removeCodePtrTag(ptr) == untagCodePtrImpl<PtrTagAction::NoAssert>(ptr, CFunctionPtrTag));
299     return retagCodePtrImpl<tagAction>(ptr, CFunctionPtrTag, tag);
300 }
301
302 template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
303 inline T tagCFunctionPtr(PtrType ptr, PtrTag tag)
304 {
305     return bitwise_cast<T>(tagCFunctionPtrImpl<PtrTagAction::DebugAssert>(ptr, tag));
306 }
307
308 template<typename T, PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
309 inline T tagCFunctionPtr(PtrType ptr)
310 {
311     return bitwise_cast<T>(tagCFunctionPtrImpl<PtrTagAction::DebugAssert>(ptr, tag));
312 }
313
314 template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
315 inline PtrType tagCFunctionPtr(PtrType ptr, PtrTag tag)
316 {
317     return tagCFunctionPtrImpl<PtrTagAction::DebugAssert>(ptr, tag);
318 }
319
320 template<PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
321 inline PtrType tagCFunctionPtr(PtrType ptr) { return tagCFunctionPtr(ptr, tag); }
322
323 template<PtrTagAction tagAction, typename PtrType>
324 inline PtrType untagCFunctionPtrImpl(PtrType ptr, PtrTag tag)
325 {
326     if (!ptr)
327         return nullptr;
328     WTF_PTRTAG_ASSERT(tagAction, ptr, tag, removeCodePtrTag(ptr) == untagCodePtrImpl<PtrTagAction::NoAssert>(ptr, tag));
329     return retagCodePtrImpl<tagAction>(ptr, tag, CFunctionPtrTag);
330 }
331
332 template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
333 inline T untagCFunctionPtr(PtrType ptr, PtrTag tag)
334 {
335     return bitwise_cast<T>(untagCFunctionPtrImpl<PtrTagAction::DebugAssert>(ptr, tag));
336 }
337
338 template<typename T, PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
339 inline T untagCFunctionPtr(PtrType ptr)
340 {
341     return bitwise_cast<T>(untagCFunctionPtrImpl<PtrTagAction::DebugAssert>(ptr, tag));
342 }
343
344 template<typename T, PtrTag tag, PtrTagAction tagAction, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
345 inline T untagCFunctionPtr(PtrType ptr)
346 {
347     return bitwise_cast<T>(untagCFunctionPtrImpl<tagAction>(ptr, tag));
348 }
349
350 template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
351 inline PtrType untagCFunctionPtr(PtrType ptr, PtrTag tag)
352 {
353     return untagCFunctionPtrImpl<PtrTagAction::DebugAssert>(ptr, tag);
354 }
355
356 template<PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
357 inline PtrType untagCFunctionPtr(PtrType ptr) { return untagCFunctionPtr(ptr, tag); }
358
359 template <typename IntType>
360 inline IntType tagInt(IntType ptrInt, PtrTag tag)
361 {
362     static_assert(sizeof(IntType) == sizeof(uintptr_t), "");
363     return bitwise_cast<IntType>(ptrauth_sign_unauthenticated(bitwise_cast<void*>(ptrInt), ptrauth_key_process_dependent_data, tag));
364 }
365
366 template<typename PtrType>
367 void assertIsCFunctionPtr(PtrType value)
368 {
369     void* ptr = bitwise_cast<void*>(value);
370     WTF_PTRTAG_ASSERT(PtrTagAction::ReleaseAssert, ptr, CFunctionPtrTag, untagCodePtrImpl<PtrTagAction::NoAssert>(ptr, CFunctionPtrTag) == removeCodePtrTag(ptr));
371 }
372
373 template<typename PtrType>
374 void assertIsNullOrCFunctionPtr(PtrType ptr)
375 {
376     if (ptr)
377         assertIsCFunctionPtr(ptr);
378 }
379
380 template<typename PtrType>
381 void assertIsNotTagged(PtrType value)
382 {
383     void* ptr = bitwise_cast<void*>(value);
384     WTF_PTRTAG_ASSERT(PtrTagAction::ReleaseAssert, ptr, NoPtrTag, ptr == removeCodePtrTag(ptr));
385 }
386
387 template<typename PtrType>
388 void assertIsTagged(PtrType value)
389 {
390     void* ptr = bitwise_cast<void*>(value);
391     WTF_PTRTAG_ASSERT(PtrTagAction::ReleaseAssert, ptr, AnyPtrTag, ptr != removeCodePtrTag(ptr));
392 }
393
394 template<typename PtrType>
395 void assertIsNullOrTagged(PtrType ptr)
396 {
397     if (ptr)
398         assertIsTagged(ptr);
399 }
400
401 template<typename PtrType>
402 bool isTaggedWith(PtrType value, PtrTag tag)
403 {
404     void* ptr = bitwise_cast<void*>(value);
405     if (tag == NoPtrTag)
406         return ptr == removeCodePtrTag(ptr);
407     return untagCodePtrImpl<PtrTagAction::NoAssert>(ptr, tag) == removeCodePtrTag(ptr);
408 }
409
410 template<typename PtrType>
411 void assertIsTaggedWith(PtrType value, PtrTag tag)
412 {
413     WTF_PTRTAG_ASSERT(PtrTagAction::ReleaseAssert, value, tag, isTaggedWith(value, tag));
414 }
415
416 template<typename PtrType>
417 void assertIsNullOrTaggedWith(PtrType ptr, PtrTag tag)
418 {
419     if (ptr)
420         assertIsTaggedWith(ptr, tag);
421 }
422
423 inline bool usesPointerTagging() { return true; }
424
425 #else // not CPU(ARM64E)
426
427 inline void registerPtrTagLookup(PtrTagLookup*) { }
428 inline void reportBadTag(const void*, PtrTag) { }
429
430 template<typename T>
431 inline T* tagArrayPtr(nullptr_t, size_t size)
432 {
433     ASSERT_UNUSED(size, !size);
434     return nullptr;
435 }
436
437 template<typename T>
438 inline T* tagArrayPtr(T* ptr, size_t)
439 {
440     return ptr;
441 }
442
443 template<typename T>
444 inline T* untagArrayPtr(T* ptr, size_t)
445 {
446     return ptr;
447 }
448
449 template<typename T>
450 inline T* removeArrayPtrTag(T* ptr)
451 {
452     return ptr;
453 }
454
455 template<typename T>
456 inline T* retagArrayPtr(T* ptr, size_t, size_t)
457 {
458     return ptr;
459 }
460
461
462 template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
463 constexpr T tagCodePtr(PtrType ptr, PtrTag) { return bitwise_cast<T>(ptr); }
464
465 template<typename T, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
466 inline T tagCodePtr(PtrType ptr) { return bitwise_cast<T>(ptr); }
467
468 template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
469 constexpr PtrType tagCodePtr(PtrType ptr, PtrTag) { return ptr; }
470
471 template<PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
472 inline PtrType tagCodePtr(PtrType ptr) { return ptr; }
473
474 template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
475 constexpr T untagCodePtr(PtrType ptr, PtrTag) { return bitwise_cast<T>(ptr); }
476
477 template<typename T, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
478 inline T untagCodePtr(PtrType ptr)  { return bitwise_cast<T>(ptr); }
479
480 template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
481 constexpr PtrType untagCodePtr(PtrType ptr, PtrTag) { return ptr; }
482
483 template<PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
484 inline PtrType untagCodePtr(PtrType ptr) { return ptr; }
485
486 template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
487 constexpr T retagCodePtr(PtrType ptr, PtrTag, PtrTag) { return bitwise_cast<T>(ptr); }
488
489 template<typename T, PtrTag, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
490 inline T retagCodePtr(PtrType ptr) { return bitwise_cast<T>(ptr); }
491
492 template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
493 constexpr PtrType retagCodePtr(PtrType ptr, PtrTag, PtrTag) { return ptr; }
494
495 template<PtrTag, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
496 inline PtrType retagCodePtr(PtrType ptr) { return ptr; }
497
498 template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
499 constexpr T removeCodePtrTag(PtrType ptr) { return bitwise_cast<T>(ptr); }
500
501 template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
502 constexpr PtrType removeCodePtrTag(PtrType ptr) { return ptr; }
503
504 template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
505 inline T tagCFunctionPtr(PtrType ptr, PtrTag) { return bitwise_cast<T>(ptr); }
506
507 template<typename T, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
508 inline T tagCFunctionPtr(PtrType ptr) { return bitwise_cast<T>(ptr); }
509
510 template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
511 inline PtrType tagCFunctionPtr(PtrType ptr, PtrTag) { return ptr; }
512
513 template<PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
514 inline PtrType tagCFunctionPtr(PtrType ptr) { return ptr; }
515
516 template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
517 inline T untagCFunctionPtr(PtrType ptr, PtrTag) { return bitwise_cast<T>(ptr); }
518
519 template<typename T, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
520 inline T untagCFunctionPtr(PtrType ptr) { return bitwise_cast<T>(ptr); }
521
522 template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
523 inline PtrType untagCFunctionPtr(PtrType ptr, PtrTag) { return ptr; }
524
525 template<PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
526 inline PtrType untagCFunctionPtr(PtrType ptr) { return ptr; }
527
528 template <typename IntType>
529 inline IntType tagInt(IntType ptrInt, PtrTag)
530 {
531     static_assert(sizeof(IntType) == sizeof(uintptr_t), "");
532     return ptrInt;
533 }
534
535 template<typename PtrType> void assertIsCFunctionPtr(PtrType) { }
536 template<typename PtrType> void assertIsNullOrCFunctionPtr(PtrType) { }
537
538 template<typename PtrType> void assertIsNotTagged(PtrType) { }
539 template<typename PtrType> void assertIsTagged(PtrType) { }
540 template<typename PtrType> void assertIsNullOrTagged(PtrType) { }
541
542 template<typename PtrType> bool isTaggedWith(PtrType, PtrTag) { return false; }
543
544 template<typename PtrType> void assertIsTaggedWith(PtrType, PtrTag) { }
545 template<typename PtrType> void assertIsNullOrTaggedWith(PtrType, PtrTag) { }
546
547 inline bool usesPointerTagging() { return false; }
548
549 #endif // CPU(ARM64E)
550
551 } // namespace WTF
552
553 using WTF::CFunctionPtrTag;
554 using WTF::NoPtrTag;
555 using WTF::PlatformRegistersLRPtrTag;
556 using WTF::PlatformRegistersPCPtrTag;
557 using WTF::PtrTag;
558
559 using WTF::reportBadTag;
560
561 using WTF::tagArrayPtr;
562 using WTF::untagArrayPtr;
563 using WTF::retagArrayPtr;
564 using WTF::removeArrayPtrTag;
565
566 using WTF::tagCodePtr;
567 using WTF::untagCodePtr;
568 using WTF::retagCodePtr;
569 using WTF::removeCodePtrTag;
570 using WTF::tagCFunctionPtr;
571 using WTF::untagCFunctionPtr;
572 using WTF::tagInt;
573
574 using WTF::assertIsCFunctionPtr;
575 using WTF::assertIsNullOrCFunctionPtr;
576 using WTF::assertIsNotTagged;
577 using WTF::assertIsTagged;
578 using WTF::assertIsNullOrTagged;
579 using WTF::isTaggedWith;
580 using WTF::assertIsTaggedWith;
581 using WTF::assertIsNullOrTaggedWith;
582 using WTF::usesPointerTagging;