Skip to content

Commit

Permalink
iOS: cabi fixes
Browse files Browse the repository at this point in the history
Changed alignment according to official Apple docs
  • Loading branch information
vhbit committed Jan 9, 2015
1 parent ac0607a commit ea045d2
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 19 deletions.
9 changes: 8 additions & 1 deletion src/librustc_trans/trans/cabi.rs
Expand Up @@ -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)
[]),
Expand Down
85 changes: 67 additions & 18 deletions src/librustc_trans/trans/cabi_arm.rs
Expand Up @@ -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 {
Expand All @@ -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();
general_ty_align(elt)
}
_ => panic!("ty_align: unhandled type")
}
}

// 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();
ty_align(elt)
ios_ty_align(elt)
}
_ => panic!("ty_align: unhandled type")
}
}

fn ty_size(ty: Type) -> uint {
fn ty_size(ty: Type, align_fn: TyAlignFn) -> uint {
match ty.kind() {
Integer => {
unsafe {
Expand All @@ -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)
Expand All @@ -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 {
Expand All @@ -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)
};
Expand Down

0 comments on commit ea045d2

Please sign in to comment.