]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_target/src/abi/call/powerpc64.rs
New upstream version 1.65.0+dfsg1
[rustc.git] / compiler / rustc_target / src / abi / call / powerpc64.rs
CommitLineData
cc61c64b 1// FIXME:
9cc50fc6
SL
2// Alignment of 128 bit types is not currently handled, this will
3// need to be fixed when PowerPC vector support is added.
4
dfeec247 5use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
94222f64 6use crate::abi::{Endian, HasDataLayout, TyAbiInterface};
9fa01778 7use crate::spec::HasTargetSpec;
9cc50fc6 8
ea8adc8c
XL
9#[derive(Debug, Clone, Copy, PartialEq)]
10enum ABI {
11 ELFv1, // original ABI used for powerpc64 (big-endian)
a1dfa0c6 12 ELFv2, // newer ABI used for powerpc64le and musl (both endians)
ea8adc8c 13}
9fa01778 14use ABI::*;
ea8adc8c 15
dfeec247
XL
16fn is_homogeneous_aggregate<'a, Ty, C>(
17 cx: &C,
18 arg: &mut ArgAbi<'a, Ty>,
19 abi: ABI,
20) -> Option<Uniform>
21where
94222f64
XL
22 Ty: TyAbiInterface<'a, C> + Copy,
23 C: HasDataLayout,
83c7162d 24{
74b04a01 25 arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
ea8adc8c
XL
26 // ELFv1 only passes one-member aggregates transparently.
27 // ELFv2 passes up to eight uniquely addressable members.
ff7c6d11 28 if (abi == ELFv1 && arg.layout.size > unit.size)
dfeec247
XL
29 || arg.layout.size > unit.size.checked_mul(8, cx).unwrap()
30 {
cc61c64b 31 return None;
9cc50fc6
SL
32 }
33
cc61c64b
XL
34 let valid_unit = match unit.kind {
35 RegKind::Integer => false,
36 RegKind::Float => true,
dfeec247 37 RegKind::Vector => arg.layout.size.bits() == 128,
cc61c64b 38 };
9cc50fc6 39
60c5eb7d 40 valid_unit.then_some(Uniform { unit, total: arg.layout.size })
9cc50fc6
SL
41 })
42}
43
60c5eb7d 44fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, abi: ABI)
dfeec247 45where
94222f64
XL
46 Ty: TyAbiInterface<'a, C> + Copy,
47 C: HasDataLayout,
83c7162d 48{
cc61c64b 49 if !ret.layout.is_aggregate() {
54a0048b
SL
50 ret.extend_integer_width_to(64);
51 return;
9cc50fc6
SL
52 }
53
ea8adc8c
XL
54 // The ELFv1 ABI doesn't return aggregates in registers
55 if abi == ELFv1 {
ff7c6d11 56 ret.make_indirect();
ea8adc8c 57 return;
9cc50fc6
SL
58 }
59
2c00a5a8 60 if let Some(uniform) = is_homogeneous_aggregate(cx, ret, abi) {
ff7c6d11 61 ret.cast_to(uniform);
54a0048b 62 return;
9cc50fc6 63 }
ea8adc8c 64
ff7c6d11 65 let size = ret.layout.size;
cc61c64b
XL
66 let bits = size.bits();
67 if bits <= 128 {
a1dfa0c6
XL
68 let unit = if cx.data_layout().endian == Endian::Big {
69 Reg { kind: RegKind::Integer, size }
70 } else if bits <= 8 {
cc61c64b
XL
71 Reg::i8()
72 } else if bits <= 16 {
73 Reg::i16()
74 } else if bits <= 32 {
75 Reg::i32()
9cc50fc6 76 } else {
cc61c64b 77 Reg::i64()
9cc50fc6 78 };
cc61c64b 79
dfeec247 80 ret.cast_to(Uniform { unit, total: size });
54a0048b 81 return;
9cc50fc6
SL
82 }
83
ff7c6d11 84 ret.make_indirect();
9cc50fc6
SL
85}
86
60c5eb7d 87fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, abi: ABI)
dfeec247 88where
94222f64
XL
89 Ty: TyAbiInterface<'a, C> + Copy,
90 C: HasDataLayout,
83c7162d 91{
cc61c64b 92 if !arg.layout.is_aggregate() {
54a0048b
SL
93 arg.extend_integer_width_to(64);
94 return;
9cc50fc6 95 }
54a0048b 96
2c00a5a8 97 if let Some(uniform) = is_homogeneous_aggregate(cx, arg, abi) {
ff7c6d11 98 arg.cast_to(uniform);
54a0048b 99 return;
9cc50fc6
SL
100 }
101
ff7c6d11 102 let size = arg.layout.size;
a1dfa0c6
XL
103 let (unit, total) = if size.bits() <= 64 {
104 // Aggregates smaller than a doubleword should appear in
105 // the least-significant bits of the parameter doubleword.
106 (Reg { kind: RegKind::Integer, size }, size)
107 } else {
108 // Aggregates larger than a doubleword should be padded
109 // at the tail to fill out a whole number of doublewords.
110 let reg_i64 = Reg::i64();
111 (reg_i64, size.align_to(reg_i64.align(cx)))
ea8adc8c
XL
112 };
113
dfeec247 114 arg.cast_to(Uniform { unit, total });
9cc50fc6
SL
115}
116
60c5eb7d 117pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
dfeec247 118where
94222f64
XL
119 Ty: TyAbiInterface<'a, C> + Copy,
120 C: HasDataLayout + HasTargetSpec,
83c7162d 121{
29967ef6 122 let abi = if cx.target_spec().env == "musl" {
a1dfa0c6
XL
123 ELFv2
124 } else {
125 match cx.data_layout().endian {
126 Endian::Big => ELFv1,
dfeec247 127 Endian::Little => ELFv2,
a1dfa0c6 128 }
ea8adc8c
XL
129 };
130
60c5eb7d
XL
131 if !fn_abi.ret.is_ignore() {
132 classify_ret(cx, &mut fn_abi.ret, abi);
54a0048b 133 }
9cc50fc6 134
f2b60f7d 135 for arg in fn_abi.args.iter_mut() {
dfeec247
XL
136 if arg.is_ignore() {
137 continue;
138 }
60c5eb7d 139 classify_arg(cx, arg, abi);
54a0048b 140 }
9cc50fc6 141}