Support SSE types in extern {} better.

This seems to work on x86-64, but I am not able to test on other
platforms.

cc #20043
This commit is contained in:
Huon Wilson 2015-01-15 00:27:38 +11:00
parent 4ebde950f5
commit 3d59a476e5
4 changed files with 102 additions and 10 deletions

View File

@ -11,7 +11,7 @@
#![allow(non_upper_case_globals)] #![allow(non_upper_case_globals)]
use llvm; use llvm;
use llvm::{Integer, Pointer, Float, Double, Struct, Array}; use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
use llvm::{StructRetAttribute, ZExtAttribute}; use llvm::{StructRetAttribute, ZExtAttribute};
use trans::cabi::{FnType, ArgType}; use trans::cabi::{FnType, ArgType};
use trans::context::CrateContext; use trans::context::CrateContext;
@ -50,6 +50,11 @@ fn ty_align(ty: Type) -> uint {
let elt = ty.element_type(); let elt = ty.element_type();
ty_align(elt) ty_align(elt)
} }
Vector => {
let len = ty.vector_length();
let elt = ty.element_type();
ty_align(elt) * len
}
_ => panic!("ty_align: unhandled type") _ => panic!("ty_align: unhandled type")
} }
} }
@ -80,6 +85,12 @@ fn ty_size(ty: Type) -> uint {
let eltsz = ty_size(elt); let eltsz = ty_size(elt);
len * eltsz 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") _ => panic!("ty_size: unhandled type")
} }
} }

View File

@ -11,7 +11,7 @@
#![allow(non_upper_case_globals)] #![allow(non_upper_case_globals)]
use llvm; use llvm;
use llvm::{Integer, Pointer, Float, Double, Struct, Array}; use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
use llvm::{StructRetAttribute, ZExtAttribute}; use llvm::{StructRetAttribute, ZExtAttribute};
use trans::cabi::{FnType, ArgType}; use trans::cabi::{FnType, ArgType};
use trans::context::CrateContext; use trans::context::CrateContext;
@ -57,6 +57,11 @@ fn general_ty_align(ty: Type) -> uint {
let elt = ty.element_type(); let elt = ty.element_type();
general_ty_align(elt) 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") _ => panic!("ty_align: unhandled type")
} }
} }
@ -90,6 +95,11 @@ fn ios_ty_align(ty: Type) -> uint {
let elt = ty.element_type(); let elt = ty.element_type();
ios_ty_align(elt) 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") _ => 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); let eltsz = ty_size(elt, align_fn);
len * eltsz 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") _ => panic!("ty_size: unhandled type")
} }
} }

View File

@ -13,7 +13,7 @@
use libc::c_uint; use libc::c_uint;
use std::cmp; use std::cmp;
use llvm; use llvm;
use llvm::{Integer, Pointer, Float, Double, Struct, Array}; use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
use llvm::{StructRetAttribute, ZExtAttribute}; use llvm::{StructRetAttribute, ZExtAttribute};
use trans::cabi::{ArgType, FnType}; use trans::cabi::{ArgType, FnType};
use trans::context::CrateContext; use trans::context::CrateContext;
@ -50,7 +50,12 @@ fn ty_align(ty: Type) -> uint {
let elt = ty.element_type(); let elt = ty.element_type();
ty_align(elt) 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); let eltsz = ty_size(elt);
len * eltsz 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") _ => panic!("ty_size: unhandled type")
} }
} }

View File

@ -16,7 +16,7 @@ use self::RegClass::*;
use llvm; use llvm;
use llvm::{Integer, Pointer, Float, Double}; use llvm::{Integer, Pointer, Float, Double};
use llvm::{Struct, Array, Attribute}; use llvm::{Struct, Array, Attribute, Vector};
use llvm::{StructRetAttribute, ByValAttribute, ZExtAttribute}; use llvm::{StructRetAttribute, ByValAttribute, ZExtAttribute};
use trans::cabi::{ArgType, FnType}; use trans::cabi::{ArgType, FnType};
use trans::context::CrateContext; use trans::context::CrateContext;
@ -114,7 +114,12 @@ fn classify_ty(ty: Type) -> Vec<RegClass> {
let elt = ty.element_type(); let elt = ty.element_type();
ty_align(elt) 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 classify_ty(ty: Type) -> Vec<RegClass> {
let eltsz = ty_size(elt); let eltsz = ty_size(elt);
len * eltsz 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") _ => panic!("ty_size: unhandled type")
} }
} }
@ -175,6 +187,12 @@ fn classify_ty(ty: Type) -> Vec<RegClass> {
(_, X87Up) | (_, X87Up) |
(_, ComplexX87) => Memory, (_, ComplexX87) => Memory,
(SSEFv, SSEUp) |
(SSEFs, SSEUp) |
(SSEDv, SSEUp) |
(SSEDs, SSEUp) |
(SSEInt(_), SSEUp) => return,
(_, _) => newv (_, _) => newv
}; };
cls[i] = to_write; cls[i] = to_write;
@ -240,6 +258,27 @@ fn classify_ty(ty: Type) -> Vec<RegClass> {
i += 1u; 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") _ => panic!("classify: unhandled type")
} }
} }
@ -248,7 +287,7 @@ fn classify_ty(ty: Type) -> Vec<RegClass> {
let mut i = 0u; let mut i = 0u;
let ty_kind = ty.kind(); let ty_kind = ty.kind();
let e = cls.len(); 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() { if cls[i].is_sse() {
i += 1u; i += 1u;
while i < e { while i < e {
@ -320,9 +359,19 @@ fn llreg_ty(ccx: &CrateContext, cls: &[RegClass]) -> Type {
Int => { Int => {
tys.push(Type::i64(ccx)); 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_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); tys.push(vec_ty);
i += vec_len; i += vec_len;
continue; continue;
@ -337,7 +386,12 @@ fn llreg_ty(ccx: &CrateContext, cls: &[RegClass]) -> Type {
} }
i += 1u; 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, pub fn compute_abi_info(ccx: &CrateContext,