compiler: Check aggregate value emission

22ef76058cc6811e47b63883311d34970a1720f4c7ccc359c806a887e063babc
Alexis Sellier committed ago 1 parent 63b266a5
lib/std/lang/lower.rad +12 -9
4444 4444
    }
4445 4445
    return index as i64;
4446 4446
}
4447 4447
4448 4448
/// Reserve stack storage for a value of the given type.
4449 -
unsafe fn emitReserve 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, typ: resolver::Type) -> il::Reg throws (LowerError) where 'arena: 'phase, 'phase: 'function {
4450 -
    let layout = resolver::getTypeLayout(typ);
4451 -
    return emitReserveLayout(self, layout);
4449 +
fn emitReserve 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, typ: resolver::Type) -> il::Reg throws (LowerError) where 'arena: 'phase, 'phase: 'function {
4450 +
    unsafe {
4451 +
        let layout = resolver::getTypeLayout(typ);
4452 +
        return emitReserveLayout(self, layout);
4453 +
    }
4452 4454
}
4453 4455
4454 4456
/// Reserve stack storage with an explicit layout.
4455 4457
fn emitReserveLayout 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, layout: resolver::Layout) -> il::Reg where 'arena: 'phase, 'phase: 'function {
4456 4458
    let dst = nextReg(self);
4462 4464
    });
4463 4465
    return dst;
4464 4466
}
4465 4467
4466 4468
/// Store a value into an address.
4467 -
unsafe fn emitStore 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, base: il::Reg, offset: i32, typ: resolver::Type, src: il::Val) throws (LowerError) where 'arena: 'phase, 'phase: 'function {
4469 +
fn emitStore 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, base: il::Reg, offset: i32, typ: resolver::Type, src: il::Val) throws (LowerError) where 'arena: 'phase, 'phase: 'function {
4468 4470
    // `undefined` values need no store.
4469 4471
    if let case il::Val::Undef = src {
4470 4472
        return;
4471 4473
    }
4472 4474
    if isAggregateType(typ) {
4473 4475
        let dst = emitPtrOffset(self, base, offset);
4474 4476
        let src = emitValToReg(self, src);
4475 -
        let layout = resolver::getTypeLayout(typ);
4476 -
4477 -
        emit(self, il::Instr::Blit { dst, src, size: il::Val::Imm(layout.size as i64) });
4477 +
        unsafe {
4478 +
            let layout = resolver::getTypeLayout(typ);
4479 +
            emit(self, il::Instr::Blit { dst, src, size: il::Val::Imm(layout.size as i64) });
4480 +
        }
4478 4481
    } else {
4479 4482
        emit(self, il::Instr::Store {
4480 4483
            typ: ilType(self.low, typ),
4481 4484
            src,
4482 4485
            dst: base,
4484 4487
        });
4485 4488
    }
4486 4489
}
4487 4490
4488 4491
/// Allocate stack space for a value and store it. Returns a pointer to the value.
4489 -
unsafe fn emitStackVal 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, typ: resolver::Type, val: il::Val) -> il::Val throws (LowerError) where 'arena: 'phase, 'phase: 'function {
4492 +
fn emitStackVal 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, typ: resolver::Type, val: il::Val) -> il::Val throws (LowerError) where 'arena: 'phase, 'phase: 'function {
4490 4493
    let ptr = try emitReserve(self, typ);
4491 4494
    try emitStore(self, ptr, 0, typ, val);
4492 4495
    return il::Val::Reg(ptr);
4493 4496
}
4494 4497
4495 4498
/// Generic helper to build any tagged aggregate.
4496 4499
/// Reserves space based on the provided layout, stores the tag, and optionally
4497 4500
/// stores the payload value at `valOffset`.
4498 -
unsafe fn buildTagged 'arena 'phase 'function (
4501 +
fn buildTagged 'arena 'phase 'function (
4499 4502
    self: &mut FnLowerer 'arena 'phase 'function,
4500 4503
    layout: resolver::Layout,
4501 4504
    tag: i64,
4502 4505
    payload: ?il::Val,
4503 4506
    payloadType: resolver::Type,