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