compiler/
lib/
examples/
std/
arch/
char/
collections/
graph/
lang/
alloc/
ast/
gen/
bitset/
regalloc/
bitset.rad
4.6 KiB
data.rad
8.6 KiB
labels.rad
2.4 KiB
regalloc.rad
2.4 KiB
types.rad
594 B
il/
module/
parser/
resolver/
scanner/
alloc.rad
7.1 KiB
ast.rad
26.9 KiB
gen.rad
513 B
il.rad
20.4 KiB
lower.rad
321.7 KiB
module.rad
17.3 KiB
package.rad
1.3 KiB
parser.rad
92.2 KiB
resolver.rad
511.1 KiB
scanner.rad
17.9 KiB
sexpr.rad
6.7 KiB
strings.rad
2.2 KiB
types.rad
1.6 KiB
sys/
arch.rad
68 B
char.rad
855 B
collections.rad
39 B
fmt.rad
8.3 KiB
graph.rad
4.3 KiB
intrinsics.rad
467 B
io.rad
1.7 KiB
lang.rad
276 B
mem.rad
2.3 KiB
sys.rad
179 B
testing.rad
2.4 KiB
tests.rad
15.7 KiB
vec.rad
3.2 KiB
std.rad
299 B
scripts/
seed/
sublime/
test/
vim/
.gitignore
336 B
.gitsigners
112 B
CELL_PERMISSIONS
6.8 KiB
CONTRIBUTING
2.1 KiB
LICENSE
1.1 KiB
Makefile
5.4 KiB
README
2.5 KiB
STYLE
2.5 KiB
std.lib
1.5 KiB
std.lib.test
808 B
lib/std/lang/gen/bitset.rad
raw
| 1 | //! Bitset utilities for register tracking. |
| 2 | //! |
| 3 | //! Provides efficient bit-level set operations for tracking live registers |
| 4 | //! during liveness analysis and register allocation. |
| 5 | @test mod tests; |
| 6 | |
| 7 | use std::lang::alloc; |
| 8 | |
| 9 | /// Return the minimum of two 32-bit values. |
| 10 | fn min(a: u32, b: u32) -> u32 { |
| 11 | if a < b { |
| 12 | return a; |
| 13 | } |
| 14 | return b; |
| 15 | } |
| 16 | |
| 17 | /// Calculate the number of 32-bit words needed to store `n` bits. |
| 18 | export fn wordsFor(n: u32) -> u32 { |
| 19 | return n / 32 + (1 if n % 32 > 0 else 0); |
| 20 | } |
| 21 | |
| 22 | /// Allocate zeroed words for at least `len` bits in a session. |
| 23 | export fn allocate 'bits (storage: &Session 'bits, len: u32) -> &'bits mut [u32] throws (alloc::AllocError) { |
| 24 | return try storage.fill(0 as u32, wordsFor(len)); |
| 25 | } |
| 26 | |
| 27 | /// Set bit `n` in the bitset. |
| 28 | export fn put(bs: &mut [u32], n: u32) { |
| 29 | let word = n / 32; |
| 30 | if word >= bs.len { |
| 31 | return; |
| 32 | } |
| 33 | let b = n % 32; |
| 34 | |
| 35 | set bs[word] |= (1 << b); |
| 36 | } |
| 37 | |
| 38 | /// Clear bit `n` in the bitset. |
| 39 | export fn clear(bs: &mut [u32], n: u32) { |
| 40 | let word = n / 32; |
| 41 | if word >= bs.len { |
| 42 | return; |
| 43 | } |
| 44 | let b = n % 32; |
| 45 | |
| 46 | set bs[word] &= ~(1 << b); |
| 47 | } |
| 48 | |
| 49 | /// Check if bit `n` is set. |
| 50 | export fn contains(bs: &[u32], n: u32) -> bool { |
| 51 | let word = n / 32; |
| 52 | if word >= bs.len { |
| 53 | return false; |
| 54 | } |
| 55 | let b = n % 32; |
| 56 | |
| 57 | return (bs[word] & (1 << b)) <> 0; |
| 58 | } |
| 59 | |
| 60 | /// Count the number of set bits. |
| 61 | export fn count(bs: &[u32]) -> u32 { |
| 62 | let mut total: u32 = 0; |
| 63 | for word in bs { |
| 64 | if word <> 0 { |
| 65 | set total += popCount(word); |
| 66 | } |
| 67 | } |
| 68 | return total; |
| 69 | } |
| 70 | |
| 71 | /// Population count for a 32-bit word. |
| 72 | fn popCount(x: u32) -> u32 { |
| 73 | let mut n = x; |
| 74 | set n -= ((n >> 1) & 0x55555555); |
| 75 | set n = (n & 0x33333333) + ((n >> 2) & 0x33333333); |
| 76 | set n = (n + (n >> 4)) & 0x0F0F0F0F; |
| 77 | set n += (n >> 8); |
| 78 | set n += (n >> 16); |
| 79 | |
| 80 | return n & 0x3F; |
| 81 | } |
| 82 | |
| 83 | /// Union: `dst = dst | src`. |
| 84 | export fn union_(dst: &mut [u32], src: &[u32]) { |
| 85 | for i in 0..min(dst.len, src.len) { |
| 86 | set dst[i] |= src[i]; |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | /// Subtract: `dst = dst - src`. |
| 91 | export fn subtract(dst: &mut [u32], src: &[u32]) { |
| 92 | for i in 0..min(dst.len, src.len) { |
| 93 | set dst[i] &= ~src[i]; |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | /// Check if two bitsets are equal. |
| 98 | export fn eq(a: &[u32], b: &[u32]) -> bool { |
| 99 | let minWords = min(a.len, b.len); |
| 100 | |
| 101 | for i in 0..minWords { |
| 102 | if a[i] <> b[i] { |
| 103 | return false; |
| 104 | } |
| 105 | } |
| 106 | for i in minWords..a.len { |
| 107 | if a[i] <> 0 { |
| 108 | return false; |
| 109 | } |
| 110 | } |
| 111 | for i in minWords..b.len { |
| 112 | if b[i] <> 0 { |
| 113 | return false; |
| 114 | } |
| 115 | } |
| 116 | return true; |
| 117 | } |
| 118 | |
| 119 | /// Copy bits from source to destination. |
| 120 | export fn copy(dst: &mut [u32], src: &[u32]) { |
| 121 | let minWords = min(dst.len, src.len); |
| 122 | |
| 123 | for i in 0..minWords { |
| 124 | set dst[i] = src[i]; |
| 125 | } |
| 126 | // Clear remaining words if destination is larger. |
| 127 | for i in minWords..dst.len { |
| 128 | set dst[i] = 0; |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | /// Clear all bits. |
| 133 | export fn clearAll(bs: &mut [u32]) { |
| 134 | for i in 0..bs.len { |
| 135 | set bs[i] = 0; |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | /// Iterator state for iterating set bits. |
| 140 | export record BitIter: Copy { |
| 141 | /// Current word index. |
| 142 | wordIdx: u32, |
| 143 | /// Remaining bits in the current word (visited bits cleared). |
| 144 | remaining: u32, |
| 145 | } |
| 146 | |
| 147 | /// Create an iterator over set bits. |
| 148 | /// The cursor retains the first word mask and its position. |
| 149 | export fn iter(bs: &[u32]) -> BitIter { |
| 150 | let remaining = bs[0] if bs.len > 0 else 0; |
| 151 | return BitIter { wordIdx: 0, remaining }; |
| 152 | } |
| 153 | |
| 154 | /// Get the next set bit from the supplied bitset, or nil if none remain. |
| 155 | /// The current word mask is a value snapshot; later words are read on demand. |
| 156 | export fn iterNext(it: &mut BitIter, bs: &[u32]) -> ?u32 { |
| 157 | // Skip to next non-zero word. |
| 158 | while it.remaining == 0 { |
| 159 | set it.wordIdx += 1; |
| 160 | if it.wordIdx >= bs.len { |
| 161 | return nil; |
| 162 | } |
| 163 | set it.remaining = bs[it.wordIdx]; |
| 164 | } |
| 165 | // Find lowest set bit position using de Bruijn sequence. |
| 166 | let b = ctz(it.remaining); |
| 167 | let n = it.wordIdx * 32 + b; |
| 168 | // Clear the lowest set bit. |
| 169 | set it.remaining &= it.remaining - 1; |
| 170 | |
| 171 | return n; |
| 172 | } |
| 173 | |
| 174 | /// Count trailing zeros in a 32-bit value. |
| 175 | /// Returns the bit position of the lowest set bit (0-31). |
| 176 | /// Behavior is undefined if `x` is 0. |
| 177 | fn ctz(x: u32) -> u32 { |
| 178 | // De Bruijn sequence for 32-bit CTZ. |
| 179 | constant DEBRUIJN: u32 = 0x077CB531; |
| 180 | constant TABLE: [u8; 32] = [ |
| 181 | 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, |
| 182 | 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9, |
| 183 | ]; |
| 184 | // Isolate lowest set bit, multiply by de Bruijn constant, look up. |
| 185 | let isolated = x & (~x + 1); |
| 186 | |
| 187 | return TABLE[(isolated * DEBRUIJN) >> 27] as u32; |
| 188 | } |