compiler: Grow initialized SSA argument storage
c3a1a901e5072c1d6b9e0fe6686c3e55e1b39279b883c3c31e2305f2b7b8e027
1 parent
05d04410
lib/std/lang/lower.rad
+5 -7
| 3198 | 3198 | /// Grow an args array to hold at least the given capacity. |
|
| 3199 | 3199 | unsafe fn growArgs 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, args: *unsafe mut [il::Val], capacity: u32) -> *unsafe mut [il::Val] where 'arena: 'phase, 'phase: 'function { |
|
| 3200 | 3200 | if args.len >= capacity { |
|
| 3201 | 3201 | return args; |
|
| 3202 | 3202 | } |
|
| 3203 | - | let newArgs = try! alloc::allocRawSlice( |
|
| 3204 | - | self.arena, @sizeOf(il::Val), @alignOf(il::Val), capacity |
|
| 3205 | - | ) as *unsafe mut [il::Val]; |
|
| 3203 | + | let mut newArgs: *mut [il::Val] = &mut []; |
|
| 3206 | 3204 | ||
| 3207 | - | for arg, i in args { |
|
| 3208 | - | set newArgs[i] = arg; |
|
| 3205 | + | for arg in args { |
|
| 3206 | + | newArgs.append(arg, alloc::arenaAllocator(self.arena)); |
|
| 3209 | 3207 | } |
|
| 3210 | 3208 | for i in args.len..capacity { |
|
| 3211 | - | set newArgs[i] = il::Val::Undef; |
|
| 3209 | + | newArgs.append(il::Val::Undef, alloc::arenaAllocator(self.arena)); |
|
| 3212 | 3210 | } |
|
| 3213 | - | return newArgs; |
|
| 3211 | + | return (&mut newArgs[..]) as *unsafe mut [il::Val]; |
|
| 3214 | 3212 | } |
|
| 3215 | 3213 | ||
| 3216 | 3214 | /// Extract the parameter name from an [`FnParam`] AST node value. |
|
| 3217 | 3215 | fn paramName(value: *ast::NodeValue) -> *[u8] throws (LowerError) { |
|
| 3218 | 3216 | let case ast::NodeValue::FnParam(param) = *value else { |
test/tests/ssa.argument.growth.rad
added
+51 -0
| 1 | + | //! returns: 0 |
|
| 2 | + | ||
| 3 | + | /// Keep eight distinct values live across branch and loop edges. |
|
| 4 | + | fn run(limit: u32) -> u32 { |
|
| 5 | + | let mut a: u32 = 1; |
|
| 6 | + | let mut b: u32 = 2; |
|
| 7 | + | let mut c: u32 = 3; |
|
| 8 | + | let mut d: u32 = 4; |
|
| 9 | + | let mut e: u32 = 5; |
|
| 10 | + | let mut f: u32 = 6; |
|
| 11 | + | let mut g: u32 = 7; |
|
| 12 | + | let mut h: u32 = 8; |
|
| 13 | + | for index in 0..limit { |
|
| 14 | + | let mut step: u32 = 0; |
|
| 15 | + | match index % 3 { |
|
| 16 | + | case 0 => set step = 1, |
|
| 17 | + | case 1 => set step = 3, |
|
| 18 | + | else => set step = 5, |
|
| 19 | + | } |
|
| 20 | + | if index % 2 == 0 { |
|
| 21 | + | set a += step; |
|
| 22 | + | set c += step * 3; |
|
| 23 | + | set e += step * 5; |
|
| 24 | + | set g += step * 7; |
|
| 25 | + | } else { |
|
| 26 | + | set b += step * 2; |
|
| 27 | + | set d += step * 4; |
|
| 28 | + | set f += step * 6; |
|
| 29 | + | set h += step * 8; |
|
| 30 | + | } |
|
| 31 | + | } |
|
| 32 | + | return a + 2*b + 3*c + 4*d + 5*e + 6*f + 7*g + 8*h; |
|
| 33 | + | } |
|
| 34 | + | ||
| 35 | + | /// Compute the weighted sum without carrying the eight separate values. |
|
| 36 | + | fn expected(limit: u32) -> u32 { |
|
| 37 | + | let mut result: u32 = 204; |
|
| 38 | + | for index in 0..limit { |
|
| 39 | + | let step = 1 + (index % 3) * 2; |
|
| 40 | + | set result += step * (84 if index % 2 == 0 else 120); |
|
| 41 | + | } |
|
| 42 | + | return result; |
|
| 43 | + | } |
|
| 44 | + | ||
| 45 | + | /// Check empty, single-iteration, and repeatedly merged control flow. |
|
| 46 | + | @default fn main() -> u32 { |
|
| 47 | + | for limit in 0..20 { |
|
| 48 | + | assert run(limit) == expected(limit); |
|
| 49 | + | } |
|
| 50 | + | return 0; |
|
| 51 | + | } |