Skip to content

Commit fa68eff

Browse files
committed
callconv: adapt mips padding logic to mips64
Similar to mips, mips64 also adds a padding register when an aggregate argument is not passed with an aligned offset, for any byte alignment `a` where `8 < a <= 16` bytes.
1 parent 72fe2ff commit fa68eff

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

compiler/rustc_target/src/callconv/mips64.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ where
3434
}
3535
}
3636

37-
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
37+
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, offset: &mut Size)
3838
where
3939
Ty: TyAbiInterface<'a, C> + Copy,
4040
C: HasDataLayout,
@@ -70,10 +70,11 @@ where
7070
ret.cast_to(Uniform::new(Reg::i64(), size));
7171
} else {
7272
ret.make_indirect();
73+
*offset += cx.data_layout().pointer_size();
7374
}
7475
}
7576

76-
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
77+
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, offset: &mut Size)
7778
where
7879
Ty: TyAbiInterface<'a, C> + Copy,
7980
C: HasDataLayout,
@@ -134,24 +135,36 @@ where
134135
}
135136
};
136137

138+
// Detect need for padding
139+
let align = arg.layout.align.abi.max(dl.i64_align).min(dl.i128_align);
140+
let pad_i32 = !offset.is_aligned(align);
137141
// Extract first 8 chunks as the prefix
138142
let rest_size = size - Size::from_bytes(8) * prefix_index as u64;
139-
arg.cast_to(CastTarget::prefixed(prefix, Uniform::new(Reg::i64(), rest_size)));
143+
// FIXME: an i32 padding is generated while clang uses i64
144+
arg.cast_to_and_pad_i32(
145+
CastTarget::prefixed(prefix, Uniform::new(Reg::i64(), rest_size)),
146+
pad_i32,
147+
);
148+
*offset = offset.align_to(align) + size.align_to(align);
140149
}
141150

142151
pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
143152
where
144153
Ty: TyAbiInterface<'a, C> + Copy,
145154
C: HasDataLayout,
146155
{
156+
// mips64 argument passing is also affected by the alignment of aggregates.
157+
// see mips.rs for how the offset is used
158+
let mut offset = Size::ZERO;
159+
147160
if !fn_abi.ret.is_ignore() {
148-
classify_ret(cx, &mut fn_abi.ret);
161+
classify_ret(cx, &mut fn_abi.ret, &mut offset);
149162
}
150163

151164
for arg in fn_abi.args.iter_mut() {
152165
if arg.is_ignore() {
153166
continue;
154167
}
155-
classify_arg(cx, arg);
168+
classify_arg(cx, arg, &mut offset);
156169
}
157170
}

0 commit comments

Comments
 (0)