compiler: Construct numeric labels in checked code

2911781f7b2e83c9ab4511fb6b678742dd1ee1fb6571a9c6ed0205330037f579
Alexis Sellier committed ago 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 {