Revamp SIMD intrinsic trans error handling.

Factor out common pieces, follow `expected ..., found ...` convention
everywhere.
This commit is contained in:
Huon Wilson 2015-08-14 15:20:22 -07:00
parent 891c91438d
commit 502f9acbe9
5 changed files with 128 additions and 130 deletions

View File

@ -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 @@ macro_rules! require {
_ => 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 @@ macro_rules! require {
};
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 @@ macro_rules! require {
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 @@ macro_rules! require {
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 @@ macro_rules! require {
}
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 @@ macro_rules! require {
_ => {}
}
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 @@ macro_rules! arith {
_ => {},
}
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)
})*
}
}

View File

@ -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`
}
}

View File

@ -40,12 +40,12 @@ fn main() {
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
}
}

View File

@ -34,42 +34,42 @@ fn main() {
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
}
}

View File

@ -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::<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
}
}