diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index f0c1dfc53aca4..b10a1282f4dd0 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -760,30 +760,18 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { count: u64, dest: PlaceRef<'tcx, &'ll Value>, ) { - let zero = self.const_usize(0); - let count = self.const_usize(count); - - let header_bb = self.append_sibling_block("repeat_loop_header"); - let body_bb = self.append_sibling_block("repeat_loop_body"); - let next_bb = self.append_sibling_block("repeat_loop_next"); - - self.br(header_bb); - - let mut header_bx = Self::build(self.cx, header_bb); - let i = header_bx.phi(self.val_ty(zero), &[zero], &[self.llbb()]); - - let keep_going = header_bx.icmp(IntPredicate::IntULT, i, count); - header_bx.cond_br(keep_going, body_bb, next_bb); - - let mut body_bx = Self::build(self.cx, body_bb); - let dest_elem = dest.project_index(&mut body_bx, i); - cg_elem.val.store(&mut body_bx, dest_elem); - - let next = body_bx.unchecked_uadd(i, self.const_usize(1)); - body_bx.br(header_bb); - header_bx.add_incoming_to_phi(i, next, body_bb); - - *self = Self::build(self.cx, next_bb); + if self.cx.sess().opts.optimize == OptLevel::No { + // To let debuggers single-step over lines like + // + // let foo = ["bar"; 42]; + // + // we need the debugger-friendly LLVM IR that `_unoptimized()` + // provides. The `_optimized()` version generates trickier LLVM IR. + // See PR #148058 for a failed attempt at handling that. + self.write_operand_repeatedly_unoptimized(cg_elem, count, dest); + } else { + self.write_operand_repeatedly_optimized(cg_elem, count, dest); + } } fn range_metadata(&mut self, load: &'ll Value, range: WrappingRange) { @@ -1514,6 +1502,78 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { self.set_metadata_node(inst, llvm::MD_unpredictable, &[]); } + fn write_operand_repeatedly_optimized( + &mut self, + cg_elem: OperandRef<'tcx, &'ll Value>, + count: u64, + dest: PlaceRef<'tcx, &'ll Value>, + ) { + let zero = self.const_usize(0); + let count = self.const_usize(count); + + let header_bb = self.append_sibling_block("repeat_loop_header"); + let body_bb = self.append_sibling_block("repeat_loop_body"); + let next_bb = self.append_sibling_block("repeat_loop_next"); + + self.br(header_bb); + + let mut header_bx = Self::build(self.cx, header_bb); + let i = header_bx.phi(self.val_ty(zero), &[zero], &[self.llbb()]); + + let keep_going = header_bx.icmp(IntPredicate::IntULT, i, count); + header_bx.cond_br(keep_going, body_bb, next_bb); + + let mut body_bx = Self::build(self.cx, body_bb); + let dest_elem = dest.project_index(&mut body_bx, i); + cg_elem.val.store(&mut body_bx, dest_elem); + + let next = body_bx.unchecked_uadd(i, self.const_usize(1)); + body_bx.br(header_bb); + header_bx.add_incoming_to_phi(i, next, body_bb); + + *self = Self::build(self.cx, next_bb); + } + + fn write_operand_repeatedly_unoptimized( + &mut self, + cg_elem: OperandRef<'tcx, &'ll Value>, + count: u64, + dest: PlaceRef<'tcx, &'ll Value>, + ) { + let zero = self.const_usize(0); + let count = self.const_usize(count); + let start = dest.project_index(self, zero).val.llval; + let end = dest.project_index(self, count).val.llval; + + let header_bb = self.append_sibling_block("repeat_loop_header"); + let body_bb = self.append_sibling_block("repeat_loop_body"); + let next_bb = self.append_sibling_block("repeat_loop_next"); + + self.br(header_bb); + + let mut header_bx = Self::build(self.cx, header_bb); + let current = header_bx.phi(self.val_ty(start), &[start], &[self.llbb()]); + + let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end); + header_bx.cond_br(keep_going, body_bb, next_bb); + + let mut body_bx = Self::build(self.cx, body_bb); + let align = dest.val.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size); + cg_elem + .val + .store(&mut body_bx, PlaceRef::new_sized_aligned(current, cg_elem.layout, align)); + + let next = body_bx.inbounds_gep( + self.backend_type(cg_elem.layout), + current, + &[self.const_usize(1)], + ); + body_bx.br(header_bb); + header_bx.add_incoming_to_phi(current, next, body_bb); + + *self = Self::build(self.cx, next_bb); + } + pub(crate) fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.call_intrinsic("llvm.minnum", &[self.val_ty(lhs)], &[lhs, rhs]) } diff --git a/tests/debuginfo/basic-stepping.rs b/tests/debuginfo/basic-stepping.rs index aa9f29259d05a..f8198f54830ca 100644 --- a/tests/debuginfo/basic-stepping.rs +++ b/tests/debuginfo/basic-stepping.rs @@ -21,8 +21,8 @@ // FIXME(#33013): gdb-command: next // FIXME(#33013): gdb-check: let g = b'9'; // FIXME(#33013): gdb-command: next -// FIXME(#33013): gdb-check: let h = ["whatever"; 8]; -// FIXME(#33013): gdb-command: next +// gdb-check: let h = ["whatever"; 8]; +// gdb-command: next // gdb-check: let i = [1,2,3,4]; // gdb-command: next // gdb-check: let j = (23, "hi");