compiler: Construct numeric labels in checked code
2911781f7b2e83c9ab4511fb6b678742dd1ee1fb6571a9c6ed0205330037f579
1 parent
b229c066
lib/std/lang/lower.rad
+10 -9
| 1342 | 1342 | return false; |
|
| 1343 | 1343 | } |
|
| 1344 | 1344 | ||
| 1345 | 1345 | /// Create a label with a numeric suffix, eg. `@base0`. |
|
| 1346 | 1346 | /// This ensures unique labels like `@then0`, `@then1`, etc. |
|
| 1347 | - | unsafe fn labelWithSuffix 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, base: *[u8], suffix: u32) -> *[u8] throws (LowerError) where 'arena: 'phase, 'phase: 'function { |
|
| 1347 | + | fn labelWithSuffix(base: &[u8], suffix: u32, allocator: alloc::Allocator) -> *[u8] { |
|
| 1348 | 1348 | let mut digits: [u8; fmt::U32_STR_LEN] = [0; fmt::U32_STR_LEN]; |
|
| 1349 | 1349 | let start = fmt::formatU32(suffix, &mut digits[..]); |
|
| 1350 | - | let totalLen = base.len + digits.len - start; |
|
| 1351 | - | let buf = try! alloc::allocSlice(self.arena, 1, 1, totalLen) as *mut [u8]; |
|
| 1352 | - | ||
| 1353 | - | try! mem::copy(&mut buf[..base.len], base); |
|
| 1354 | - | try! mem::copy(&mut buf[base.len..totalLen], &digits[start..]); |
|
| 1355 | - | ||
| 1356 | - | return &buf[..totalLen]; |
|
| 1350 | + | let mut buf: *mut [u8] = &mut []; |
|
| 1351 | + | for byte in base { |
|
| 1352 | + | buf.append(byte, allocator); |
|
| 1353 | + | } |
|
| 1354 | + | for byte in &digits[start..] { |
|
| 1355 | + | buf.append(byte, allocator); |
|
| 1356 | + | } |
|
| 1357 | + | return buf; |
|
| 1357 | 1358 | } |
|
| 1358 | 1359 | ||
| 1359 | 1360 | /// Generate a unique label by appending the global counter to the base. |
|
| 1360 | 1361 | unsafe fn nextLabel 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, base: *[u8]) -> *[u8] throws (LowerError) where 'arena: 'phase, 'phase: 'function { |
|
| 1361 | 1362 | let idx = self.labelCounter; |
|
| 1362 | 1363 | set self.labelCounter += 1; |
|
| 1363 | 1364 | ||
| 1364 | - | return try labelWithSuffix(self, base, idx); |
|
| 1365 | + | return labelWithSuffix(base, idx, alloc::arenaAllocator(self.arena)); |
|
| 1365 | 1366 | } |
|
| 1366 | 1367 | ||
| 1367 | 1368 | /////////////////////////////// |
|
| 1368 | 1369 | // Data Section Construction // |
|
| 1369 | 1370 | /////////////////////////////// |
test/tests/ssa.block.storage.rad
+20 -0
| 32 | 32 | } |
|
| 33 | 33 | } |
|
| 34 | 34 | return limit; |
|
| 35 | 35 | } |
|
| 36 | 36 | ||
| 37 | + | /// Exercise distinct labels across decimal suffix boundaries. |
|
| 38 | + | fn staircase(value: u32) -> u32 { |
|
| 39 | + | let mut result: u32 = 0; |
|
| 40 | + | if value >= 1 { set result += 1; } |
|
| 41 | + | if value >= 2 { set result += 2; } |
|
| 42 | + | if value >= 3 { set result += 3; } |
|
| 43 | + | if value >= 4 { set result += 4; } |
|
| 44 | + | if value >= 5 { set result += 5; } |
|
| 45 | + | if value >= 6 { set result += 6; } |
|
| 46 | + | if value >= 7 { set result += 7; } |
|
| 47 | + | if value >= 8 { set result += 8; } |
|
| 48 | + | if value >= 9 { set result += 9; } |
|
| 49 | + | if value >= 10 { set result += 10; } |
|
| 50 | + | if value >= 11 { set result += 11; } |
|
| 51 | + | if value >= 12 { set result += 12; } |
|
| 52 | + | return result; |
|
| 53 | + | } |
|
| 54 | + | ||
| 37 | 55 | /// Compare repeated branch and loop execution with a straight-line reference. |
|
| 38 | 56 | @default fn main() -> u32 { |
|
| 39 | 57 | let values = [11 as u32, 13, 17, 19]; |
|
| 40 | 58 | for limit in 0..24 { |
|
| 59 | + | let steps: u32 = 12 if limit > 12 else limit; |
|
| 60 | + | assert staircase(limit) == steps * (steps + 1) / 2; |
|
| 41 | 61 | assert early(limit) == (3 if limit > 3 else limit); |
|
| 42 | 62 | let mut all: u32 = 7; |
|
| 43 | 63 | let mut odd: u32 = 7; |
|
| 44 | 64 | for index in 1..16 { |
|
| 45 | 65 | if index <= limit { |