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 @safe
390 pure
391 uint vec_numBitsSet(const vec_t vec)
392 {
393     uint n = 0;
394     size_t length = vec_numbits(vec);
395     for (size_t i = 0; (i = vec_index(i, vec)) < length; ++i)
396         ++n;
397     return n;
398 }
399 
400 /********************************
401  * Compute v1 &= v2.
402  */
403 
404 @trusted
405 pure
406 void vec_andass(vec_t v1, const(vec_base_t)* v2)
407 {
408     if (v1)
409     {
410         assert(v2);
411         assert(vec_numbits(v1)==vec_numbits(v2));
412         const vtop = &v1[vec_dim(v1)];
413         for (; v1 < vtop; v1++,v2++)
414             *v1 &= *v2;
415     }
416     else
417         assert(!v2);
418 }
419 
420 /********************************
421  * Compute v1 = v2 & v3.
422  */
423 
424 @trusted
425 pure
426 void vec_and(vec_t v1, const(vec_base_t)* v2, const(vec_base_t)* v3)
427 {
428     if (v1)
429     {
430         assert(v2 && v3);
431         assert(vec_numbits(v1)==vec_numbits(v2) && vec_numbits(v1)==vec_numbits(v3));
432         const vtop = &v1[vec_dim(v1)];
433         for (; v1 < vtop; v1++,v2++,v3++)
434             *v1 = *v2 & *v3;
435     }
436     else
437         assert(!v2 && !v3);
438 }
439 
440 /********************************
441  * Compute v1 ^= v2.
442  */
443 
444 @trusted
445 pure
446 void vec_xorass(vec_t v1, const(vec_base_t)* v2)
447 {
448     if (v1)
449     {
450         assert(v2);
451         assert(vec_numbits(v1)==vec_numbits(v2));
452         const vtop = &v1[vec_dim(v1)];
453         for (; v1 < vtop; v1++,v2++)
454             *v1 ^= *v2;
455     }
456     else
457         assert(!v2);
458 }
459 
460 /********************************
461  * Compute v1 = v2 ^ v3.
462  */
463 
464 @trusted
465 pure
466 void vec_xor(vec_t v1, const(vec_base_t)* v2, const(vec_base_t)* v3)
467 {
468     if (v1)
469     {
470         assert(v2 && v3);
471         assert(vec_numbits(v1)==vec_numbits(v2) && vec_numbits(v1)==vec_numbits(v3));
472         const vtop = &v1[vec_dim(v1)];
473         for (; v1 < vtop; v1++,v2++,v3++)
474             *v1 = *v2 ^ *v3;
475     }
476     else
477         assert(!v2 && !v3);
478 }
479 
480 /********************************
481  * Compute v1 |= v2.
482  */
483 
484 @trusted
485 pure
486 void vec_orass(vec_t v1, const(vec_base_t)* v2)
487 {
488     if (v1)
489     {
490         debug assert(v2);
491         debug assert(vec_numbits(v1)==vec_numbits(v2));
492         const vtop = &v1[vec_dim(v1)];
493         for (; v1 < vtop; v1++,v2++)
494             *v1 |= *v2;
495     }
496     else
497         assert(!v2);
498 }
499 
500 /********************************
501  * Compute v1 = v2 | v3.
502  */
503 
504 @trusted
505 pure
506 void vec_or(vec_t v1, const(vec_base_t)* v2, const(vec_base_t)* v3)
507 {
508     if (v1)
509     {
510         assert(v2 && v3);
511         assert(vec_numbits(v1)==vec_numbits(v2) && vec_numbits(v1)==vec_numbits(v3));
512         const vtop = &v1[vec_dim(v1)];
513         for (; v1 < vtop; v1++,v2++,v3++)
514                 *v1 = *v2 | *v3;
515     }
516     else
517         assert(!v2 && !v3);
518 }
519 
520 /********************************
521  * Compute v1 -= v2.
522  */
523 
524 @trusted
525 pure
526 void vec_subass(vec_t v1, const(vec_base_t)* v2)
527 {
528     if (v1)
529     {
530         assert(v2);
531         assert(vec_numbits(v1)==vec_numbits(v2));
532         const vtop = &v1[vec_dim(v1)];
533         for (; v1 < vtop; v1++,v2++)
534             *v1 &= ~*v2;
535     }
536     else
537         assert(!v2);
538 }
539 
540 /********************************
541  * Compute v1 = v2 - v3.
542  */
543 
544 @trusted
545 pure
546 void vec_sub(vec_t v1, const(vec_base_t)* v2, const(vec_base_t)* v3)
547 {
548     if (v1)
549     {
550         assert(v2 && v3);
551         assert(vec_numbits(v1)==vec_numbits(v2) && vec_numbits(v1)==vec_numbits(v3));
552         const vtop = &v1[vec_dim(v1)];
553         for (; v1 < vtop; v1++,v2++,v3++)
554             *v1 = *v2 & ~*v3;
555     }
556     else
557         assert(!v2 && !v3);
558 }
559 
560 /****************
561  * Clear vector.
562  */
563 
564 @trusted
565 pure
566 void vec_clear(vec_t v)
567 {
568     if (v)
569         memset(v, 0, v[0].sizeof * vec_dim(v));
570 }
571 
572 /****************
573  * Set vector.
574  */
575 
576 @trusted
577 pure
578 void vec_set(vec_t v)
579 {
580     if (v)
581     {
582         memset(v, ~0, v[0].sizeof * vec_dim(v));
583         vec_clearextrabits(v);
584     }
585 }
586 
587 /***************
588  * Copy vector.
589  */
590 
591 @trusted
592 pure
593 void vec_copy(vec_t to, const vec_t from)
594 {
595     if (to != from)
596     {
597         debug
598         {
599             if (!(to && from && vec_numbits(to) == vec_numbits(from)))
600                 printf("to = x%p, from = x%p, numbits(to) = %d, numbits(from) = %d\n",
601                     to, from, cast(int) (to ? vec_numbits(to) : 0),
602                     cast(int) (from ? vec_numbits(from): 0));
603         }
604         assert(to && from && vec_numbits(to) == vec_numbits(from));
605         memcpy(to, from, to[0].sizeof * vec_dim(to));
606     }
607 }
608 
609 /****************
610  * Return 1 if vectors are equal.
611  */
612 
613 @trusted
614 pure
615 int vec_equal(const vec_t v1, const vec_t v2)
616 {
617     if (v1 == v2)
618         return 1;
619     assert(v1 && v2 && vec_numbits(v1) == vec_numbits(v2));
620     return !memcmp(v1, v2, v1[0].sizeof * vec_dim(v1));
621 }
622 
623 /********************************
624  * Return 1 if (v1 & v2) == 0
625  */
626 
627 @trusted
628 pure
629 int vec_disjoint(const(vec_base_t)* v1, const(vec_base_t)* v2)
630 {
631     assert(v1 && v2);
632     assert(vec_numbits(v1) == vec_numbits(v2));
633     const vtop = &v1[vec_dim(v1)];
634     for (; v1 < vtop; v1++,v2++)
635         if (*v1 & *v2)
636             return 0;
637     return 1;
638 }
639 
640 /*********************
641  * Clear any extra bits in vector.
642  */
643 
644 @trusted
645 pure
646 void vec_clearextrabits(vec_t v)
647 {
648     assert(v);
649     const n = vec_numbits(v);
650     if (n & VECMASK)
651         v[vec_dim(v) - 1] &= MASK(cast(uint)n) - 1;
652 }
653 
654 /**************************************
655  * Turn a vec_t into an InputRange so we can foreach
656  * over each bit in the bit vector.
657  * Replaces
658  *    for (size_t i = 0; (i = vec_index(i, v)) < vec_numbits(v); ++i) { ... }
659  * With
660  *    foreach (i; VecRange(v)) { ... }
661  */
662 struct VecRange
663 {
664     size_t i;
665     const vec_t v;
666 
667   @nogc @safe nothrow pure:
668     this(const vec_t v) { this.v = v; i = vec_index(0, v); }
669     bool empty() const { return i == vec_numbits(v); }
670     size_t front() const { return i; }
671     void popFront() { i = vec_index(i + 1, v); }
672 }
673 
674 /******************
675  * Write out vector.
676  */
677 
678 pure
679 void vec_println(const vec_t v)
680 {
681     debug
682     {
683         vec_print(v);
684         fputc('\n',stdout);
685     }
686 }
687 
688 @trusted
689 pure
690 void vec_print(const vec_t v)
691 {
692     debug
693     {
694         printf(" Vec %p, numbits %d dim %d", v, cast(int) vec_numbits(v), cast(int) vec_dim(v));
695         if (v)
696         {
697             fputc('\t',stdout);
698             for (size_t i = 0; i < vec_numbits(v); i++)
699                 fputc((vec_testbit(i,v)) ? '1' : '0',stdout);
700         }
701     }
702 }