Skip to content

Commit 34fe97c

Browse files
committed
sparc64 cleanup
1 parent c948df9 commit 34fe97c

1 file changed

Lines changed: 40 additions & 32 deletions

File tree

‎compiler/rustc_target/src/callconv/mips64.rs‎

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use arrayvec::ArrayVec;
22
use rustc_abi::{
3-
BackendRepr, FieldsShape, Float, HasDataLayout, Numeric, Primitive, Reg, RegKind, Size,
4-
TyAbiInterface,
3+
BackendRepr, FieldsShape, Float, HasDataLayout, Integer, Numeric, Primitive, Reg, RegKind,
4+
Size, TyAbiInterface,
55
};
66

77
use crate::callconv::{ArgAbi, ArgAttribute, ArgExtension, CastTarget, FnAbi, PassMode, Uniform};
@@ -59,14 +59,17 @@ where
5959
let bits = size.bits();
6060
if bits <= 128 {
6161
if let Some(component) = ret.layout.complex_number(cx) {
62-
if matches!(component, Numeric::Int(..)) && size <= cx.data_layout().pointer_size() {
63-
// Return a Complex<{integer}> packed into a single register when that fits.
64-
// We match GCC, not Clang, see https://github.com/llvm/llvm-project/issues/212109.
65-
ret.cast_to(Reg { kind: RegKind::Integer, size });
66-
} else {
67-
// Otherwise pass in 2 registers.
68-
let reg = Reg { kind: component.reg_kind(), size: component.size() };
69-
ret.cast_to(CastTarget::pair(reg, reg));
62+
match component {
63+
Numeric::Int(Integer::I8 | Integer::I16 | Integer::I32, _) => {
64+
// Return a Complex<{integer}> packed into a single register when that fits.
65+
// We match GCC, not Clang, see https://github.com/llvm/llvm-project/issues/212109.
66+
ret.cast_to(Reg { kind: RegKind::Integer, size });
67+
}
68+
_ => {
69+
// Otherwise pass in 2 registers.
70+
let reg = Reg { kind: component.reg_kind(), size: component.size() };
71+
ret.cast_to(CastTarget::pair(reg, reg));
72+
}
7073
}
7174
return;
7275
}
@@ -118,33 +121,38 @@ where
118121
extend_integer_width_mips(arg, 64);
119122
} else if arg.layout.pass_indirectly_in_non_rustic_abis(cx) {
120123
arg.make_indirect();
121-
} else if arg.layout.complex_float(cx).is_some() && size > dl.pointer_size() * 2 {
122-
// Complex<f128> is passed in 4 GPRs, but aligned to 16 so may need padding.
123-
let reg = Reg { kind: RegKind::Float, size: arg.layout.field(cx, 0).size };
124-
arg.cast_to_and_pad_i32(CastTarget::pair(reg, reg), pad_i32);
125-
} else if arg.layout.is_complex_number(cx) && size <= dl.pointer_size() * 2 {
124+
} else if let Some(component) = arg.layout.complex_number(cx) {
126125
let slot = dl.pointer_size();
127126
let curr_offset = offset.align_to(align);
128127

129-
if arg.layout.complex_float(cx).is_some() {
130-
// Only pass a Complex<f32>/Complex<f64> in FPRs when two argument slots are free,
131-
// otherwise pack it into GPRs (or the stack) like an integer of the same size.
132-
if curr_offset.bytes() / slot.bytes() + 2 <= NUM_ARG_SLOTS {
133-
// The default `PassMode::Pair` already passes one component per register. Both
134-
// components claim a slot, even for a Complex<f32> which could fit into one slot.
135-
*offset = curr_offset + slot * 2;
136-
return;
128+
match component {
129+
Numeric::Float(Float::F128) => {
130+
// Complex<f128> is passed in 4 GPRs, but aligned to 16 so may need padding.
131+
let reg = Reg { kind: RegKind::Float, size: arg.layout.field(cx, 0).size };
132+
arg.cast_to_and_pad_i32(CastTarget::pair(reg, reg), pad_i32);
137133
}
134+
Numeric::Float(_) => {
135+
// Only pass a Complex<f32>/Complex<f64> in FPRs when two argument slots are free,
136+
if curr_offset.bytes() / slot.bytes() + 2 <= NUM_ARG_SLOTS {
137+
// The default `PassMode::Pair` already passes one component per register. Both
138+
// components claim a slot, even a Complex<f32> which could fit into one slot.
139+
*offset = curr_offset + slot * 2;
140+
return;
141+
}
138142

139-
arg.cast_to_and_pad_i32(Uniform::new(Reg::i64(), size), pad_i32);
140-
} else if size > slot {
141-
// Complex<i64> is passed as 2 separate arguments, which is what the default
142-
// `PassMode::Pair` already does.
143-
} else {
144-
// Cast Complex<i8> into i16, Complex<i16> to i32, etc. The inreg attribute is required
145-
// to make the bits land in the right (upper) bits on big endian targets.
146-
let cast_target = CastTarget::from(Reg { kind: RegKind::Integer, size });
147-
arg.cast_to(cast_target.with_attrs(ArgAttribute::InReg.into()));
143+
// Otherwise pack it into GPRs (or the stack) like an integer of the same size.
144+
arg.cast_to_and_pad_i32(Uniform::new(Reg::i64(), size), pad_i32);
145+
}
146+
Numeric::Int(Integer::I8 | Integer::I16 | Integer::I32, _) => {
147+
// Cast Complex<i8> into i16, Complex<i16> to i32, etc.
148+
let cast_target = CastTarget::from(Reg { kind: RegKind::Integer, size });
149+
// The inreg attribute makes the bits land in the right (upper) bits on BE targets.
150+
arg.cast_to(cast_target.with_attrs(ArgAttribute::InReg.into()));
151+
}
152+
Numeric::Int(Integer::I64 | Integer::I128, _) => {
153+
// Complex<i64> is passed as 2 separate arguments, which is what the default
154+
// `PassMode::Pair` already does.
155+
}
148156
}
149157
} else {
150158
match arg.layout.fields {

0 commit comments

Comments
 (0)