Skip to main content

rustc_target/callconv/
mips.rs

1use rustc_abi::{Float, HasDataLayout, Integer, Numeric, Reg, RegKind, Size, TyAbiInterface};
2use rustc_span::bug;
3
4use crate::callconv::{ArgAbi, CastTarget, FnAbi, Uniform};
5
6fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, offset: &mut Size)
7where
8    Ty: TyAbiInterface<'a, C> + Copy,
9    C: HasDataLayout,
10{
11    let dl = cx.data_layout();
12    let size = ret.layout.size;
13
14    // Complex types with unsupported component types are returned as an aggregate.
15    let is_supported_complex_component = |numeric| match numeric {
16        Numeric::Int(Integer::I8 | Integer::I16 | Integer::I32 | Integer::I64, _) => true,
17        Numeric::Int(Integer::I128, _) => false,
18        Numeric::Float(Float::F32 | Float::F64) => true,
19        Numeric::Float(Float::F16 | Float::F128) => false,
20        Numeric::Float(Float::F16B | Float::PpcF128) => ::rustc_span::macros::bug_impl(None, format_args!("unsupported on mips"),
    Location::caller())bug!("unsupported on mips"),
21    };
22
23    if let Some(component) = ret.layout.complex_number(cx)
24        && is_supported_complex_component(component)
25    {
26        match component {
27            Numeric::Int(Integer::I8 | Integer::I16, _) => {
28                // Pack Complex<{integer}> into a single register if that fits.
29                ret.cast_to(Reg { kind: RegKind::Integer, size });
30            }
31            _ => {
32                let reg = Reg { kind: component.reg_kind(), size: component.size() };
33                ret.cast_to(CastTarget::from(Uniform::new(reg, size)));
34            }
35        }
36    } else if ret.layout.is_aggregate() {
37        ret.make_indirect();
38        *offset += dl.pointer_size();
39    } else {
40        ret.extend_integer_width_to(32);
41    }
42}
43
44fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, offset: &mut Size)
45where
46    Ty: TyAbiInterface<'a, C> + Copy,
47    C: HasDataLayout,
48{
49    if !arg.layout.is_sized() {
50        // FIXME: Update offset?
51        // Not touching this...
52        return;
53    }
54    let dl = cx.data_layout();
55    let align = arg.layout.align.abi.max(dl.i32_align).min(dl.i64_align);
56
57    if arg.layout.pass_indirectly_in_non_rustic_abis(cx) {
58        arg.make_indirect();
59        *offset = offset.align_to(align) + dl.pointer_size().align_to(align);
60        return;
61    }
62
63    let size = arg.layout.size;
64    if arg.layout.is_aggregate() {
65        let pad_i32 = u8::from(!offset.is_aligned(align));
66        arg.cast_to_and_pad_i32(Uniform::new(Reg::i32(), size), pad_i32);
67    } else {
68        arg.extend_integer_width_to(32);
69    }
70
71    *offset = offset.align_to(align) + size.align_to(align);
72}
73
74pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
75where
76    Ty: TyAbiInterface<'a, C> + Copy,
77    C: HasDataLayout,
78{
79    let mut offset = Size::ZERO;
80    if !fn_abi.ret.is_ignore() {
81        classify_ret(cx, &mut fn_abi.ret, &mut offset);
82    }
83
84    for arg in fn_abi.args.iter_mut() {
85        if arg.is_ignore() {
86            continue;
87        }
88        classify_arg(cx, arg, &mut offset);
89    }
90}