compiler: Check complete block construction
6a788bde93685bb45da1f6270c866daa00b78b29c4b1b828e59bc326c81cea50
1 parent
10f56b05
lib/std/lang/lower.rad
+17 -4
| 2175 | 2175 | /// The block is initially unsealed (predecessors may be added later) and empty. |
|
| 2176 | 2176 | /// Returns a [`BlockId`] that can be used for jumps and branches. The block must |
|
| 2177 | 2177 | /// be switched to via [`switchToBlock`] before instructions can be emitted. |
|
| 2178 | 2178 | unsafe fn createBlock 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, labelBase: *[u8]) -> BlockId throws (LowerError) where 'arena: 'phase, 'phase: 'function { |
|
| 2179 | 2179 | let label = try nextLabel(self, labelBase); |
|
| 2180 | - | let id = BlockId(self.blockData.len); |
|
| 2181 | 2180 | let varCount = self.localCount; |
|
| 2182 | 2181 | let vars = try! alloc::allocSlice( |
|
| 2183 | 2182 | self.arena, @sizeOf(?il::Val), @alignOf(?il::Val), varCount |
|
| 2184 | 2183 | ) as *mut [?il::Val]; |
|
| 2185 | 2184 | ||
| 2186 | 2185 | for i in 0..varCount { |
|
| 2187 | 2186 | set vars[i] = nil; |
|
| 2188 | 2187 | } |
|
| 2189 | - | self.blockData.append(BlockData { |
|
| 2188 | + | let allocator = alloc::arenaAllocator(self.arena); |
|
| 2189 | + | let depth = self.loopDepth; |
|
| 2190 | + | return appendBlock(&mut self.blockData, label, vars, depth, allocator); |
|
| 2191 | + | } |
|
| 2192 | + | ||
| 2193 | + | /// Append a complete unsealed block with initialized variable slots. |
|
| 2194 | + | fn appendBlock( |
|
| 2195 | + | blocks: &mut *mut [BlockData], |
|
| 2196 | + | label: *[u8], |
|
| 2197 | + | vars: *mut [?il::Val], |
|
| 2198 | + | loopDepth: u32, |
|
| 2199 | + | allocator: alloc::Allocator, |
|
| 2200 | + | ) -> BlockId { |
|
| 2201 | + | let id = BlockId(blocks.len); |
|
| 2202 | + | blocks.append(BlockData { |
|
| 2190 | 2203 | label, |
|
| 2191 | 2204 | params: &mut [], |
|
| 2192 | 2205 | paramVars: &mut [], |
|
| 2193 | 2206 | instrs: &mut [], |
|
| 2194 | 2207 | locs: &mut [], |
|
| 2195 | 2208 | preds: &mut [], |
|
| 2196 | 2209 | vars, |
|
| 2197 | 2210 | sealState: Sealed::No, |
|
| 2198 | - | loopDepth: self.loopDepth, |
|
| 2199 | - | }, alloc::arenaAllocator(self.arena)); |
|
| 2211 | + | loopDepth, |
|
| 2212 | + | }, allocator); |
|
| 2200 | 2213 | ||
| 2201 | 2214 | return id; |
|
| 2202 | 2215 | } |
|
| 2203 | 2216 | ||
| 2204 | 2217 | /// Create a new block with a single parameter. |
test/tests/ssa.block.storage.rad
+11 -0
| 22 | 22 | set total += value; |
|
| 23 | 23 | } |
|
| 24 | 24 | return total; |
|
| 25 | 25 | } |
|
| 26 | 26 | ||
| 27 | + | /// Return through either a loop-body block or the final block. |
|
| 28 | + | fn early(limit: u32) -> u32 { |
|
| 29 | + | for index in 0..limit { |
|
| 30 | + | if index == 3 { |
|
| 31 | + | return index; |
|
| 32 | + | } |
|
| 33 | + | } |
|
| 34 | + | return limit; |
|
| 35 | + | } |
|
| 36 | + | ||
| 27 | 37 | /// Compare repeated branch and loop execution with a straight-line reference. |
|
| 28 | 38 | @default fn main() -> u32 { |
|
| 29 | 39 | let values = [11 as u32, 13, 17, 19]; |
|
| 30 | 40 | for limit in 0..24 { |
|
| 41 | + | assert early(limit) == (3 if limit > 3 else limit); |
|
| 31 | 42 | let mut all: u32 = 7; |
|
| 32 | 43 | let mut odd: u32 = 7; |
|
| 33 | 44 | for index in 1..16 { |
|
| 34 | 45 | if index <= limit { |
|
| 35 | 46 | set all += values[index % 4]; |