1 // Copyright 2014-2016 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.
12 // Alignment of 128 bit types is not currently handled, this will
13 // need to be fixed when PowerPC vector support is added.
15 use abi
::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform}
;
16 use context
::CrateContext
;
17 use rustc
::ty
::layout
;
19 #[derive(Debug, Clone, Copy, PartialEq)]
21 ELFv1
, // original ABI used for powerpc64 (big-endian)
22 ELFv2
, // newer ABI used for powerpc64le
26 fn is_homogeneous_aggregate
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>,
27 arg
: &mut ArgType
<'tcx
>,
30 arg
.layout
.homogeneous_aggregate(ccx
).and_then(|unit
| {
31 let size
= arg
.layout
.size(ccx
);
33 // ELFv1 only passes one-member aggregates transparently.
34 // ELFv2 passes up to eight uniquely addressable members.
35 if (abi
== ELFv1
&& size
> unit
.size
)
36 || size
> unit
.size
.checked_mul(8, ccx
).unwrap() {
40 let valid_unit
= match unit
.kind
{
41 RegKind
::Integer
=> false,
42 RegKind
::Float
=> true,
43 RegKind
::Vector
=> size
.bits() == 128
57 fn classify_ret_ty
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>, ret
: &mut ArgType
<'tcx
>, abi
: ABI
) {
58 if !ret
.layout
.is_aggregate() {
59 ret
.extend_integer_width_to(64);
63 // The ELFv1 ABI doesn't return aggregates in registers
65 ret
.make_indirect(ccx
);
69 if let Some(uniform
) = is_homogeneous_aggregate(ccx
, ret
, abi
) {
70 ret
.cast_to(ccx
, uniform
);
74 let size
= ret
.layout
.size(ccx
);
75 let bits
= size
.bits();
77 let unit
= if bits
<= 8 {
79 } else if bits
<= 16 {
81 } else if bits
<= 32 {
87 ret
.cast_to(ccx
, Uniform
{
94 ret
.make_indirect(ccx
);
97 fn classify_arg_ty
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>, arg
: &mut ArgType
<'tcx
>, abi
: ABI
) {
98 if !arg
.layout
.is_aggregate() {
99 arg
.extend_integer_width_to(64);
103 if let Some(uniform
) = is_homogeneous_aggregate(ccx
, arg
, abi
) {
104 arg
.cast_to(ccx
, uniform
);
108 let size
= arg
.layout
.size(ccx
);
109 let (unit
, total
) = match abi
{
111 // In ELFv1, aggregates smaller than a doubleword should appear in
112 // the least-significant bits of the parameter doubleword. The rest
113 // should be padded at their tail to fill out multiple doublewords.
114 if size
.bits() <= 64 {
115 (Reg { kind: RegKind::Integer, size }
, size
)
117 let align
= layout
::Align
::from_bits(64, 64).unwrap();
118 (Reg
::i64(), size
.abi_align(align
))
122 // In ELFv2, we can just cast directly.
127 arg
.cast_to(ccx
, Uniform
{
133 pub fn compute_abi_info
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>, fty
: &mut FnType
<'tcx
>) {
134 let abi
= match ccx
.sess().target
.target
.target_endian
.as_str() {
137 _
=> unimplemented
!(),
140 if !fty
.ret
.is_ignore() {
141 classify_ret_ty(ccx
, &mut fty
.ret
, abi
);
144 for arg
in &mut fty
.args
{
145 if arg
.is_ignore() { continue; }
146 classify_arg_ty(ccx
, arg
, abi
);