Skip to content

Commit 3249381

Browse files
committed
handle suffixes
1 parent 6abbd31 commit 3249381

File tree

3 files changed

+91
-39
lines changed

3 files changed

+91
-39
lines changed

compiler/rustc_hir/src/lang_items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ language_item_table! {
421421
// FIXME(xacrimon): Used for lowering of match/if let statements. will made obsolete by const PartialEq.
422422
PatternConstEq, sym::PatternConstEq, pattern_const_eq, Target::Trait, GenericRequirement::None;
423423
AggregateRawPtr, sym::aggregate_raw_ptr, aggregate_raw_ptr, Target::Fn, GenericRequirement::None;
424+
Offset, sym::offset, offset, Target::Fn, GenericRequirement::None;
424425
}
425426

426427
pub enum GenericRequirement {

compiler/rustc_mir_build/src/builder/matches/test.rs

+89-39
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use tracing::{debug, instrument};
2222

2323
use crate::builder::matches::util::Range;
2424
use crate::builder::matches::{Candidate, MatchPairTree, Test, TestBranch, TestCase, TestKind};
25-
use crate::builder::{Builder, PlaceBuilder};
25+
use crate::builder::{BlockAnd, BlockAndExtension, Builder, PlaceBuilder};
2626

2727
impl<'a, 'tcx> Builder<'a, 'tcx> {
2828
/// Identifies what test is needed to decide if `match_pair` is applicable.
@@ -182,21 +182,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
182182
ref_str_ty,
183183
);
184184
} 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+
)
195196
);
196197

197-
(subslice, target_block)
198+
(block, subslice)
198199
} else {
199-
(place, block)
200+
(block, place)
200201
};
201202

202203
// Use `PartialEq::eq` instead of `BinOp::Eq`
@@ -310,20 +311,82 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
310311
}
311312
}
312313

313-
fn subslice(
314+
fn offset(
314315
&mut self,
315316
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,
317355
input: Place<'tcx>,
318356
input_ty: Ty<'tcx>,
319357
span: Span,
320358
elem_ty: Ty<'tcx>,
321359
range: Range,
322-
) -> Place<'tcx> {
360+
) -> BlockAnd<Place<'tcx>> {
323361
let tcx = self.tcx;
324362
let source_info = self.source_info(span);
325363

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+
};
327390

328391
let temp_source_ptr = self.temp(Ty::new_ptr(tcx, input_ty, Mutability::Not), span);
329392
self.cfg.push_assign(
@@ -336,31 +399,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
336399
let elem_ptr_ty = Ty::new_ptr(tcx, elem_ty, Mutability::Not);
337400
let slice_ptr_ty = Ty::new_ptr(tcx, Ty::new_slice(tcx, elem_ty), Mutability::Not);
338401

339-
let mut temp_elem_ptr = self.temp(elem_ptr_ty, span);
402+
let temp_elem_ptr = self.temp(elem_ptr_ty, span);
340403
self.cfg.push_assign(
341404
block,
342405
source_info,
343406
temp_elem_ptr,
344407
Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(temp_source_ptr), elem_ptr_ty),
345408
);
346409

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));
364411

365412
let aggregate_raw_ptr = Operand::function_handle(
366413
tcx,
@@ -371,21 +418,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
371418

372419
let subslice_ptr = self.temp(slice_ptr_ty, span);
373420

421+
let next_block = self.cfg.start_new_block();
422+
374423
self.cfg.terminate(block, source_info, TerminatorKind::Call {
375424
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),
378427
span,
379428
}]
380429
.into(),
381430
destination: subslice_ptr,
382-
target: Some(target_block),
431+
target: Some(next_block),
383432
unwind: UnwindAction::Continue,
384433
call_source: CallSource::Misc,
385434
fn_span: source_info.span,
386435
});
387436

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)
389439
}
390440

391441
/// Perform `let temp = <ty as Deref>::deref(&place)`.

library/core/src/intrinsics/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1965,6 +1965,7 @@ pub const fn needs_drop<T: ?Sized>() -> bool {
19651965
/// of bounds or arithmetic overflow occurs then this operation is undefined behavior.
19661966
///
19671967
/// The stabilized version of this intrinsic is [`pointer::offset`].
1968+
#[cfg_attr(not(bootstrap), lang = "offset")]
19681969
#[must_use = "returns a new pointer rather than modifying its argument"]
19691970
#[rustc_intrinsic_const_stable_indirect]
19701971
#[rustc_nounwind]

0 commit comments

Comments
 (0)