]> git.proxmox.com Git - rustc.git/blame - src/librustc_trans/trans/cabi_arm.rs
Imported Upstream version 1.8.0+dfsg1
[rustc.git] / src / librustc_trans / trans / cabi_arm.rs
CommitLineData
223e47cc
LB
1// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
1a4d82fc 11#![allow(non_upper_case_globals)]
223e47cc 12
d9579d0f 13use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector, Attribute};
1a4d82fc
JJ
14use trans::cabi::{FnType, ArgType};
15use trans::context::CrateContext;
16use trans::type_::Type;
970d7e83 17
1a4d82fc 18use std::cmp;
223e47cc 19
85aaf69f
SL
20pub enum Flavor {
21 General,
22 Ios
23}
24
c34b1796 25type TyAlignFn = fn(ty: Type) -> usize;
85aaf69f 26
c34b1796 27fn align_up_to(off: usize, a: usize) -> usize {
85aaf69f 28 return (off + a - 1) / a * a;
223e47cc
LB
29}
30
c34b1796 31fn align(off: usize, ty: Type, align_fn: TyAlignFn) -> usize {
85aaf69f 32 let a = align_fn(ty);
223e47cc
LB
33 return align_up_to(off, a);
34}
35
c34b1796 36fn general_ty_align(ty: Type) -> usize {
970d7e83 37 match ty.kind() {
c34b1796 38 Integer => ((ty.int_width() as usize) + 7) / 8,
970d7e83
LB
39 Pointer => 4,
40 Float => 4,
41 Double => 8,
42 Struct => {
43 if ty.is_packed() {
44 1
45 } else {
46 let str_tys = ty.field_types();
85aaf69f 47 str_tys.iter().fold(1, |a, t| cmp::max(a, general_ty_align(*t)))
223e47cc 48 }
970d7e83
LB
49 }
50 Array => {
51 let elt = ty.element_type();
85aaf69f
SL
52 general_ty_align(elt)
53 }
54 Vector => {
55 let len = ty.vector_length();
56 let elt = ty.element_type();
57 general_ty_align(elt) * len
970d7e83 58 }
1a4d82fc 59 _ => panic!("ty_align: unhandled type")
223e47cc
LB
60 }
61}
62
85aaf69f
SL
63// For more information see:
64// ARMv7
65// https://developer.apple.com/library/ios/documentation/Xcode/Conceptual
66// /iPhoneOSABIReference/Articles/ARMv7FunctionCallingConventions.html
67// ARMv6
68// https://developer.apple.com/library/ios/documentation/Xcode/Conceptual
69// /iPhoneOSABIReference/Articles/ARMv6FunctionCallingConventions.html
c34b1796 70fn ios_ty_align(ty: Type) -> usize {
970d7e83 71 match ty.kind() {
c34b1796 72 Integer => cmp::min(4, ((ty.int_width() as usize) + 7) / 8),
85aaf69f
SL
73 Pointer => 4,
74 Float => 4,
75 Double => 4,
76 Struct => {
77 if ty.is_packed() {
78 1
79 } else {
80 let str_tys = ty.field_types();
81 str_tys.iter().fold(1, |a, t| cmp::max(a, ios_ty_align(*t)))
223e47cc 82 }
970d7e83 83 }
85aaf69f
SL
84 Array => {
85 let elt = ty.element_type();
86 ios_ty_align(elt)
87 }
88 Vector => {
89 let len = ty.vector_length();
90 let elt = ty.element_type();
91 ios_ty_align(elt) * len
92 }
93 _ => panic!("ty_align: unhandled type")
94 }
95}
96
c34b1796 97fn ty_size(ty: Type, align_fn: TyAlignFn) -> usize {
85aaf69f 98 match ty.kind() {
c34b1796 99 Integer => ((ty.int_width() as usize) + 7) / 8,
970d7e83
LB
100 Pointer => 4,
101 Float => 4,
102 Double => 8,
103 Struct => {
104 if ty.is_packed() {
105 let str_tys = ty.field_types();
85aaf69f 106 str_tys.iter().fold(0, |s, t| s + ty_size(*t, align_fn))
970d7e83
LB
107 } else {
108 let str_tys = ty.field_types();
85aaf69f
SL
109 let size = str_tys.iter()
110 .fold(0, |s, t| {
111 align(s, *t, align_fn) + ty_size(*t, align_fn)
112 });
113 align(size, ty, align_fn)
223e47cc 114 }
970d7e83
LB
115 }
116 Array => {
117 let len = ty.array_length();
118 let elt = ty.element_type();
85aaf69f
SL
119 let eltsz = ty_size(elt, align_fn);
120 len * eltsz
121 }
122 Vector => {
123 let len = ty.vector_length();
124 let elt = ty.element_type();
125 let eltsz = ty_size(elt, align_fn);
970d7e83
LB
126 len * eltsz
127 }
1a4d82fc 128 _ => panic!("ty_size: unhandled type")
223e47cc
LB
129 }
130}
131
85aaf69f 132fn classify_ret_ty(ccx: &CrateContext, ty: Type, align_fn: TyAlignFn) -> ArgType {
223e47cc 133 if is_reg_ty(ty) {
d9579d0f 134 let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExt) } else { None };
1a4d82fc 135 return ArgType::direct(ty, None, None, attr);
223e47cc 136 }
85aaf69f 137 let size = ty_size(ty, align_fn);
223e47cc
LB
138 if size <= 4 {
139 let llty = if size <= 1 {
1a4d82fc 140 Type::i8(ccx)
223e47cc 141 } else if size <= 2 {
1a4d82fc 142 Type::i16(ccx)
223e47cc 143 } else {
1a4d82fc 144 Type::i32(ccx)
223e47cc 145 };
1a4d82fc 146 return ArgType::direct(ty, Some(llty), None, None);
223e47cc 147 }
d9579d0f 148 ArgType::indirect(ty, Some(Attribute::StructRet))
223e47cc
LB
149}
150
85aaf69f 151fn classify_arg_ty(ccx: &CrateContext, ty: Type, align_fn: TyAlignFn) -> ArgType {
223e47cc 152 if is_reg_ty(ty) {
d9579d0f 153 let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExt) } else { None };
1a4d82fc 154 return ArgType::direct(ty, None, None, attr);
223e47cc 155 }
85aaf69f
SL
156 let align = align_fn(ty);
157 let size = ty_size(ty, align_fn);
223e47cc 158 let llty = if align <= 4 {
1a4d82fc 159 Type::array(&Type::i32(ccx), ((size + 3) / 4) as u64)
223e47cc 160 } else {
1a4d82fc 161 Type::array(&Type::i64(ccx), ((size + 7) / 8) as u64)
223e47cc 162 };
1a4d82fc 163 ArgType::direct(ty, Some(llty), None, None)
223e47cc
LB
164}
165
970d7e83
LB
166fn is_reg_ty(ty: Type) -> bool {
167 match ty.kind() {
168 Integer
169 | Pointer
170 | Float
85aaf69f
SL
171 | Double
172 | Vector => true,
970d7e83 173 _ => false
223e47cc
LB
174 }
175}
176
1a4d82fc
JJ
177pub fn compute_abi_info(ccx: &CrateContext,
178 atys: &[Type],
179 rty: Type,
85aaf69f
SL
180 ret_def: bool,
181 flavor: Flavor) -> FnType {
182 let align_fn = match flavor {
183 Flavor::General => general_ty_align as TyAlignFn,
184 Flavor::Ios => ios_ty_align as TyAlignFn,
185 };
186
1a4d82fc 187 let mut arg_tys = Vec::new();
85aaf69f
SL
188 for &aty in atys {
189 let ty = classify_arg_ty(ccx, aty, align_fn);
1a4d82fc 190 arg_tys.push(ty);
223e47cc 191 }
223e47cc 192
1a4d82fc 193 let ret_ty = if ret_def {
85aaf69f 194 classify_ret_ty(ccx, rty, align_fn)
1a4d82fc
JJ
195 } else {
196 ArgType::direct(Type::void(ccx), None, None, None)
197 };
198
199 return FnType {
200 arg_tys: arg_tys,
201 ret_ty: ret_ty,
202 };
223e47cc 203}