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 {
_ => 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),
};
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);
-
- let in_len = arg_tys[0].simd_size(tcx);
+ require_simd!(ret_ty, "return");
+
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)
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;
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)),
}
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) |
_ => {}
}
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)
_ => {},
}
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)
})*
}
}
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`
}
}
unsafe {
simd_cast::<i32, i32>(0);
- //~^ ERROR SIMD cast intrinsic monomorphized with non-SIMD input type `i32`
+ //~^ ERROR expected SIMD input type, found non-SIMD `i32`
simd_cast::<i32, i32x4>(0);
- //~^ ERROR SIMD cast intrinsic monomorphized with non-SIMD input type `i32`
+ //~^ ERROR expected SIMD input type, found non-SIMD `i32`
simd_cast::<i32x4, i32>(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
}
}
unsafe {
simd_eq::<i32, i32>(0, 0);
- //~^ ERROR SIMD comparison intrinsic monomorphized for non-SIMD argument type
+ //~^ ERROR expected SIMD input type, found non-SIMD `i32`
simd_ne::<i32, i32>(0, 0);
- //~^ ERROR SIMD comparison intrinsic monomorphized for non-SIMD argument type
+ //~^ ERROR expected SIMD input type, found non-SIMD `i32`
simd_lt::<i32, i32>(0, 0);
- //~^ ERROR SIMD comparison intrinsic monomorphized for non-SIMD argument type
+ //~^ ERROR expected SIMD input type, found non-SIMD `i32`
simd_le::<i32, i32>(0, 0);
- //~^ ERROR SIMD comparison intrinsic monomorphized for non-SIMD argument type
+ //~^ ERROR expected SIMD input type, found non-SIMD `i32`
simd_gt::<i32, i32>(0, 0);
- //~^ ERROR SIMD comparison intrinsic monomorphized for non-SIMD argument type
+ //~^ ERROR expected SIMD input type, found non-SIMD `i32`
simd_ge::<i32, i32>(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
}
}
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::<i32, i32>(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::<i32, i32>(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::<i32, i32>(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::<i32, i32>(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
}
}