compiler: Check numeric conversion emission
732b4a2c57473baf145897f4e30de2cf13391f02e2a68629e833ac4b27da3ec2
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 { |