From a2d328fa12ca66edb47398c4a620523d252ff727 Mon Sep 17 00:00:00 2001
From: Weihang Lo <me@weihanglo.tw>
Date: Mon, 27 Nov 2023 12:35:27 -0500
Subject: [PATCH 1/3] test: demonstrate that dwarf debug names sections are
 emitted

---
 tests/assembly/dwarf4.rs | 24 ++++++++++++++++++++++++
 tests/assembly/dwarf5.rs |  1 +
 2 files changed, 25 insertions(+)
 create mode 100644 tests/assembly/dwarf4.rs

diff --git a/tests/assembly/dwarf4.rs b/tests/assembly/dwarf4.rs
new file mode 100644
index 00000000000..a5009021141
--- /dev/null
+++ b/tests/assembly/dwarf4.rs
@@ -0,0 +1,24 @@
+// Makes sure that `-Z dwarf-version=4` causes `rustc` to emit DWARF version 4.
+// assembly-output: emit-asm
+// compile-flags: -g --target x86_64-unknown-linux-gnu -Z dwarf-version=4 -Copt-level=0
+// needs-llvm-components: x86
+
+#![feature(no_core, lang_items)]
+#![crate_type = "rlib"]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+pub fn wibble() {}
+
+pub struct X;
+
+// CHECK: .section .debug_info
+// CHECK-NOT: .short 2
+// CHECK-NOT: .short 5
+// CHECK: .short 4
+// CHECK: .section .debug_pubnames
+// CHECK: .section .debug_pubtypes
diff --git a/tests/assembly/dwarf5.rs b/tests/assembly/dwarf5.rs
index 253baafb887..46d4e84b41b 100644
--- a/tests/assembly/dwarf5.rs
+++ b/tests/assembly/dwarf5.rs
@@ -18,3 +18,4 @@ pub fn wibble() {}
 // CHECK-NOT: .short 2
 // CHECK-NOT: .short 4
 // CHECK: .short 5
+// CHECK: .section .debug_names

From 1667f3d2cc131e1f39d4314296b7cafa9dbfa0f4 Mon Sep 17 00:00:00 2001
From: Weihang Lo <me@weihanglo.tw>
Date: Wed, 15 Nov 2023 23:07:37 -0500
Subject: [PATCH 2/3] fix: stop emitting `.debug_pubnames` and
 `.debug_pubtypes`

`.debug_pubnames` and `.debug_pubtypes` are poorly designed and people
seldom use them. However, they take a considerable portion of size in
the final binary. This tells LLVM stop emitting those sections on
DWARFv4 or lower. DWARFv5 use `.debug_names` which is more concise
in size and performant for name lookup.
---
 .../src/debuginfo/metadata.rs                 |  8 ++++++
 compiler/rustc_codegen_llvm/src/llvm/ffi.rs   | 12 ++++++++-
 .../rustc_llvm/llvm-wrapper/RustWrapper.cpp   | 25 +++++++++++++++++--
 tests/assembly/dwarf4.rs                      |  4 +--
 4 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 98563673c30..0f807ee6e57 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -17,6 +17,7 @@ use crate::debuginfo::utils::FatPtrKind;
 use crate::llvm;
 use crate::llvm::debuginfo::{
     DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType, DebugEmissionKind,
+    DebugNameTableKind,
 };
 use crate::value::Value;
 
@@ -878,6 +879,12 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
     let split_name = split_name.to_str().unwrap();
     let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo);
 
+    let dwarf_version =
+        tcx.sess.opts.unstable_opts.dwarf_version.unwrap_or(tcx.sess.target.default_dwarf_version);
+    // Don't emit `.debug_pubnames` and `.debug_pubtypes` on DWARFv4 or lower.
+    let debug_name_table_kind =
+        if dwarf_version > 4 { DebugNameTableKind::Default } else { DebugNameTableKind::None };
+
     unsafe {
         let compile_unit_file = llvm::LLVMRustDIBuilderCreateFile(
             debug_context.builder,
@@ -907,6 +914,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
             kind,
             0,
             tcx.sess.opts.unstable_opts.split_dwarf_inlining,
+            debug_name_table_kind,
         );
 
         if tcx.sess.opts.unstable_opts.profile {
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 432cfe203c8..81702baa8c0 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -5,7 +5,7 @@ use super::debuginfo::{
     DIArray, DIBasicType, DIBuilder, DICompositeType, DIDerivedType, DIDescriptor, DIEnumerator,
     DIFile, DIFlags, DIGlobalVariableExpression, DILexicalBlock, DILocation, DINameSpace,
     DISPFlags, DIScope, DISubprogram, DISubrange, DITemplateTypeParameter, DIType, DIVariable,
-    DebugEmissionKind,
+    DebugEmissionKind, DebugNameTableKind,
 };
 
 use libc::{c_char, c_int, c_uint, size_t};
@@ -794,6 +794,15 @@ pub mod debuginfo {
             }
         }
     }
