compiler: Check function lowerer construction
355d20b03f11d81b809004aa2add6ce762af6c0a6381d74379dac5d79f133759
1 parent
b0694d26
lib/std/lang/lower.rad
+6 -6
| 1021 | 1021 | } |
|
| 1022 | 1022 | return entries; |
|
| 1023 | 1023 | } |
|
| 1024 | 1024 | ||
| 1025 | 1025 | /// Create a new function lowerer for a given function type and name. |
|
| 1026 | - | unsafe fn fnLowerer 'arena 'phase 'function ( |
|
| 1026 | + | fn fnLowerer 'arena 'phase 'function ( |
|
| 1027 | 1027 | self: &'function mut Lowerer 'arena 'phase, |
|
| 1028 | - | node: *ast::Node, |
|
| 1028 | + | sourceOffset: u32, |
|
| 1029 | 1029 | fnType: *resolver::FnType, |
|
| 1030 | 1030 | qualName: *[u8], |
|
| 1031 | 1031 | functionArena: &'function mut alloc::Arena, |
|
| 1032 | 1032 | variables: &'function mut [VarData] |
|
| 1033 | 1033 | ) -> FnLowerer 'arena 'phase 'function where 'arena: 'phase, 'phase: 'function { |
|
| 1034 | - | let localCount = resolver::nodeData(self.resolver, node).localCount; |
|
| 1034 | + | let localCount = variables.len; |
|
| 1035 | 1035 | let mut fnLow = FnLowerer 'arena 'phase 'function { |
|
| 1036 | 1036 | low: self, |
|
| 1037 | 1037 | arena: functionArena, |
|
| 1038 | 1038 | fnType, |
|
| 1039 | 1039 | localCount, |
| 1057 | 1057 | let modId = fnLow.low.currentMod else { |
|
| 1058 | 1058 | panic "fnLowerer: debug enabled but no current module"; |
|
| 1059 | 1059 | }; |
|
| 1060 | 1060 | set fnLow.srcLoc = il::SrcLoc { |
|
| 1061 | 1061 | moduleId: modId, |
|
| 1062 | - | offset: node.span.offset, |
|
| 1062 | + | offset: sourceOffset, |
|
| 1063 | 1063 | }; |
|
| 1064 | 1064 | } |
|
| 1065 | 1065 | return fnLow; |
|
| 1066 | 1066 | } |
|
| 1067 | 1067 |
| 1097 | 1097 | if let sym = resolver::symbolFor(self.resolver, node) { |
|
| 1098 | 1098 | registerSymbolName(&mut self.symbolNames, sym, qualName, alloc::arenaAllocator(self.arena)); |
|
| 1099 | 1099 | } |
|
| 1100 | 1100 | let variableSlots = variableStorage(functionArena, data.localCount); |
|
| 1101 | 1101 | let parent: 'function = &mut *self, arena = &mut *functionArena, variables = &mut variableSlots[..] where 'phase: 'function in { |
|
| 1102 | - | let mut fnLow = fnLowerer(parent, node, fnType, qualName, arena, variables); |
|
| 1102 | + | let mut fnLow = fnLowerer(parent, node.span.offset, fnType, qualName, arena, variables); |
|
| 1103 | 1103 | ||
| 1104 | 1104 | // If the function returns an aggregate or is throwing, prepend a hidden |
|
| 1105 | 1105 | // return parameter. The caller allocates the buffer and passes it |
|
| 1106 | 1106 | // as the first argument; the callee writes the return value into it. |
|
| 1107 | 1107 | if requiresReturnParam(fnType) and not isExtern { |
| 1279 | 1279 | let sym = resolver::symbolFor(self.resolver, node) else throw LowerError::MissingSymbol(node); |
|
| 1280 | 1280 | registerSymbolName(&mut self.symbolNames, sym, qualName, alloc::arenaAllocator(self.arena)); |
|
| 1281 | 1281 | ||
| 1282 | 1282 | let variableSlots = variableStorage(functionArena, data.localCount); |
|
| 1283 | 1283 | let parent: 'function = &mut *self, arena = &mut *functionArena, variables = &mut variableSlots[..] where 'phase: 'function in { |
|
| 1284 | - | let mut fnLow = fnLowerer(parent, node, fnType, qualName, arena, variables); |
|
| 1284 | + | let mut fnLow = fnLowerer(parent, node.span.offset, fnType, qualName, arena, variables); |
|
| 1285 | 1285 | if requiresReturnParam(fnType) { |
|
| 1286 | 1286 | set fnLow.returnReg = nextReg(&mut fnLow); |
|
| 1287 | 1287 | } |
|
| 1288 | 1288 | let lowParams = try lowerParams(&mut fnLow, *fnType, sig.params, receiverName); |
|
| 1289 | 1289 | let func = try! alloc::allocRaw(fnLow.arena, @sizeOf(il::Fn), @alignOf(il::Fn)) as *unsafe mut il::Fn; |
test/tests/ssa.instruction.storage.rad
+14 -0
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | ||
| 3 | + | /// Input for method calls with branch-local values. |
|
| 4 | + | record Input: Copy { |
|
| 5 | + | /// Full-width input retained by the receiver. |
|
| 6 | + | value: u64, |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | /// Lower a method with a receiver, explicit parameter, and nested calls. |
|
| 10 | + | fn (input: &Input) combine(selected: bool) -> u64 { |
|
| 11 | + | return combine(input.value, selected); |
|
| 12 | + | } |
|
| 13 | + | ||
| 3 | 14 | /// Leaf computation used by a non-leaf function. |
|
| 4 | 15 | fn advance(value: u64) -> u64 { |
|
| 5 | 16 | return value + 7; |
|
| 6 | 17 | } |
|
| 7 | 18 |
| 24 | 35 | for index in 0..32 { |
|
| 25 | 36 | let value = (index as u64) + 0x100000000; |
|
| 26 | 37 | let base = (value + 7) * 3 + (value + 14) * 5; |
|
| 27 | 38 | assert combine(value, true) == base + (value + 21) * 11; |
|
| 28 | 39 | assert combine(value, false) == base + (value + 21) * 13; |
|
| 40 | + | let input = Input { value }; |
|
| 41 | + | assert input.combine(true) == base + (value + 21) * 11; |
|
| 42 | + | assert input.combine(false) == base + (value + 21) * 13; |
|
| 29 | 43 | } |
|
| 30 | 44 | return 0; |
|
| 31 | 45 | } |