compiler: Check SSA merge construction
3122b8f773d97914d63aefe4d37e3bb16f9ac51c9fa8d67a2bfa10b22fece608
1 parent
df26efaa
lib/std/lang/lower.rad
+8 -3
| 3019 | 3019 | set self.blockData[*block].vars[*v] = val; // Cache. |
|
| 3020 | 3020 | return val; |
|
| 3021 | 3021 | } |
|
| 3022 | 3022 | case VarSource::Merge => { |
|
| 3023 | 3023 | unsafe { |
|
| 3024 | - | return try createBlockParam(self, block, v); |
|
| 3024 | + | let allocator = alloc::arenaAllocator(self.arena); |
|
| 3025 | + | return try createBlockParam(self, block, v, allocator); |
|
| 3025 | 3026 | } |
|
| 3026 | 3027 | }, |
|
| 3027 | 3028 | case VarSource::Invalid => throw LowerError::InvalidUse, |
|
| 3028 | 3029 | } |
|
| 3029 | 3030 | } |
| 3113 | 3114 | /// @end(w32 %1) // x = %1, merged from predecessors |
|
| 3114 | 3115 | /// ret %1; |
|
| 3115 | 3116 | /// |
|
| 3116 | 3117 | /// Create a register `%1` as a block parameter. In a sealed block, patch each |
|
| 3117 | 3118 | /// predecessor's jump to pass its value of `x`. Otherwise, defer until sealing. |
|
| 3118 | - | unsafe fn createBlockParam 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, block: BlockId, v: Var) -> il::Val throws (LowerError) where 'arena: 'phase, 'phase: 'function { |
|
| 3119 | + | fn createBlockParam 'arena 'phase 'function ( |
|
| 3120 | + | self: &mut FnLowerer 'arena 'phase 'function, |
|
| 3121 | + | block: BlockId, |
|
| 3122 | + | v: Var, |
|
| 3123 | + | allocator: alloc::Allocator |
|
| 3124 | + | ) -> il::Val throws (LowerError) where 'arena: 'phase, 'phase: 'function { |
|
| 3119 | 3125 | // Entry block must not have block parameters. |
|
| 3120 | 3126 | assert block <> self.entryBlock, "createBlockParam: entry block must not have block parameters"; |
|
| 3121 | 3127 | // Allocate a register to hold the merged value. |
|
| 3122 | 3128 | let reg = nextReg(self); |
|
| 3123 | 3129 | let type = getVar(&self.vars, v).type; |
|
| 3124 | 3130 | ||
| 3125 | 3131 | // Create block parameter and add it to the block. |
|
| 3126 | 3132 | let param = il::Param { value: reg, type }; |
|
| 3127 | - | let allocator = alloc::arenaAllocator(self.arena); |
|
| 3128 | 3133 | let paramIdx = bindBlockParam(&mut self.blockData[*block], param, v, allocator); |
|
| 3129 | 3134 | ||
| 3130 | 3135 | if self.blockData[*block].sealState == Sealed::Yes { |
|
| 3131 | 3136 | // Block sealed: check for trivial phi before committing. If all |
|
| 3132 | 3137 | // predecessors provide the same value, we can remove the param we |