From ecb3df5a91b71e31e242737d9203b2798bd489de Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Wed, 29 Jul 2015 16:40:22 -0700 Subject: [PATCH] Add simd_cast intrinsic. --- src/librustc_trans/trans/intrinsic.rs | 51 +++++++++++++++++++++++++++ src/librustc_trans/trans/type_of.rs | 8 +++-- src/librustc_typeck/check/mod.rs | 1 + 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index 7c8deb9a791..88a80076640 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -1445,5 +1445,56 @@ fn generic_simd_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, "SIMD insert intrinsic monomorphised with returned type not SIMD element type"); return ExtractElement(bcx, llargs[0], llargs[1]) } + + if name == "simd_cast" { + require!(arg_tys[0].simd_size(tcx) == ret_ty.simd_size(tcx), + "SIMD cast intrinsic monomorphised with input and \ + return types of different lengths"); + // casting cares about nominal type, not just structural type + let in_ = arg_tys[0].simd_type(tcx); + let out = ret_ty.simd_type(tcx); + + if in_ == out { return llargs[0]; } + + match (&in_.sty, &out.sty) { + (&ty::TyInt(lhs), &ty::TyUint(rhs)) => { + match (lhs, rhs) { + (ast::TyI8, ast::TyU8) | + (ast::TyI16, ast::TyU16) | + (ast::TyI32, ast::TyU32) | + (ast::TyI64, ast::TyU64) => return llargs[0], + _ => {}, + } + } + (&ty::TyUint(lhs), &ty::TyInt(rhs)) => { + match (lhs, rhs) { + (ast::TyU8, ast::TyI8) | + (ast::TyU16, ast::TyI16) | + (ast::TyU32, ast::TyI32) | + (ast::TyU64, ast::TyI64) => return llargs[0], + _ => {}, + } + } + (&ty::TyInt(ast::TyI32), &ty::TyFloat(ast::TyF32)) | + (&ty::TyInt(ast::TyI64), &ty::TyFloat(ast::TyF64)) => { + return SIToFP(bcx, llargs[0], llret_ty) + } + (&ty::TyUint(ast::TyU32), &ty::TyFloat(ast::TyF32)) | + (&ty::TyUint(ast::TyU64), &ty::TyFloat(ast::TyF64)) => { + return UIToFP(bcx, llargs[0], llret_ty) + } + + (&ty::TyFloat(ast::TyF32), &ty::TyInt(ast::TyI32)) | + (&ty::TyFloat(ast::TyF64), &ty::TyInt(ast::TyI64)) => { + return FPToSI(bcx, llargs[0], llret_ty) + } + (&ty::TyFloat(ast::TyF32), &ty::TyUint(ast::TyU32)) | + (&ty::TyFloat(ast::TyF64), &ty::TyUint(ast::TyU64)) => { + return FPToUI(bcx, llargs[0], llret_ty) + } + _ => {} + } + require!(false, "SIMD cast intrinsic monomorphised with incompatible cast"); + } bcx.sess().span_bug(call_info.span, "unknown SIMD intrinsic"); } diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs index 5991d61a1e4..3edd4530ceb 100644 --- a/src/librustc_trans/trans/type_of.rs +++ b/src/librustc_trans/trans/type_of.rs @@ -182,6 +182,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ None => () } + debug!("sizing_type_of {:?}", t); let llsizingty = match t.sty { _ if !type_is_sized(cx.tcx(), t) => { Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false) @@ -240,6 +241,10 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ ty::TySlice(_) | ty::TyTrait(..) | ty::TyStr => unreachable!() }; + debug!("--> mapped t={:?} to llsizingty={}", + t, + cx.tn().type_to_string(llsizingty)); + cx.llsizingtypes().borrow_mut().insert(t, llsizingty); llsizingty } @@ -426,8 +431,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> ty::TyError(..) => cx.sess().bug("type_of with TyError"), }; - debug!("--> mapped t={:?} {:?} to llty={}", - t, + debug!("--> mapped t={:?} to llty={}", t, cx.tn().type_to_string(llty)); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2821538a295..742bd57a130 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5346,6 +5346,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { } "simd_insert" => (2, vec![param(ccx, 0), tcx.types.u32, param(ccx, 1)], param(ccx, 0)), "simd_extract" => (2, vec![param(ccx, 0), tcx.types.u32], param(ccx, 1)), + "simd_cast" => (2, vec![param(ccx, 0)], param(ccx, 1)), name if name.starts_with("simd_shuffle") => { match name["simd_shuffle".len()..].parse() { Ok(n) => {