Skip to main content

rustc_target/callconv/
amdgpu.rs

1use rustc_abi::{
2    AddressSpace, BackendRepr, CanonAbi, HasDataLayout, Reg, RegKind, TyAbiInterface, TyAndLayout,
3};
4
5use crate::callconv::{FnAbi, Uniform};
6
7// For reference, see llvm-project/clang/lib/CodeGen/Targets/AMDGPU.cpp
8
9/// If the given type is a (potentially nested) struct containing a single scalar, return
10/// a `Uniform` for the contained, single element.
11fn single_element_struct_to_reg<'a, Ty, C>(cx: &C, ty: TyAndLayout<'a, Ty>) -> Option<Uniform>
12where
13    Ty: TyAbiInterface<'a, C> + Copy,
14    C: HasDataLayout,
15{
16    if !ty.is_aggregate() {
    {
        ::core::panicking::panic_fmt(format_args!("Only handles aggregate types"));
    }
};assert!(ty.is_aggregate(), "Only handles aggregate types");
17    if ty.layout.fields.count() != 1 {
18        return None;
19    }
20    let field = ty.field(cx, 0);
21    match field.backend_repr {
22        BackendRepr::SimdScalableVector { .. } => {
    ::core::panicking::panic_fmt(format_args!("scalable vectors are unsupported"));
}panic!("scalable vectors are unsupported"),
23        BackendRepr::Scalar(_) => {
24            // Check that the size is the same as the size for ty, so no extra padding
25            let size = field.layout.size.bytes();
26            if ty.layout.size.bytes() != size {
27                return None;
28            }
29
30            // clang passes the inner type directly, we emulate it with fitting integer types
31            match size {
32                1 => Some(Uniform::new(Reg::i8(), field.layout.size)),
33                2 => Some(Uniform::new(Reg::i16(), field.layout.size)),
34                4 => Some(Uniform::new(Reg::i32(), field.layout.size)),
35                8 => Some(Uniform::new(Reg::i64(), field.layout.size)),
36                16 => Some(Uniform::new(Reg::i128(), field.layout.size)),
37                s => {
    ::core::panicking::panic_fmt(format_args!("Unhandled scalar of size {0} in amdgpu gpu-kernel ABI",
            s));
}panic!("Unhandled scalar of size {s} in amdgpu gpu-kernel ABI"),
38            }
39        }
40        BackendRepr::SimdVector { element, .. } => {
41            // Check that the size is the same as the size for ty, so no extra padding
42            let size = field.layout.size.bytes();
43            if ty.layout.size.bytes() != size {
44                return None;
45            }
46
47            // clang passes the inner type directly, we emulate it with a vector of the same type.
48            // The size is rounded up to the size of the complete type (including alignment).
49            let reg = Reg {
50                kind: RegKind::Vector { hint_vector_elem: element.primitive() },
51                size: field.layout.size,
52            };
53            Some(Uniform::new(reg, field.layout.size))
54        }
55        BackendRepr::Memory { .. } => single_element_struct_to_reg(cx, field),
56        BackendRepr::ScalarPair { .. } => None,
57    }
58}
59
60pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
61where
62    Ty: TyAbiInterface<'a, C> + Copy,
63    C: HasDataLayout,
64{
65    // Kernels cannot return values, so do not handle return types
66
67    // Try to fill first registers with values and pass by_ref pointers for later indirect arguments
68    for arg in fn_abi.args.iter_mut() {
69        if arg.is_ignore() {
70            continue;
71        }
72        if fn_abi.conv == CanonAbi::GpuKernel {
73            if arg.layout.is_aggregate() {
74                if let Some(uniform) = single_element_struct_to_reg(cx, arg.layout) {
75                    // Single element structs are passed directly as the inner type
76                    arg.cast_to(uniform);
77                } else {
78                    // All other aggregates are passed as by_ref pointer in the constant address space
79                    arg.pass_amdgpu_kernel_arg(Some(AddressSpace::GPU_CONSTANT));
80                }
81            }
82        } else {
83            // FIXME: C ABI is not yet implemented
84        }
85    }
86}