+
+    /// LLVMRustDebugNameTableKind
+    #[derive(Clone, Copy)]
+    #[repr(C)]
+    pub enum DebugNameTableKind {
+        Default,
+        Gnu,
+        None,
+    }
 }
 
 use bitflags::bitflags;
@@ -1812,6 +1821,7 @@ extern "C" {
         kind: DebugEmissionKind,
         DWOId: u64,
         SplitDebugInlining: bool,
+        DebugNameTableKind: DebugNameTableKind,
     ) -> &'a DIDescriptor;
 
     pub fn LLVMRustDIBuilderCreateFile<'a>(
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index b227dd76f02..0df7b7eed11 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -697,6 +697,25 @@ static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind)
   }
 }
 
+enum class LLVMRustDebugNameTableKind {
+    Default,
+    GNU,
+    None,
+};
+
+static DICompileUnit::DebugNameTableKind fromRust(LLVMRustDebugNameTableKind Kind) {
+  switch (Kind) {
+  case LLVMRustDebugNameTableKind::Default:
+    return DICompileUnit::DebugNameTableKind::Default;
+  case LLVMRustDebugNameTableKind::GNU:
+    return DICompileUnit::DebugNameTableKind::GNU;
+  case LLVMRustDebugNameTableKind::None:
+    return DICompileUnit::DebugNameTableKind::None;
+  default:
+    report_fatal_error("bad DebugNameTableKind.");
+  }
+}
+
 enum class LLVMRustChecksumKind {
   None,
   MD5,
@@ -765,13 +784,15 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
     const char *Flags, unsigned RuntimeVer,
     const char *SplitName, size_t SplitNameLen,
     LLVMRustDebugEmissionKind Kind,
-    uint64_t DWOId, bool SplitDebugInlining) {
+    uint64_t DWOId, bool SplitDebugInlining,
+    LLVMRustDebugNameTableKind TableKind) {
   auto *File = unwrapDI<DIFile>(FileRef);
 
   return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
                                          isOptimized, Flags, RuntimeVer,
                                          StringRef(SplitName, SplitNameLen),
-                                         fromRust(Kind), DWOId, SplitDebugInlining));
+                                         fromRust(Kind), DWOId, SplitDebugInlining,
+                                         false, fromRust(TableKind)));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
diff --git a/tests/assembly/dwarf4.rs b/tests/assembly/dwarf4.rs
index a5009021141..6e1584458b6 100644
--- a/tests/assembly/dwarf4.rs
+++ b/tests/assembly/dwarf4.rs
@@ -20,5 +20,5 @@ pub struct X;
 // CHECK-NOT: .short 2
 // CHECK-NOT: .short 5
 // CHECK: .short 4
-// CHECK: .section .debug_pubnames
-// CHECK: .section .debug_pubtypes
+// CHECK-NOT: .section .debug_pubnames
+// CHECK-NOT: .section .debug_pubtypes

From 6aac62cdcb9ba84dddca920e8528dd4d62d78801 Mon Sep 17 00:00:00 2001
From: Weihang Lo <me@weihanglo.tw>
Date: Mon, 11 Dec 2023 16:24:24 -0500
Subject: [PATCH 3/3] refactor: only check dwarf version when emitting dwarf

---
 compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 0f807ee6e57..acd5a1ff5c6 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -39,6 +39,7 @@ use rustc_span::FileName;
 use rustc_span::{FileNameDisplayPreference, SourceFile};
 use rustc_symbol_mangling::typeid_for_trait_ref;
 use rustc_target::abi::{Align, Size};
+use rustc_target::spec::DebuginfoKind;
 use smallvec::smallvec;
 
 use libc::{c_char, c_longlong, c_uint};
@@ -881,9 +882,14 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
 
     let dwarf_version =
         tcx.sess.opts.unstable_opts.dwarf_version.unwrap_or(tcx.sess.target.default_dwarf_version);
+    let is_dwarf_kind =
+        matches!(tcx.sess.target.debuginfo_kind, DebuginfoKind::Dwarf | DebuginfoKind::DwarfDsym);
     // Don't emit `.debug_pubnames` and `.debug_pubtypes` on DWARFv4 or lower.
-    let debug_name_table_kind =
-        if dwarf_version > 4 { DebugNameTableKind::Default } else { DebugNameTableKind::None };
+    let debug_name_table_kind = if is_dwarf_kind && dwarf_version <= 4 {
+        DebugNameTableKind::None
+    } else {
+        DebugNameTableKind::Default
+    };
 
     unsafe {
         let compile_unit_file = llvm::LLVMRustDIBuilderCreateFile(