mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-16 17:03:35 +00:00
iOS: cabi fixes
Changed alignment according to official Apple docs
This commit is contained in:
parent
ac0607acb2
commit
ea045d2055
@ -115,8 +115,15 @@ pub fn compute_abi_info(ccx: &CrateContext,
|
||||
} else {
|
||||
cabi_x86_64::compute_abi_info(ccx, atys, rty, ret_def)
|
||||
},
|
||||
"arm" => cabi_arm::compute_abi_info(ccx, atys, rty, ret_def),
|
||||
"aarch64" => cabi_aarch64::compute_abi_info(ccx, atys, rty, ret_def),
|
||||
"arm" => {
|
||||
let flavor = if ccx.sess().target.target.target_os == "ios" {
|
||||
cabi_arm::Flavor::Ios
|
||||
} else {
|
||||
cabi_arm::Flavor::General
|
||||
};
|
||||
cabi_arm::compute_abi_info(ccx, atys, rty, ret_def, flavor)
|
||||
},
|
||||
"mips" => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def),
|
||||
a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a)
|
||||
[]),
|
||||
|
@ -19,16 +19,23 @@ use trans::type_::Type;
|
||||
|
||||
use std::cmp;
|
||||
|
||||
pub enum Flavor {
|
||||
General,
|
||||
Ios
|
||||
}
|
||||
|
||||
type TyAlignFn = fn(ty: Type) -> uint;
|
||||
|
||||
fn align_up_to(off: uint, a: uint) -> uint {
|
||||
return (off + a - 1u) / a * a;
|
||||
}
|
||||
|
||||
fn align(off: uint, ty: Type) -> uint {
|
||||
let a = ty_align(ty);
|
||||
fn align(off: uint, ty: Type, align_fn: TyAlignFn) -> uint {
|
||||
let a = align_fn(ty);
|
||||
return align_up_to(off, a);
|
||||
}
|
||||
|
||||
fn ty_align(ty: Type) -> uint {
|
||||
fn general_ty_align(ty: Type) -> uint {
|
||||
match ty.kind() {
|
||||
Integer => {
|
||||
unsafe {
|
||||
@ -43,18 +50,51 @@ fn ty_align(ty: Type) -> uint {
|
||||
1
|
||||
} else {
|
||||
let str_tys = ty.field_types();
|
||||
str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t)))
|
||||
str_tys.iter().fold(1, |a, t| cmp::max(a, general_ty_align(*t)))
|
||||
}
|
||||
}
|
||||
Array => {
|
||||
let elt = ty.element_type();
|
||||
ty_align(elt)
|
||||
general_ty_align(elt)
|
||||
}
|
||||
_ => panic!("ty_align: unhandled type")
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_size(ty: Type) -> uint {
|
||||
// For more information see:
|
||||
// ARMv7
|
||||
// https://developer.apple.com/library/ios/documentation/Xcode/Conceptual
|
||||
// /iPhoneOSABIReference/Articles/ARMv7FunctionCallingConventions.html
|
||||
// ARMv6
|
||||
// https://developer.apple.com/library/ios/documentation/Xcode/Conceptual
|
||||
// /iPhoneOSABIReference/Articles/ARMv6FunctionCallingConventions.html
|
||||
fn ios_ty_align(ty: Type) -> uint {
|
||||
match ty.kind() {
|
||||
Integer => {
|
||||
unsafe {
|
||||
cmp::min(4, ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8)
|
||||
}
|
||||
}
|
||||
Pointer => 4,
|
||||
Float => 4,
|
||||
Double => 4,
|
||||
Struct => {
|
||||
if ty.is_packed() {
|
||||
1
|
||||
} else {
|
||||
let str_tys = ty.field_types();
|
||||
str_tys.iter().fold(1, |a, t| cmp::max(a, ios_ty_align(*t)))
|
||||
}
|
||||
}
|
||||
Array => {
|
||||
let elt = ty.element_type();
|
||||
ios_ty_align(elt)
|
||||
}
|
||||
_ => panic!("ty_align: unhandled type")
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_size(ty: Type, align_fn: TyAlignFn) -> uint {
|
||||
match ty.kind() {
|
||||
Integer => {
|
||||
unsafe {
|
||||
@ -67,29 +107,32 @@ fn ty_size(ty: Type) -> uint {
|
||||
Struct => {
|
||||
if ty.is_packed() {
|
||||
let str_tys = ty.field_types();
|
||||
str_tys.iter().fold(0, |s, t| s + ty_size(*t))
|
||||
str_tys.iter().fold(0, |s, t| s + ty_size(*t, align_fn))
|
||||
} else {
|
||||
let str_tys = ty.field_types();
|
||||
let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
|
||||
align(size, ty)
|
||||
let size = str_tys.iter()
|
||||
.fold(0, |s, t| {
|
||||
align(s, *t, align_fn) + ty_size(*t, align_fn)
|
||||
});
|
||||
align(size, ty, align_fn)
|
||||
}
|
||||
}
|
||||
Array => {
|
||||
let len = ty.array_length();
|
||||
let elt = ty.element_type();
|
||||
let eltsz = ty_size(elt);
|
||||
let eltsz = ty_size(elt, align_fn);
|
||||
len * eltsz
|
||||
}
|
||||
_ => panic!("ty_size: unhandled type")
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
|
||||
fn classify_ret_ty(ccx: &CrateContext, ty: Type, align_fn: TyAlignFn) -> ArgType {
|
||||
if is_reg_ty(ty) {
|
||||
let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
|
||||
return ArgType::direct(ty, None, None, attr);
|
||||
}
|
||||
let size = ty_size(ty);
|
||||
let size = ty_size(ty, align_fn);
|
||||
if size <= 4 {
|
||||
let llty = if size <= 1 {
|
||||
Type::i8(ccx)
|
||||
@ -103,13 +146,13 @@ fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
|
||||
ArgType::indirect(ty, Some(StructRetAttribute))
|
||||
}
|
||||
|
||||
fn classify_arg_ty(ccx: &CrateContext, ty: Type) -> ArgType {
|
||||
fn classify_arg_ty(ccx: &CrateContext, ty: Type, align_fn: TyAlignFn) -> ArgType {
|
||||
if is_reg_ty(ty) {
|
||||
let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
|
||||
return ArgType::direct(ty, None, None, attr);
|
||||
}
|
||||
let align = ty_align(ty);
|
||||
let size = ty_size(ty);
|
||||
let align = align_fn(ty);
|
||||
let size = ty_size(ty, align_fn);
|
||||
let llty = if align <= 4 {
|
||||
Type::array(&Type::i32(ccx), ((size + 3) / 4) as u64)
|
||||
} else {
|
||||
@ -131,15 +174,21 @@ fn is_reg_ty(ty: Type) -> bool {
|
||||
pub fn compute_abi_info(ccx: &CrateContext,
|
||||
atys: &[Type],
|
||||
rty: Type,
|
||||
ret_def: bool) -> FnType {
|
||||
ret_def: bool,
|
||||
flavor: Flavor) -> FnType {
|
||||
let align_fn = match flavor {
|
||||
Flavor::General => general_ty_align as TyAlignFn,
|
||||
Flavor::Ios => ios_ty_align as TyAlignFn,
|
||||
};
|
||||
|
||||
let mut arg_tys = Vec::new();
|
||||
for &aty in atys.iter() {
|
||||
let ty = classify_arg_ty(ccx, aty);
|
||||
let ty = classify_arg_ty(ccx, aty, align_fn);
|
||||
arg_tys.push(ty);
|
||||
}
|
||||
|
||||
let ret_ty = if ret_def {
|
||||
classify_ret_ty(ccx, rty)
|
||||
classify_ret_ty(ccx, rty, align_fn)
|
||||
} else {
|
||||
ArgType::direct(Type::void(ccx), None, None, None)
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user