Skip to content

Commit a7b3af8

Browse files
cuviperpietroalbini
authored andcommitted
rustc_codegen_llvm: Restore the closure env alloca hack for LLVM 5.
This hack was removed in #50949, but without it I found that building `std` with full debuginfo would print many LLVM `DW_OP_LLVM_fragment` errors, then die `LLVM ERROR: Failed to strip malformed debug info`. It doesn't seem to be a problem for LLVM 6, so we can re-enable the hack just for older LLVM. This reverts commit da579ef. Fixes #53204. r? @eddyb
1 parent 7832643 commit a7b3af8

File tree

1 file changed

+24
-2
lines changed
  • src/librustc_codegen_llvm/mir

1 file changed

+24
-2
lines changed

src/librustc_codegen_llvm/mir/mod.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,25 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
572572
};
573573
let upvar_tys = upvar_substs.upvar_tys(def_id, tcx);
574574

575+
// Store the pointer to closure data in an alloca for debuginfo
576+
// because that's what the llvm.dbg.declare intrinsic expects.
577+
578+
// FIXME(eddyb) this shouldn't be necessary but SROA seems to
579+
// mishandle DW_OP_plus not preceded by DW_OP_deref, i.e. it
580+
// doesn't actually strip the offset when splitting the closure
581+
// environment into its components so it ends up out of bounds.
582+
// (cuviper) It seems to be fine without the alloca on LLVM 6 and later.
583+
let env_alloca = !env_ref && unsafe { llvm::LLVMRustVersionMajor() < 6 };
584+
let env_ptr = if env_alloca {
585+
let scratch = PlaceRef::alloca(bx,
586+
bx.cx.layout_of(tcx.mk_mut_ptr(arg.layout.ty)),
587+
"__debuginfo_env_ptr");
588+
bx.store(place.llval, scratch.llval, scratch.align);
589+
scratch.llval
590+
} else {
591+
place.llval
592+
};
593+
575594
for (i, (decl, ty)) in mir.upvar_decls.iter().zip(upvar_tys).enumerate() {
576595
let byte_offset_of_var_in_env = closure_layout.fields.offset(i).bytes();
577596

@@ -583,7 +602,10 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
583602
};
584603

585604
// The environment and the capture can each be indirect.
586-
let mut ops = if env_ref { &ops[..] } else { &ops[1..] };
605+
606+
// FIXME(eddyb) see above why we sometimes have to keep
607+
// a pointer in an alloca for debuginfo atm.
608+
let mut ops = if env_ref || env_alloca { &ops[..] } else { &ops[1..] };
587609

588610
let ty = if let (true, &ty::TyRef(_, ty, _)) = (decl.by_ref, &ty.sty) {
589611
ty
@@ -593,7 +615,7 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
593615
};
594616

595617
let variable_access = VariableAccess::IndirectVariable {
596-
alloca: place.llval,
618+
alloca: env_ptr,
597619
address_operations: &ops
598620
};
599621
declare_local(

0 commit comments

Comments
 (0)