diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index dbfd76d3082..185a5cb4746 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -1329,14 +1329,33 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a> call_debug_location: DebugLoc, call_info: NodeIdAndSpan) -> ValueRef { + // macros for error handling: + macro_rules! emit_error { + ($msg: tt) => { + emit_error!($msg, ) + }; + ($msg: tt, $($fmt: tt)*) => { + bcx.sess().span_err(call_info.span, + &format!(concat!("invalid monomorphization of `{}` intrinsic: ", + $msg), + name, $($fmt)*)); + } + } macro_rules! require { ($cond: expr, $($fmt: tt)*) => { if !$cond { - bcx.sess().span_err(call_info.span, &format!($($fmt)*)); + emit_error!($($fmt)*); return C_null(llret_ty) } } } + macro_rules! require_simd { + ($ty: expr, $position: expr) => { + require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty) + } + } + + let tcx = bcx.tcx(); let arg_tys = match callee_ty.sty { @@ -1346,6 +1365,12 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a> _ => unreachable!() }; + // every intrinsic takes a SIMD vector as its first argument + require_simd!(arg_tys[0], "input"); + let in_ty = arg_tys[0]; + let in_elem = arg_tys[0].simd_type(tcx); + let in_len = arg_tys[0].simd_size(tcx); + let comparison = match name { "simd_eq" => Some(ast::BiEq), "simd_ne" => Some(ast::BiNe), @@ -1357,30 +1382,23 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a> }; if let Some(cmp_op) = comparison { - assert_eq!(arg_tys.len(), 2); - require!(arg_tys[0].is_simd(), - "SIMD comparison intrinsic monomorphized for non-SIMD argument type `{}`", - arg_tys[0]); - require!(ret_ty.is_simd(), - "SIMD comparison intrinsic monomorphized for non-SIMD return type `{}`", - ret_ty); + require_simd!(ret_ty, "return"); - let in_len = arg_tys[0].simd_size(tcx); let out_len = ret_ty.simd_size(tcx); require!(in_len == out_len, - "SIMD cast intrinsic monomorphized with input type `{}` and \ - return type `{}` with different lengths: {} vs. {}", - arg_tys[0], - ret_ty, - in_len, - out_len); + "expected return type with length {} (same as input type `{}`), \ + found `{}` with length {}", + in_len, in_ty, + ret_ty, out_len); require!(llret_ty.element_type().kind() == llvm::Integer, - "SIMD comparison intrinsic monomorphized with non-integer return"); + "expected return type with integer elements, found `{}` with non-integer `{}`", + ret_ty, + ret_ty.simd_type(tcx)); return compare_simd_types(bcx, llargs[0], llargs[1], - arg_tys[0].simd_type(tcx), + in_elem, llret_ty, cmp_op, call_debug_location) @@ -1390,24 +1408,20 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a> let n: usize = match name["simd_shuffle".len()..].parse() { Ok(n) => n, Err(_) => tcx.sess.span_bug(call_info.span, - "bad `simd_shuffle` instruction only caught in trans?") + "bad `simd_shuffle` instruction only caught in trans?") }; - require!(arg_tys[0].is_simd(), - "SIMD shuffle intrinsic monomorphized with non-SIMD input type `{}`", - arg_tys[0]); - require!(ret_ty.is_simd(), - "SIMD shuffle intrinsic monomorphized for non-SIMD return type `{}`", - ret_ty); + require_simd!(ret_ty, "return"); - let in_len = arg_tys[0].simd_size(tcx); let out_len = ret_ty.simd_size(tcx); require!(out_len == n, - "SIMD shuffle intrinsic monomorphized with return type of length {} (expected {})", - out_len, n); - require!(arg_tys[0].simd_type(tcx) == ret_ty.simd_type(tcx), - "SIMD shuffle intrinsic monomorphized with different \ - input and return element types"); + "expected return type of length {}, found `{}` with length {}", + n, ret_ty, out_len); + require!(in_elem == ret_ty.simd_type(tcx), + "expected return element type `{}` (element of input `{}`), \ + found `{}` with element type `{}`", + in_elem, in_ty, + ret_ty, ret_ty.simd_type(tcx)); let total_len = in_len as u64 * 2; @@ -1425,17 +1439,12 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a> let c = const_to_opt_uint(val); match c { None => { - bcx.sess().span_err(call_info.span, - &format!("SIMD shuffle intrinsic argument #{} \ - is not a constant", - arg_idx)); + emit_error!("shuffle index #{} is not a constant", arg_idx); None } Some(idx) if idx >= total_len => { - bcx.sess().span_err(call_info.span, - &format!("SIMD shuffle intrinsic argument #{} \ - is out of bounds (limit {})", - arg_idx, total_len)); + emit_error!("shuffle index #{} is out of bounds (limit {})", + arg_idx, total_len); None } Some(idx) => Some(C_i32(bcx.ccx(), idx as i32)), @@ -1451,45 +1460,32 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a> } if name == "simd_insert" { - require!(arg_tys[0].is_simd(), - "SIMD insert intrinsic monomorphized for non-SIMD input type"); - - let elem_ty = arg_tys[0].simd_type(tcx); - require!(arg_tys[2] == elem_ty, - "SIMD insert intrinsic monomorphized with inserted type not SIMD element type"); + require!(in_elem == arg_tys[2], + "expected inserted type `{}` (element of input `{}`), found `{}`", + in_elem, in_ty, arg_tys[2]); return InsertElement(bcx, llargs[0], llargs[2], llargs[1]) } if name == "simd_extract" { - require!(arg_tys[0].is_simd(), - "SIMD insert intrinsic monomorphized for non-SIMD input type"); - - let elem_ty = arg_tys[0].simd_type(tcx); - require!(ret_ty == elem_ty, - "SIMD insert intrinsic monomorphized with returned type not SIMD element type"); + require!(ret_ty == in_elem, + "expected return type `{}` (element of input `{}`), found `{}`", + in_elem, in_ty, ret_ty); return ExtractElement(bcx, llargs[0], llargs[1]) } if name == "simd_cast" { - require!(arg_tys[0].is_simd(), - "SIMD cast intrinsic monomorphized with non-SIMD input type `{}`", - arg_tys[0]); - require!(ret_ty.is_simd(), - "SIMD cast intrinsic monomorphized with non-SIMD return type `{}`", - ret_ty); - require!(arg_tys[0].simd_size(tcx) == ret_ty.simd_size(tcx), - "SIMD cast intrinsic monomorphized with input type `{}` and \ - return type `{}` with different lengths: {} vs. {}", - arg_tys[0], - ret_ty, - arg_tys[0].simd_size(tcx), - ret_ty.simd_size(tcx)); + require_simd!(ret_ty, "return"); + let out_len = ret_ty.simd_size(tcx); + require!(in_len == out_len, + "expected return type with length {} (same as input type `{}`), \ + found `{}` with length {}", + in_len, in_ty, + ret_ty, out_len); // casting cares about nominal type, not just structural type - let in_ = arg_tys[0].simd_type(tcx); - let out = ret_ty.simd_type(tcx); + let out_elem = ret_ty.simd_type(tcx); - if in_ == out { return llargs[0]; } + if in_elem == out_elem { return llargs[0]; } - match (&in_.sty, &out.sty) { + match (&in_elem.sty, &out_elem.sty) { (&ty::TyInt(lhs), &ty::TyInt(rhs)) => { match (lhs, rhs) { (ast::TyI8, ast::TyI8) | @@ -1605,20 +1601,15 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a> _ => {} } require!(false, - "SIMD cast intrinsic monomorphized with incompatible cast \ - from `{}` (element `{}`)to `{}` (element `{}`)", - arg_tys[0], in_, - ret_ty, out); + "unsupported cast from `{}` with element `{}` to `{}` with element `{}`", + in_ty, in_elem, + ret_ty, out_elem); } macro_rules! arith { ($($name: ident: $($($p: ident),* => $call: expr),*;)*) => { $( if name == stringify!($name) { - require!(arg_tys[0].is_simd(), - "`{}` intrinsic monomorphized with non-SIMD type `{}`", - name, arg_tys[0]); - let in_ = arg_tys[0].simd_type(tcx); - match in_.sty { + match in_elem.sty { $( $(ty::$p(_))|* => { return $call(bcx, llargs[0], llargs[1], call_debug_location) @@ -1627,11 +1618,9 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a> _ => {}, } require!(false, - "`{}` intrinsic monomorphized with SIMD vector `{}` \ - with unsupported element type `{}`", - name, - arg_tys[0], - in_) + "unsupported operation on `{}` with element `{}`", + in_ty, + in_elem) })* } } diff --git a/src/test/compile-fail/simd-intrinsic-generic-arithmetic.rs b/src/test/compile-fail/simd-intrinsic-generic-arithmetic.rs index d4fbcb41e2a..35c368f4cbe 100644 --- a/src/test/compile-fail/simd-intrinsic-generic-arithmetic.rs +++ b/src/test/compile-fail/simd-intrinsic-generic-arithmetic.rs @@ -65,38 +65,38 @@ fn main() { simd_add(0, 0); - //~^ ERROR `simd_add` intrinsic monomorphized with non-SIMD type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_sub(0, 0); - //~^ ERROR `simd_sub` intrinsic monomorphized with non-SIMD type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_mul(0, 0); - //~^ ERROR `simd_mul` intrinsic monomorphized with non-SIMD type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_div(0, 0); - //~^ ERROR `simd_div` intrinsic monomorphized with non-SIMD type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_shl(0, 0); - //~^ ERROR `simd_shl` intrinsic monomorphized with non-SIMD type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_shr(0, 0); - //~^ ERROR `simd_shr` intrinsic monomorphized with non-SIMD type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_and(0, 0); - //~^ ERROR `simd_and` intrinsic monomorphized with non-SIMD type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_or(0, 0); - //~^ ERROR `simd_or` intrinsic monomorphized with non-SIMD type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_xor(0, 0); - //~^ ERROR `simd_xor` intrinsic monomorphized with non-SIMD type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_div(x, x); -//~^ ERROR `simd_div` intrinsic monomorphized with SIMD vector `i32x4` with unsupported element type +//~^ ERROR unsupported operation on `i32x4` with element `i32` simd_div(y, y); -//~^ ERROR `simd_div` intrinsic monomorphized with SIMD vector `u32x4` with unsupported element type +//~^ ERROR unsupported operation on `u32x4` with element `u32` simd_shl(z, z); -//~^ ERROR `simd_shl` intrinsic monomorphized with SIMD vector `f32x4` with unsupported element type +//~^ ERROR unsupported operation on `f32x4` with element `f32` simd_shr(z, z); -//~^ ERROR `simd_shr` intrinsic monomorphized with SIMD vector `f32x4` with unsupported element type +//~^ ERROR unsupported operation on `f32x4` with element `f32` simd_and(z, z); -//~^ ERROR `simd_and` intrinsic monomorphized with SIMD vector `f32x4` with unsupported element type +//~^ ERROR unsupported operation on `f32x4` with element `f32` simd_or(z, z); -//~^ ERROR `simd_or` intrinsic monomorphized with SIMD vector `f32x4` with unsupported element type +//~^ ERROR unsupported operation on `f32x4` with element `f32` simd_xor(z, z); -//~^ ERROR `simd_xor` intrinsic monomorphized with SIMD vector `f32x4` with unsupported element type +//~^ ERROR unsupported operation on `f32x4` with element `f32` } } diff --git a/src/test/compile-fail/simd-intrinsic-generic-cast.rs b/src/test/compile-fail/simd-intrinsic-generic-cast.rs index 333ef756e1f..4999b790b13 100644 --- a/src/test/compile-fail/simd-intrinsic-generic-cast.rs +++ b/src/test/compile-fail/simd-intrinsic-generic-cast.rs @@ -40,12 +40,12 @@ fn main() { unsafe { simd_cast::(0); - //~^ ERROR SIMD cast intrinsic monomorphized with non-SIMD input type `i32` + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_cast::(0); - //~^ ERROR SIMD cast intrinsic monomorphized with non-SIMD input type `i32` + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_cast::(x); - //~^ ERROR SIMD cast intrinsic monomorphized with non-SIMD return type `i32` + //~^ ERROR expected SIMD return type, found non-SIMD `i32` simd_cast::<_, i32x8>(x); -//~^ ERROR monomorphized with input type `i32x4` and return type `i32x8` with different lengths +//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i32x8` with length 8 } } diff --git a/src/test/compile-fail/simd-intrinsic-generic-comparison.rs b/src/test/compile-fail/simd-intrinsic-generic-comparison.rs index 37827fbb6fb..617b03a8711 100644 --- a/src/test/compile-fail/simd-intrinsic-generic-comparison.rs +++ b/src/test/compile-fail/simd-intrinsic-generic-comparison.rs @@ -34,42 +34,42 @@ fn main() { unsafe { simd_eq::(0, 0); - //~^ ERROR SIMD comparison intrinsic monomorphized for non-SIMD argument type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_ne::(0, 0); - //~^ ERROR SIMD comparison intrinsic monomorphized for non-SIMD argument type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_lt::(0, 0); - //~^ ERROR SIMD comparison intrinsic monomorphized for non-SIMD argument type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_le::(0, 0); - //~^ ERROR SIMD comparison intrinsic monomorphized for non-SIMD argument type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_gt::(0, 0); - //~^ ERROR SIMD comparison intrinsic monomorphized for non-SIMD argument type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_ge::(0, 0); - //~^ ERROR SIMD comparison intrinsic monomorphized for non-SIMD argument type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_eq::<_, i32>(x, x); - //~^ ERROR SIMD comparison intrinsic monomorphized for non-SIMD return type + //~^ ERROR expected SIMD return type, found non-SIMD `i32` simd_ne::<_, i32>(x, x); - //~^ ERROR SIMD comparison intrinsic monomorphized for non-SIMD return type + //~^ ERROR expected SIMD return type, found non-SIMD `i32` simd_lt::<_, i32>(x, x); - //~^ ERROR SIMD comparison intrinsic monomorphized for non-SIMD return type + //~^ ERROR expected SIMD return type, found non-SIMD `i32` simd_le::<_, i32>(x, x); - //~^ ERROR SIMD comparison intrinsic monomorphized for non-SIMD return type + //~^ ERROR expected SIMD return type, found non-SIMD `i32` simd_gt::<_, i32>(x, x); - //~^ ERROR SIMD comparison intrinsic monomorphized for non-SIMD return type + //~^ ERROR expected SIMD return type, found non-SIMD `i32` simd_ge::<_, i32>(x, x); - //~^ ERROR SIMD comparison intrinsic monomorphized for non-SIMD return type + //~^ ERROR expected SIMD return type, found non-SIMD `i32` simd_eq::<_, i16x8>(x, x); -//~^ ERROR monomorphized with input type `i32x4` and return type `i16x8` with different lengths +//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 simd_ne::<_, i16x8>(x, x); -//~^ ERROR monomorphized with input type `i32x4` and return type `i16x8` with different lengths +//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 simd_lt::<_, i16x8>(x, x); -//~^ ERROR monomorphized with input type `i32x4` and return type `i16x8` with different lengths +//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 simd_le::<_, i16x8>(x, x); -//~^ ERROR monomorphized with input type `i32x4` and return type `i16x8` with different lengths +//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 simd_gt::<_, i16x8>(x, x); -//~^ ERROR monomorphized with input type `i32x4` and return type `i16x8` with different lengths +//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 simd_ge::<_, i16x8>(x, x); -//~^ ERROR monomorphized with input type `i32x4` and return type `i16x8` with different lengths +//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 } } diff --git a/src/test/compile-fail/simd-intrinsic-generic-elements.rs b/src/test/compile-fail/simd-intrinsic-generic-elements.rs index ebe442c1a2e..b0198c411d5 100644 --- a/src/test/compile-fail/simd-intrinsic-generic-elements.rs +++ b/src/test/compile-fail/simd-intrinsic-generic-elements.rs @@ -61,28 +61,37 @@ fn main() { unsafe { simd_insert(0, 0, 0); - //~^ ERROR SIMD insert intrinsic monomorphized for non-SIMD input type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_insert(x, 0, 1.0); - //~^ ERROR SIMD insert intrinsic monomorphized with inserted type not SIMD element type + //~^ ERROR expected inserted type `i32` (element of input `i32x4`), found `f64` simd_extract::<_, f32>(x, 0); - //~^ ERROR SIMD insert intrinsic monomorphized with returned type not SIMD element type + //~^ ERROR expected return type `i32` (element of input `i32x4`), found `f32` simd_shuffle2::(0, 0, [0; 2]); - //~^ ERROR SIMD shuffle intrinsic monomorphized with non-SIMD input type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_shuffle3::(0, 0, [0; 3]); - //~^ ERROR SIMD shuffle intrinsic monomorphized with non-SIMD input type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_shuffle4::(0, 0, [0; 4]); - //~^ ERROR SIMD shuffle intrinsic monomorphized with non-SIMD input type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_shuffle8::(0, 0, [0; 8]); - //~^ ERROR SIMD shuffle intrinsic monomorphized with non-SIMD input type + //~^ ERROR expected SIMD input type, found non-SIMD `i32` simd_shuffle2::<_, f32x2>(x, x, [0; 2]); - //~^ ERROR SIMD shuffle intrinsic monomorphized with different input and return element +//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` simd_shuffle3::<_, f32x3>(x, x, [0; 3]); - //~^ ERROR SIMD shuffle intrinsic monomorphized with different input and return element +//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x3` with element type `f32` simd_shuffle4::<_, f32x4>(x, x, [0; 4]); - //~^ ERROR SIMD shuffle intrinsic monomorphized with different input and return element +//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` simd_shuffle8::<_, f32x8>(x, x, [0; 8]); - //~^ ERROR SIMD shuffle intrinsic monomorphized with different input and return element +//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` + + simd_shuffle2::<_, i32x8>(x, x, [0; 2]); + //~^ ERROR expected return type of length 2, found `i32x8` with length 8 + simd_shuffle3::<_, i32x4>(x, x, [0; 3]); + //~^ ERROR expected return type of length 3, found `i32x4` with length 4 + simd_shuffle4::<_, i32x3>(x, x, [0; 4]); + //~^ ERROR expected return type of length 4, found `i32x3` with length 3 + simd_shuffle8::<_, i32x2>(x, x, [0; 8]); + //~^ ERROR expected return type of length 8, found `i32x2` with length 2 } }