@@ -22,7 +22,7 @@ use tracing::{debug, instrument};
22
22
23
23
use crate :: builder:: matches:: util:: Range ;
24
24
use crate :: builder:: matches:: { Candidate , MatchPairTree , Test , TestBranch , TestCase , TestKind } ;
25
- use crate :: builder:: { Builder , PlaceBuilder } ;
25
+ use crate :: builder:: { BlockAnd , BlockAndExtension , Builder , PlaceBuilder } ;
26
26
27
27
impl < ' a , ' tcx > Builder < ' a , ' tcx > {
28
28
/// Identifies what test is needed to decide if `match_pair` is applicable.
@@ -182,21 +182,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
182
182
ref_str_ty,
183
183
) ;
184
184
} else if !ty. is_scalar ( ) {
185
- let ( place, block) = if let Some ( range) = range {
186
- let target_block = self . cfg . start_new_block ( ) ;
187
- let subslice = self . subslice (
188
- block,
189
- target_block,
190
- place,
191
- place_ty. ty ,
192
- test. span ,
193
- ty. sequence_element_type ( tcx) ,
194
- range,
185
+ let ( block, place) = if let Some ( range) = range {
186
+ let mut block = block;
187
+ let subslice = unpack ! (
188
+ block = self . subslice(
189
+ block,
190
+ place,
191
+ place_ty. ty,
192
+ test. span,
193
+ ty. sequence_element_type( tcx) ,
194
+ range,
195
+ )
195
196
) ;
196
197
197
- ( subslice , target_block )
198
+ ( block , subslice )
198
199
} else {
199
- ( place , block )
200
+ ( block , place )
200
201
} ;
201
202
202
203
// Use `PartialEq::eq` instead of `BinOp::Eq`
@@ -310,20 +311,82 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
310
311
}
311
312
}
312
313
313
- fn subslice (
314
+ fn offset (
314
315
& mut self ,
315
316
block : BasicBlock ,
316
- target_block : BasicBlock ,
317
+ ptr : Place < ' tcx > ,
318
+ offset : Place < ' tcx > ,
319
+ span : Span ,
320
+ ) -> BlockAnd < Place < ' tcx > > {
321
+ let ptr_ty = ptr. ty ( & self . local_decls , self . tcx ) . ty ;
322
+ let offset_ty = offset. ty ( & self . local_decls , self . tcx ) . ty ;
323
+
324
+ let tcx = self . tcx ;
325
+ let func = Operand :: function_handle (
326
+ tcx,
327
+ tcx. require_lang_item ( LangItem :: Offset , Some ( span) ) ,
328
+ [ ptr_ty. into ( ) , offset_ty. into ( ) ] ,
329
+ span,
330
+ ) ;
331
+
332
+ let out = self . temp ( ptr_ty, span) ;
333
+ let next_block = self . cfg . start_new_block ( ) ;
334
+
335
+ self . cfg . terminate ( block, self . source_info ( span) , TerminatorKind :: Call {
336
+ func,
337
+ args : [ Spanned { node : Operand :: Copy ( ptr) , span } , Spanned {
338
+ node : Operand :: Copy ( offset) ,
339
+ span,
340
+ } ]
341
+ . into ( ) ,
342
+ destination : out,
343
+ target : Some ( next_block) ,
344
+ unwind : UnwindAction :: Continue ,
345
+ call_source : CallSource :: Misc ,
346
+ fn_span : span,
347
+ } ) ;
348
+
349
+ next_block. and ( out)
350
+ }
351
+
352
+ fn subslice (
353
+ & mut self ,
354
+ mut block : BasicBlock ,
317
355
input : Place < ' tcx > ,
318
356
input_ty : Ty < ' tcx > ,
319
357
span : Span ,
320
358
elem_ty : Ty < ' tcx > ,
321
359
range : Range ,
322
- ) -> Place < ' tcx > {
360
+ ) -> BlockAnd < Place < ' tcx > > {
323
361
let tcx = self . tcx ;
324
362
let source_info = self . source_info ( span) ;
325
363
326
- // TODO: handle range.from_end == true
364
+ let ( ptr_offset, slice_len) = {
365
+ if !range. from_end {
366
+ let start = self . push_usize ( block, source_info, range. start ) ;
367
+ let len = self . push_usize ( block, source_info, range. len ( ) ) ;
368
+ ( start, len)
369
+ } else {
370
+ let source_len = self . temp ( tcx. types . usize , span) ;
371
+ self . cfg . push_assign ( block, source_info, source_len, Rvalue :: Len ( input) ) ;
372
+
373
+ let start = self . temp ( tcx. types . usize , span) ;
374
+ let from_end = self . push_usize ( block, source_info, range. start ) ;
375
+
376
+ self . cfg . push_assign (
377
+ block,
378
+ source_info,
379
+ start,
380
+ Rvalue :: BinaryOp (
381
+ BinOp :: Sub ,
382
+ Box :: new ( ( Operand :: Copy ( source_len) , Operand :: Copy ( from_end) ) ) ,
383
+ ) ,
384
+ ) ;
385
+ let len = self . push_usize ( block, source_info, range. len ( ) ) ;
386
+
387
+ ( start, len)
388
+ }
389
+ } ;
327
390
328
391
let temp_source_ptr = self . temp ( Ty :: new_ptr ( tcx, input_ty, Mutability :: Not ) , span) ;
329
392
self . cfg . push_assign (
@@ -336,31 +399,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
336
399
let elem_ptr_ty = Ty :: new_ptr ( tcx, elem_ty, Mutability :: Not ) ;
337
400
let slice_ptr_ty = Ty :: new_ptr ( tcx, Ty :: new_slice ( tcx, elem_ty) , Mutability :: Not ) ;
338
401
339
- let mut temp_elem_ptr = self . temp ( elem_ptr_ty, span) ;
402
+ let temp_elem_ptr = self . temp ( elem_ptr_ty, span) ;
340
403
self . cfg . push_assign (
341
404
block,
342
405
source_info,
343
406
temp_elem_ptr,
344
407
Rvalue :: Cast ( CastKind :: PtrToPtr , Operand :: Copy ( temp_source_ptr) , elem_ptr_ty) ,
345
408
) ;
346
409
347
- if range. start != 0 {
348
- let offset = self . temp ( elem_ptr_ty, span) ;
349
- let offset_by = self . push_usize ( block, source_info, range. start ) ;
350
- self . cfg . push_assign (
351
- block,
352
- source_info,
353
- offset,
354
- Rvalue :: BinaryOp (
355
- BinOp :: Offset ,
356
- Box :: new ( ( Operand :: Copy ( temp_elem_ptr) , Operand :: Move ( offset_by) ) ) ,
357
- ) ,
358
- ) ;
359
-
360
- temp_elem_ptr = offset;
361
- }
362
-
363
- let temp_len = self . push_usize ( block, source_info, range. len ( ) ) ;
410
+ let updated_ptr = unpack ! ( block = self . offset( block, temp_elem_ptr, ptr_offset, span) ) ;
364
411
365
412
let aggregate_raw_ptr = Operand :: function_handle (
366
413
tcx,
@@ -371,21 +418,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
371
418
372
419
let subslice_ptr = self . temp ( slice_ptr_ty, span) ;
373
420
421
+ let next_block = self . cfg . start_new_block ( ) ;
422
+
374
423
self . cfg . terminate ( block, source_info, TerminatorKind :: Call {
375
424
func : aggregate_raw_ptr,
376
- args : [ Spanned { node : Operand :: Move ( temp_elem_ptr ) , span } , Spanned {
377
- node : Operand :: Move ( temp_len ) ,
425
+ args : [ Spanned { node : Operand :: Move ( updated_ptr ) , span } , Spanned {
426
+ node : Operand :: Move ( slice_len ) ,
378
427
span,
379
428
} ]
380
429
. into ( ) ,
381
430
destination : subslice_ptr,
382
- target : Some ( target_block ) ,
431
+ target : Some ( next_block ) ,
383
432
unwind : UnwindAction :: Continue ,
384
433
call_source : CallSource :: Misc ,
385
434
fn_span : source_info. span ,
386
435
} ) ;
387
436
388
- PlaceBuilder :: from ( subslice_ptr) . deref ( ) . to_place ( self )
437
+ let subslice = PlaceBuilder :: from ( subslice_ptr) . deref ( ) . to_place ( self ) ;
438
+ next_block. and ( subslice)
389
439
}
390
440
391
441
/// Perform `let temp = <ty as Deref>::deref(&place)`.
0 commit comments