compiler: Check session initialization emission

6bebd6db26274993190d06f0261c38e9a0d809f5eb40ca5ac30f0017d875ca9c
Alexis Sellier committed ago 1 parent 694546bb
lib/std/lang/lower.rad +16 -5
5782 5782
        try emitFillLoop(self, r.dataReg, fillVal, r.count, *info.itemType, elemSize);
5783 5783
    }
5784 5784
}
5785 5785
5786 5786
/// Emit a typed fill loop: `for i in 0..count { dst[i * stride] = value; }`.
5787 -
unsafe fn emitFillLoop 'arena 'phase 'function (
5787 +
fn emitFillLoop 'arena 'phase 'function (
5788 5788
    self: &mut FnLowerer 'arena 'phase 'function,
5789 5789
    dst: il::Reg,
5790 5790
    value: il::Val,
5791 5791
    count: il::Val,
5792 5792
    elemType: resolver::Type,
7058 7058
    let result = try emitCallValue(self, il::Val::Reg(functionReg), runtime, args);
7059 7059
    return SessionInitialization { allocation, result, value, count };
7060 7060
}
7061 7061
7062 7062
/// Initialize successful reservation storage before its reference is published.
7063 -
unsafe fn initializeSessionAllocation 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, prepared: SessionInitialization)
7063 +
fn initializeSessionAllocation 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, prepared: SessionInitialization)
7064 7064
    throws (LowerError) where 'arena: 'phase, 'phase: 'function
7065 7065
{
7066 7066
    let allocation = prepared.allocation;
7067 7067
    let base = emitValToReg(self, prepared.result);
7068 +
    unsafe {
7069 +
        let layout = resolver::getTypeLayout(*allocation.item);
7070 +
        try emitSessionInitialization(self, prepared, base, layout.size);
7071 +
    }
7072 +
}
7073 +
7074 +
/// Emit writes to reserved session storage using its resolved item size.
7075 +
fn emitSessionInitialization 'arena 'phase 'function (
7076 +
    self: &mut FnLowerer 'arena 'phase 'function, prepared: SessionInitialization,
7077 +
    base: il::Reg, itemSize: u32
7078 +
) throws (LowerError) where 'arena: 'phase, 'phase: 'function {
7079 +
    let allocation = prepared.allocation;
7068 7080
    let value = prepared.value;
7069 7081
    let count = prepared.count;
7070 -
    let layout = resolver::getTypeLayout(*allocation.item);
7071 7082
    let destination = nextReg(self);
7072 7083
    emitLoadW64At(self, destination, base, RESULT_VAL_OFFSET);
7073 7084
    match allocation.kind {
7074 7085
        case resolver::SessionAllocationKind::New =>
7075 7086
            try emitStore(self, destination, 0, *allocation.item, value),
7076 7087
        case resolver::SessionAllocationKind::Copy => {
7077 7088
            let source = loadSlicePtr(self, emitValToReg(self, value));
7078 -
            let bytes = emitTypedBinOp(self, il::BinOp::Mul, il::Type::W32, count, il::Val::Imm(layout.size as i64));
7089 +
            let bytes = emitTypedBinOp(self, il::BinOp::Mul, il::Type::W32, count, il::Val::Imm(itemSize as i64));
7079 7090
            try emitByteCopyLoop(self, destination, source, bytes, "allocate.copy");
7080 7091
        }
7081 7092
        case resolver::SessionAllocationKind::Fill =>
7082 -
            try emitFillLoop(self, destination, value, count, *allocation.item, layout.size),
7093 +
            try emitFillLoop(self, destination, value, count, *allocation.item, itemSize),
7083 7094
    }
7084 7095
}
7085 7096
7086 7097
/// Lower a call expression, which may be a function call or type constructor.
7087 7098
unsafe fn lowerCallOrCtor 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, node: *ast::Node, call: ast::Call) -> il::Val throws (LowerError) where 'arena: 'phase, 'phase: 'function {