1 
2 module traits_getPointerBitmap;
3 
4 import core.stdc.stdio;
5 
6 // version = RTInfo;
7 // debug = LOG;
8 
9 version(RTInfo)
10     import gc.rtinfo;
11 else
12     enum bool RTInfoMark__Monitor = false; // is __monitor GC allocated?
13 
14 
15 enum bytesPerPtr = (size_t.sizeof);
16 enum bytesPerBitmapWord = bytesPerPtr * bytesPerPtr * 8;
17 
18 template allocatedSize(T)
19 {
20     static if (is (T == class))
21         enum allocatedSize = __traits(classInstanceSize, T);
22     else
23         enum allocatedSize = T.sizeof;
24 }
25 
26 bool testBit(const(size_t)* p, size_t biti)
27 {
28     enum BITS_SHIFT = (size_t.sizeof == 8 ? 6 : 5);
29     enum BITS_MASK = (bytesPerPtr - 1);
30 
31     return (p[biti >> BITS_SHIFT] & (1 << (biti & BITS_MASK))) != 0;
32 }
33 
34 void __testType(T)(size_t[] expected)
35 {
36     // check compile time info
37     enum bits  = (T.sizeof + bytesPerPtr - 1) / bytesPerPtr;
38     enum words = (T.sizeof + bytesPerBitmapWord - 1) / bytesPerBitmapWord;
39     version(RTInfo)
40         enum info = RTInfoImpl2!(Unqual!T); // we want the array, not the pointer
41     else
42         enum info = __traits(getPointerBitmap,T); // we want the array, not the pointer
43 
44     debug(LOG) writef("%-20s:", T.stringof);
45     debug(LOG) writef(" CT:%s", info);
46     debug(LOG) writef(" EXP:%d %s", allocatedSize!T, expected);
47     assert(info[0] == allocatedSize!T);
48     assert(info[1..$] == expected);
49     assert(words == expected.length);
50 
51     debug(LOG) writeln();
52 }
53 
54 ///////////////////////////////////////
55 struct S(T, aliasTo = void)
56 {
57     static if(!is(aliasTo == void))
58     {
59         aliasTo a;
60         alias a this;
61     }
62 
63     size_t x;
64     T t = void;
65     void* p;
66 
67 }
68 
69 template tOff(T)
70 {
71     enum tOff = T.t.offsetof / bytesPerPtr;
72 }
73 
74 template pOff(T)
75 {
76     enum pOff = T.p.offsetof / bytesPerPtr;
77 }
78 
79 class C(T, aliasTo = void)
80 {
81     static if(!is(aliasTo == void))
82     {
83         aliasTo a;
84         alias a this;
85     }
86 
87     size_t x;
88     T t = void;
89     void* p;
90 }
91 
92 ///////////////////////////////////////
93 
94 void _testType(T)(size_t[] expected)
95 {
96     __testType!(T)(expected);
97     __testType!(const(T))(expected);
98     __testType!(immutable(T))(expected);
99     version(RTInfo) {} else // Unqual does not work with shared(T[N])
100         __testType!(shared(T))(expected);
101 }
102 
103 void testType(T)(size_t[] expected)
104 {
105     _testType!(T)(expected);
106 
107     // generate bit pattern for S!T
108     assert(expected.length == 1);
109     size_t[] sexp;
110 
111     sexp ~= (expected[0] << tOff!(S!T)) | (1 << pOff!((S!T)));
112     _testType!(S!T)(sexp);
113 
114     // prepend Object
115     sexp[0] = (expected[0] << tOff!(S!(T, Object))) | (1 << pOff!(S!(T, Object))) | 1;
116     _testType!(S!(T, Object))(sexp);
117 
118     // prepend string
119     sexp[0] = (expected[0] << tOff!(S!(T, string))) | (1 << pOff!(S!(T, string))) | 2; // arr ptr
120     _testType!(S!(T, string))(sexp);
121 
122     // generate bit pattern for C!T
123     C!T ct = null;
124     size_t mutexBit = (RTInfoMark__Monitor ? 2 : 0);
125     size_t ctpOff = ct.p.offsetof / bytesPerPtr;
126     size_t cttOff = ct.t.offsetof / bytesPerPtr;
127     sexp[0] = (expected[0] << cttOff) | (1 << ctpOff) | mutexBit;
128     _testType!(C!(T))(sexp);
129 
130     C!(T, string) cts = null;
131     size_t ctspOff = cts.p.offsetof / bytesPerPtr;
132     size_t ctstOff = cts.t.offsetof / bytesPerPtr;
133     // generate bit pattern for C!T
134     sexp[0] = (expected[0] << ctstOff) | (1 << ctspOff) | mutexBit | 0b1000; // arr ptr
135     _testType!(C!(T, string))(sexp);
136 }
137 
138 ///////////////////////////////////////
139 alias void[2*size_t.sizeof] void2;
140 alias size_t[3] int3;
141 alias size_t*[3] pint3;
142 alias string[3] sint3;
143 alias string[3][2] sint3_2;
144 alias int delegate() dg;
145 alias int function() fn;
146 alias typeof(null) NullType;
147 
148 // span multiple bitmap elements
149 struct Large
150 {
151     size_t[30] data1;
152     void* p1;
153     size_t[1] val1;
154 
155     size_t[28] data2;
156     void* p2;
157     size_t[3] val2;
158 
159     size_t[16] data3;
160     void* p3;
161     size_t[15] val3;
162 }
163 
164 class N
165 {
166     struct Nested
167     {
168         // no outer for structs
169         size_t x;
170         void* p1;
171         Large* s;
172 
173         void foo() {} // need member fnction to not be POD
174     }
175     class CNested
176     {
177         // implicit vtptr,monitor
178         size_t x;
179         void* p1;
180         size_t y;
181         // implicit outer
182     }
183     class CNestedDerived : CNested
184     {
185         size_t[3] z;
186         void* p;
187     }
188 }
189 
190 union U
191 {
192     size_t[4] data;
193     Large*[] arr; // { length, ptr }
194 
195     struct
196     {
197         size_t d1;
198         size_t d2;
199         size_t d3;
200         void* p;
201     }
202 }
203 
204 void testRTInfo()
205 {
206     testType!(bool)         ([ 0b0 ]);
207     testType!(ubyte)        ([ 0b0 ]);
208     testType!(short)        ([ 0b0 ]);
209     testType!(int)          ([ 0b0 ]);
210     testType!(long)         ([ 0b00 ]);
211     testType!(double)       ([ 0b00 ]);
212     testType!(ifloat)       ([ 0b0 ]);
213     testType!(cdouble)      ([ 0b0000 ]);
214     testType!(dg)           ([ 0b01 ]);
215     testType!(fn)           ([ 0b0 ]);
216     testType!(S!fn)         ([ 0b100 ]);
217     testType!(NullType)     ([ 0b0 ]);
218     version(D_LP64)
219         testType!(__vector(float[4]))  ([ 0b00 ]);
220 
221     testType!(Object[int])       ([ 0b1 ]);
222     testType!(Object[])       ([ 0b10 ]);
223     testType!(string)         ([ 0b10 ]);
224 
225     testType!(int3)           ([ 0b000 ]);
226     testType!(pint3)          ([ 0b111 ]);
227     testType!(sint3)          ([ 0b101010 ]);
228     testType!(sint3_2)        ([ 0b101010101010 ]);
229     testType!(void2)          ([ 0b11 ]);
230     testType!(U)              ([ 0b1010 ]);
231 
232     version(D_LP64)
233         _testType!(Large)          ([ 0x1000_0000__4000_0000, 0x0001_0000 ]);
234     else
235         _testType!(Large)          ([ 0x4000_0000, 0x1000_0000, 0x0001_0000 ]);
236 
237     _testType!(N.CNested)     ([ 0b101000 ]);
238     _testType!(N.CNestedDerived) ([ 0b1000101000 ]);
239 
240     testType!(N.Nested)       ([ 0b110 ]);
241 
242     struct SFNested
243     {
244         size_t[2] d;
245         void* p1;
246         fn f;
247         // implicite outer
248 
249         void foo() {} // need member fnction to not be POD
250     }
251 
252     class CFNested
253     {
254         // implicit vtptr,monitor
255         size_t[2] d;
256         void* p1;
257         // implicite outer
258     }
259 
260     testType!(SFNested)      ([ 0b10100 ]);
261     _testType!(CFNested)     ([ 0b110000 ]);
262 }
263 
264 void main()
265 {
266     testRTInfo();
267 }