]> git.lizzy.rs Git - rust.git/commitdiff
Support SSE types in extern {} better.
authorHuon Wilson <dbau.pp+github@gmail.com>
Wed, 14 Jan 2015 13:27:38 +0000 (00:27 +1100)
committerHuon Wilson <dbau.pp+github@gmail.com>
Fri, 16 Jan 2015 11:49:39 +0000 (22:49 +1100)
This seems to work on x86-64, but I am not able to test on other
platforms.

cc #20043

src/librustc_trans/trans/cabi_aarch64.rs
src/librustc_trans/trans/cabi_arm.rs
src/librustc_trans/trans/cabi_mips.rs
src/librustc_trans/trans/cabi_x86_64.rs

index 66308503b818d15fabc9f3deed1088bca9988568..ca9b3791ea9806d696c3c630a8956fb978b63214 100644 (file)
@@ -11,7 +11,7 @@
 #![allow(non_upper_case_globals)]
 
 use llvm;
-use llvm::{Integer, Pointer, Float, Double, Struct, Array};
+use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
 use llvm::{StructRetAttribute, ZExtAttribute};
 use trans::cabi::{FnType, ArgType};
 use trans::context::CrateContext;
@@ -50,6 +50,11 @@ fn ty_align(ty: Type) -> uint {
             let elt = ty.element_type();
             ty_align(elt)
         }
+        Vector => {
+            let len = ty.vector_length();
+            let elt = ty.element_type();
+            ty_align(elt) * len
+        }
         _ => panic!("ty_align: unhandled type")
     }
 }
@@ -80,6 +85,12 @@ fn ty_size(ty: Type) -> uint {
             let eltsz = ty_size(elt);
             len * eltsz
         }
+        Vector => {
+            let len = ty.vector_length();
+            let elt = ty.element_type();
+            let eltsz = ty_size(elt);
+            len * eltsz
+        }
         _ => panic!("ty_size: unhandled type")
     }
 }
index 830771d7397e2d3c7c3a16a40f4c4814df7f4d91..2da0c3787e8c5d2f85d52cf124a72e5c54a74d85 100644 (file)
@@ -11,7 +11,7 @@
 #![allow(non_upper_case_globals)]
 
 use llvm;
-use llvm::{Integer, Pointer, Float, Double, Struct, Array};
+use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
 use llvm::{StructRetAttribute, ZExtAttribute};
 use trans::cabi::{FnType, ArgType};
 use trans::context::CrateContext;
@@ -57,6 +57,11 @@ fn general_ty_align(ty: Type) -> uint {
             let elt = ty.element_type();
             general_ty_align(elt)
         }
+        Vector => {
+            let len = ty.vector_length();
+            let elt = ty.element_type();
+            general_ty_align(elt) * len
+        }
         _ => panic!("ty_align: unhandled type")
     }
 }
@@ -90,6 +95,11 @@ fn ios_ty_align(ty: Type) -> uint {
             let elt = ty.element_type();
             ios_ty_align(elt)
         }
+        Vector => {
+            let len = ty.vector_length();
+            let elt = ty.element_type();
+            ios_ty_align(elt) * len
+        }
         _ => panic!("ty_align: unhandled type")
     }
 }
@@ -123,6 +133,12 @@ fn ty_size(ty: Type, align_fn: TyAlignFn) -> uint {
             let eltsz = ty_size(elt, align_fn);
             len * eltsz
         }
+        Vector => {
+            let len = ty.vector_length();
+            let elt = ty.element_type();
+            let eltsz = ty_size(elt, align_fn);
+            len * eltsz
+        }
         _ => panic!("ty_size: unhandled type")
     }
 }
index 4dfe8daf33946806519e8579285338af39efb96c..0a0ab784f57fccb011be70adcee32ec1a70e8092 100644 (file)
@@ -13,7 +13,7 @@
 use libc::c_uint;
 use std::cmp;
 use llvm;
-use llvm::{Integer, Pointer, Float, Double, Struct, Array};
+use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
 use llvm::{StructRetAttribute, ZExtAttribute};
 use trans::cabi::{ArgType, FnType};
 use trans::context::CrateContext;
@@ -50,7 +50,12 @@ fn ty_align(ty: Type) -> uint {
             let elt = ty.element_type();
             ty_align(elt)
         }
-        _ => panic!("ty_size: unhandled type")
+        Vector => {
+            let len = ty.vector_length();
+            let elt = ty.element_type();
+            ty_align(elt) * len
+        }
+        _ => panic!("ty_align: unhandled type")
     }
 }
 
