Skip to content

Commit

Permalink
rustc_codegen_llvm: Restore the closure env alloca hack for LLVM 5.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
cuviper committed Aug 9, 2018
1 parent b73535f commit 763e721
Showing 1 changed file with 24 additions and 2 deletions.
26 changes: 24 additions & 2 deletions src/librustc_codegen_llvm/mir/mod.rs
Expand Up @@ -574,6 +574,25 @@ fn arg_local_refs(
};
let upvar_tys = upvar_substs.upvar_tys(def_id, tcx);

// Store the pointer to closure data in an alloca for debuginfo
// because that's what the llvm.dbg.declare intrinsic expects.

// FIXME(eddyb) this shouldn't be necessary but SROA seems to
// mishandle DW_OP_plus not preceded by DW_OP_deref, i.e. it
// doesn't actually strip the offset when splitting the closure
// environment into its components so it ends up out of bounds.
// (cuviper) It seems to be fine without the alloca on LLVM 6 and later.
let env_alloca = !env_ref && unsafe { llvm::LLVMRustVersionMajor() < 6 };
let env_ptr = if env_alloca {
let scratch = PlaceRef::alloca(bx,
bx.cx.layout_of(tcx.mk_mut_ptr(arg.layout.ty)),
"__debuginfo_env_ptr");
bx.store(place.llval, scratch.llval, scratch.align);
scratch.llval
} else {
place.llval
};

for (i, (decl, ty)) in mir.upvar_decls.iter().zip(upvar_tys).enumerate() {
let byte_offset_of_var_in_env = closure_layout.fields.offset(i).bytes();

Expand All @@ -585,7 +604,10 @@ fn arg_local_refs(
};

// The environment and the capture can each be indirect.
let mut ops = if env_ref { &ops[..] } else { &ops[1..] };

// FIXME(eddyb) see above why we sometimes have to keep
// a pointer in an alloca for debuginfo atm.
let mut ops = if env_ref || env_alloca { &ops[..] } else { &ops[1..] };

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

let variable_access = VariableAccess::IndirectVariable {
alloca: place.llval,
alloca: env_ptr,
address_operations: &ops
};
declare_local(
Expand Down

0 comments on commit 763e721

Please sign in to comment.