Skip to content

Commit 3a1db90

Browse files
authored
Rollup merge of #91278 - SparrowLii:place, r=spastorino
Use iterator instead of recursion in `codegen_place` This PR fixes the FIXME in `codegen_place` about using iterator instead of recursion when processing the `projection` field in `mir::PlaceRef`. At the same time, it also reduces the right drift.
2 parents 2a4381d + 61ff847 commit 3a1db90

File tree

1 file changed

+67
-76
lines changed
  • compiler/rustc_codegen_ssa/src/mir

1 file changed

+67
-76
lines changed

compiler/rustc_codegen_ssa/src/mir/place.rs

+67-76
Original file line numberDiff line numberDiff line change
@@ -429,87 +429,78 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
429429
let cx = self.cx;
430430
let tcx = self.cx.tcx();
431431

432-
let result = match place_ref {
433-
mir::PlaceRef { local, projection: [] } => match self.locals[local] {
434-
LocalRef::Place(place) => {
435-
return place;
436-
}
437-
LocalRef::UnsizedPlace(place) => {
438-
return bx.load_operand(place).deref(cx);
439-
}
440-
LocalRef::Operand(..) => {
432+
let mut base = 0;
433+
let mut cg_base = match self.locals[place_ref.local] {
434+
LocalRef::Place(place) => place,
435+
LocalRef::UnsizedPlace(place) => bx.load_operand(place).deref(cx),
436+
LocalRef::Operand(..) => {
437+
if let Some(elem) = place_ref
438+
.projection
439+
.iter()
440+
.enumerate()
441+
.find(|elem| matches!(elem.1, mir::ProjectionElem::Deref))
442+
{
443+
base = elem.0 + 1;
444+
self.codegen_consume(
445+
bx,
446+
mir::PlaceRef { projection: &place_ref.projection[..elem.0], ..place_ref },
447+
)
448+
.deref(bx.cx())
449+
} else {
441450
bug!("using operand local {:?} as place", place_ref);
442451
}
443-
},
444-
mir::PlaceRef { local, projection: [proj_base @ .., mir::ProjectionElem::Deref] } => {
445-
// Load the pointer from its location.
446-
self.codegen_consume(bx, mir::PlaceRef { local, projection: proj_base })
447-
.deref(bx.cx())
448452
}
449-
mir::PlaceRef { local, projection: &[ref proj_base @ .., elem] } => {
450-
// FIXME turn this recursion into iteration
451-
let cg_base =
452-
self.codegen_place(bx, mir::PlaceRef { local, projection: proj_base });
453-
454-
match elem {
455-
mir::ProjectionElem::Deref => bug!(),
456-
mir::ProjectionElem::Field(ref field, _) => {
457-
cg_base.project_field(bx, field.index())
458-
}
459-
mir::ProjectionElem::Index(index) => {
460-
let index = &mir::Operand::Copy(mir::Place::from(index));
461-
let index = self.codegen_operand(bx, index);
462-
let llindex = index.immediate();
463-
cg_base.project_index(bx, llindex)
464-
}
465-
mir::ProjectionElem::ConstantIndex {
466-
offset,
467-
from_end: false,
468-
min_length: _,
469-
} => {
470-
let lloffset = bx.cx().const_usize(offset as u64);
471-
cg_base.project_index(bx, lloffset)
472-
}
473-
mir::ProjectionElem::ConstantIndex {
474-
offset,
475-
from_end: true,
476-
min_length: _,
477-
} => {
478-
let lloffset = bx.cx().const_usize(offset as u64);
479-
let lllen = cg_base.len(bx.cx());
480-
let llindex = bx.sub(lllen, lloffset);
481-
cg_base.project_index(bx, llindex)
482-
}
483-
mir::ProjectionElem::Subslice { from, to, from_end } => {
484-
let mut subslice =
485-
cg_base.project_index(bx, bx.cx().const_usize(from as u64));
486-
let projected_ty =
487-
PlaceTy::from_ty(cg_base.layout.ty).projection_ty(tcx, elem).ty;
488-
subslice.layout = bx.cx().layout_of(self.monomorphize(projected_ty));
489-
490-
if subslice.layout.is_unsized() {
491-
assert!(from_end, "slice subslices should be `from_end`");
492-
subslice.llextra = Some(bx.sub(
493-
cg_base.llextra.unwrap(),
494-
bx.cx().const_usize((from as u64) + (to as u64)),
495-
));
496-
}
497-
498-
// Cast the place pointer type to the new
499-
// array or slice type (`*[%_; new_len]`).
500-
subslice.llval = bx.pointercast(
501-
subslice.llval,
502-
bx.cx().type_ptr_to(bx.cx().backend_type(subslice.layout)),
503-
);
504-
505-
subslice
453+
};
454+
for elem in place_ref.projection[base..].iter() {
455+
cg_base = match elem.clone() {
456+
mir::ProjectionElem::Deref => bx.load_operand(cg_base).deref(bx.cx()),
457+
mir::ProjectionElem::Field(ref field, _) => {
458+
cg_base.project_field(bx, field.index())
459+
}
460+
mir::ProjectionElem::Index(index) => {
461+
let index = &mir::Operand::Copy(mir::Place::from(index));
462+
let index = self.codegen_operand(bx, index);
463+
let llindex = index.immediate();
464+
cg_base.project_index(bx, llindex)
465+
}
466+
mir::ProjectionElem::ConstantIndex { offset, from_end: false, min_length: _ } => {
467+
let lloffset = bx.cx().const_usize(offset as u64);
468+
cg_base.project_index(bx, lloffset)
469+
}
470+
mir::ProjectionElem::ConstantIndex { offset, from_end: true, min_length: _ } => {
471+
let lloffset = bx.cx().const_usize(offset as u64);
472+
let lllen = cg_base.len(bx.cx());
473+
let llindex = bx.sub(lllen, lloffset);
474+
cg_base.project_index(bx, llindex)
475+
}
476+
mir::ProjectionElem::Subslice { from, to, from_end } => {
477+
let mut subslice = cg_base.project_index(bx, bx.cx().const_usize(from as u64));
478+
let projected_ty =
479+
PlaceTy::from_ty(cg_base.layout.ty).projection_ty(tcx, elem.clone()).ty;
480+
subslice.layout = bx.cx().layout_of(self.monomorphize(projected_ty));
481+
482+
if subslice.layout.is_unsized() {
483+
assert!(from_end, "slice subslices should be `from_end`");
484+
subslice.llextra = Some(bx.sub(
485+
cg_base.llextra.unwrap(),
486+
bx.cx().const_usize((from as u64) + (to as u64)),
487+
));
506488
}
507-
mir::ProjectionElem::Downcast(_, v) => cg_base.project_downcast(bx, v),
489+
490+
// Cast the place pointer type to the new
491+
// array or slice type (`*[%_; new_len]`).
492+
subslice.llval = bx.pointercast(
493+
subslice.llval,
494+
bx.cx().type_ptr_to(bx.cx().backend_type(subslice.layout)),
495+
);
496+
497+
subslice
508498
}
509-
}
510-
};
511-
debug!("codegen_place(place={:?}) => {:?}", place_ref, result);
512-
result
499+
mir::ProjectionElem::Downcast(_, v) => cg_base.project_downcast(bx, v),
500+
};
501+
}
502+
debug!("codegen_place(place={:?}) => {:?}", place_ref, cg_base);
503+
cg_base
513504
}
514505

515506
pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'tcx>) -> Ty<'tcx> {

0 commit comments

Comments
 (0)