@@ -19,16 +19,23 @@ use trans::type_::Type;
19
19
20
20
use std:: cmp;
21
21
22
+ pub enum Flavor {
23
+ General ,
24
+ Ios
25
+ }
26
+
27
+ type TyAlignFn = fn ( ty : Type ) -> uint ;
28
+
22
29
fn align_up_to ( off : uint , a : uint ) -> uint {
23
30
return ( off + a - 1 u) / a * a;
24
31
}
25
32
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) ;
28
35
return align_up_to ( off, a) ;
29
36
}
30
37
31
- fn ty_align ( ty : Type ) -> uint {
38
+ fn general_ty_align ( ty : Type ) -> uint {
32
39
match ty. kind ( ) {
33
40
Integer => {
34
41
unsafe {
@@ -43,18 +50,51 @@ fn ty_align(ty: Type) -> uint {
43
50
1
44
51
} else {
45
52
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) ) )
47
87
}
48
88
}
49
89
Array => {
50
90
let elt = ty. element_type ( ) ;
51
- ty_align ( elt)
91
+ ios_ty_align ( elt)
52
92
}
53
93
_ => panic ! ( "ty_align: unhandled type" )
54
94
}
55
95
}
56
96
57
- fn ty_size ( ty : Type ) -> uint {
97
+ fn ty_size ( ty : Type , align_fn : TyAlignFn ) -> uint {
58
98
match ty. kind ( ) {
59
99
Integer => {
60
100
unsafe {
@@ -67,29 +107,32 @@ fn ty_size(ty: Type) -> uint {
67
107
Struct => {
68
108
if ty. is_packed ( ) {
69
109
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 ) )
71
111
} else {
72
112
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)
75
118
}
76
119
}
77
120
Array => {
78
121
let len = ty. array_length ( ) ;
79
122
let elt = ty. element_type ( ) ;
80
- let eltsz = ty_size ( elt) ;
123
+ let eltsz = ty_size ( elt, align_fn ) ;
81
124
len * eltsz
82
125
}
83
126
_ => panic ! ( "ty_size: unhandled type" )
84
127
}
85
128
}
86
129
87
- fn classify_ret_ty ( ccx : & CrateContext , ty : Type ) -> ArgType {
130
+ fn classify_ret_ty ( ccx : & CrateContext , ty : Type , align_fn : TyAlignFn ) -> ArgType {
88
131
if is_reg_ty ( ty) {
89
132
let attr = if ty == Type :: i1 ( ccx) { Some ( ZExtAttribute ) } else { None } ;
90
133
return ArgType :: direct ( ty, None , None , attr) ;
91
134
}
92
- let size = ty_size ( ty) ;
135
+ let size = ty_size ( ty, align_fn ) ;
93
136
if size <= 4 {
94
137
let llty = if size <= 1 {
95
138
Type :: i8 ( ccx)
@@ -103,13 +146,13 @@ fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
103
146
ArgType :: indirect ( ty, Some ( StructRetAttribute ) )
104
147
}
105
148
106
- fn classify_arg_ty ( ccx : & CrateContext , ty : Type ) -> ArgType {
149
+ fn classify_arg_ty ( ccx : & CrateContext , ty : Type , align_fn : TyAlignFn ) -> ArgType {
107
150
if is_reg_ty ( ty) {
108
151
let attr = if ty == Type :: i1 ( ccx) { Some ( ZExtAttribute ) } else { None } ;
109
152
return ArgType :: direct ( ty, None , None , attr) ;
110
153
}
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 ) ;
113
156
let llty = if align <= 4 {
114
157
Type :: array ( & Type :: i32 ( ccx) , ( ( size + 3 ) / 4 ) as u64 )
115
158
} else {
@@ -131,15 +174,21 @@ fn is_reg_ty(ty: Type) -> bool {
131
174
pub fn compute_abi_info ( ccx : & CrateContext ,
132
175
atys : & [ Type ] ,
133
176
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
+
135
184
let mut arg_tys = Vec :: new ( ) ;
136
185
for & aty in atys. iter ( ) {
137
- let ty = classify_arg_ty ( ccx, aty) ;
186
+ let ty = classify_arg_ty ( ccx, aty, align_fn ) ;
138
187
arg_tys. push ( ty) ;
139
188
}
140
189
141
190
let ret_ty = if ret_def {
142
- classify_ret_ty ( ccx, rty)
191
+ classify_ret_ty ( ccx, rty, align_fn )
143
192
} else {
144
193
ArgType :: direct ( Type :: void ( ccx) , None , None , None )
145
194
} ;
0 commit comments