rustc_middle/ty/
offload_meta.rs

1use bitflags::bitflags;
2
3use crate::ty::{self, PseudoCanonicalInput, Ty, TyCtxt, TypingEnv};
4
5pub struct OffloadMetadata {
6    pub payload_size: u64,
7    pub mode: MappingFlags,
8}
9
10bitflags! {
11    /// Mirrors `OpenMPOffloadMappingFlags` from Clang/OpenMP.
12    #[derive(Debug, Copy, Clone)]
13    #[repr(transparent)]
14    pub struct MappingFlags: u64 {
15        /// No flags.
16        const NONE           = 0x0;
17        /// Allocate memory on the device and move data from host to device.
18        const TO             = 0x01;
19        /// Allocate memory on the device and move data from device to host.
20        const FROM           = 0x02;
21        /// Always perform the requested mapping action, even if already mapped.
22        const ALWAYS         = 0x04;
23        /// Delete the element from the device environment, ignoring ref count.
24        const DELETE         = 0x08;
25        /// The element being mapped is a pointer-pointee pair.
26        const PTR_AND_OBJ    = 0x10;
27        /// The base address should be passed to the target kernel as argument.
28        const TARGET_PARAM   = 0x20;
29        /// The runtime must return the device pointer.
30        const RETURN_PARAM   = 0x40;
31        /// The reference being passed is a pointer to private data.
32        const PRIVATE        = 0x80;
33        /// Pass the element by value.
34        const LITERAL        = 0x100;
35        /// Implicit map (generated by compiler, not explicit in code).
36        const IMPLICIT       = 0x200;
37        /// Hint to allocate memory close to the target device.
38        const CLOSE          = 0x400;
39        /// Reserved (0x800 in OpenMP for XLC compatibility).
40        const RESERVED       = 0x800;
41        /// Require that the data is already allocated on the device.
42        const PRESENT        = 0x1000;
43        /// Increment/decrement a separate ref counter (OpenACC compatibility).
44        const OMPX_HOLD      = 0x2000;
45        /// Used for non-contiguous list items in target update.
46        const NON_CONTIG     = 0x100000000000;
47        /// 16 MSBs indicate membership in a struct.
48        const MEMBER_OF      = 0xffff000000000000;
49    }
50}
51
52impl OffloadMetadata {
53    pub fn from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
54        OffloadMetadata {
55            payload_size: get_payload_size(tcx, ty),
56            mode: MappingFlags::from_ty(tcx, ty),
57        }
58    }
59}
60
61// FIXME(Sa4dUs): implement a solid logic to determine the payload size
62fn get_payload_size<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> u64 {
63    match ty.kind() {
64        ty::RawPtr(inner, _) | ty::Ref(_, inner, _) => get_payload_size(tcx, *inner),
65        _ => tcx
66            .layout_of(PseudoCanonicalInput {
67                typing_env: TypingEnv::fully_monomorphized(),
68                value: ty,
69            })
70            .unwrap()
71            .size
72            .bytes(),
73    }
74}
75
76impl MappingFlags {
77    fn from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
78        use rustc_ast::Mutability::*;
79
80        match ty.kind() {
81            ty::Bool
82            | ty::Char
83            | ty::Int(_)
84            | ty::Uint(_)
85            | ty::Float(_)
86            | ty::Adt(_, _)
87            | ty::Tuple(_)
88            | ty::Array(_, _)
89            | ty::Alias(_, _)
90            | ty::Param(_) => MappingFlags::TO,
91
92            ty::RawPtr(_, Not) | ty::Ref(_, _, Not) => MappingFlags::TO,
93
94            ty::RawPtr(_, Mut) | ty::Ref(_, _, Mut) => MappingFlags::TO | MappingFlags::FROM,
95
96            ty::Slice(_) | ty::Str | ty::Dynamic(_, _) => MappingFlags::TO | MappingFlags::FROM,
97
98            ty::Foreign(_) | ty::Pat(_, _) | ty::UnsafeBinder(_) => {
99                MappingFlags::TO | MappingFlags::FROM
100            }
101
102            ty::FnDef(_, _)
103            | ty::FnPtr(_, _)
104            | ty::Closure(_, _)
105            | ty::CoroutineClosure(_, _)
106            | ty::Coroutine(_, _)
107            | ty::CoroutineWitness(_, _)
108            | ty::Never
109            | ty::Bound(_, _)
110            | ty::Placeholder(_)
111            | ty::Infer(_)
112            | ty::Error(_) => {
113                tcx.dcx()
114                    .span_err(rustc_span::DUMMY_SP, format!("type `{ty:?}` cannot be offloaded"));
115                MappingFlags::empty()
116            }
117        }
118    }
119}