Skip to content

Commit be77e34

Browse files
authored
Rollup merge of rust-lang#53239 - cuviper:llvm5-closure-alloca, r=eddyb
rustc_codegen_llvm: Restore the closure env alloca hack for LLVM 5. This hack was removed in rust-lang#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 rust-lang#53204. r? @eddyb
2 parents 5931aa7 + 763e721 commit be77e34

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
@@ -574,6 +574,25 @@ fn arg_local_refs(
574574
};
575575
let upvar_tys = upvar_substs.upvar_tys(def_id, tcx);
576576

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

@@ -585,7 +604,10 @@ fn arg_local_refs(
585604
};
586605

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

590612
let ty = if let (true, &ty::TyRef(_, ty, _)) = (decl.by_ref, &ty.sty) {
591613
ty
@@ -595,7 +617,7 @@ fn arg_local_refs(
595617
};
596618

597619
let variable_access = VariableAccess::IndirectVariable {
598-
alloca: place.llval,
620+
alloca: env_ptr,
599621
address_operations: &ops
600622
};
601623
declare_local(

0 commit comments

Comments
 (0)