compiler: Check numeric conversion emission

732b4a2c57473baf145897f4e30de2cf13391f02e2a68629e833ac4b27da3ec2
Alexis Sellier committed ago 1 parent f77a58b2
lib/std/lang/lower.rad +9 -2
7455 7455
/// Handles widening conversions between integer types. Uses sign-extension
7456 7456
/// for signed source types and zero-extension for unsigned source types.
7457 7457
unsafe fn lowerNumericCast 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, val: il::Val, srcType: resolver::Type, dstType: resolver::Type) -> il::Val where 'arena: 'phase, 'phase: 'function {
7458 7458
    let srcLayout = resolver::getTypeLayout(srcType);
7459 7459
    let dstLayout = resolver::getTypeLayout(dstType);
7460 +
    return emitNumericCast(self, val, srcType, dstType, srcLayout.size, dstLayout.size);
7461 +
}
7460 7462
7461 -
    if srcLayout.size == dstLayout.size {
7463 +
/// Emit an integer conversion from resolved storage sizes and signedness.
7464 +
fn emitNumericCast 'arena 'phase 'function (
7465 +
    self: &mut FnLowerer 'arena 'phase 'function, val: il::Val,
7466 +
    srcType: resolver::Type, dstType: resolver::Type, srcSize: u32, dstSize: u32
7467 +
) -> il::Val where 'arena: 'phase, 'phase: 'function {
7468 +
    if srcSize == dstSize {
7462 7469
        // Same size: bit pattern is unchanged, value is returned as-is.
7463 7470
        return val;
7464 7471
    }
7465 7472
    // Widening: extend based on source signedness.
7466 7473
    // Narrowing: truncate and normalize to destination width.
7467 -
    let widening = srcLayout.size < dstLayout.size;
7474 +
    let widening = srcSize < dstSize;
7468 7475
    let extType = ilType(self.low, srcType) if widening else ilType(self.low, dstType);
7469 7476
    let signed = isSignedType(srcType) if widening else isSignedType(dstType);
7470 7477
    let dst = nextReg(self);
7471 7478
7472 7479
    if signed {