@@ -1318,28 +1318,80 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
1318
1318
fn checked_binop (
1319
1319
& mut self ,
1320
1320
oop : OverflowOp ,
1321
- _ty : Ty < ' _ > ,
1321
+ ty : Ty < ' _ > ,
1322
1322
lhs : Self :: Value ,
1323
1323
rhs : Self :: Value ,
1324
1324
) -> ( Self :: Value , Self :: Value ) {
1325
- // NOTE(eddyb) this needs to be `undef`, not `false`/`true`, because
1326
- // we don't want the user's boolean constants to keep the zombie alive.
1327
- let bool = SpirvType :: Bool . def ( self . span ( ) , self ) ;
1328
- let overflowed = self . undef ( bool) ;
1329
- let result = match oop {
1330
- OverflowOp :: Add => ( self . add ( lhs, rhs) , overflowed) ,
1331
- OverflowOp :: Sub => ( self . sub ( lhs, rhs) , overflowed) ,
1332
- OverflowOp :: Mul => ( self . mul ( lhs, rhs) , overflowed) ,
1325
+ // adopted partially from https://github.com/ziglang/zig/blob/master/src/codegen/spirv.zig
1326
+ let is_add = match oop {
1327
+ OverflowOp :: Add => true ,
1328
+ OverflowOp :: Sub => false ,
1329
+ OverflowOp :: Mul => {
1330
+ // NOTE(eddyb) this needs to be `undef`, not `false`/`true`, because
1331
+ // we don't want the user's boolean constants to keep the zombie alive.
1332
+ let bool = SpirvType :: Bool . def ( self . span ( ) , self ) ;
1333
+ let overflowed = self . undef ( bool) ;
1334
+
1335
+ let result = ( self . mul ( lhs, rhs) , overflowed) ;
1336
+ self . zombie ( result. 1 . def ( self ) , "checked mul is not supported yet" ) ;
1337
+ return result;
1338
+ }
1333
1339
} ;
1334
- self . zombie (
1335
- result. 1 . def ( self ) ,
1336
- match oop {
1337
- OverflowOp :: Add => "checked add is not supported yet" ,
1338
- OverflowOp :: Sub => "checked sub is not supported yet" ,
1339
- OverflowOp :: Mul => "checked mul is not supported yet" ,
1340
- } ,
1341
- ) ;
1342
- result
1340
+ let signed = match ty. kind ( ) {
1341
+ ty:: Int ( _) => true ,
1342
+ ty:: Uint ( _) => false ,
1343
+ other => self . fatal ( format ! (
1344
+ "Unexpected {} type: {other:#?}" ,
1345
+ match oop {
1346
+ OverflowOp :: Add => "checked add" ,
1347
+ OverflowOp :: Sub => "checked sub" ,
1348
+ OverflowOp :: Mul => "checked mul" ,
1349
+ }
1350
+ ) ) ,
1351
+ } ;
1352
+
1353
+ let result = if is_add {
1354
+ self . add ( lhs, rhs)
1355
+ } else {
1356
+ self . sub ( lhs, rhs)
1357
+ } ;
1358
+
1359
+ let overflowed = if signed {
1360
+ // when adding, overflow could happen if
1361
+ // - rhs is positive and result < lhs; or
1362
+ // - rhs is negative and result > lhs
1363
+ // this is equivalent to (rhs < 0) == (result > lhs)
1364
+ //
1365
+ // when subtracting, overflow happens if
1366
+ // - rhs is positive and result > lhs; or
1367
+ // - rhs is negative and result < lhs
1368
+ // this is equivalent to (rhs < 0) == (result < lhs)
1369
+ let rhs_lt_zero = self . icmp ( IntPredicate :: IntSLT , rhs, self . constant_int ( rhs. ty , 0 ) ) ;
1370
+ let result_gt_lhs = self . icmp (
1371
+ if is_add {
1372
+ IntPredicate :: IntSGT
1373
+ } else {
1374
+ IntPredicate :: IntSLT
1375
+ } ,
1376
+ result,
1377
+ lhs,
1378
+ ) ;
1379
+ self . icmp ( IntPredicate :: IntEQ , rhs_lt_zero, result_gt_lhs)
1380
+ } else {
1381
+ // for unsigned addition, overflow occured if the result is less than any of the operands.
1382
+ // for subtraction, overflow occured if the result is greater.
1383
+ self . icmp (
1384
+ if is_add {
1385
+ IntPredicate :: IntULT
1386
+ } else {
1387
+ IntPredicate :: IntUGT
1388
+ } ,
1389
+ result,
1390
+ lhs,
1391
+ )
1392
+ } ;
1393
+
1394
+ ( result, overflowed)
1343
1395
}
1344
1396
1345
1397
// rustc has the concept of an immediate vs. memory type - bools are compiled to LLVM bools as
@@ -2766,8 +2818,9 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
2766
2818
kind : SpirvValueKind :: Def ( b_id) ,
2767
2819
..
2768
2820
} ,
2769
- _, // `&'static panic::Location<'static>`
2770
- ] = args[ ..]
2821
+ // NOTE(fee1-dead): the standard `panic` takes in a `Location` due to `track_caller`.
2822
+ // but for `panic_nounwind` it does not, therefore we only look at the first two arguments.
2823
+ ] = args[ ..2 ]
2771
2824
{
2772
2825
if let Some ( const_msg) = const_str_as_utf8 ( & [ a_id, b_id] ) {
2773
2826
decoded_format_args. const_pieces = Some ( [ const_msg] . into_iter ( ) . collect ( ) ) ;
0 commit comments