1 /*
2  * This file is part of the Yices SMT Solver.
3  * Copyright (C) 2017 SRI International.
4  *
5  * Yices is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * Yices is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Yices.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef __TAGGED_POINTERS_H
20 #define __TAGGED_POINTERS_H
21 
22 #include <stdbool.h>
23 #include <assert.h>
24 #include <stdint.h>
25 
26 /*
27  * First version: 2bit tags are stored in the two low-order bits
28  * of (void *) pointers.
29  */
30 #define PTR_TAG_MASK ((uintptr_t) 0x3)
31 
32 // get the tag of pointer p
ptr_tag(void * p)33 static inline uint32_t ptr_tag(void *p) {
34   return ((uintptr_t) p) & PTR_TAG_MASK;
35 }
36 
37 // untag the pointer
untag_ptr(void * p)38 static inline void *untag_ptr(void *p) {
39   return (void*)(((uintptr_t) p) & ~PTR_TAG_MASK);
40 }
41 
42 // add tag to pointer p
tag_ptr(void * p,uint32_t tag)43 static inline void *tag_ptr(void *p, uint32_t tag) {
44   assert((tag & ~PTR_TAG_MASK) == 0 && ptr_tag(p) == 0);
45   return (void *) (((uintptr_t) p) | (uintptr_t) tag);
46 }
47 
48 
49 /*
50  * Second version: void *p stores either a pointer
51  * or a 31 bit integer. The tag is the low-order bit
52  * - for an integer, the tag is 1
53  * - for a pointer, the tag is 0
54  */
55 #define IPTR_TAG_MASK ((uintptr_t) 1)
56 
57 // check whether p is a pointer or an int
has_int_tag(void * p)58 static inline bool has_int_tag(void *p) {
59   return (((uintptr_t) p) & IPTR_TAG_MASK);
60 }
61 
62 // extract the integer from p (as a signed integer)
untag_i32(void * p)63 static inline int32_t untag_i32(void *p) {
64   assert(has_int_tag(p));
65   return ((int32_t) ((uintptr_t) p)) >> 1;
66 }
67 
68 // extract an unsigned integer from p
untag_u32(void * p)69 static inline uint32_t untag_u32(void *p) {
70   assert(has_int_tag(p));
71   return ((uint32_t)((uintptr_t) p)) >> 1;
72 }
73 
74 // pack x into a void * pointer and add the tag
tag_i32(int32_t x)75 static inline void *tag_i32(int32_t x) {
76   return (void *) ((uintptr_t)((uint32_t)((x << 1)|1)));
77 }
78 
79 // same thing for an unsigned integer x
tag_u32(uint32_t x)80 static inline void *tag_u32(uint32_t x) {
81   return (void *) ((uintptr_t)((x << 1)|1));
82 }
83 
84 
85 #endif /* __TAGGED_POINTERS_H */
86