compiler: Check SSA cache rewrite traversal

5a3af878d1693741707270610d59831961d508029e4d14233c6c6e9f728286d7
Alexis Sellier committed ago 1 parent 86f24335
lib/std/lang/lower.rad +23 -8
2089 2089
/// Rewrite cached SSA values for a variable across all blocks, and also
2090 2090
/// rewrite any terminator arguments that reference the provisional register.
2091 2091
/// The latter is necessary because recursive SSA resolution may have already
2092 2092
/// patched terminator arguments with the provisional value before it was
2093 2093
/// found to be trivial.
2094 -
unsafe fn rewriteCachedVarValue 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, v: Var, from: il::Val, to: il::Val) where 'arena: 'phase, 'phase: 'function {
2094 +
fn rewriteCachedVarValue 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, v: Var, from: il::Val, to: il::Val) where 'arena: 'phase, 'phase: 'function {
2095 2095
    for i in 0..self.blockData.len {
2096 2096
        let blk = &mut self.blockData[i];
2097 2097
        if blk.vars[*v] == from {
2098 2098
            set blk.vars[*v] = to;
2099 2099
        }
2100 2100
        if blk.instrs.len > 0 {
2101 2101
            let ix = blk.instrs.len - 1;
2102 2102
            match &mut blk.instrs[ix] {
2103 -
                case il::Instr::Jmp { args, .. } =>
2104 -
                    rewriteValInSlice(*args, from, to),
2103 +
                case il::Instr::Jmp { args, .. } => {
2104 +
                    unsafe {
2105 +
                        rewriteValInSlice(*args, from, to);
2106 +
                    }
2107 +
                },
2105 2108
                case il::Instr::Br { thenArgs, elseArgs, .. } => {
2106 -
                    rewriteValInSlice(*thenArgs, from, to);
2107 -
                    rewriteValInSlice(*elseArgs, from, to);
2109 +
                    unsafe {
2110 +
                        rewriteValInSlice(*thenArgs, from, to);
2111 +
                        rewriteValInSlice(*elseArgs, from, to);
2112 +
                    }
2108 2113
                }
2109 2114
                case il::Instr::Switch { defaultArgs, cases, .. } => {
2110 -
                    rewriteValInSlice(*defaultArgs, from, to);
2111 -
                    for j in 0..cases.len {
2112 -
                        rewriteValInSlice(cases[j].args, from, to);
2115 +
                    unsafe {
2116 +
                        rewriteValInSlice(*defaultArgs, from, to);
2117 +
                        rewriteSwitchArgs(*cases, from, to);
2113 2118
                    }
2114 2119
                }
2115 2120
                else => {}
2116 2121
            }
2117 2122
        }
2118 2123
    }
2119 2124
}
2120 2125
2126 +
/// Replace a provisional value in each switch case's argument sequence.
2127 +
fn rewriteSwitchArgs(cases: &mut [il::SwitchCase], from: il::Val, to: il::Val) {
2128 +
    for i in 0..cases.len {
2129 +
        let branch = &mut cases[i];
2130 +
        unsafe {
2131 +
            rewriteValInSlice(branch.args, from, to);
2132 +
        }
2133 +
    }
2134 +
}
2135 +
2121 2136
/// Replace all occurrences of `from` with `to` in an args slice.
2122 2137
fn rewriteValInSlice(args: &mut [il::Val], from: il::Val, to: il::Val) {
2123 2138
    for i in 0..args.len {
2124 2139
        if args[i] == from {
2125 2140
            set args[i] = to;