]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
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 | ||
11 | #![allow(non_upper_case_globals)] | |
12 | ||
13 | use libc::c_uint; | |
14 | use std::cmp; | |
15 | use llvm; | |
d9579d0f | 16 | use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector, Attribute}; |
1a4d82fc JJ |
17 | use trans::cabi::{ArgType, FnType}; |
18 | use trans::context::CrateContext; | |
19 | use trans::type_::Type; | |
20 | ||
c34b1796 | 21 | fn align_up_to(off: usize, a: usize) -> usize { |
85aaf69f | 22 | return (off + a - 1) / a * a; |
1a4d82fc JJ |
23 | } |
24 | ||
c34b1796 | 25 | fn align(off: usize, ty: Type) -> usize { |
1a4d82fc JJ |
26 | let a = ty_align(ty); |
27 | return align_up_to(off, a); | |
28 | } | |
29 | ||
c34b1796 | 30 | fn ty_align(ty: Type) -> usize { |
1a4d82fc | 31 | match ty.kind() { |
c34b1796 | 32 | Integer => ((ty.int_width() as usize) + 7) / 8, |
1a4d82fc JJ |
33 | Pointer => 4, |
34 | Float => 4, | |
35 | Double => 8, | |
36 | Struct => { | |
37 | if ty.is_packed() { | |
38 | 1 | |
39 | } else { | |
40 | let str_tys = ty.field_types(); | |
41 | str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t))) | |
42 | } | |
43 | } | |
44 | Array => { | |
45 | let elt = ty.element_type(); | |
46 | ty_align(elt) | |
47 | } | |
85aaf69f SL |
48 | Vector => { |
49 | let len = ty.vector_length(); | |
50 | let elt = ty.element_type(); | |
51 | ty_align(elt) * len | |
52 | } | |
53 | _ => panic!("ty_align: unhandled type") | |
1a4d82fc JJ |
54 | } |
55 | } | |
56 | ||
c34b1796 | 57 | fn ty_size(ty: Type) -> usize { |
1a4d82fc | 58 | match ty.kind() { |
c34b1796 | 59 | Integer => ((ty.int_width() as usize) + 7) / 8, |
1a4d82fc JJ |
60 | Pointer => 4, |
61 | Float => 4, | |
62 | Double => 8, | |
63 | Struct => { | |
64 | if ty.is_packed() { | |
65 | let str_tys = ty.field_types(); | |
66 | str_tys.iter().fold(0, |s, t| s + ty_size(*t)) | |
67 | } else { | |
68 | let str_tys = ty.field_types(); | |
69 | let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t)); | |
70 | align(size, ty) | |
71 | } | |
72 | } | |
73 | Array => { | |
74 | let len = ty.array_length(); | |
75 | let elt = ty.element_type(); | |
76 | let eltsz = ty_size(elt); | |
77 | len * eltsz | |
78 | } | |
85aaf69f SL |
79 | Vector => { |
80 | let len = ty.vector_length(); | |
81 | let elt = ty.element_type(); | |
82 | let eltsz = ty_size(elt); | |
83 | len * eltsz | |
84 | } | |
1a4d82fc JJ |
85 | _ => panic!("ty_size: unhandled type") |
86 | } | |
87 | } | |
88 | ||
89 | fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType { | |
90 | if is_reg_ty(ty) { | |
d9579d0f | 91 | let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExt) } else { None }; |
1a4d82fc JJ |
92 | ArgType::direct(ty, None, None, attr) |
93 | } else { | |
d9579d0f | 94 | ArgType::indirect(ty, Some(Attribute::StructRet)) |
1a4d82fc JJ |
95 | } |
96 | } | |
97 | ||
c34b1796 | 98 | fn classify_arg_ty(ccx: &CrateContext, ty: Type, offset: &mut usize) -> ArgType { |
1a4d82fc JJ |
99 | let orig_offset = *offset; |
100 | let size = ty_size(ty) * 8; | |
101 | let mut align = ty_align(ty); | |
102 | ||
103 | align = cmp::min(cmp::max(align, 4), 8); | |
104 | *offset = align_up_to(*offset, align); | |
105 | *offset += align_up_to(size, align * 8) / 8; | |
106 | ||
107 | if is_reg_ty(ty) { | |
d9579d0f | 108 | let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExt) } else { None }; |
1a4d82fc JJ |
109 | ArgType::direct(ty, None, None, attr) |
110 | } else { | |
111 | ArgType::direct( | |
112 | ty, | |
113 | Some(struct_ty(ccx, ty)), | |
114 | padding_ty(ccx, align, orig_offset), | |
115 | None | |
116 | ) | |
117 | } | |
118 | } | |
119 | ||
120 | fn is_reg_ty(ty: Type) -> bool { | |
121 | return match ty.kind() { | |
122 | Integer | |
123 | | Pointer | |
124 | | Float | |
85aaf69f SL |
125 | | Double |
126 | | Vector => true, | |
1a4d82fc JJ |
127 | _ => false |
128 | }; | |
129 | } | |
130 | ||
c34b1796 | 131 | fn padding_ty(ccx: &CrateContext, align: usize, offset: usize) -> Option<Type> { |
1a4d82fc JJ |
132 | if ((align - 1 ) & offset) > 0 { |
133 | Some(Type::i32(ccx)) | |
134 | } else { | |
135 | None | |
136 | } | |
137 | } | |
138 | ||
c34b1796 | 139 | fn coerce_to_int(ccx: &CrateContext, size: usize) -> Vec<Type> { |
1a4d82fc JJ |
140 | let int_ty = Type::i32(ccx); |
141 | let mut args = Vec::new(); | |
142 | ||
143 | let mut n = size / 32; | |
144 | while n > 0 { | |
145 | args.push(int_ty); | |
146 | n -= 1; | |
147 | } | |
148 | ||
149 | let r = size % 32; | |
150 | if r > 0 { | |
151 | unsafe { | |
152 | args.push(Type::from_ref(llvm::LLVMIntTypeInContext(ccx.llcx(), r as c_uint))); | |
153 | } | |
154 | } | |
155 | ||
156 | args | |
157 | } | |
158 | ||
159 | fn struct_ty(ccx: &CrateContext, ty: Type) -> Type { | |
160 | let size = ty_size(ty) * 8; | |
85aaf69f | 161 | Type::struct_(ccx, &coerce_to_int(ccx, size), false) |
1a4d82fc JJ |
162 | } |
163 | ||
164 | pub fn compute_abi_info(ccx: &CrateContext, | |
165 | atys: &[Type], | |
166 | rty: Type, | |
167 | ret_def: bool) -> FnType { | |
168 | let ret_ty = if ret_def { | |
169 | classify_ret_ty(ccx, rty) | |
170 | } else { | |
171 | ArgType::direct(Type::void(ccx), None, None, None) | |
172 | }; | |
173 | ||
174 | let sret = ret_ty.is_indirect(); | |
175 | let mut arg_tys = Vec::new(); | |
176 | let mut offset = if sret { 4 } else { 0 }; | |
177 | ||
85aaf69f | 178 | for aty in atys { |
1a4d82fc JJ |
179 | let ty = classify_arg_ty(ccx, *aty, &mut offset); |
180 | arg_tys.push(ty); | |
181 | }; | |
182 | ||
183 | return FnType { | |
184 | arg_tys: arg_tys, | |
185 | ret_ty: ret_ty, | |
186 | }; | |
187 | } |