1 /**
2  * Compiler implementation of the
3  * $(LINK2 http://www.dlang.org, D programming language).
4  *
5  * Simple bit vector implementation.
6  *
7  * Copyright:   Copyright (C) 2013-2021 by The D Language Foundation, All Rights Reserved
8  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
9  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
10  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/dvec.d, backend/dvec.d)
11  */
12 
13 module dmd.backend.dvec;
14 
15 import core.stdc.stdio;
16 import core.stdc.stdlib;
17 import core.stdc.string;
18 
19 import core.bitop;
20 
21 extern (C):
22 
23 nothrow:
24 @nogc:
25 
26 alias vec_base_t = size_t;                     // base type of vector
27 alias vec_t = vec_base_t*;
28 
29 enum VECBITS = vec_base_t.sizeof * 8;        // # of bits per entry
30 enum VECMASK = VECBITS - 1;                  // mask for bit position
31 enum VECSHIFT = (VECBITS == 16) ? 4 : (VECBITS == 32 ? 5 : 6);   // # of bits in VECMASK
32 
33 static assert(vec_base_t.sizeof == 2 && VECSHIFT == 4 ||
34               vec_base_t.sizeof == 4 && VECSHIFT == 5 ||
35               vec_base_t.sizeof == 8 && VECSHIFT == 6);
36 
37 struct VecGlobal
38 {
39     int count;           // # of vectors allocated
40     int initcount;       // # of times package is initialized
41     vec_t[30] freelist;  // free lists indexed by dim
42 
43   nothrow:
44   @nogc:
45 
46     void initialize()
47     {
48         if (initcount++ == 0)
49             count = 0;
50     }
51 
52     void terminate()
53     {
54         if (--initcount == 0)
55         {
56             debug
57             {
58                 if (count != 0)
59                 {
60                     printf("vecGlobal.count = %d\n", count);
61                     assert(0);
62                 }
63             }
64             else
65                 assert(count == 0);
66 
67             foreach (size_t i; 0 .. freelist.length)
68             {
69                 void **vn;
70                 for (void** v = cast(void **)freelist[i]; v; v = vn)
71                 {
72                     vn = cast(void **)(*v);
73                     //mem_free(v);
74                     .free(v);
75                 }
76                 freelist[i] = null;
77             }
78         }
79     }
80 
81     vec_t allocate(size_t numbits)
82     {
83         if (numbits == 0)
84             return cast(vec_t) null;
85         const dim = (numbits + (VECBITS - 1)) >> VECSHIFT;
86         vec_t v;
87         if (dim < freelist.length && (v = freelist[dim]) != null)
88         {
89             freelist[dim] = *cast(vec_t *)v;
90             v += 2;
91             switch (dim)
92             {
93                 case 5:     v[4] = 0;  goto case 4;
94                 case 4:     v[3] = 0;  goto case 3;
95                 case 3:     v[2] = 0;  goto case 2;
96                 case 2:     v[1] = 0;  goto case 1;
97                 case 1:     v[0] = 0;
98                             break;
99                 default:    memset(v,0,dim * vec_base_t.sizeof);
100                             break;
101             }
102             goto L1;
103         }
104         else
105         {
106             v = cast(vec_t) calloc(dim + 2, vec_base_t.sizeof);
107             assert(v);
108         }
109         if (v)
110         {
111             v += 2;
112         L1:
113             vec_dim(v) = dim;
114             vec_numbits(v) = numbits;
115             /*printf("vec_calloc(%d): v = %p vec_numbits = %d vec_dim = %d\n",
116                 numbits,v,vec_numbits(v),vec_dim(v));*/
117             count++;
118         }
119         return v;
120     }
121 
122     vec_t dup(const vec_t v)
123     {
124         if (!v)
125             return null;
126 
127         const dim = vec_dim(v);
128         const nbytes = (dim + 2) * vec_base_t.sizeof;
129         vec_t vc;
130         vec_t result;
131         if (dim < freelist.length && (vc = freelist[dim]) != null)
132         {
133             freelist[dim] = *cast(vec_t *)vc;
134             goto L1;
135         }
136         else
137         {
138             vc = cast(vec_t) calloc(nbytes, 1);
139             assert(vc);
140         }
141         if (vc)
142         {
143           L1:
144             memcpy(vc,v - 2,nbytes);
145             count++;
146             result = vc + 2;
147         }
148         else
149             result = null;
150         return result;
151     }
152 
153     void free(vec_t v)
154     {
155         /*printf("vec_free(%p)\n",v);*/
156         if (v)
157         {
158             const dim = vec_dim(v);
159             v -= 2;
160             if (dim < freelist.length)
161             {
162                 *cast(vec_t *)v = freelist[dim];
163                 freelist[dim] = v;
164             }
165             else
166                 .free(v);
167             count--;
168         }
169     }
170 
171 }
172 
173 __gshared VecGlobal vecGlobal;
174 
175 private pure vec_base_t MASK(uint b) { return cast(vec_base_t)1 << (b & VECMASK); }
176 
177 pure ref inout(vec_base_t) vec_numbits(inout vec_t v) { return v[-1]; }
178 pure ref inout(vec_base_t) vec_dim(inout vec_t v) { return v[-2]; }
179 
180 /**************************
181  * Initialize package.
182  */
183 
184 void vec_init()
185 {
186     vecGlobal.initialize();
187 }
188 
189 
190 /**************************
191  * Terminate package.
192  */
193 
194 void vec_term()
195 {
196     vecGlobal.terminate();
197 }
198 
199 /********************************
200  * Allocate a vector given # of bits in it.
201  * Clear the vector.
202  */
203 
204 vec_t vec_calloc(size_t numbits)
205 {
206     return vecGlobal.allocate(numbits);
207 }
208 
209 /********************************
210  * Allocate copy of existing vector.
211  */
212 
213 vec_t vec_clone(const vec_t v)
214 {
215     return vecGlobal.dup(v);
216 }
217 
218 /**************************
219  * Free a vector.
220  */
221 
222 void vec_free(vec_t v)
223 {
224     /*printf("vec_free(%p)\n",v);*/
225     return vecGlobal.free(v);
226 }
227 
228 /**************************
229  * Realloc a vector to have numbits bits in it.
230  * Extra bits are set to 0.
231  */
232 
233 vec_t vec_realloc(vec_t v, size_t numbits)
234 {
235     /*printf("vec_realloc(%p,%d)\n",v,numbits);*/
236     if (!v)
237         return vec_calloc(numbits);
238     if (!numbits)
239     {   vec_free(v);
240         return null;
241     }
242     const vbits = vec_numbits(v);
243     if (numbits == vbits)
244         return v;
245     vec_t newv = vec_calloc(numbits);
246     if (newv)
247     {
248         const nbytes = (vec_dim(v) < vec_dim(newv)) ? vec_dim(v) : vec_dim(newv);
249         memcpy(newv,v,nbytes * vec_base_t.sizeof);
250         vec_clearextrabits(newv);
251     }
252     vec_free(v);
253     return newv;
254 }
255 
256 /********************************
257  * Recycle a vector `v` to a new size `numbits`, clear all bits.
258  * Re-uses original if possible.
259  */
260 void vec_recycle(ref vec_t v, size_t numbits)
261 {
262     vec_free(v);
263     v = vec_calloc(numbits);
264 }
265 
266 
267 /**************************
268  * Set bit b in vector v.
269  */
270 
271 pure
272 void vec_setbit(size_t b, vec_t v)
273 {
274     debug
275     {
276         if (!(v && b < vec_numbits(v)))
277             printf("vec_setbit(v = %p,b = %d): numbits = %d dim = %d\n",
278                 v, cast(int) b, cast(int) (v ? vec_numbits(v) : 0), cast(int) (v ? vec_dim(v) : 0));
279     }
280     assert(v && b < vec_numbits(v));
281     core.bitop.bts(v, b);
282 }
283 
284 /**************************
285  * Clear bit b in vector v.
286  */
287 
288 pure
289 void vec_clearbit(size_t b, vec_t v)
290 {
291     assert(v && b < vec_numbits(v));
292     core.bitop.btr(v, b);
293 }
294 
295 /**************************
296  * Test bit b in vector v.
297  */
298 
299 pure
300 size_t vec_testbit(size_t b, const vec_t v)
301 {
302     if (!v)
303         return 0;
304     debug
305     {
306         if (!(v && b < vec_numbits(v)))
307             printf("vec_setbit(v = %p,b = %d): numbits = %d dim = %d\n",
308                 v, cast(int) b, cast(int) (v ? vec_numbits(v) : 0), cast(int) (v ? vec_dim(v) : 0));
309     }
310     assert(v && b < vec_numbits(v));
311     return core.bitop.bt(v, b);
312 }
313 
314 /********************************
315  * Find first set bit starting from b in vector v.
316  * If no bit is found, return vec_numbits(v).
317  */
318 
319 pure
320 size_t vec_index(size_t b, const vec_t vec)
321 {
322     if (!vec)
323         return 0;
324     const(vec_base_t)* v = vec;
325     if (b < vec_numbits(v))
326     {
327         const vtop = &vec[vec_dim(v)];
328         const bit = b & VECMASK;
329         if (bit != b)                   // if not starting in first word
330             v += b >> VECSHIFT;
331         size_t starv = *v >> bit;
332         while (1)
333         {
334             while (starv)
335             {
336                 if (starv & 1)
337                     return b;
338                 b++;
339                 starv >>= 1;
340             }
341             b = (b + VECBITS) & ~VECMASK;   // round up to next word
342             if (++v >= vtop)
343                 break;
344             starv = *v;
345         }
346     }
347     return vec_numbits(vec);
348 }
349 
350 /********************************
351  * Compute v1 &= v2.
352  */
353 
354 pure
355 void vec_andass(vec_t v1, const(vec_base_t)* v2)
356 {
357     if (v1)
358     {
359         assert(v2);
360         assert(vec_numbits(v1)==vec_numbits(v2));
361         const vtop = &v1[vec_dim(v1)];
362         for (; v1 < vtop; v1++,v2++)
363             *v1 &= *v2;
364     }
365     else
366         assert(!v2);
367 }
368 
369 /********************************
370  * Compute v1 = v2 & v3.
371  */
372 
373 pure
374 void vec_and(vec_t v1, const(vec_base_t)* v2, const(vec_base_t)* v3)
375 {
376     if (v1)
377     {
378         assert(v2 && v3);
379         assert(vec_numbits(v1)==vec_numbits(v2) && vec_numbits(v1)==vec_numbits(v3));
380         const vtop = &v1[vec_dim(v1)];
381         for (; v1 < vtop; v1++,v2++,v3++)
382             *v1 = *v2 & *v3;
383     }
384     else
385         assert(!v2 && !v3);
386 }
387 
388 /********************************
389  * Compute v1 ^= v2.
390  */
391 
392 pure
393 void vec_xorass(vec_t v1, const(vec_base_t)* v2)
394 {
395     if (v1)
396     {
397         assert(v2);
398         assert(vec_numbits(v1)==vec_numbits(v2));
399         const vtop = &v1[vec_dim(v1)];
400         for (; v1 < vtop; v1++,v2++)
401             *v1 ^= *v2;
402     }
403     else
404         assert(!v2);
405 }
406 
407 /********************************
408  * Compute v1 = v2 ^ v3.
409  */
410 
411 pure
412 void vec_xor(vec_t v1, const(vec_base_t)* v2, const(vec_base_t)* v3)
413 {
414     if (v1)
415     {
416         assert(v2 && v3);
417         assert(vec_numbits(v1)==vec_numbits(v2) && vec_numbits(v1)==vec_numbits(v3));
418         const vtop = &v1[vec_dim(v1)];
419         for (; v1 < vtop; v1++,v2++,v3++)
420             *v1 = *v2 ^ *v3;
421     }
422     else
423         assert(!v2 && !v3);
424 }
425 
426 /********************************
427  * Compute v1 |= v2.
428  */
429 
430 pure
431 void vec_orass(vec_t v1, const(vec_base_t)* v2)
432 {
433     if (v1)
434     {
435         debug assert(v2);
436         debug assert(vec_numbits(v1)==vec_numbits(v2));
437         const vtop = &v1[vec_dim(v1)];
438         for (; v1 < vtop; v1++,v2++)
439             *v1 |= *v2;
440     }
441     else
442         assert(!v2);
443 }
444 
445 /********************************
446  * Compute v1 = v2 | v3.
447  */
448 
449 pure
450 void vec_or(vec_t v1, const(vec_base_t)* v2, const(vec_base_t)* v3)
451 {
452     if (v1)
453     {
454         assert(v2 && v3);
455         assert(vec_numbits(v1)==vec_numbits(v2) && vec_numbits(v1)==vec_numbits(v3));
456         const vtop = &v1[vec_dim(v1)];
457         for (; v1 < vtop; v1++,v2++,v3++)
458                 *v1 = *v2 | *v3;
459     }
460     else
461         assert(!v2 && !v3);
462 }
463 
464 /********************************
465  * Compute v1 -= v2.
466  */
467 
468 pure
469 void vec_subass(vec_t v1, const(vec_base_t)* v2)
470 {
471     if (v1)
472     {
473         assert(v2);
474         assert(vec_numbits(v1)==vec_numbits(v2));
475         const vtop = &v1[vec_dim(v1)];
476         for (; v1 < vtop; v1++,v2++)
477             *v1 &= ~*v2;
478     }
479     else
480         assert(!v2);
481 }
482 
483 /********************************
484  * Compute v1 = v2 - v3.
485  */
486 
487 pure
488 void vec_sub(vec_t v1, const(vec_base_t)* v2, const(vec_base_t)* v3)
489 {
490     if (v1)
491     {
492         assert(v2 && v3);
493         assert(vec_numbits(v1)==vec_numbits(v2) && vec_numbits(v1)==vec_numbits(v3));
494         const vtop = &v1[vec_dim(v1)];
495         for (; v1 < vtop; v1++,v2++,v3++)
496             *v1 = *v2 & ~*v3;
497     }
498     else
499         assert(!v2 && !v3);
500 }
501 
502 /****************
503  * Clear vector.
504  */
505 
506 pure
507 void vec_clear(vec_t v)
508 {
509     if (v)
510         memset(v, 0, v[0].sizeof * vec_dim(v));
511 }
512 
513 /****************
514  * Set vector.
515  */
516 
517 pure
518 void vec_set(vec_t v)
519 {
520     if (v)
521     {
522         memset(v, ~0, v[0].sizeof * vec_dim(v));
523         vec_clearextrabits(v);
524     }
525 }
526 
527 /***************
528  * Copy vector.
529  */
530 
531 pure
532 void vec_copy(vec_t to, const vec_t from)
533 {
534     if (to != from)
535     {
536         debug
537         {
538             if (!(to && from && vec_numbits(to) == vec_numbits(from)))
539                 printf("to = x%p, from = x%p, numbits(to) = %d, numbits(from) = %d\n",
540                     to, from, cast(int) (to ? vec_numbits(to) : 0),
541                     cast(int) (from ? vec_numbits(from): 0));
542         }
543         assert(to && from && vec_numbits(to) == vec_numbits(from));
544         memcpy(to, from, to[0].sizeof * vec_dim(to));
545     }
546 }
547 
548 /****************
549  * Return 1 if vectors are equal.
550  */
551 
552 pure
553 int vec_equal(const vec_t v1, const vec_t v2)
554 {
555     if (v1 == v2)
556         return 1;
557     assert(v1 && v2 && vec_numbits(v1) == vec_numbits(v2));
558     return !memcmp(v1, v2, v1[0].sizeof * vec_dim(v1));
559 }
560 
561 /********************************
562  * Return 1 if (v1 & v2) == 0
563  */
564 
565 pure
566 int vec_disjoint(const(vec_base_t)* v1, const(vec_base_t)* v2)
567 {
568     assert(v1 && v2);
569     assert(vec_numbits(v1) == vec_numbits(v2));
570     const vtop = &v1[vec_dim(v1)];
571     for (; v1 < vtop; v1++,v2++)
572         if (*v1 & *v2)
573             return 0;
574     return 1;
575 }
576 
577 /*********************
578  * Clear any extra bits in vector.
579  */
580 
581 pure
582 void vec_clearextrabits(vec_t v)
583 {
584     assert(v);
585     const n = vec_numbits(v);
586     if (n & VECMASK)
587         v[vec_dim(v) - 1] &= MASK(cast(uint)n) - 1;
588 }
589 
590 /******************
591  * Write out vector.
592  */
593 
594 pure
595 void vec_println(const vec_t v)
596 {
597     debug
598     {
599         vec_print(v);
600         fputc('\n',stdout);
601     }
602 }
603 
604 pure
605 void vec_print(const vec_t v)
606 {
607     debug
608     {
609         printf(" Vec %p, numbits %d dim %d", v, cast(int) vec_numbits(v), cast(int) vec_dim(v));
610         if (v)
611         {
612             fputc('\t',stdout);
613             for (size_t i = 0; i < vec_numbits(v); i++)
614                 fputc((vec_testbit(i,v)) ? '1' : '0',stdout);
615         }
616     }
617 }
618 
619