Skip to content

Commit 23c4a9f

Browse files
committed
upstream fix for "Cannot represent a difference across sections"; rel 3
from: rust-lang/rust#111167
1 parent ebe4488 commit 23c4a9f

File tree

2 files changed

+251
-1
lines changed

2 files changed

+251
-1
lines changed

111167.patch

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
From 10b69dde3fd15334ea2382d2dc9e9a261de1afaf Mon Sep 17 00:00:00 2001
2+
From: Josh Stone <[email protected]>
3+
Date: Wed, 3 May 2023 15:52:31 -0700
4+
Subject: [PATCH] debuginfo: split method declaration and definition
5+
6+
When we're adding a method to a type DIE, we only want a DW_AT_declaration
7+
there, because LLVM LTO can't unify type definitions when a child DIE is a
8+
full subprogram definition. Now the subprogram definition gets added at the
9+
CU level with a specification link back to the abstract declaration.
10+
---
11+
.../rustc_codegen_llvm/src/debuginfo/mod.rs | 85 +++++++++++--------
12+
compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 15 ++++
13+
.../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 22 +++++
14+
.../issue-109934-lto-debuginfo/Makefile | 12 +++
15+
.../issue-109934-lto-debuginfo/lib.rs | 9 ++
16+
5 files changed, 109 insertions(+), 34 deletions(-)
17+
create mode 100644 tests/run-make/issue-109934-lto-debuginfo/Makefile
18+
create mode 100644 tests/run-make/issue-109934-lto-debuginfo/lib.rs
19+
20+
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
21+
index 2e9f89f419696..b138b0c0e70a1 100644
22+
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
23+
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
24+
@@ -322,7 +322,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
25+
let tcx = self.tcx;
26+
27+
let def_id = instance.def_id();
28+
- let containing_scope = get_containing_scope(self, instance);
29+
+ let (containing_scope, is_method) = get_containing_scope(self, instance);
30+
let span = tcx.def_span(def_id);
31+
let loc = self.lookup_debug_loc(span.lo());
32+
let file_metadata = file_metadata(self, &loc.file);
33+
@@ -378,8 +378,29 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
34+
}
35+
}
36+
37+
- unsafe {
38+
- return llvm::LLVMRustDIBuilderCreateFunction(
39+
+ // When we're adding a method to a type DIE, we only want a DW_AT_declaration there, because
40+
+ // LLVM LTO can't unify type definitions when a child DIE is a full subprogram definition.
41+
+ // When we use this `decl` below, the subprogram definition gets created at the CU level
42+
+ // with a DW_AT_specification pointing back to the type's declaration.
43+
+ let decl = is_method.then(|| unsafe {
44+
+ llvm::LLVMRustDIBuilderCreateMethod(
45+
+ DIB(self),
46+
+ containing_scope,
47+
+ name.as_ptr().cast(),
48+
+ name.len(),
49+
+ linkage_name.as_ptr().cast(),
50+
+ linkage_name.len(),
51+
+ file_metadata,
52+
+ loc.line,
53+
+ function_type_metadata,
54+
+ flags,
55+
+ spflags & !DISPFlags::SPFlagDefinition,
56+
+ template_parameters,
57+
+ )
58+
+ });
59+
+
60+
+ return unsafe {
61+
+ llvm::LLVMRustDIBuilderCreateFunction(
62+
DIB(self),
63+
containing_scope,
64+
name.as_ptr().cast(),
65+
@@ -394,9 +415,9 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
66+
spflags,
67+
maybe_definition_llfn,
68+
template_parameters,
69+
- None,
70+
- );
71+
- }
72+
+ decl,
73+
+ )
74+
+ };
75+
76+
fn get_function_signature<'ll, 'tcx>(
77+
cx: &CodegenCx<'ll, 'tcx>,
78+
@@ -493,14 +514,16 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
79+
names
80+
}
81+
82+
+ /// Returns a scope, plus `true` if that's a type scope for "class" methods,
83+
+ /// otherwise `false` for plain namespace scopes.
84+
fn get_containing_scope<'ll, 'tcx>(
85+
cx: &CodegenCx<'ll, 'tcx>,
86+
instance: Instance<'tcx>,
87+
- ) -> &'ll DIScope {
88+
+ ) -> (&'ll DIScope, bool) {
89+
// First, let's see if this is a method within an inherent impl. Because
90+
// if yes, we want to make the result subroutine DIE a child of the
91+
// subroutine's self-type.
92+
- let self_type = cx.tcx.impl_of_method(instance.def_id()).and_then(|impl_def_id| {
93+
+ if let Some(impl_def_id) = cx.tcx.impl_of_method(instance.def_id()) {
94+
// If the method does *not* belong to a trait, proceed
95+
if cx.tcx.trait_id_of_impl(impl_def_id).is_none() {
96+
let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions(
97+
@@ -511,39 +534,33 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
98+
99+
// Only "class" methods are generally understood by LLVM,
100+
// so avoid methods on other types (e.g., `<*mut T>::null`).
101+
- match impl_self_ty.kind() {
102+
- ty::Adt(def, ..) if !def.is_box() => {
103+
- // Again, only create type information if full debuginfo is enabled
104+
- if cx.sess().opts.debuginfo == DebugInfo::Full
105+
- && !impl_self_ty.needs_subst()
106+
- {
107+
- Some(type_di_node(cx, impl_self_ty))
108+
- } else {
109+
- Some(namespace::item_namespace(cx, def.did()))
110+
- }
111+
+ if let ty::Adt(def, ..) = impl_self_ty.kind() && !def.is_box() {
112+
+ // Again, only create type information if full debuginfo is enabled
113+
+ if cx.sess().opts.debuginfo == DebugInfo::Full && !impl_self_ty.needs_subst()
114+
+ {
115+
+ return (type_di_node(cx, impl_self_ty), true);
116+
+ } else {
117+
+ return (namespace::item_namespace(cx, def.did()), false);
118+
}
119+
- _ => None,
120+
}
121+
} else {
122+
// For trait method impls we still use the "parallel namespace"
123+
// strategy
124+
- None
125+
}
126+
- });
127+
+ }
128+
129+
- self_type.unwrap_or_else(|| {
130+
- namespace::item_namespace(
131+
- cx,
132+
- DefId {
133+
- krate: instance.def_id().krate,
134+
- index: cx
135+
- .tcx
136+
- .def_key(instance.def_id())
137+
- .parent
138+
- .expect("get_containing_scope: missing parent?"),
139+
- },
140+
- )
141+
- })
142+
+ let scope = namespace::item_namespace(
143+
+ cx,
144+
+ DefId {
145+
+ krate: instance.def_id().krate,
146+
+ index: cx
147+
+ .tcx
148+
+ .def_key(instance.def_id())
149+
+ .parent
150+
+ .expect("get_containing_scope: missing parent?"),
151+
+ },
152+
+ );
153+
+ (scope, false)
154+
}
155+
}
156+
157+
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
158+
index c95148013eb74..1f98d91c32054 100644
159+
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
160+
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
161+
@@ -1987,6 +1987,21 @@ extern "C" {
162+
Decl: Option<&'a DIDescriptor>,
163+
) -> &'a DISubprogram;
164+
165+
+ pub fn LLVMRustDIBuilderCreateMethod<'a>(
166+
+ Builder: &DIBuilder<'a>,
167+
+ Scope: &'a DIDescriptor,
168+
+ Name: *const c_char,
169+
+ NameLen: size_t,
170+
+ LinkageName: *const c_char,
171+
+ LinkageNameLen: size_t,
172+
+ File: &'a DIFile,
173+
+ LineNo: c_uint,
174+
+ Ty: &'a DIType,
175+
+ Flags: DIFlags,
176+
+ SPFlags: DISPFlags,
177+
+ TParam: &'a DIArray,
178+
+ ) -> &'a DISubprogram;
179+
+
180+
pub fn LLVMRustDIBuilderCreateBasicType<'a>(
181+
Builder: &DIBuilder<'a>,
182+
Name: *const c_char,
183+
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
184+
index cadb6b1e23fe9..49acd71b3e106 100644
185+
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
186+
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
187+
@@ -831,6 +831,28 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
188+
return wrap(Sub);
189+
}
190+
191+
+extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMethod(
192+
+ LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
193+
+ const char *Name, size_t NameLen,
194+
+ const char *LinkageName, size_t LinkageNameLen,
195+
+ LLVMMetadataRef File, unsigned LineNo,
196+
+ LLVMMetadataRef Ty, LLVMRustDIFlags Flags,
197+
+ LLVMRustDISPFlags SPFlags, LLVMMetadataRef TParam) {
198+
+ DITemplateParameterArray TParams =
199+
+ DITemplateParameterArray(unwrap<MDTuple>(TParam));
200+
+ DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
201+
+ DINode::DIFlags llvmFlags = fromRust(Flags);
202+
+ DISubprogram *Sub = Builder->createMethod(
203+
+ unwrapDI<DIScope>(Scope),
204+
+ StringRef(Name, NameLen),
205+
+ StringRef(LinkageName, LinkageNameLen),
206+
+ unwrapDI<DIFile>(File), LineNo,
207+
+ unwrapDI<DISubroutineType>(Ty),
208+
+ 0, 0, nullptr, // VTable params aren't used
209+
+ llvmFlags, llvmSPFlags, TParams);
210+
+ return wrap(Sub);
211+
+}
212+
+
213+
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
214+
LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
215+
uint64_t SizeInBits, unsigned Encoding) {
216+
diff --git a/tests/run-make/issue-109934-lto-debuginfo/Makefile b/tests/run-make/issue-109934-lto-debuginfo/Makefile
217+
new file mode 100644
218+
index 0000000000000..3b7a99d3dbc62
219+
--- /dev/null
220+
+++ b/tests/run-make/issue-109934-lto-debuginfo/Makefile
221+
@@ -0,0 +1,12 @@
222+
+# ignore-cross-compile
223+
+include ../tools.mk
224+
+
225+
+# With the upgrade to LLVM 16, this was getting:
226+
+#
227+
+# error: Cannot represent a difference across sections
228+
+#
229+
+# The error stemmed from DI function definitions under type scopes, fixed by
230+
+# only declaring in type scope and defining the subprogram elsewhere.
231+
+
232+
+all:
233+
+ $(RUSTC) lib.rs --test -C lto=fat -C debuginfo=2 -C incremental=$(TMPDIR)/inc-fat
234+
diff --git a/tests/run-make/issue-109934-lto-debuginfo/lib.rs b/tests/run-make/issue-109934-lto-debuginfo/lib.rs
235+
new file mode 100644
236+
index 0000000000000..c405928bd1824
237+
--- /dev/null
238+
+++ b/tests/run-make/issue-109934-lto-debuginfo/lib.rs
239+
@@ -0,0 +1,9 @@
240+
+extern crate alloc;
241+
+
242+
+#[cfg(test)]
243+
+mod tests {
244+
+ #[test]
245+
+ fn something_alloc() {
246+
+ assert_eq!(Vec::<u32>::new(), Vec::<u32>::new());
247+
+ }
248+
+}

rust.spec

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Summary: The Rust Programming Language
3737
Summary(pl.UTF-8): Język programowania Rust
3838
Name: rust
3939
Version: 1.69.0
40-
Release: 2
40+
Release: 3
4141
# Licenses: (rust itself) and (bundled libraries)
4242
License: (Apache v2.0 or MIT) and (BSD and ISC and MIT)
4343
Group: Development/Languages
@@ -54,6 +54,7 @@ Source4: https://static.rust-lang.org/dist/%{bootstrap_date}/rust-%{bootstrap_ru
5454
Source5: https://static.rust-lang.org/dist/%{bootstrap_date}/rust-%{bootstrap_rust}-armv7-unknown-linux-gnueabihf.tar.xz
5555
# Source5-md5: 5691b194302d66b40c3e4eee0eeb1813
5656
Patch0: llvm-tools-install.patch
57+
Patch1: 111167.patch
5758
URL: https://www.rust-lang.org/
5859
# for src/compiler-rt
5960
BuildRequires: cmake >= 3.4.3
@@ -333,6 +334,7 @@ Dopełnianie parametrów polecenia cargo w powłoce Zsh.
333334
%prep
334335
%setup -q -n %{rustc_package}
335336
%patch0 -p1
337+
%patch1 -p1
336338

337339
%if %{with bootstrap}
338340
%ifarch %{x8664} x32

0 commit comments

Comments
 (0)