compiler: Build initialized function parameter tables

8a2ef421ff998c0cebb8c28ed62308dcb048fc9ade0114d701ec4f75ea29a6a0
Alexis Sellier committed ago 1 parent 7988f48b
lib/std/lang/lower.rad +4 -6
3237 3237
    if totalLen == 0 {
3238 3238
        return &[];
3239 3239
    }
3240 3240
    assert fnType.paramTypes.len as u32 <= resolver::MAX_FN_PARAMS;
3241 3241
3242 -
    let params = try! alloc::allocRawSlice(
3243 -
        self.arena, @sizeOf(il::Param), @alignOf(il::Param), totalLen
3244 -
    ) as *unsafe mut [il::Param];
3242 +
    let mut params: *mut [il::Param] = &mut [];
3245 3243
3246 3244
    if let reg = self.returnReg {
3247 -
        set params[0] = il::Param { value: reg, type: il::Type::W64 };
3245 +
        params.append(il::Param { value: reg, type: il::Type::W64 }, alloc::arenaAllocator(self.arena));
3248 3246
    }
3249 3247
    for i in 0..fnType.paramTypes.len as u32 {
3250 3248
        let type = ilType(self.low, *fnType.paramTypes[i]);
3251 3249
        let reg = nextReg(self);
3252 3250
3253 -
        set params[i + offset] = il::Param { value: reg, type };
3251 +
        params.append(il::Param { value: reg, type }, alloc::arenaAllocator(self.arena));
3254 3252
3255 3253
        // Declare the parameter variable. For the receiver, the name comes
3256 3254
        // from the receiver node.
3257 3255
        // For all other parameters, the name comes from the AST params.
3258 3256
        let mut name: *[u8] = undefined;
3271 3269
        let v = newVar(self, name, type, false, il::Val::Undef);
3272 3270
3273 3271
        set self.params[i] = FnParamBinding { var: v, reg };
3274 3272
        set self.paramsLen += 1;
3275 3273
    }
3276 -
    return params;
3274 +
    return (&params[..]) as *unsafe [il::Param];
3277 3275
}
3278 3276
3279 3277
/// Resolve match subject.
3280 3278
unsafe fn lowerMatchSubject 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, subject: *ast::Node) -> MatchSubject throws (LowerError) where 'arena: 'phase, 'phase: 'function {
3281 3279
    let mut val = try lowerExpr(self, subject);
test/tests/fn.parameter.table.rad added +46 -0
1 +
//! returns: 0
2 +
3 +
/// Aggregate result that uses a hidden return-buffer parameter.
4 +
record Result: Copy {
5 +
    /// Weighted argument sum.
6 +
    sum: u32,
7 +
    /// Last argument.
8 +
    last: u64,
9 +
}
10 +
11 +
/// Return a scalar without explicit parameters.
12 +
fn zero() -> u32 {
13 +
    return 17;
14 +
}
15 +
16 +
/// Return an aggregate without explicit parameters.
17 +
fn empty() -> Result {
18 +
    return Result { sum: 19, last: 0x100000000 };
19 +
}
20 +
21 +
/// Check each of the eight scalar parameter positions.
22 +
fn scalar(a: u32, b: u32, c: u32, d: u32, e: u32, f: u32, g: u32, h: u32) -> u32 {
23 +
    return a + 2*b + 3*c + 4*d + 5*e + 6*f + 7*g + 8*h;
24 +
}
25 +
26 +
/// Check explicit parameters alongside the hidden return buffer.
27 +
fn aggregate(a: u32, b: u32, c: u32, d: u32, e: u32, f: u32, h: u64) -> Result {
28 +
    return Result { sum: scalar(a, b, c, d, e, f, 7, h as u32), last: h };
29 +
}
30 +
31 +
/// Verify parameter order over repeated scalar and aggregate calls.
32 +
@default fn main() -> u32 {
33 +
    assert zero() == 17;
34 +
    let initial = empty();
35 +
    assert initial.sum == 19;
36 +
    assert initial.last == 0x100000000;
37 +
    for index in 0..8 {
38 +
        assert scalar(index, 2, 3, 4, 5, 6, 7, 8) == index + 203;
39 +
        let result = aggregate(index, 2, 3, 4, 5, 6, 0x100000008);
40 +
        assert result.sum == index + 203;
41 +
        assert result.last == 0x100000008;
42 +
        assert initial.sum == 19;
43 +
        assert initial.last == 0x100000000;
44 +
    }
45 +
    return 0;
46 +
}