compiler: Check function lowerer construction

355d20b03f11d81b809004aa2add6ce762af6c0a6381d74379dac5d79f133759
Alexis Sellier committed ago 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
}