@@ -1329,14 +1329,33 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
1329
1329
call_debug_location : DebugLoc ,
1330
1330
call_info : NodeIdAndSpan ) -> ValueRef
1331
1331
{
1332
+ // macros for error handling:
1333
+ macro_rules! emit_error {
1334
+ ( $msg: tt) => {
1335
+ emit_error!( $msg, )
1336
+ } ;
1337
+ ( $msg: tt, $( $fmt: tt) * ) => {
1338
+ bcx. sess( ) . span_err( call_info. span,
1339
+ & format!( concat!( "invalid monomorphization of `{}` intrinsic: " ,
1340
+ $msg) ,
1341
+ name, $( $fmt) * ) ) ;
1342
+ }
1343
+ }
1332
1344
macro_rules! require {
1333
1345
( $cond: expr, $( $fmt: tt) * ) => {
1334
1346
if !$cond {
1335
- bcx . sess ( ) . span_err ( call_info . span , & format !( $( $fmt) * ) ) ;
1347
+ emit_error !( $( $fmt) * ) ;
1336
1348
return C_null ( llret_ty)
1337
1349
}
1338
1350
}
1339
1351
}
1352
+ macro_rules! require_simd {
1353
+ ( $ty: expr, $position: expr) => {
1354
+ require!( $ty. is_simd( ) , "expected SIMD {} type, found non-SIMD `{}`" , $position, $ty)
1355
+ }
1356
+ }
1357
+
1358
+
1340
1359
1341
1360
let tcx = bcx. tcx ( ) ;
1342
1361
let arg_tys = match callee_ty. sty {
@@ -1346,6 +1365,12 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
1346
1365
_ => unreachable ! ( )
1347
1366
} ;
1348
1367
1368
+ // every intrinsic takes a SIMD vector as its first argument
1369
+ require_simd ! ( arg_tys[ 0 ] , "input" ) ;
1370
+ let in_ty = arg_tys[ 0 ] ;
1371
+ let in_elem = arg_tys[ 0 ] . simd_type ( tcx) ;
1372
+ let in_len = arg_tys[ 0 ] . simd_size ( tcx) ;
1373
+
1349
1374
let comparison = match name {
1350
1375
"simd_eq" => Some ( ast:: BiEq ) ,
1351
1376
"simd_ne" => Some ( ast:: BiNe ) ,
@@ -1357,30 +1382,23 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
1357
1382
} ;
1358
1383
1359
1384
if let Some ( cmp_op) = comparison {
1360
- assert_eq ! ( arg_tys. len( ) , 2 ) ;
1361
- require ! ( arg_tys[ 0 ] . is_simd( ) ,
1362
- "SIMD comparison intrinsic monomorphized for non-SIMD argument type `{}`" ,
1363
- arg_tys[ 0 ] ) ;
1364
- require ! ( ret_ty. is_simd( ) ,
1365
- "SIMD comparison intrinsic monomorphized for non-SIMD return type `{}`" ,
1366
- ret_ty) ;
1367
-
1368
- let in_len = arg_tys[ 0 ] . simd_size ( tcx) ;
1385
+ require_simd ! ( ret_ty, "return" ) ;
1386
+
1369
1387
let out_len = ret_ty. simd_size ( tcx) ;
1370
1388
require ! ( in_len == out_len,
1371
- "SIMD cast intrinsic monomorphized with input type `{}` and \
1372
- return type `{}` with different lengths: {} vs. {}",
1373
- arg_tys[ 0 ] ,
1374
- ret_ty,
1375
- in_len,
1376
- out_len) ;
1389
+ "expected return type with length {} (same as input type `{}`), \
1390
+ found `{}` with length {}",
1391
+ in_len, in_ty,
1392
+ ret_ty, out_len) ;
1377
1393
require ! ( llret_ty. element_type( ) . kind( ) == llvm:: Integer ,
1378
- "SIMD comparison intrinsic monomorphized with non-integer return" ) ;
1394
+ "expected return type with integer elements, found `{}` with non-integer `{}`" ,
1395
+ ret_ty,
1396
+ ret_ty. simd_type( tcx) ) ;
1379
1397
1380
1398
return compare_simd_types ( bcx,
1381
1399
llargs[ 0 ] ,
1382
1400
llargs[ 1 ] ,
1383
- arg_tys [ 0 ] . simd_type ( tcx ) ,
1401
+ in_elem ,
1384
1402
llret_ty,
1385
1403
cmp_op,
1386
1404
call_debug_location)
@@ -1390,24 +1408,20 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
1390
1408
let n: usize = match name[ "simd_shuffle" . len ( ) ..] . parse ( ) {
1391
1409
Ok ( n) => n,
1392
1410
Err ( _) => tcx. sess . span_bug ( call_info. span ,
1393
- "bad `simd_shuffle` instruction only caught in trans?" )
1411
+ "bad `simd_shuffle` instruction only caught in trans?" )
1394
1412
} ;
1395
1413
1396
- require ! ( arg_tys[ 0 ] . is_simd( ) ,
1397
- "SIMD shuffle intrinsic monomorphized with non-SIMD input type `{}`" ,
1398
- arg_tys[ 0 ] ) ;
1399
- require ! ( ret_ty. is_simd( ) ,
1400
- "SIMD shuffle intrinsic monomorphized for non-SIMD return type `{}`" ,
1401
- ret_ty) ;
1414
+ require_simd ! ( ret_ty, "return" ) ;
1402
1415
1403
- let in_len = arg_tys[ 0 ] . simd_size ( tcx) ;
1404
1416
let out_len = ret_ty. simd_size ( tcx) ;
1405
1417
require ! ( out_len == n,
1406
- "SIMD shuffle intrinsic monomorphized with return type of length {} (expected {})" ,
1407
- out_len, n) ;
1408
- require ! ( arg_tys[ 0 ] . simd_type( tcx) == ret_ty. simd_type( tcx) ,
1409
- "SIMD shuffle intrinsic monomorphized with different \
1410
- input and return element types") ;
1418
+ "expected return type of length {}, found `{}` with length {}" ,
1419
+ n, ret_ty, out_len) ;
1420
+ require ! ( in_elem == ret_ty. simd_type( tcx) ,
1421
+ "expected return element type `{}` (element of input `{}`), \
1422
+ found `{}` with element type `{}`",
1423
+ in_elem, in_ty,
1424
+ ret_ty, ret_ty. simd_type( tcx) ) ;
1411
1425
1412
1426
let total_len = in_len as u64 * 2 ;
1413
1427
@@ -1425,17 +1439,12 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
1425
1439
let c = const_to_opt_uint ( val) ;
1426
1440
match c {
1427
1441
None => {
1428
- bcx. sess ( ) . span_err ( call_info. span ,
1429
- & format ! ( "SIMD shuffle intrinsic argument #{} \
1430
- is not a constant",
1431
- arg_idx) ) ;
1442
+ emit_error ! ( "shuffle index #{} is not a constant" , arg_idx) ;
1432
1443
None
1433
1444
}
1434
1445
Some ( idx) if idx >= total_len => {
1435
- bcx. sess ( ) . span_err ( call_info. span ,
1436
- & format ! ( "SIMD shuffle intrinsic argument #{} \
1437
- is out of bounds (limit {})",
1438
- arg_idx, total_len) ) ;
1446
+ emit_error ! ( "shuffle index #{} is out of bounds (limit {})" ,
1447
+ arg_idx, total_len) ;
1439
1448
None
1440
1449
}
1441
1450
Some ( idx) => Some ( C_i32 ( bcx. ccx ( ) , idx as i32 ) ) ,
@@ -1451,45 +1460,32 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
1451
1460
}
1452
1461
1453
1462
if name == "simd_insert" {
1454
- require ! ( arg_tys[ 0 ] . is_simd( ) ,
1455
- "SIMD insert intrinsic monomorphized for non-SIMD input type" ) ;
1456
-
1457
- let elem_ty = arg_tys[ 0 ] . simd_type ( tcx) ;
1458
- require ! ( arg_tys[ 2 ] == elem_ty,
1459
- "SIMD insert intrinsic monomorphized with inserted type not SIMD element type" ) ;
1463
+ require ! ( in_elem == arg_tys[ 2 ] ,
1464
+ "expected inserted type `{}` (element of input `{}`), found `{}`" ,
1465
+ in_elem, in_ty, arg_tys[ 2 ] ) ;
1460
1466
return InsertElement ( bcx, llargs[ 0 ] , llargs[ 2 ] , llargs[ 1 ] )
1461
1467
}
1462
1468
if name == "simd_extract" {
1463
- require ! ( arg_tys[ 0 ] . is_simd( ) ,
1464
- "SIMD insert intrinsic monomorphized for non-SIMD input type" ) ;
1465
-
1466
- let elem_ty = arg_tys[ 0 ] . simd_type ( tcx) ;
1467
- require ! ( ret_ty == elem_ty,
1468
- "SIMD insert intrinsic monomorphized with returned type not SIMD element type" ) ;
1469
+ require ! ( ret_ty == in_elem,
1470
+ "expected return type `{}` (element of input `{}`), found `{}`" ,
1471
+ in_elem, in_ty, ret_ty) ;
1469
1472
return ExtractElement ( bcx, llargs[ 0 ] , llargs[ 1 ] )
1470
1473
}
1471
1474
1472
1475
if name == "simd_cast" {
1473
- require ! ( arg_tys[ 0 ] . is_simd( ) ,
1474
- "SIMD cast intrinsic monomorphized with non-SIMD input type `{}`" ,
1475
- arg_tys[ 0 ] ) ;
1476
- require ! ( ret_ty. is_simd( ) ,
1477
- "SIMD cast intrinsic monomorphized with non-SIMD return type `{}`" ,
1478
- ret_ty) ;
1479
- require ! ( arg_tys[ 0 ] . simd_size( tcx) == ret_ty. simd_size( tcx) ,
1480
- "SIMD cast intrinsic monomorphized with input type `{}` and \
1481
- return type `{}` with different lengths: {} vs. {}",
1482
- arg_tys[ 0 ] ,
1483
- ret_ty,
1484
- arg_tys[ 0 ] . simd_size( tcx) ,
1485
- ret_ty. simd_size( tcx) ) ;
1476
+ require_simd ! ( ret_ty, "return" ) ;
1477
+ let out_len = ret_ty. simd_size ( tcx) ;
1478
+ require ! ( in_len == out_len,
1479
+ "expected return type with length {} (same as input type `{}`), \
1480
+ found `{}` with length {}",
1481
+ in_len, in_ty,
1482
+ ret_ty, out_len) ;
1486
1483
// casting cares about nominal type, not just structural type
1487
- let in_ = arg_tys[ 0 ] . simd_type ( tcx) ;
1488
- let out = ret_ty. simd_type ( tcx) ;
1484
+ let out_elem = ret_ty. simd_type ( tcx) ;
1489
1485
1490
- if in_ == out { return llargs[ 0 ] ; }
1486
+ if in_elem == out_elem { return llargs[ 0 ] ; }
1491
1487
1492
- match ( & in_ . sty , & out . sty ) {
1488
+ match ( & in_elem . sty , & out_elem . sty ) {
1493
1489
( & ty:: TyInt ( lhs) , & ty:: TyInt ( rhs) ) => {
1494
1490
match ( lhs, rhs) {
1495
1491
( ast:: TyI8 , ast:: TyI8 ) |
@@ -1605,20 +1601,15 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
1605
1601
_ => { }
1606
1602
}
1607
1603
require ! ( false ,
1608
- "SIMD cast intrinsic monomorphized with incompatible cast \
1609
- from `{}` (element `{}`)to `{}` (element `{}`)",
1610
- arg_tys[ 0 ] , in_,
1611
- ret_ty, out) ;
1604
+ "unsupported cast from `{}` with element `{}` to `{}` with element `{}`" ,
1605
+ in_ty, in_elem,
1606
+ ret_ty, out_elem) ;
1612
1607
}
1613
1608
macro_rules! arith {
1614
1609
( $( $name: ident: $( $( $p: ident) ,* => $call: expr) ,* ; ) * ) => {
1615
1610
$(
1616
1611
if name == stringify!( $name) {
1617
- require!( arg_tys[ 0 ] . is_simd( ) ,
1618
- "`{}` intrinsic monomorphized with non-SIMD type `{}`" ,
1619
- name, arg_tys[ 0 ] ) ;
1620
- let in_ = arg_tys[ 0 ] . simd_type( tcx) ;
1621
- match in_. sty {
1612
+ match in_elem. sty {
1622
1613
$(
1623
1614
$( ty:: $p( _) ) |* => {
1624
1615
return $call( bcx, llargs[ 0 ] , llargs[ 1 ] , call_debug_location)
@@ -1627,11 +1618,9 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
1627
1618
_ => { } ,
1628
1619
}
1629
1620
require!( false ,
1630
- "`{}` intrinsic monomorphized with SIMD vector `{}` \
1631
- with unsupported element type `{}`",
1632
- name,
1633
- arg_tys[ 0 ] ,
1634
- in_)
1621
+ "unsupported operation on `{}` with element `{}`" ,
1622
+ in_ty,
1623
+ in_elem)
1635
1624
} ) *
1636
1625
}
1637
1626
}
0 commit comments