about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorHuon Wilson <dbau.pp+github@gmail.com>2015-07-29 16:40:22 -0700
committerHuon Wilson <dbau.pp+github@gmail.com>2015-08-17 14:41:38 -0700
commitecb3df5a91b71e31e242737d9203b2798bd489de (patch)
tree278555f6cd710143bb47bf982a90b3bb37d51299 /src
parentf1d3b0271ef62e52e65962744701861c32534114 (diff)
downloadrust-ecb3df5a91b71e31e242737d9203b2798bd489de.tar.gz
rust-ecb3df5a91b71e31e242737d9203b2798bd489de.zip
Add simd_cast intrinsic.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_trans/trans/intrinsic.rs51
-rw-r--r--src/librustc_trans/trans/type_of.rs8
-rw-r--r--src/librustc_typeck/check/mod.rs1
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) => {