75 lines
3.1 KiB
Diff
75 lines
3.1 KiB
Diff
From 763e72110a913c7aab396a0f687e2ebd3c9e572a Mon Sep 17 00:00:00 2001
|
|
From: Josh Stone <jistone@redhat.com>
|
|
Date: Thu, 9 Aug 2018 16:35:25 -0700
|
|
Subject: [PATCH] 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 da579ef75e4a8ca11fb98b24a0a3ea0c7ccffeeb.
|
|
Fixes #53204.
|
|
r? @eddyb
|
|
---
|
|
src/librustc_codegen_llvm/mir/mod.rs | 26 ++++++++++++++++++++++++--
|
|
1 file changed, 24 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/src/librustc_codegen_llvm/mir/mod.rs b/src/librustc_codegen_llvm/mir/mod.rs
|
|
index 8fdb67f5930c..8bb049be3054 100644
|
|
--- a/src/librustc_codegen_llvm/mir/mod.rs
|
|
+++ b/src/librustc_codegen_llvm/mir/mod.rs
|
|
@@ -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();
|
|
|
|
@@ -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
|
|
@@ -595,7 +617,7 @@ fn arg_local_refs(
|
|
};
|
|
|
|
let variable_access = VariableAccess::IndirectVariable {
|
|
- alloca: place.llval,
|
|
+ alloca: env_ptr,
|
|
address_operations: &ops
|
|
};
|
|
declare_local(
|
|
--
|
|
2.17.1
|
|
|