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
31namespace 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
47enum 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
57template<size_t N>
58constexpr 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
73static_assert(static_cast<uintptr_t>(NoPtrTag) == static_cast<uintptr_t>(0), "");
74static_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
81FOR_EACH_ADDITIONAL_WTF_PTRTAG(WTF_DECLARE_PTRTAG)
82
83#if COMPILER(MSVC)
84#pragma warning(pop)
85#endif
86
87struct PtrTagLookup {
88 const char* (*tagForPtr)(const void*);
89 const char* (*ptrTagName)(PtrTag);
90 PtrTagLookup* next { nullptr };
91};
92
93#if CPU(ARM64E)
94
95enum class PtrTagAction {
96 ReleaseAssert,
97 DebugAssert,
98 NoAssert,
99};
100
101constexpr PtrTag AnyPtrTag = static_cast<PtrTag>(-1); // Only used for assertion messages.
102
103WTF_EXPORT_PRIVATE void registerPtrTagLookup(PtrTagLookup*);
104WTF_EXPORT_PRIVATE void reportBadTag(const void*, PtrTag expectedTag);
105
106#if ASSERT_DISABLED
107constexpr bool enablePtrTagDebugAssert = false;
108#else
109constexpr 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
125template<typename T>
126inline T* tagArrayPtr(std::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
133template<typename T>
134inline T* tagArrayPtr(T* ptr, size_t length)
135{
136 return ptrauth_sign_unauthenticated(ptr, ptrauth_key_process_dependent_data, length);
137}
138
139template<typename T>
140inline T* untagArrayPtr(T* ptr, size_t length)
141{
142 return ptrauth_auth_data(ptr, ptrauth_key_process_dependent_data, length);
143}
144
145template<typename T>
146inline T* removeArrayPtrTag(T* ptr)
147{
148 return ptrauth_strip(ptr, ptrauth_key_process_dependent_data);
149}
150
151template<typename T>
152inline 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
157template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
158inline constexpr T removeCodePtrTag(PtrType ptr)
159{
160 return bitwise_cast<T>(ptrauth_strip(ptr, ptrauth_key_process_dependent_code));
161}
162
163template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
164inline constexpr PtrType removeCodePtrTag(PtrType ptr)
165{
166 return ptrauth_strip(ptr, ptrauth_key_process_dependent_code);
167}
168
169template<PtrTagAction tagAction, typename PtrType>
170inline 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
182template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
183inline T tagCodePtr(PtrType ptr, PtrTag tag)
184{
185 return bitwise_cast<T>(tagCodePtrImpl<PtrTagAction::DebugAssert>(ptr, tag));
186}
187
188template<typename T, PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
189inline T tagCodePtr(PtrType ptr)
190{
191 return bitwise_cast<T>(tagCodePtrImpl<PtrTagAction::DebugAssert>(ptr, tag));
192}
193
194template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
195inline PtrType tagCodePtr(PtrType ptr, PtrTag tag)
196{
197 return tagCodePtrImpl<PtrTagAction::DebugAssert>(ptr, tag);
198}
199
200template<PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
201inline PtrType tagCodePtr(PtrType ptr) { return tagCodePtr(ptr, tag); }
202
203template<typename PtrType>
204inline 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
213template<PtrTagAction tagAction, typename PtrType>
214inline 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
223template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
224inline T untagCodePtr(PtrType ptr, PtrTag tag)
225{
226 return bitwise_cast<T>(untagCodePtrImpl<PtrTagAction::ReleaseAssert>(ptr, tag));
227}
228
229template<typename T, PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
230inline T untagCodePtr(PtrType ptr)
231{
232 return bitwise_cast<T>(untagCodePtrImpl<PtrTagAction::ReleaseAssert>(ptr, tag));
233}
234
235template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
236inline PtrType untagCodePtr(PtrType ptr, PtrTag tag)
237{
238 return untagCodePtrImpl<PtrTagAction::ReleaseAssert>(ptr, tag);
239}
240
241template<PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
242inline PtrType untagCodePtr(PtrType ptr) { return untagCodePtr(ptr, tag); }
243
244template<PtrTagAction tagAction, typename PtrType>
245inline 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
260template<PtrTagAction tagAction, typename PtrType>
261inline 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
272template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
273inline T retagCodePtr(PtrType ptr, PtrTag oldTag, PtrTag newTag)
274{
275 return bitwise_cast<T>(retagCodePtrImpl<PtrTagAction::DebugAssert>(ptr, oldTag, newTag));
276}
277
278template<typename T, PtrTag oldTag, PtrTag newTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
279inline T retagCodePtr(PtrType ptr)
280{
281 return bitwise_cast<T>(retagCodePtrImpl<PtrTagAction::DebugAssert>(ptr, oldTag, newTag));
282}
283
284template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
285inline PtrType retagCodePtr(PtrType ptr, PtrTag oldTag, PtrTag newTag)
286{
287 return retagCodePtrImpl<PtrTagAction::DebugAssert>(ptr, oldTag, newTag);
288}
289
290template<PtrTag oldTag, PtrTag newTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
291inline PtrType retagCodePtr(PtrType ptr) { return retagCodePtr(ptr, oldTag, newTag); }
292
293template<PtrTagAction tagAction, typename PtrType>
294inline 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
302template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
303inline T tagCFunctionPtr(PtrType ptr, PtrTag tag)
304{
305 return bitwise_cast<T>(tagCFunctionPtrImpl<PtrTagAction::DebugAssert>(ptr, tag));
306}
307
308template<typename T, PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
309inline T tagCFunctionPtr(PtrType ptr)
310{
311 return bitwise_cast<T>(tagCFunctionPtrImpl<PtrTagAction::DebugAssert>(ptr, tag));
312}
313
314template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
315inline PtrType tagCFunctionPtr(PtrType ptr, PtrTag tag)
316{
317 return tagCFunctionPtrImpl<PtrTagAction::DebugAssert>(ptr, tag);
318}
319
320template<PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
321inline PtrType tagCFunctionPtr(PtrType ptr) { return tagCFunctionPtr(ptr, tag); }
322
323template<PtrTagAction tagAction, typename PtrType>
324inline 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
332template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
333inline T untagCFunctionPtr(PtrType ptr, PtrTag tag)
334{
335 return bitwise_cast<T>(untagCFunctionPtrImpl<PtrTagAction::DebugAssert>(ptr, tag));
336}
337
338template<typename T, PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
339inline T untagCFunctionPtr(PtrType ptr)
340{
341 return bitwise_cast<T>(untagCFunctionPtrImpl<PtrTagAction::DebugAssert>(ptr, tag));
342}
343
344template<typename T, PtrTag tag, PtrTagAction tagAction, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
345inline T untagCFunctionPtr(PtrType ptr)
346{
347 return bitwise_cast<T>(untagCFunctionPtrImpl<tagAction>(ptr, tag));
348}
349
350template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
351inline PtrType untagCFunctionPtr(PtrType ptr, PtrTag tag)
352{
353 return untagCFunctionPtrImpl<PtrTagAction::DebugAssert>(ptr, tag);
354}
355
356template<PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
357inline PtrType untagCFunctionPtr(PtrType ptr) { return untagCFunctionPtr(ptr, tag); }
358
359template <typename IntType>
360inline 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
366template<typename PtrType>
367void 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
373template<typename PtrType>
374void assertIsNullOrCFunctionPtr(PtrType ptr)
375{
376 if (ptr)
377 assertIsCFunctionPtr(ptr);
378}
379
380template<typename PtrType>
381void assertIsNotTagged(PtrType value)
382{
383 void* ptr = bitwise_cast<void*>(value);
384 WTF_PTRTAG_ASSERT(PtrTagAction::ReleaseAssert, ptr, NoPtrTag, ptr == removeCodePtrTag(ptr));
385}
386
387template<typename PtrType>
388void assertIsTagged(PtrType value)
389{
390 void* ptr = bitwise_cast<void*>(value);
391 WTF_PTRTAG_ASSERT(PtrTagAction::ReleaseAssert, ptr, AnyPtrTag, ptr != removeCodePtrTag(ptr));
392}
393
394template<typename PtrType>
395void assertIsNullOrTagged(PtrType ptr)
396{
397 if (ptr)
398 assertIsTagged(ptr);
399}
400
401template<typename PtrType>
402bool 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
410template<typename PtrType>
411void assertIsTaggedWith(PtrType value, PtrTag tag)
412{
413 WTF_PTRTAG_ASSERT(PtrTagAction::ReleaseAssert, value, tag, isTaggedWith(value, tag));
414}
415
416template<typename PtrType>
417void assertIsNullOrTaggedWith(PtrType ptr, PtrTag tag)
418{
419 if (ptr)
420 assertIsTaggedWith(ptr, tag);
421}
422
423inline bool usesPointerTagging() { return true; }
424
425#else // not CPU(ARM64E)
426
427inline void registerPtrTagLookup(PtrTagLookup*) { }
428inline void reportBadTag(const void*, PtrTag) { }
429
430template<typename T>
431inline T* tagArrayPtr(std::nullptr_t, size_t size)
432{
433 ASSERT_UNUSED(size, !size);
434 return nullptr;
435}
436
437template<typename T>
438inline T* tagArrayPtr(T* ptr, size_t)
439{
440 return ptr;
441}
442
443template<typename T>
444inline T* untagArrayPtr(T* ptr, size_t)
445{
446 return ptr;
447}
448
449template<typename T>
450inline T* removeArrayPtrTag(T* ptr)
451{
452 return ptr;
453}
454
455template<typename T>
456inline T* retagArrayPtr(T* ptr, size_t, size_t)
457{
458 return ptr;
459}
460
461
462template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
463constexpr T tagCodePtr(PtrType ptr, PtrTag) { return bitwise_cast<T>(ptr); }
464
465template<typename T, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
466inline T tagCodePtr(PtrType ptr) { return bitwise_cast<T>(ptr); }
467
468template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
469constexpr PtrType tagCodePtr(PtrType ptr, PtrTag) { return ptr; }
470
471template<PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
472inline PtrType tagCodePtr(PtrType ptr) { return ptr; }
473
474template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
475constexpr T untagCodePtr(PtrType ptr, PtrTag) { return bitwise_cast<T>(ptr); }
476
477template<typename T, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
478inline T untagCodePtr(PtrType ptr) { return bitwise_cast<T>(ptr); }
479
480template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
481constexpr PtrType untagCodePtr(PtrType ptr, PtrTag) { return ptr; }
482
483template<PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
484inline PtrType untagCodePtr(PtrType ptr) { return ptr; }
485
486template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
487constexpr T retagCodePtr(PtrType ptr, PtrTag, PtrTag) { return bitwise_cast<T>(ptr); }
488
489template<typename T, PtrTag, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
490inline T retagCodePtr(PtrType ptr) { return bitwise_cast<T>(ptr); }
491
492template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
493constexpr PtrType retagCodePtr(PtrType ptr, PtrTag, PtrTag) { return ptr; }
494
495template<PtrTag, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
496inline PtrType retagCodePtr(PtrType ptr) { return ptr; }
497
498template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
499constexpr T removeCodePtrTag(PtrType ptr) { return bitwise_cast<T>(ptr); }
500
501template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
502constexpr PtrType removeCodePtrTag(PtrType ptr) { return ptr; }
503
504template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
505inline T tagCFunctionPtr(PtrType ptr, PtrTag) { return bitwise_cast<T>(ptr); }
506
507template<typename T, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
508inline T tagCFunctionPtr(PtrType ptr) { return bitwise_cast<T>(ptr); }
509
510template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
511inline PtrType tagCFunctionPtr(PtrType ptr, PtrTag) { return ptr; }
512
513template<PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
514inline PtrType tagCFunctionPtr(PtrType ptr) { return ptr; }
515
516template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
517inline T untagCFunctionPtr(PtrType ptr, PtrTag) { return bitwise_cast<T>(ptr); }
518
519template<typename T, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
520inline T untagCFunctionPtr(PtrType ptr) { return bitwise_cast<T>(ptr); }
521
522template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
523inline PtrType untagCFunctionPtr(PtrType ptr, PtrTag) { return ptr; }
524
525template<PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
526inline PtrType untagCFunctionPtr(PtrType ptr) { return ptr; }
527
528template <typename IntType>
529inline IntType tagInt(IntType ptrInt, PtrTag)
530{
531 static_assert(sizeof(IntType) == sizeof(uintptr_t), "");
532 return ptrInt;
533}
534
535template<typename PtrType> void assertIsCFunctionPtr(PtrType) { }
536template<typename PtrType> void assertIsNullOrCFunctionPtr(PtrType) { }
537
538template<typename PtrType> void assertIsNotTagged(PtrType) { }
539template<typename PtrType> void assertIsTagged(PtrType) { }
540template<typename PtrType> void assertIsNullOrTagged(PtrType) { }
541
542template<typename PtrType> bool isTaggedWith(PtrType, PtrTag) { return false; }
543
544template<typename PtrType> void assertIsTaggedWith(PtrType, PtrTag) { }
545template<typename PtrType> void assertIsNullOrTaggedWith(PtrType, PtrTag) { }
546
547inline bool usesPointerTagging() { return false; }
548
549#endif // CPU(ARM64E)
550
551} // namespace WTF
552
553using WTF::CFunctionPtrTag;
554using WTF::NoPtrTag;
555using WTF::PlatformRegistersLRPtrTag;
556using WTF::PlatformRegistersPCPtrTag;
557using WTF::PtrTag;
558
559using WTF::reportBadTag;
560
561using WTF::tagArrayPtr;
562using WTF::untagArrayPtr;
563using WTF::retagArrayPtr;
564using WTF::removeArrayPtrTag;
565
566using WTF::tagCodePtr;
567using WTF::untagCodePtr;
568using WTF::retagCodePtr;
569using WTF::removeCodePtrTag;
570using WTF::tagCFunctionPtr;
571using WTF::untagCFunctionPtr;
572using WTF::tagInt;
573
574using WTF::assertIsCFunctionPtr;
575using WTF::assertIsNullOrCFunctionPtr;
576using WTF::assertIsNotTagged;
577using WTF::assertIsTagged;
578using WTF::assertIsNullOrTagged;
579using WTF::isTaggedWith;
580using WTF::assertIsTaggedWith;
581using WTF::assertIsNullOrTaggedWith;
582using WTF::usesPointerTagging;
583