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.
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.
11 use abi
::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform}
;
12 use context
::CrateContext
;
15 fn is_homogeneous_aggregate
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>, arg
: &mut ArgType
<'tcx
>)
17 arg
.layout
.homogeneous_aggregate(ccx
).and_then(|unit
| {
18 let size
= arg
.layout
.size(ccx
);
20 // Ensure we have at most four uniquely addressable members.
21 if size
> unit
.size
.checked_mul(4, ccx
).unwrap() {
25 let valid_unit
= match unit
.kind
{
26 RegKind
::Integer
=> false,
27 RegKind
::Float
=> true,
28 RegKind
::Vector
=> size
.bits() == 64 || size
.bits() == 128
42 fn classify_ret_ty
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>, ret
: &mut ArgType
<'tcx
>, vfp
: bool
) {
43 if !ret
.layout
.is_aggregate() {
44 ret
.extend_integer_width_to(32);
49 if let Some(uniform
) = is_homogeneous_aggregate(ccx
, ret
) {
50 ret
.cast_to(ccx
, uniform
);
55 let size
= ret
.layout
.size(ccx
);
56 let bits
= size
.bits();
58 let unit
= if bits
<= 8 {
60 } else if bits
<= 16 {
65 ret
.cast_to(ccx
, Uniform
{
71 ret
.make_indirect(ccx
);
74 fn classify_arg_ty
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>, arg
: &mut ArgType
<'tcx
>, vfp
: bool
) {
75 if !arg
.layout
.is_aggregate() {
76 arg
.extend_integer_width_to(32);
81 if let Some(uniform
) = is_homogeneous_aggregate(ccx
, arg
) {
82 arg
.cast_to(ccx
, uniform
);
87 let align
= arg
.layout
.align(ccx
).abi();
88 let total
= arg
.layout
.size(ccx
);
89 arg
.cast_to(ccx
, Uniform
{
90 unit
: if align
<= 4 { Reg::i32() }
else { Reg::i64() }
,
95 pub fn compute_abi_info
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>, fty
: &mut FnType
<'tcx
>) {
96 // If this is a target with a hard-float ABI, and the function is not explicitly
97 // `extern "aapcs"`, then we must use the VFP registers for homogeneous aggregates.
98 let vfp
= ccx
.sess().target
.target
.llvm_target
.ends_with("hf")
99 && fty
.cconv
!= CallConv
::ArmAapcsCallConv
102 if !fty
.ret
.is_ignore() {
103 classify_ret_ty(ccx
, &mut fty
.ret
, vfp
);
106 for arg
in &mut fty
.args
{
107 if arg
.is_ignore() { continue; }
108 classify_arg_ty(ccx
, arg
, vfp
);