compiler: Initialize block caches in checked construction

b229c0660397974dd2df9c1513c1258b02e104f61276e3dd597d4a1ba521a38c
Alexis Sellier committed ago 1 parent 447c3f8a
lib/std/lang/lower.rad +6 -9
2175 2175
/// Returns a [`BlockId`] that can be used for jumps and branches. The block must
2176 2176
/// be switched to via [`switchToBlock`] before instructions can be emitted.
2177 2177
unsafe fn createBlock 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, labelBase: *[u8]) -> BlockId throws (LowerError) where 'arena: 'phase, 'phase: 'function {
2178 2178
    let label = try nextLabel(self, labelBase);
2179 2179
    let varCount = self.localCount;
2180 -
    let vars = try! alloc::allocSlice(
2181 -
        self.arena, @sizeOf(?il::Val), @alignOf(?il::Val), varCount
2182 -
    ) as *mut [?il::Val];
2183 -
2184 -
    for i in 0..varCount {
2185 -
        set vars[i] = nil;
2186 -
    }
2187 2180
    let allocator = alloc::arenaAllocator(self.arena);
2188 2181
    let depth = self.loopDepth;
2189 -
    return appendBlock(&mut self.blockData, label, vars, depth, allocator);
2182 +
    return appendBlock(&mut self.blockData, label, varCount, depth, allocator);
2190 2183
}
2191 2184
2192 2185
/// Append a complete unsealed block with initialized variable slots.
2193 2186
fn appendBlock(
2194 2187
    blocks: &mut *mut [BlockData],
2195 2188
    label: *[u8],
2196 -
    vars: *mut [?il::Val],
2189 +
    varCount: u32,
2197 2190
    loopDepth: u32,
2198 2191
    allocator: alloc::Allocator,
2199 2192
) -> BlockId {
2200 2193
    let id = BlockId(blocks.len);
2194 +
    let mut vars: *mut [?il::Val] = &mut [];
2195 +
    for i in 0..varCount {
2196 +
        vars.append(nil, allocator);
2197 +
    }
2201 2198
    blocks.append(BlockData {
2202 2199
        label,
2203 2200
        params: &mut [],
2204 2201
        paramVars: &mut [],
2205 2202
        instrs: &mut [],
test/tests/ssa.cache.values.rad +18 -0
19 19
20 20
/// Exercise a function with no local cache entries.
21 21
fn empty() {
22 22
}
23 23
24 +
/// Preserve cached values across continue and break edges.
25 +
fn exits(limit: u32, start: u64) -> u64 {
26 +
    let mut result = start;
27 +
    for index in 0..limit {
28 +
        if index == 7 {
29 +
            break;
30 +
        }
31 +
        if index % 2 == 0 {
32 +
            continue;
33 +
        }
34 +
        set result += index as u64;
35 +
    }
36 +
    return result;
37 +
}
38 +
24 39
/// Compare cache joins with the closed-form sums of odd and even integers.
25 40
@default fn main() -> u32 {
26 41
    for start in [0 as u64, 0x100000001, 0x8000000000000000] {
27 42
        for limit in 0..32 {
28 43
            empty();
30 45
            let evens = (limit / 2) as u64;
31 46
            let first = start + odds * odds;
32 47
            let second = start + 2 * evens * (evens + 1);
33 48
            assert run(limit, start) == first ^ second;
34 49
            assert run(limit, start) == first ^ second;
50 +
            let bound: u32 = 7 if limit > 7 else limit;
51 +
            let count = (bound / 2) as u64;
52 +
            assert exits(limit, start) == start + count * count;
35 53
        }
36 54
    }
37 55
    return 0;
38 56
}