Skip to main content

rustc_codegen_llvm/
type_of.rs

1use std::fmt::Write;
2
3use rustc_abi::Primitive::{Float, Int, Pointer};
4use rustc_abi::{Align, BackendRepr, FieldsShape, Scalar, Size, Variants};
5use rustc_codegen_ssa::traits::*;
6use rustc_middle::bug;
7use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
8use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
9use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt};
10use rustc_span::{DUMMY_SP, Span};
11use tracing::debug;
12
13use crate::common::*;
14use crate::llvm::Type;
15
16fn uncached_llvm_type<'a, 'tcx>(
17    cx: &CodegenCx<'a, 'tcx>,
18    layout: TyAndLayout<'tcx>,
19    defer: &mut Option<(&'a Type, TyAndLayout<'tcx>)>,
20) -> &'a Type {
21    match layout.backend_repr {
22        BackendRepr::Scalar(_) => ::rustc_middle::util::bug::bug_fmt(format_args!("handled elsewhere"))bug!("handled elsewhere"),
23        BackendRepr::SimdVector { element, count } => {
24            let element = layout.scalar_llvm_type_at(cx, element);
25            return cx.type_vector(element, count);
26        }
27        BackendRepr::SimdScalableVector { ref element, count, number_of_vectors } => {
28            let element = if element.is_bool() {
29                cx.type_i1()
30            } else {
31                layout.scalar_llvm_type_at(cx, *element)
32            };
33
34            let vector_type = cx.type_scalable_vector(element, count);
35            return match number_of_vectors.0 {
36                1 => vector_type,
37                2 => cx.type_struct(&[vector_type, vector_type], false),
38                3 => cx.type_struct(&[vector_type, vector_type, vector_type], false),
39                4 => cx.type_struct(&[vector_type, vector_type, vector_type, vector_type], false),
40                5 => cx.type_struct(
41                    &[vector_type, vector_type, vector_type, vector_type, vector_type],
42                    false,
43                ),
44                6 => cx.type_struct(
45                    &[vector_type, vector_type, vector_type, vector_type, vector_type, vector_type],
46                    false,
47                ),
48                7 => cx.type_struct(
49                    &[
50                        vector_type,
51                        vector_type,
52                        vector_type,
53                        vector_type,
54                        vector_type,
55                        vector_type,
56                        vector_type,
57                    ],
58                    false,
59                ),
60                8 => cx.type_struct(
61                    &[
62                        vector_type,
63                        vector_type,
64                        vector_type,
65                        vector_type,
66                        vector_type,
67                        vector_type,
68                        vector_type,
69                        vector_type,
70                    ],
71                    false,
72                ),
73                _ => ::rustc_middle::util::bug::bug_fmt(format_args!("`#[rustc_scalable_vector]` tuple struct with too many fields"))bug!("`#[rustc_scalable_vector]` tuple struct with too many fields"),
74            };
75        }
76        BackendRepr::Memory { .. } | BackendRepr::ScalarPair(..) => {}
77    }
78
79    let name = match layout.ty.kind() {
80        // FIXME(eddyb) producing readable type names for trait objects can result
81        // in problematically distinct types due to HRTB and subtyping (see #47638).
82        // ty::Dynamic(..) |
83        ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str
84            // For performance reasons we use names only when emitting LLVM IR.
85            if !cx.sess().fewer_names() =>
86        {
87            let mut name = {
    let _guard = NoVisibleGuard::new();
    { let _guard = NoTrimmedGuard::new(); layout.ty.to_string() }
}with_no_visible_paths!(with_no_trimmed_paths!(layout.ty.to_string()));
88            if let (&ty::Adt(def, _), &Variants::Single { index }) =
89                (layout.ty.kind(), &layout.variants)
90            {
91                if def.is_enum() {
92                    (&mut name).write_fmt(format_args!("::{0}", def.variant(index).name))write!(&mut name, "::{}", def.variant(index).name).unwrap();
93                }
94            }
95            if let (&ty::Coroutine(_, _), &Variants::Single { index }) =
96                (layout.ty.kind(), &layout.variants)
97            {
98                (&mut name).write_fmt(format_args!("::{0}",
        ty::CoroutineArgs::variant_name(index)))write!(&mut name, "::{}", ty::CoroutineArgs::variant_name(index)).unwrap();
99            }
100            Some(name)
101        }
102        _ => None,
103    };
104
105    match layout.fields {
106        FieldsShape::Primitive | FieldsShape::Union(_) => {
107            let fill = cx.type_padding_filler(layout.size, layout.align.abi);
108            let packed = false;
109            match name {
110                None => cx.type_struct(&[fill], packed),
111                Some(ref name) => {
112                    let llty = cx.type_named_struct(name);
113                    cx.set_struct_body(llty, &[fill], packed);
114                    llty
115                }
116            }
117        }
118        FieldsShape::Array { count, .. } => cx.type_array(layout.field(cx, 0).llvm_type(cx), count),
119        FieldsShape::Arbitrary { .. } => match name {
120            None => {
121                let (llfields, packed) = struct_llfields(cx, layout);
122                cx.type_struct(&llfields, packed)
123            }
124            Some(ref name) => {
125                let llty = cx.type_named_struct(name);
126                *defer = Some((llty, layout));
127                llty
128            }
129        },
130    }
131}
132
133fn struct_llfields<'a, 'tcx>(
134    cx: &CodegenCx<'a, 'tcx>,
135    layout: TyAndLayout<'tcx>,
136) -> (Vec<&'a Type>, bool) {
137    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_llvm/src/type_of.rs:137",
                        "rustc_codegen_llvm::type_of", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_llvm/src/type_of.rs"),
                        ::tracing_core::__macro_support::Option::Some(137u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_codegen_llvm::type_of"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("struct_llfields: {0:#?}",
                                                    layout) as &dyn Value))])
            });
    } else { ; }
};debug!("struct_llfields: {:#?}", layout);
138    let field_count = layout.fields.count();
139
140    let mut packed = false;
141    let mut offset = Size::ZERO;
142    let mut prev_effective_align = layout.align.abi;
143    let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2);
144    for i in layout.fields.index_by_increasing_offset() {
145        let target_offset = layout.fields.offset(i as usize);
146        let field = layout.field(cx, i);
147        let effective_field_align =
148            layout.align.abi.min(field.align.abi).restrict_for_offset(target_offset);
149        packed |= effective_field_align < field.align.abi;
150
151        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_llvm/src/type_of.rs:151",
                        "rustc_codegen_llvm::type_of", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_llvm/src/type_of.rs"),
                        ::tracing_core::__macro_support::Option::Some(151u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_codegen_llvm::type_of"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("struct_llfields: {0}: {1:?} offset: {2:?} target_offset: {3:?} effective_field_align: {4}",
                                                    i, field, offset, target_offset,
                                                    effective_field_align.bytes()) as &dyn Value))])
            });
    } else { ; }
};debug!(
152            "struct_llfields: {}: {:?} offset: {:?} target_offset: {:?} \
153                effective_field_align: {}",
154            i,
155            field,
156            offset,
157            target_offset,
158            effective_field_align.bytes()
159        );
160        if !(target_offset >= offset) {
    ::core::panicking::panic("assertion failed: target_offset >= offset")
};assert!(target_offset >= offset);
161        let padding = target_offset - offset;
162        if padding != Size::ZERO {
163            let padding_align = prev_effective_align.min(effective_field_align);
164            match (&(offset.align_to(padding_align) + padding), &target_offset) {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::None);
        }
    }
};assert_eq!(offset.align_to(padding_align) + padding, target_offset);
165            result.push(cx.type_padding_filler(padding, padding_align));
166            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_llvm/src/type_of.rs:166",
                        "rustc_codegen_llvm::type_of", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_llvm/src/type_of.rs"),
                        ::tracing_core::__macro_support::Option::Some(166u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_codegen_llvm::type_of"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("    padding before: {0:?}",
                                                    padding) as &dyn Value))])
            });
    } else { ; }
};debug!("    padding before: {:?}", padding);
167        }
168        result.push(field.llvm_type(cx));
169        offset = target_offset + field.size;
170        prev_effective_align = effective_field_align;
171    }
172    if layout.is_sized() && field_count > 0 {
173        if offset > layout.size {
174            ::rustc_middle::util::bug::bug_fmt(format_args!("layout: {0:#?} stride: {1:?} offset: {2:?}",
        layout, layout.size, offset));bug!("layout: {:#?} stride: {:?} offset: {:?}", layout, layout.size, offset);
175        }
176        let padding = layout.size - offset;
177        if padding != Size::ZERO {
178            let padding_align = prev_effective_align;
179            match (&(offset.align_to(padding_align) + padding), &layout.size) {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::None);
        }
    }
};assert_eq!(offset.align_to(padding_align) + padding, layout.size);
180            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_llvm/src/type_of.rs:180",
                        "rustc_codegen_llvm::type_of", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_llvm/src/type_of.rs"),
                        ::tracing_core::__macro_support::Option::Some(180u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_codegen_llvm::type_of"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("struct_llfields: pad_bytes: {0:?} offset: {1:?} stride: {2:?}",
                                                    padding, offset, layout.size) as &dyn Value))])
            });
    } else { ; }
};debug!(
181                "struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}",
182                padding, offset, layout.size
183            );
184            result.push(cx.type_padding_filler(padding, padding_align));
185        }
186    } else {
187        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_llvm/src/type_of.rs:187",
                        "rustc_codegen_llvm::type_of", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_llvm/src/type_of.rs"),
                        ::tracing_core::__macro_support::Option::Some(187u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_codegen_llvm::type_of"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("struct_llfields: offset: {0:?} stride: {1:?}",
                                                    offset, layout.size) as &dyn Value))])
            });
    } else { ; }
};debug!("struct_llfields: offset: {:?} stride: {:?}", offset, layout.size);
188    }
189    (result, packed)
190}
191
192impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
193    pub(crate) fn align_of(&self, ty: Ty<'tcx>) -> Align {
194        self.layout_of(ty).align.abi
195    }
196
197    pub(crate) fn size_of(&self, ty: Ty<'tcx>) -> Size {
198        self.layout_of(ty).size
199    }
200
201    pub(crate) fn size_and_align_of(&self, ty: Ty<'tcx>) -> (Size, Align) {
202        self.spanned_size_and_align_of(ty, DUMMY_SP)
203    }
204
205    pub(crate) fn spanned_size_and_align_of(&self, ty: Ty<'tcx>, span: Span) -> (Size, Align) {
206        let layout = self.spanned_layout_of(ty, span);
207        (layout.size, layout.align.abi)
208    }
209}
210
211pub(crate) trait LayoutLlvmExt<'tcx> {
212    fn is_llvm_immediate(&self) -> bool;
213    fn is_llvm_scalar_pair(&self) -> bool;
214    fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type;
215    fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type;
216    fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, scalar: Scalar) -> &'a Type;
217    fn scalar_pair_element_llvm_type<'a>(
218        &self,
219        cx: &CodegenCx<'a, 'tcx>,
220        index: usize,
221        immediate: bool,
222    ) -> &'a Type;
223}
224
225impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
226    fn is_llvm_immediate(&self) -> bool {
227        match self.backend_repr {
228            BackendRepr::Scalar(_)
229            | BackendRepr::SimdVector { .. }
230            | BackendRepr::SimdScalableVector { .. } => true,
231            BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false,
232        }
233    }
234
235    fn is_llvm_scalar_pair(&self) -> bool {
236        match self.backend_repr {
237            BackendRepr::ScalarPair(..) => true,
238            BackendRepr::Scalar(_)
239            | BackendRepr::SimdVector { .. }
240            | BackendRepr::SimdScalableVector { .. }
241            | BackendRepr::Memory { .. } => false,
242        }
243    }
244
245    /// Gets the LLVM type corresponding to a Rust type, i.e., `rustc_middle::ty::Ty`.
246    /// The pointee type of the pointer in `PlaceRef` is always this type.
247    /// For sized types, it is also the right LLVM type for an `alloca`
248    /// containing a value of that type, and most immediates (except `bool`).
249    /// Unsized types, however, are represented by a "minimal unit", e.g.
250    /// `[T]` becomes `T`, while `str` and `Trait` turn into `i8` - this
251    /// is useful for indexing slices, as `&[T]`'s data pointer is `T*`.
252    /// If the type is an unsized struct, the regular layout is generated,
253    /// with the innermost trailing unsized field using the "minimal unit"
254    /// of that field's type - this is useful for taking the address of
255    /// that field and ensuring the struct has the right alignment.
256    fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
257        // This must produce the same result for `repr(transparent)` wrappers as for the inner type!
258        // In other words, this should generally not look at the type at all, but only at the
259        // layout.
260        if let BackendRepr::Scalar(scalar) = self.backend_repr {
261            // Use a different cache for scalars because pointers to DSTs
262            // can be either wide or thin (data pointers of wide pointers).
263            if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) {
264                return llty;
265            }
266            let llty = self.scalar_llvm_type_at(cx, scalar);
267            cx.scalar_lltypes.borrow_mut().insert(self.ty, llty);
268            return llty;
269        }
270
271        // Check the cache.
272        let variant_index = match self.variants {
273            Variants::Single { index } => Some(index),
274            _ => None,
275        };
276        if let Some(llty) = cx.type_lowering.borrow().get(&(self.ty, variant_index)) {
277            return llty;
278        }
279
280        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_llvm/src/type_of.rs:280",
                        "rustc_codegen_llvm::type_of", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_llvm/src/type_of.rs"),
                        ::tracing_core::__macro_support::Option::Some(280u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_codegen_llvm::type_of"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("llvm_type({0:#?})",
                                                    self) as &dyn Value))])
            });
    } else { ; }
};debug!("llvm_type({:#?})", self);
281
282        if !!self.ty.has_escaping_bound_vars() {
    {
        ::core::panicking::panic_fmt(format_args!("{0:?} has escaping bound vars",
                self.ty));
    }
};assert!(!self.ty.has_escaping_bound_vars(), "{:?} has escaping bound vars", self.ty);
283
284        // Make sure lifetimes are erased, to avoid generating distinct LLVM
285        // types for Rust types that only differ in the choice of lifetimes.
286        let normal_ty = cx.tcx.erase_and_anonymize_regions(self.ty);
287
288        let mut defer = None;
289        let llty = if self.ty != normal_ty {
290            let mut layout = cx.layout_of(normal_ty);
291            if let Some(v) = variant_index {
292                layout = layout.for_variant(cx, v);
293            }
294            layout.llvm_type(cx)
295        } else {
296            uncached_llvm_type(cx, *self, &mut defer)
297        };
298        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_llvm/src/type_of.rs:298",
                        "rustc_codegen_llvm::type_of", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_llvm/src/type_of.rs"),
                        ::tracing_core::__macro_support::Option::Some(298u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_codegen_llvm::type_of"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("--> mapped {0:#?} to llty={1:?}",
                                                    self, llty) as &dyn Value))])
            });
    } else { ; }
};debug!("--> mapped {:#?} to llty={:?}", self, llty);
299
300        cx.type_lowering.borrow_mut().insert((self.ty, variant_index), llty);
301
302        if let Some((llty, layout)) = defer {
303            let (llfields, packed) = struct_llfields(cx, layout);
304            cx.set_struct_body(llty, &llfields, packed);
305        }
306        llty
307    }
308
309    fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
310        match self.backend_repr {
311            BackendRepr::Scalar(scalar) => {
312                if scalar.is_bool() {
313                    return cx.type_i1();
314                }
315            }
316            BackendRepr::ScalarPair(..) => {
317                // An immediate pair always contains just the two elements, without any padding
318                // filler, as it should never be stored to memory.
319                return cx.type_struct(
320                    &[
321                        self.scalar_pair_element_llvm_type(cx, 0, true),
322                        self.scalar_pair_element_llvm_type(cx, 1, true),
323                    ],
324                    false,
325                );
326            }
327            _ => {}
328        };
329        self.llvm_type(cx)
330    }
331
332    fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, scalar: Scalar) -> &'a Type {
333        match scalar.primitive() {
334            Int(i, _) => cx.type_from_integer(i),
335            Float(f) => cx.type_from_float(f),
336            Pointer(address_space) => cx.type_ptr_ext(address_space),
337        }
338    }
339
340    fn scalar_pair_element_llvm_type<'a>(
341        &self,
342        cx: &CodegenCx<'a, 'tcx>,
343        index: usize,
344        immediate: bool,
345    ) -> &'a Type {
346        // This must produce the same result for `repr(transparent)` wrappers as for the inner type!
347        // In other words, this should generally not look at the type at all, but only at the
348        // layout.
349        let BackendRepr::ScalarPair(a, b) = self.backend_repr else {
350            ::rustc_middle::util::bug::bug_fmt(format_args!("TyAndLayout::scalar_pair_element_llty({0:?}): not applicable",
        self));bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self);
351        };
352        let scalar = [a, b][index];
353
354        // Make sure to return the same type `immediate_llvm_type` would when
355        // dealing with an immediate pair. This means that `(bool, bool)` is
356        // effectively represented as `{i8, i8}` in memory and two `i1`s as an
357        // immediate, just like `bool` is typically `i8` in memory and only `i1`
358        // when immediate. We need to load/store `bool` as `i8` to avoid
359        // crippling LLVM optimizations or triggering other LLVM bugs with `i1`.
360        if immediate && scalar.is_bool() {
361            return cx.type_i1();
362        }
363
364        self.scalar_llvm_type_at(cx, scalar)
365    }
366}