Skip to content

Commit ea045d2

Browse files
committed
iOS: cabi fixes
Changed alignment according to official Apple docs
1 parent ac0607a commit ea045d2

File tree

2 files changed

+75
-19
lines changed

2 files changed

+75
-19
lines changed

src/librustc_trans/trans/cabi.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,15 @@ pub fn compute_abi_info(ccx: &CrateContext,
115115
} else {
116116
cabi_x86_64::compute_abi_info(ccx, atys, rty, ret_def)
117117
},
118-
"arm" => cabi_arm::compute_abi_info(ccx, atys, rty, ret_def),
119118
"aarch64" => cabi_aarch64::compute_abi_info(ccx, atys, rty, ret_def),
119+
"arm" => {
120+
let flavor = if ccx.sess().target.target.target_os == "ios" {
121+
cabi_arm::Flavor::Ios
122+
} else {
123+
cabi_arm::Flavor::General
124+
};
125+
cabi_arm::compute_abi_info(ccx, atys, rty, ret_def, flavor)
126+
},
120127
"mips" => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def),
121128
a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a)
122129
[]),

src/librustc_trans/trans/cabi_arm.rs

Lines changed: 67 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,23 @@ use trans::type_::Type;
1919

2020
use std::cmp;
2121

22+
pub enum Flavor {
23+
General,
24+
Ios
25+
}
26+
27+
type TyAlignFn = fn(ty: Type) -> uint;
28+
2229
fn align_up_to(off: uint, a: uint) -> uint {
2330
return (off + a - 1u) / a * a;
2431
}
2532

26-
fn align(off: uint, ty: Type) -> uint {
27-
let a = ty_align(ty);
33+
fn align(off: uint, ty: Type, align_fn: TyAlignFn) -> uint {
34+
let a = align_fn(ty);
2835
return align_up_to(off, a);
2936
}
3037

31-
fn ty_align(ty: Type) -> uint {
38+
fn general_ty_align(ty: Type) -> uint {
3239
match ty.kind() {
3340
Integer => {
3441
unsafe {
@@ -43,18 +50,51 @@ fn ty_align(ty: Type) -> uint {
4350
1
4451
} else {
4552
let str_tys = ty.field_types();
46-
str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t)))
53+
str_tys.iter().fold(1, |a, t| cmp::max(a, general_ty_align(*t)))
54+
}
55+
}
56+
Array => {
57+
let elt = ty.element_type();
58+
general_ty_align(elt)
59+
}
60+
_ => panic!("ty_align: unhandled type")
61+
}
62+
}
63+
64+
// For more information see:
65+
// ARMv7
66+
// https://developer.apple.com/library/ios/documentation/Xcode/Conceptual
67+
// /iPhoneOSABIReference/Articles/ARMv7FunctionCallingConventions.html
68+
// ARMv6
69+
// https://developer.apple.com/library/ios/documentation/Xcode/Conceptual
70+
// /iPhoneOSABIReference/Articles/ARMv6FunctionCallingConventions.html
71+
fn ios_ty_align(ty: Type) -> uint {
72+
match ty.kind() {
73+
Integer => {
74+
unsafe {
75+
cmp::min(4, ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8)
76+
}
77+
}
78+
Pointer => 4,
79+
Float => 4,
80+
Double => 4,
81+
Struct => {
82+
if ty.is_packed() {
83+
1
84+
} else {
85+
let str_tys = ty.field_types();
86+
str_tys.iter().fold(1, |a, t| cmp::max(a, ios_ty_align(*t)))
4787
}
4888
}
4989
Array => {
5090
let elt = ty.element_type();
51-
ty_align(elt)
91+
ios_ty_align(elt)
5292
}
5393
_ => panic!("ty_align: unhandled type")
5494
}
5595
}
5696

57-
fn ty_size(ty: Type) -> uint {
97+
fn ty_size(ty: Type, align_fn: TyAlignFn) -> uint {
5898
match ty.kind() {
5999
Integer => {
60100
unsafe {
@@ -67,29 +107,32 @@ fn ty_size(ty: Type) -> uint {
67107
Struct => {
68108
if ty.is_packed() {
69109
let str_tys = ty.field_types();
70-
str_tys.iter().fold(0, |s, t| s + ty_size(*t))
110+
str_tys.iter().fold(0, |s, t| s + ty_size(*t, align_fn))
71111
} else {
72112
let str_tys = ty.field_types();
73-
let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
74-
align(size, ty)
113+
let size = str_tys.iter()
114+
.fold(0, |s, t| {
115+
align(s, *t, align_fn) + ty_size(*t, align_fn)
116+
});
117+
align(size, ty, align_fn)
75118
}
76119
}
77120
Array => {
78121
let len = ty.array_length();
79122
let elt = ty.element_type();
80-
let eltsz = ty_size(elt);
123+
let eltsz = ty_size(elt, align_fn);
81124
len * eltsz
82125
}
83126
_ => panic!("ty_size: unhandled type")
84127
}
85128
}
86129

87-
fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
130+
fn classify_ret_ty(ccx: &CrateContext, ty: Type, align_fn: TyAlignFn) -> ArgType {
88131
if is_reg_ty(ty) {
89132
let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
90133
return ArgType::direct(ty, None, None, attr);
91134
}
92-
let size = ty_size(ty);
135+
let size = ty_size(ty, align_fn);
93136
if size <= 4 {
94137
let llty = if size <= 1 {
95138
Type::i8(ccx)
@@ -103,13 +146,13 @@ fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
103146
ArgType::indirect(ty, Some(StructRetAttribute))
104147
}
105148

106-
fn classify_arg_ty(ccx: &CrateContext, ty: Type) -> ArgType {
149+
fn classify_arg_ty(ccx: &CrateContext, ty: Type, align_fn: TyAlignFn) -> ArgType {
107150
if is_reg_ty(ty) {
108151
let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
109152
return ArgType::direct(ty, None, None, attr);
110153
}
111-
let align = ty_align(ty);
112-
let size = ty_size(ty);
154+
let align = align_fn(ty);
155+
let size = ty_size(ty, align_fn);
113156
let llty = if align <= 4 {
114157
Type::array(&Type::i32(ccx), ((size + 3) / 4) as u64)
115158
} else {
@@ -131,15 +174,21 @@ fn is_reg_ty(ty: Type) -> bool {
131174
pub fn compute_abi_info(ccx: &CrateContext,
132175
atys: &[Type],
133176
rty: Type,
134-
ret_def: bool) -> FnType {
177+
ret_def: bool,
178+
flavor: Flavor) -> FnType {
179+
let align_fn = match flavor {
180+
Flavor::General => general_ty_align as TyAlignFn,
181+
Flavor::Ios => ios_ty_align as TyAlignFn,
182+
};
183+
135184
let mut arg_tys = Vec::new();
136185
for &aty in atys.iter() {
137-
let ty = classify_arg_ty(ccx, aty);
186+
let ty = classify_arg_ty(ccx, aty, align_fn);
138187
arg_tys.push(ty);
139188
}
140189

141190
let ret_ty = if ret_def {
142-
classify_ret_ty(ccx, rty)
191+
classify_ret_ty(ccx, rty, align_fn)
143192
} else {
144193
ArgType::direct(Type::void(ccx), None, None, None)
145194
};

0 commit comments

Comments
 (0)