@@ -80,6 +85,12 @@ fn ty_size(ty: Type) -> uint {
             let eltsz = ty_size(elt);
             len * eltsz
         }
+        Vector => {
+            let len = ty.vector_length();
+            let elt = ty.element_type();
+            let eltsz = ty_size(elt);
+            len * eltsz
+        }
         _ => panic!("ty_size: unhandled type")
     }
 }
index c0e80ff08a22eeff54f14228e1c8648b68166ed0..72ace5f95617df94c21fface97bccfcac817cf75 100644 (file)
@@ -16,7 +16,7 @@
 
 use llvm;
 use llvm::{Integer, Pointer, Float, Double};
-use llvm::{Struct, Array, Attribute};
+use llvm::{Struct, Array, Attribute, Vector};
 use llvm::{StructRetAttribute, ByValAttribute, ZExtAttribute};
 use trans::cabi::{ArgType, FnType};
 use trans::context::CrateContext;
@@ -114,7 +114,12 @@ fn ty_align(ty: Type) -> uint {
                 let elt = ty.element_type();
                 ty_align(elt)
             }
-            _ => panic!("ty_size: unhandled type")
+            Vector => {
+                let len = ty.vector_length();
+                let elt = ty.element_type();
+                ty_align(elt) * len
+            }
+            _ => panic!("ty_align: unhandled type")
         }
     }
 
@@ -143,6 +148,13 @@ fn ty_size(ty: Type) -> uint {
                 let eltsz = ty_size(elt);
                 len * eltsz
             }
+            Vector => {
+                let len = ty.vector_length();
+                let elt = ty.element_type();
+                let eltsz = ty_size(elt);
+                len * eltsz
+            }
+
             _ => panic!("ty_size: unhandled type")
         }
     }
@@ -175,6 +187,12 @@ fn unify(cls: &mut [RegClass],
             (_,           X87Up) |
             (_,           ComplexX87) => Memory,
 
+            (SSEFv,       SSEUp) |
+            (SSEFs,       SSEUp) |
+            (SSEDv,       SSEUp) |
+            (SSEDs,       SSEUp) |
+            (SSEInt(_),   SSEUp) => return,
+
             (_,           _) => newv
         };
         cls[i] = to_write;
@@ -240,6 +258,27 @@ fn classify(ty: Type,
                     i += 1u;
                 }
             }
+            Vector => {
+                let len = ty.vector_length();
+                let elt = ty.element_type();
+                let eltsz = ty_size(elt);
+                let mut reg = match elt.kind() {
+                    Integer => SSEInt,
+                    Float => SSEFv,
+                    Double => SSEDv,
+                    _ => panic!("classify: unhandled vector element type")
+                };
+
+                let mut i = 0u;
+                while i < len {
+                    unify(cls, ix + (off + i * eltsz) / 8, reg);
+
+                    // everything after the first one is the upper
+                    // half of a register.
+                    reg = SSEUp;
+                    i += 1u;
+                }
+            }
             _ => panic!("classify: unhandled type")
         }
     }
@@ -248,7 +287,7 @@ fn fixup(ty: Type, cls: &mut [RegClass]) {
         let mut i = 0u;
         let ty_kind = ty.kind();
         let e = cls.len();
-        if cls.len() > 2u && (ty_kind == Struct || ty_kind == Array) {
+        if cls.len() > 2u && (ty_kind == Struct || ty_kind == Array || ty_kind == Vector) {
             if cls[i].is_sse() {
                 i += 1u;
                 while i < e {
@@ -320,9 +359,19 @@ fn llvec_len(cls: &[RegClass]) -> uint {
             Int => {
                 tys.push(Type::i64(ccx));
             }
-            SSEFv => {
+            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"),
+                    _ => unreachable!(),
+                };
                 let vec_len = llvec_len(&cls[(i + 1u)..]);
-                let vec_ty = Type::vector(&Type::f32(ccx), (vec_len * 2u) as u64);
+                let vec_ty = Type::vector(&elt_ty, (vec_len * elts_per_word) as u64);
                 tys.push(vec_ty);
                 i += vec_len;
                 continue;
@@ -337,7 +386,12 @@ fn llvec_len(cls: &[RegClass]) -> uint {
         }
         i += 1u;
     }
-    return Type::struct_(ccx, tys.as_slice(), false);
+    if tys.len() == 1 && tys[0].kind() == Vector {
+        // if the type contains only a vector, pass it as that vector.
+        tys[0]
+    } else {
+        Type::struct_(ccx, tys.as_slice(), false)
+    }
 }
 
 pub fn compute_abi_info(ccx: &CrateContext,