1use std::ops::Deref as _;
2
3use rustc_abi::{
4 Align, BackendRepr, FieldIdx, FieldsShape, Size, TagEncoding, VariantIdx, Variants,
5};
6use rustc_middle::mir;
7use rustc_middle::mir::PlaceTy;
8use rustc_middle::mir::interpret::Scalar;
9use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
10use rustc_middle::ty::{self, Ty};
11use rustc_span::{DUMMY_SP, bug};
12use tracing::{debug, instrument};
13
14use super::operand::OperandValue;
15use super::{FunctionCx, LocalRef};
16use crate::common::IntPredicate;
17use crate::size_of_val;
18use crate::traits::*;
19
20#[derive(#[automatically_derived]
impl<V: ::core::marker::Copy> ::core::marker::Copy for PlaceValue<V> { }Copy, #[automatically_derived]
impl<V: ::core::clone::Clone> ::core::clone::Clone for PlaceValue<V> {
#[inline]
fn clone(&self) -> Self {
PlaceValue {
llval: ::core::clone::Clone::clone(&self.llval),
llextra: ::core::clone::Clone::clone(&self.llextra),
align: ::core::clone::Clone::clone(&self.align),
}
}
}Clone, #[automatically_derived]
impl<V: ::core::fmt::Debug> ::core::fmt::Debug for PlaceValue<V> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "PlaceValue",
"llval", &self.llval, "llextra", &self.llextra, "align",
&&self.align)
}
}Debug)]
27pub struct PlaceValue<V> {
28 pub llval: V,
30
31 pub llextra: Option<V>,
33
34 pub align: Align,
36}
37
38impl<V: CodegenObject> PlaceValue<V> {
39 pub fn new_sized(llval: V, align: Align) -> PlaceValue<V> {
43 PlaceValue { llval, llextra: None, align }
44 }
45
46 pub fn alloca<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx, Value = V>>(
51 bx: &mut Bx,
52 size: Size,
53 align: Align,
54 ) -> PlaceValue<V> {
55 let llval = bx.alloca(size, align);
56 PlaceValue::new_sized(llval, align)
57 }
58
59 pub fn with_type<'tcx>(self, layout: TyAndLayout<'tcx>) -> PlaceRef<'tcx, V> {
61 if !(layout.is_unsized() || layout.is_uninhabited() || self.llextra.is_none())
{
{
::core::panicking::panic_fmt(format_args!("Had pointer metadata {0:?} for sized type {1:?}",
self.llextra, layout));
}
};assert!(
62 layout.is_unsized() || layout.is_uninhabited() || self.llextra.is_none(),
63 "Had pointer metadata {:?} for sized type {layout:?}",
64 self.llextra,
65 );
66 PlaceRef { val: self, layout }
67 }
68
69 pub fn address(self) -> OperandValue<V> {
74 if let Some(llextra) = self.llextra {
75 OperandValue::Pair(self.llval, llextra)
76 } else {
77 OperandValue::Immediate(self.llval)
78 }
79 }
80}
81
82#[derive(#[automatically_derived]
impl<'tcx, V: ::core::marker::Copy> ::core::marker::Copy for PlaceRef<'tcx, V>
{
}Copy, #[automatically_derived]
impl<'tcx, V: ::core::clone::Clone> ::core::clone::Clone for PlaceRef<'tcx, V>
{
#[inline]
fn clone(&self) -> Self {
PlaceRef {
val: ::core::clone::Clone::clone(&self.val),
layout: ::core::clone::Clone::clone(&self.layout),
}
}
}Clone, #[automatically_derived]
impl<'tcx, V: ::core::fmt::Debug> ::core::fmt::Debug for PlaceRef<'tcx, V> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "PlaceRef",
"val", &self.val, "layout", &&self.layout)
}
}Debug)]
83pub struct PlaceRef<'tcx, V> {
84 pub val: PlaceValue<V>,
86
87 pub layout: TyAndLayout<'tcx>,
93}
94
95impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
96 pub fn new_sized(llval: V, layout: TyAndLayout<'tcx>) -> PlaceRef<'tcx, V> {
97 PlaceRef::new_sized_aligned(llval, layout, layout.align.abi)
98 }
99
100 pub fn new_sized_aligned(
101 llval: V,
102 layout: TyAndLayout<'tcx>,
103 align: Align,
104 ) -> PlaceRef<'tcx, V> {
105 if !layout.is_sized() {
::core::panicking::panic("assertion failed: layout.is_sized()")
};assert!(layout.is_sized());
106 PlaceValue::new_sized(llval, align).with_type(layout)
107 }
108
109 pub fn alloca<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
112 bx: &mut Bx,
113 layout: TyAndLayout<'tcx>,
114 ) -> Self {
115 if layout.peel_transparent_wrappers_from_non_1zst(bx).deref().is_scalable_vector() {
118 Self::alloca_scalable(bx, layout)
119 } else {
120 Self::alloca_size(bx, layout.size, layout)
121 }
122 }
123
124 pub fn alloca_size<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
125 bx: &mut Bx,
126 size: Size,
127 layout: TyAndLayout<'tcx>,
128 ) -> Self {
129 if !layout.is_sized() {
{
::core::panicking::panic_fmt(format_args!("tried to statically allocate unsized place"));
}
};assert!(layout.is_sized(), "tried to statically allocate unsized place");
130 PlaceValue::alloca(bx, size, layout.align.abi).with_type(layout)
131 }
132
133 pub fn alloca_unsized_indirect<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
137 bx: &mut Bx,
138 layout: TyAndLayout<'tcx>,
139 ) -> Self {
140 if !layout.is_unsized() {
{
::core::panicking::panic_fmt(format_args!("tried to allocate indirect place for sized values"));
}
};assert!(layout.is_unsized(), "tried to allocate indirect place for sized values");
141 let ptr_ty = Ty::new_mut_ptr(bx.cx().tcx(), layout.ty);
142 let ptr_layout = bx.cx().layout_of(ptr_ty);
143 Self::alloca(bx, ptr_layout)
144 }
145
146 pub fn len<Cx: ConstCodegenMethods<Value = V>>(&self, cx: &Cx) -> V {
147 if let FieldsShape::Array { count, .. } = self.layout.fields {
148 if self.layout.is_unsized() {
149 {
match (&count, &0) {
(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!(count, 0);
150 self.val.llextra.unwrap()
151 } else {
152 cx.const_usize(count)
153 }
154 } else {
155 ::rustc_span::macros::bug_impl(None,
format_args!("unexpected layout `{0:#?}` in PlaceRef::len", self.layout),
Location::caller())bug!("unexpected layout `{:#?}` in PlaceRef::len", self.layout)
156 }
157 }
158
159 fn alloca_scalable<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
160 bx: &mut Bx,
161 layout: TyAndLayout<'tcx>,
162 ) -> Self {
163 PlaceValue::new_sized(
164 bx.alloca_with_ty(layout.peel_transparent_wrappers_from_non_1zst(bx)),
167 layout.align.abi,
168 )
169 .with_type(layout)
170 }
171}
172
173impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
174 pub fn project_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
176 self,
177 bx: &mut Bx,
178 ix: usize,
179 ) -> Self {
180 let field = self.layout.field(bx.cx(), ix);
181 let offset = self.layout.fields.offset(ix);
182 let effective_field_align = self.val.align.restrict_for_offset(offset);
183
184 let mut simple = || {
187 let llval = if offset.bytes() == 0 {
188 self.val.llval
189 } else {
190 bx.inbounds_ptradd(self.val.llval, bx.const_usize(offset.bytes()))
191 };
192 let val = PlaceValue {
193 llval,
194 llextra: if bx.cx().tcx().type_has_metadata(field.ty, bx.cx().typing_env()) {
195 self.val.llextra
196 } else {
197 None
198 },
199 align: effective_field_align,
200 };
201 val.with_type(field)
202 };
203
204 match field.ty.kind() {
210 _ if field.is_sized() => return simple(),
211 ty::Slice(..) | ty::Str => return simple(),
212 _ if offset.bytes() == 0 => return simple(),
213 _ => {}
214 }
215
216 let meta = self.val.llextra;
232
233 let unaligned_offset = bx.cx().const_usize(offset.bytes());
234
235 let (_, mut unsized_align) =
237 size_of_val::size_and_align_of_dst(bx, field.ty, meta, DUMMY_SP);
238
239 if let ty::Adt(def, _) = self.layout.ty.kind()
241 && let Some(packed) = def.repr().pack
242 {
243 let packed = bx.const_usize(packed.bytes());
244 let cmp = bx.icmp(IntPredicate::IntULT, unsized_align, packed);
245 unsized_align = bx.select(cmp, unsized_align, packed)
246 }
247
248 let offset = round_up_const_value_to_alignment(bx, unaligned_offset, unsized_align);
250
251 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/080cc27146389dbb5c8772c476b1937be9c6110f/compiler/rustc_codegen_ssa/src/mir/place.rs:251",
"rustc_codegen_ssa::mir::place", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/080cc27146389dbb5c8772c476b1937be9c6110f/compiler/rustc_codegen_ssa/src/mir/place.rs"),
::tracing_core::__macro_support::Option::Some(251u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::mir::place"),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("struct_field_ptr: DST field offset: {0:?}",
offset) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("struct_field_ptr: DST field offset: {:?}", offset);
252
253 let ptr = bx.inbounds_ptradd(self.val.llval, offset);
255 let val =
256 PlaceValue { llval: ptr, llextra: self.val.llextra, align: effective_field_align };
257 val.with_type(field)
258 }
259
260 pub fn codegen_set_discr<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
263 &self,
264 bx: &mut Bx,
265 variant_index: VariantIdx,
266 ) {
267 match codegen_tag_value(bx.cx(), variant_index, self.layout) {
268 Err(UninhabitedVariantError) => {
269 bx.abort_immediate();
272 }
273 Ok(Some((tag_field, imm))) => {
274 let tag_place = self.project_field(bx, tag_field.as_usize());
275 OperandValue::Immediate(imm).store(bx, tag_place);
276 }
277 Ok(None) => {}
278 }
279 }
280
281 pub fn project_index<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
282 &self,
283 bx: &mut Bx,
284 llindex: V,
285 ) -> Self {
286 let layout = self.layout.field(bx, 0);
289 let offset = if let Some(llindex) = bx.const_to_opt_uint(llindex) {
290 layout.size.checked_mul(llindex, bx).unwrap_or(layout.size)
291 } else {
292 layout.size
293 };
294
295 let llval = bx.inbounds_nuw_gep(bx.cx().backend_type(layout), self.val.llval, &[llindex]);
296 let align = self.val.align.restrict_for_offset(offset);
297 PlaceValue::new_sized(llval, align).with_type(layout)
298 }
299
300 pub fn project_downcast<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
301 &self,
302 bx: &mut Bx,
303 variant_index: VariantIdx,
304 ) -> Self {
305 let mut downcast = *self;
306 downcast.layout = self.layout.for_variant(bx.cx(), variant_index);
307 downcast
308 }
309
310 pub fn project_type<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
311 &self,
312 bx: &mut Bx,
313 ty: Ty<'tcx>,
314 ) -> Self {
315 let mut downcast = *self;
316 downcast.layout = bx.cx().layout_of(ty);
317 downcast
318 }
319
320 pub fn storage_live<Bx: BuilderMethods<'a, 'tcx, Value = V>>(&self, bx: &mut Bx) {
321 bx.lifetime_start(self.val.llval, self.layout.size);
322 }
323
324 pub fn storage_dead<Bx: BuilderMethods<'a, 'tcx, Value = V>>(&self, bx: &mut Bx) {
325 bx.lifetime_end(self.val.llval, self.layout.size);
326 }
327
328 pub fn unaligned(self) -> Self {
330 let Self { val, layout } = self;
331 let val = PlaceValue { align: Align::ONE, ..val };
332 Self { val, layout }
333 }
334}
335
336impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
337 {}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("codegen_place",
"rustc_codegen_ssa::mir::place", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/080cc27146389dbb5c8772c476b1937be9c6110f/compiler/rustc_codegen_ssa/src/mir/place.rs"),
::tracing_core::__macro_support::Option::Some(337u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::mir::place"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("place_ref")
}> =
::tracing::__macro_support::FieldName::new("place_ref");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place_ref)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: PlaceRef<'tcx, Bx::Value> =
loop {};
return __tracing_attr_fake_return;
}
{
let cx = self.cx;
let tcx = self.cx.tcx();
let mut base = 0;
let mut cg_base =
match self.locals[place_ref.local] {
LocalRef::Place(place) => place,
LocalRef::UnsizedPlace(place) =>
bx.load_operand(place).deref(cx),
LocalRef::Operand(..) => {
if place_ref.is_indirect_first_projection() {
base = 1;
let cg_base =
self.codegen_consume(bx,
mir::PlaceRef {
projection: &place_ref.projection[..0],
..place_ref
});
cg_base.deref(bx.cx())
} else {
::rustc_span::macros::bug_impl(None,
format_args!("using operand local {0:?} as place",
place_ref), Location::caller());
}
}
LocalRef::PendingOperand => {
::rustc_span::macros::bug_impl(None,
format_args!("using still-pending operand local {0:?} as place",
place_ref), Location::caller());
}
};
for elem in place_ref.projection[base..].iter() {
cg_base =
match *elem {
mir::ProjectionElem::Deref =>
bx.load_operand(cg_base).deref(bx.cx()),
mir::ProjectionElem::PhantomDeref => {
::rustc_span::macros::bug_impl(None,
format_args!("encountered PhantomDeref in codegen"),
Location::caller())
}
mir::ProjectionElem::Field(ref field, _) => {
if !!cg_base.layout.ty.is_any_ptr() {
{
::core::panicking::panic_fmt(format_args!("Bad PlaceRef: destructing pointers should use cast/PtrMetadata, but tried to access field {0:?} of pointer {1:?}",
field, cg_base));
}
};
cg_base.project_field(bx, field.index())
}
mir::ProjectionElem::OpaqueCast(ty) => {
::rustc_span::macros::bug_impl(None,
format_args!("encountered OpaqueCast({0}) in codegen", ty),
Location::caller())
}
mir::ProjectionElem::UnwrapUnsafeBinder(ty) => {
cg_base.project_type(bx, self.monomorphize(ty))
}
mir::ProjectionElem::Index(index) => {
let index = &mir::Operand::Copy(mir::Place::from(index));
let index = self.codegen_operand(bx, index);
let llindex = index.immediate();
cg_base.project_index(bx, llindex)
}
mir::ProjectionElem::ConstantIndex {
offset, from_end: false, min_length: _ } => {
let lloffset = bx.cx().const_usize(offset);
cg_base.project_index(bx, lloffset)
}
mir::ProjectionElem::ConstantIndex {
offset, from_end: true, min_length: _ } => {
let lloffset = bx.cx().const_usize(offset);
let lllen = cg_base.len(bx.cx());
let llindex = bx.sub(lllen, lloffset);
cg_base.project_index(bx, llindex)
}
mir::ProjectionElem::Subslice { from, to, from_end } => {
let mut subslice =
cg_base.project_index(bx, bx.cx().const_usize(from));
let projected_ty =
PlaceTy::from_ty(cg_base.layout.ty).projection_ty(tcx,
*elem).ty;
subslice.layout =
bx.cx().layout_of(self.monomorphize(projected_ty));
if subslice.layout.is_unsized() {
if !from_end {
{
::core::panicking::panic_fmt(format_args!("slice subslices should be `from_end`"));
}
};
subslice.val.llextra =
Some(bx.sub(cg_base.val.llextra.unwrap(),
bx.cx().const_usize(from + to)));
}
subslice
}
mir::ProjectionElem::Downcast(_, v) =>
cg_base.project_downcast(bx, v),
};
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/080cc27146389dbb5c8772c476b1937be9c6110f/compiler/rustc_codegen_ssa/src/mir/place.rs:420",
"rustc_codegen_ssa::mir::place", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/080cc27146389dbb5c8772c476b1937be9c6110f/compiler/rustc_codegen_ssa/src/mir/place.rs"),
::tracing_core::__macro_support::Option::Some(420u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::mir::place"),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("codegen_place(place={0:?}) => {1:?}",
place_ref, cg_base) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
cg_base
}
}
}#[instrument(level = "trace", skip(self, bx))]
338 pub fn codegen_place(
339 &mut self,
340 bx: &mut Bx,
341 place_ref: mir::PlaceRef<'tcx>,
342 ) -> PlaceRef<'tcx, Bx::Value> {
343 let cx = self.cx;
344 let tcx = self.cx.tcx();
345
346 let mut base = 0;
347 let mut cg_base = match self.locals[place_ref.local] {
348 LocalRef::Place(place) => place,
349 LocalRef::UnsizedPlace(place) => bx.load_operand(place).deref(cx),
350 LocalRef::Operand(..) => {
351 if place_ref.is_indirect_first_projection() {
352 base = 1;
353 let cg_base = self.codegen_consume(
354 bx,
355 mir::PlaceRef { projection: &place_ref.projection[..0], ..place_ref },
356 );
357 cg_base.deref(bx.cx())
358 } else {
359 bug!("using operand local {:?} as place", place_ref);
360 }
361 }
362 LocalRef::PendingOperand => {
363 bug!("using still-pending operand local {:?} as place", place_ref);
364 }
365 };
366 for elem in place_ref.projection[base..].iter() {
367 cg_base = match *elem {
368 mir::ProjectionElem::Deref => bx.load_operand(cg_base).deref(bx.cx()),
369 mir::ProjectionElem::PhantomDeref => {
370 bug!("encountered PhantomDeref in codegen")
371 }
372 mir::ProjectionElem::Field(ref field, _) => {
373 assert!(
374 !cg_base.layout.ty.is_any_ptr(),
375 "Bad PlaceRef: destructing pointers should use cast/PtrMetadata, \
376 but tried to access field {field:?} of pointer {cg_base:?}",
377 );
378 cg_base.project_field(bx, field.index())
379 }
380 mir::ProjectionElem::OpaqueCast(ty) => {
381 bug!("encountered OpaqueCast({ty}) in codegen")
382 }
383 mir::ProjectionElem::UnwrapUnsafeBinder(ty) => {
384 cg_base.project_type(bx, self.monomorphize(ty))
385 }
386 mir::ProjectionElem::Index(index) => {
387 let index = &mir::Operand::Copy(mir::Place::from(index));
388 let index = self.codegen_operand(bx, index);
389 let llindex = index.immediate();
390 cg_base.project_index(bx, llindex)
391 }
392 mir::ProjectionElem::ConstantIndex { offset, from_end: false, min_length: _ } => {
393 let lloffset = bx.cx().const_usize(offset);
394 cg_base.project_index(bx, lloffset)
395 }
396 mir::ProjectionElem::ConstantIndex { offset, from_end: true, min_length: _ } => {
397 let lloffset = bx.cx().const_usize(offset);
398 let lllen = cg_base.len(bx.cx());
399 let llindex = bx.sub(lllen, lloffset);
400 cg_base.project_index(bx, llindex)
401 }
402 mir::ProjectionElem::Subslice { from, to, from_end } => {
403 let mut subslice = cg_base.project_index(bx, bx.cx().const_usize(from));
404 let projected_ty =
405 PlaceTy::from_ty(cg_base.layout.ty).projection_ty(tcx, *elem).ty;
406 subslice.layout = bx.cx().layout_of(self.monomorphize(projected_ty));
407
408 if subslice.layout.is_unsized() {
409 assert!(from_end, "slice subslices should be `from_end`");
410 subslice.val.llextra = Some(
411 bx.sub(cg_base.val.llextra.unwrap(), bx.cx().const_usize(from + to)),
412 );
413 }
414
415 subslice
416 }
417 mir::ProjectionElem::Downcast(_, v) => cg_base.project_downcast(bx, v),
418 };
419 }
420 debug!("codegen_place(place={:?}) => {:?}", place_ref, cg_base);
421 cg_base
422 }
423
424 pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'tcx>) -> Ty<'tcx> {
425 let tcx = self.cx.tcx();
426 let place_ty = place_ref.ty(self.mir, tcx);
427 self.monomorphize(place_ty.ty)
428 }
429}
430
431fn round_up_const_value_to_alignment<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
432 bx: &mut Bx,
433 value: Bx::Value,
434 align: Bx::Value,
435) -> Bx::Value {
436 let one = bx.const_usize(1);
467 let align_minus_1 = bx.sub(align, one);
468 let neg_value = bx.neg(value);
469 let offset = bx.and(neg_value, align_minus_1);
470 bx.add(value, offset)
471}
472
473pub(super) fn codegen_tag_value<'tcx, V>(
483 cx: &impl CodegenMethods<'tcx, Value = V>,
484 variant_index: VariantIdx,
485 layout: TyAndLayout<'tcx>,
486) -> Result<Option<(FieldIdx, V)>, UninhabitedVariantError> {
487 if layout.is_variant_uninhabited(variant_index) {
490 return Err(UninhabitedVariantError);
491 }
492
493 Ok(match layout.variants {
494 Variants::Empty => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("we already handled uninhabited types")));
}unreachable!("we already handled uninhabited types"),
495 Variants::Single { index } => {
496 {
match (&index, &variant_index) {
(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!(index, variant_index);
497 None
498 }
499
500 Variants::Multiple { tag_encoding: TagEncoding::Direct, tag_field, .. } => {
501 let discr = layout.ty.discriminant_for_variant(cx.tcx(), variant_index);
502 let to = discr.unwrap().val;
503 let tag_layout = layout.field(cx, tag_field.as_usize());
504 let tag_llty = cx.immediate_backend_type(tag_layout);
505 let imm = cx.const_uint_big(tag_llty, to);
506 Some((tag_field, imm))
507 }
508 Variants::Multiple {
509 tag_encoding: TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start },
510 tag_field,
511 ..
512 } => {
513 if variant_index != untagged_variant {
514 let niche_layout = layout.field(cx, tag_field.as_usize());
515 let niche_llty = cx.immediate_backend_type(niche_layout);
516 let BackendRepr::Scalar(scalar) = niche_layout.backend_repr else {
517 ::rustc_span::macros::bug_impl(None,
format_args!("expected a scalar placeref for the niche"),
Location::caller());bug!("expected a scalar placeref for the niche");
518 };
519 let niche_value = variant_index.as_u32() - niche_variants.start.as_u32();
524 let niche_value = (niche_value as u128).wrapping_add(niche_start);
525 let niche_value = niche_value & niche_layout.size.unsigned_int_max();
526
527 let niche_llval = cx.scalar_to_backend(
528 Scalar::from_uint(niche_value, niche_layout.size),
529 scalar,
530 niche_llty,
531 );
532 Some((tag_field, niche_llval))
533 } else {
534 None
535 }
536 }
537 })
538}
539
540#[derive(#[automatically_derived]
impl ::core::fmt::Debug for UninhabitedVariantError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "UninhabitedVariantError")
}
}Debug)]
541pub(super) struct UninhabitedVariantError;