@@ -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