@@ -1329,14 +1329,33 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
13291329 call_debug_location : DebugLoc ,
13301330 call_info : NodeIdAndSpan ) -> ValueRef
13311331{
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+ }
13321344 macro_rules! require {
13331345 ( $cond: expr, $( $fmt: tt) * ) => {
13341346 if !$cond {
1335- bcx . sess ( ) . span_err ( call_info . span , & format !( $( $fmt) * ) ) ;
1347+ emit_error !( $( $fmt) * ) ;
13361348 return C_null ( llret_ty)
13371349 }
13381350 }
13391351 }
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+
13401359
13411360 let tcx = bcx. tcx ( ) ;
13421361 let arg_tys = match callee_ty. sty {
@@ -1346,6 +1365,12 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
13461365 _ => unreachable ! ( )
13471366 } ;
13481367
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+
13491374 let comparison = match name {
13501375 "simd_eq" => Some ( ast:: BiEq ) ,
13511376 "simd_ne" => Some ( ast:: BiNe ) ,
@@ -1357,30 +1382,23 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
13571382 } ;
13581383
13591384 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+
13691387 let out_len = ret_ty. simd_size ( tcx) ;
13701388 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) ;
13771393 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) ) ;
13791397
13801398 return compare_simd_types ( bcx,
13811399 llargs[ 0 ] ,
13821400 llargs[ 1 ] ,
1383- arg_tys [ 0 ] . simd_type ( tcx ) ,
1401+ in_elem ,
13841402 llret_ty,
13851403 cmp_op,
13861404 call_debug_location)
@@ -1390,24 +1408,20 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
13901408 let n: usize = match name[ "simd_shuffle" . len ( ) ..] . parse ( ) {
13911409 Ok ( n) => n,
13921410 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?" )
13941412 } ;
13951413
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" ) ;
14021415
1403- let in_len = arg_tys[ 0 ] . simd_size ( tcx) ;
14041416 let out_len = ret_ty. simd_size ( tcx) ;
14051417 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) ) ;
14111425
14121426 let total_len = in_len as u64 * 2 ;
14131427
@@ -1425,17 +1439,12 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
14251439 let c = const_to_opt_uint ( val) ;
14261440 match c {
14271441 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) ;
14321443 None
14331444 }
14341445 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) ;
14391448 None
14401449 }
14411450 Some ( idx) => Some ( C_i32 ( bcx. ccx ( ) , idx as i32 ) ) ,
@@ -1451,45 +1460,32 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
14511460 }
14521461
14531462 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 ] ) ;
14601466 return InsertElement ( bcx, llargs[ 0 ] , llargs[ 2 ] , llargs[ 1 ] )
14611467 }
14621468 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) ;
14691472 return ExtractElement ( bcx, llargs[ 0 ] , llargs[ 1 ] )
14701473 }
14711474
14721475 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) ;
14861483 // 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) ;
14891485
1490- if in_ == out { return llargs[ 0 ] ; }
1486+ if in_elem == out_elem { return llargs[ 0 ] ; }
14911487
1492- match ( & in_ . sty , & out . sty ) {
1488+ match ( & in_elem . sty , & out_elem . sty ) {
14931489 ( & ty:: TyInt ( lhs) , & ty:: TyInt ( rhs) ) => {
14941490 match ( lhs, rhs) {
14951491 ( ast:: TyI8 , ast:: TyI8 ) |
@@ -1605,20 +1601,15 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
16051601 _ => { }
16061602 }
16071603 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) ;
16121607 }
16131608 macro_rules! arith {
16141609 ( $( $name: ident: $( $( $p: ident) ,* => $call: expr) ,* ; ) * ) => {
16151610 $(
16161611 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 {
16221613 $(
16231614 $( ty:: $p( _) ) |* => {
16241615 return $call( bcx, llargs[ 0 ] , llargs[ 1 ] , call_debug_location)
@@ -1627,11 +1618,9 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
16271618 _ => { } ,
16281619 }
16291620 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)
16351624 } ) *
16361625 }
16371626 }
0 commit comments