compiler: Build variable metadata in checked storage
447c3f8a45e1a871dee38f2ad4f80eb8dff2aa8963e9374e4d0217b46621ef57
1 parent
355d20b0
lib/std/lang/lower.rad
+5 -6
| 1011 | 1011 | set self.currentMod = nil; |
|
| 1012 | 1012 | set self.packageDataStart = self.data.len; |
|
| 1013 | 1013 | } |
|
| 1014 | 1014 | ||
| 1015 | 1015 | /// Allocate initialized variable metadata for one function. |
|
| 1016 | - | unsafe fn variableStorage(arena: &mut alloc::Arena, count: u32) -> *mut [VarData] { |
|
| 1017 | - | let entries = try! alloc::allocSlice(arena, @sizeOf(VarData), @alignOf(VarData), count) |
|
| 1018 | - | as *mut [VarData]; |
|
| 1016 | + | fn variableStorage(count: u32, allocator: alloc::Allocator) -> *mut [VarData] { |
|
| 1017 | + | let mut entries: *mut [VarData] = &mut []; |
|
| 1019 | 1018 | for i in 0..count { |
|
| 1020 | - | set entries[i] = VarData { name: nil, type: il::Type::W64, mutable: false, addressTaken: false }; |
|
| 1019 | + | entries.append(VarData { name: nil, type: il::Type::W64, mutable: false, addressTaken: false }, allocator); |
|
| 1021 | 1020 | } |
|
| 1022 | 1021 | return entries; |
|
| 1023 | 1022 | } |
|
| 1024 | 1023 | ||
| 1025 | 1024 | /// Create a new function lowerer for a given function type and name. |
| 1095 | 1094 | ||
| 1096 | 1095 | // Register function symbol for cross-package call resolution. |
|
| 1097 | 1096 | if let sym = resolver::symbolFor(self.resolver, node) { |
|
| 1098 | 1097 | registerSymbolName(&mut self.symbolNames, sym, qualName, alloc::arenaAllocator(self.arena)); |
|
| 1099 | 1098 | } |
|
| 1100 | - | let variableSlots = variableStorage(functionArena, data.localCount); |
|
| 1099 | + | let variableSlots = variableStorage(data.localCount, alloc::arenaAllocator(functionArena)); |
|
| 1101 | 1100 | let parent: 'function = &mut *self, arena = &mut *functionArena, variables = &mut variableSlots[..] where 'phase: 'function in { |
|
| 1102 | 1101 | let mut fnLow = fnLowerer(parent, node.span.offset, fnType, qualName, arena, variables); |
|
| 1103 | 1102 | ||
| 1104 | 1103 | // If the function returns an aggregate or is throwing, prepend a hidden |
|
| 1105 | 1104 | // return parameter. The caller allocates the buffer and passes it |
| 1277 | 1276 | throw LowerError::ExpectedFunction; |
|
| 1278 | 1277 | }; |
|
| 1279 | 1278 | let sym = resolver::symbolFor(self.resolver, node) else throw LowerError::MissingSymbol(node); |
|
| 1280 | 1279 | registerSymbolName(&mut self.symbolNames, sym, qualName, alloc::arenaAllocator(self.arena)); |
|
| 1281 | 1280 | ||
| 1282 | - | let variableSlots = variableStorage(functionArena, data.localCount); |
|
| 1281 | + | let variableSlots = variableStorage(data.localCount, alloc::arenaAllocator(functionArena)); |
|
| 1283 | 1282 | let parent: 'function = &mut *self, arena = &mut *functionArena, variables = &mut variableSlots[..] where 'phase: 'function in { |
|
| 1284 | 1283 | let mut fnLow = fnLowerer(parent, node.span.offset, fnType, qualName, arena, variables); |
|
| 1285 | 1284 | if requiresReturnParam(fnType) { |
|
| 1286 | 1285 | set fnLow.returnReg = nextReg(&mut fnLow); |
|
| 1287 | 1286 | } |
test/tests/variable.slots.scopes.rad
+24 -0
| 44 | 44 | } |
|
| 45 | 45 | ||
| 46 | 46 | /// Check repeated invocations and slot initialization in an empty function. |
|
| 47 | 47 | fn empty() {} |
|
| 48 | 48 | ||
| 49 | + | /// Keep local metadata live across multiple slice growth boundaries. |
|
| 50 | + | fn wide(seed: u64) -> u64 { |
|
| 51 | + | let a = seed + 1; |
|
| 52 | + | let b = seed + 2; |
|
| 53 | + | let c = seed + 3; |
|
| 54 | + | let d = seed + 4; |
|
| 55 | + | let e = seed + 5; |
|
| 56 | + | let f = seed + 6; |
|
| 57 | + | let g = seed + 7; |
|
| 58 | + | let h = seed + 8; |
|
| 59 | + | let i = seed + 9; |
|
| 60 | + | let j = seed + 10; |
|
| 61 | + | let k = seed + 11; |
|
| 62 | + | let l = seed + 12; |
|
| 63 | + | let m = seed + 13; |
|
| 64 | + | let n = seed + 14; |
|
| 65 | + | let o = seed + 15; |
|
| 66 | + | let mut p = seed + 16; |
|
| 67 | + | increment(&mut p); |
|
| 68 | + | return a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p; |
|
| 69 | + | } |
|
| 70 | + | ||
| 49 | 71 | /// Verify scoped metadata over several argument values. |
|
| 50 | 72 | @default fn main() -> u32 { |
|
| 51 | 73 | empty(); |
|
| 52 | 74 | for seed in 0..16 { |
|
| 53 | 75 | assert check(seed) == seed * 3 + 7; |
|
| 76 | + | let value = 0x100000000 + seed as u64; |
|
| 77 | + | assert wide(value) == value * 16 + 137; |
|
| 54 | 78 | } |
|
| 55 | 79 | empty(); |
|
| 56 | 80 | return 0; |
|
| 57 | 81 | } |