Skip to main content

rustc_codegen_ssa/mir/
locals.rs

1//! Locals are in a private module as updating `LocalRef::Operand` has to
2//! be careful wrt to subtyping. To deal with this we only allow updates by using
3//! `FunctionCx::overwrite_local` which handles it automatically.
4
5use std::ops::{Index, IndexMut};
6
7use rustc_index::IndexVec;
8use rustc_middle::mir;
9use rustc_middle::ty::print::with_no_trimmed_paths;
10use tracing::{debug, warn};
11
12use crate::mir::{FunctionCx, LocalRef};
13use crate::traits::BuilderMethods;
14
15pub(super) struct Locals<'tcx, V> {
16    values: IndexVec<mir::Local, LocalRef<'tcx, V>>,
17}
18
19impl<'tcx, V> Index<mir::Local> for Locals<'tcx, V> {
20    type Output = LocalRef<'tcx, V>;
21    #[inline]
22    fn index(&self, index: mir::Local) -> &LocalRef<'tcx, V> {
23        &self.values[index]
24    }
25}
26
27/// To mutate locals, use `FunctionCx::overwrite_local` instead.
28impl<'tcx, V, Idx: ?Sized> !IndexMut<Idx> for Locals<'tcx, V> {}
29
30impl<'tcx, V> Locals<'tcx, V> {
31    pub(super) fn empty() -> Locals<'tcx, V> {
32        Locals { values: IndexVec::default() }
33    }
34
35    pub(super) fn indices(&self) -> impl DoubleEndedIterator<Item = mir::Local> + Clone + 'tcx {
36        self.values.indices()
37    }
38}
39
40impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
41    pub(super) fn initialize_locals(&mut self, values: Vec<LocalRef<'tcx, Bx::Value>>) {
42        if !self.locals.values.is_empty() {
    ::core::panicking::panic("assertion failed: self.locals.values.is_empty()")
};assert!(self.locals.values.is_empty());
43        self.locals.values = IndexVec::from_raw(values);
44        // FIXME(#115215): After #115025 get's merged this might not be necessary
45        for (local, value) in self.locals.values.iter_enumerated() {
46            match value {
47                LocalRef::Place(_) | LocalRef::UnsizedPlace(_) | LocalRef::PendingOperand => (),
48                LocalRef::Operand(op) => {
49                    let expected_ty = self.monomorphize(self.mir.local_decls[local].ty);
50                    if expected_ty != op.layout.ty {
51                        {
    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_ssa/src/mir/locals.rs:51",
                        "rustc_codegen_ssa::mir::locals", ::tracing::Level::WARN,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/mir/locals.rs"),
                        ::tracing_core::__macro_support::Option::Some(51u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::mir::locals"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::WARN <=
                    ::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!("Unexpected initial operand type:\nexpected {1:?},\nfound    {0:?}.\nSee <https://github.com/rust-lang/rust/issues/114858>.",
                                                    op.layout.ty, expected_ty) as &dyn Value))])
            });
    } else { ; }
};warn!(
52                            "Unexpected initial operand type:\nexpected {expected_ty:?},\nfound    {:?}.\n\
53                            See <https://github.com/rust-lang/rust/issues/114858>.",
54                            op.layout.ty
55                        );
56                    }
57                }
58            }
59        }
60    }
61
62    pub(super) fn overwrite_local(
63        &mut self,
64        local: mir::Local,
65        mut value: LocalRef<'tcx, Bx::Value>,
66    ) {
67        match value {
68            LocalRef::Place(_) | LocalRef::UnsizedPlace(_) | LocalRef::PendingOperand => (),
69            LocalRef::Operand(ref mut op) => {
70                let local_ty = self.monomorphize(self.mir.local_decls[local].ty);
71                if local_ty != op.layout.ty {
72                    // FIXME(#112651): This can be changed to an ICE afterwards.
73                    {
    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_ssa/src/mir/locals.rs:73",
                        "rustc_codegen_ssa::mir::locals", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/mir/locals.rs"),
                        ::tracing_core::__macro_support::Option::Some(73u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::mir::locals"),
                        ::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!("updating type of operand due to subtyping")
                                            as &dyn Value))])
            });
    } else { ; }
};debug!("updating type of operand due to subtyping");
74                    {
    let _guard = NoTrimmedGuard::new();
    {
        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_ssa/src/mir/locals.rs:74",
                            "rustc_codegen_ssa::mir::locals", ::tracing::Level::DEBUG,
                            ::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/mir/locals.rs"),
                            ::tracing_core::__macro_support::Option::Some(74u32),
                            ::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::mir::locals"),
                            ::tracing_core::field::FieldSet::new(&["op.layout.ty"],
                                ::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(&debug(&op.layout.ty)
                                                as &dyn Value))])
                });
        } else { ; }
    }
};with_no_trimmed_paths!(debug!(?op.layout.ty));
75                    {
    let _guard = NoTrimmedGuard::new();
    {
        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_ssa/src/mir/locals.rs:75",
                            "rustc_codegen_ssa::mir::locals", ::tracing::Level::DEBUG,
                            ::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/mir/locals.rs"),
                            ::tracing_core::__macro_support::Option::Some(75u32),
                            ::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::mir::locals"),
                            ::tracing_core::field::FieldSet::new(&["local_ty"],
                                ::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(&debug(&local_ty)
                                                as &dyn Value))])
                });
        } else { ; }
    }
};with_no_trimmed_paths!(debug!(?local_ty));
76                    op.layout.ty = local_ty;
77                }
78            }
79        };
80
81        self.locals.values[local] = value;
82    }
83}