]> git.lizzy.rs Git - rust.git/commitdiff
Support SSE with integer types in x86-64 FFI.
authorHuon Wilson <dbau.pp+github@gmail.com>
Thu, 15 Jan 2015 02:49:41 +0000 (13:49 +1100)
committerHuon Wilson <dbau.pp+github@gmail.com>
Fri, 16 Jan 2015 11:49:40 +0000 (22:49 +1100)
Unlike the intrinics in C, this types the SSE values base on integer
size. This matches the LLVM intrinsics which have concrete vector types
(`<4 x i32>` etc.), and is no loss of expressivity: if one is using a C
function that really takes an untyped integral SSE value, just give it
whatever Rust type makes most sense.

src/librustc_trans/trans/cabi_x86_64.rs

index d8bd57785d21317e7b9b7d56e062350bc3685713..980a70256e9369fb1514f7fffa5ad48d9bac88d3 100644 (file)
@@ -32,7 +32,7 @@ enum RegClass {
     SSEFv,
     SSEDs,
     SSEDv,
-    SSEInt,
+    SSEInt(/* bitwidth */ u64),
     /// Data that can appear in the upper half of an SSE register.
     SSEUp,
     X87,
@@ -57,7 +57,7 @@ fn is_reg_ty(&self) -> bool {
 impl RegClass {
     fn is_sse(&self) -> bool {
         match *self {
-            SSEFs | SSEFv | SSEDs | SSEDv => true,
+            SSEFs | SSEFv | SSEDs | SSEDv | SSEInt(_) => true,
             _ => false
         }
     }
@@ -254,7 +254,7 @@ fn classify(ty: Type,
                 let elt = ty.element_type();
                 let eltsz = ty_size(elt);
                 let mut reg = match elt.kind() {
-                    Integer => SSEInt,
+                    Integer => SSEInt(elt.int_width()),
                     Float => SSEFv,
                     Double => SSEDv,
                     _ => panic!("classify: unhandled vector element type")
@@ -350,19 +350,19 @@ fn llvec_len(cls: &[RegClass]) -> uint {
             Int => {
                 tys.push(Type::i64(ccx));
             }
-            SSEFv | SSEDv | SSEInt => {
+            SSEFv | SSEDv | SSEInt(_) => {
                 let (elts_per_word, elt_ty) = match cls[i] {
                     SSEFv => (2, Type::f32(ccx)),
                     SSEDv => (1, Type::f64(ccx)),
-                    // FIXME: need to handle the element types, since
-                    // C doesn't distinguish between the contained
-                    // types of the vector at all; normalise to u8,
-                    // maybe?
-                    SSEInt => panic!("llregtype: SSEInt not yet supported"),
+                    SSEInt(bits) => {
+                        assert!(bits == 8 || bits == 16 || bits == 32 || bits == 64,
+                                "llreg_ty: unsupported SSEInt width {}", bits);
+                        (64 / bits, Type::ix(ccx, bits))
+                    }
                     _ => unreachable!(),
                 };
                 let vec_len = llvec_len(&cls[(i + 1u)..]);
-                let vec_ty = Type::vector(&elt_ty, (vec_len * elts_per_word) as u64);
+                let vec_ty = Type::vector(&elt_ty, vec_len as u64 * elts_per_word);
                 tys.push(vec_ty);
                 i += vec_len;
                 continue;