From 77a96ed5646f7c3ee8897693decc4626fe380643 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Tue, 31 Aug 2021 11:16:10 -0700 Subject: [PATCH] Include debug info for the allocator shim Issue Details: In some cases it is necessary to generate an "allocator shim" to forward various Rust allocation functions (e.g., `__rust_alloc`) to an underlying function (e.g., `malloc`). However, since this allocator shim is a manually created LLVM module it is not processed via the normal module processing code and so no debug info is generated for it (if debugging info is enabled). Fix Details: * Modify the `debuginfo` code to allow creating debug info for a module without a `CodegenCx` (since it is difficult, and expensive, to create one just to emit some debug info). * After creating the allocator shim add in basic debug info. --- compiler/rustc_codegen_llvm/src/allocator.rs | 15 +++- .../rustc_codegen_llvm/src/debuginfo/mod.rs | 72 ++++++++++--------- compiler/rustc_codegen_llvm/src/lib.rs | 5 +- compiler/rustc_codegen_ssa/src/base.rs | 12 +++- .../rustc_codegen_ssa/src/traits/backend.rs | 3 +- 5 files changed, 66 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index 2d79b73cf9f..30d91b41a8e 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -3,19 +3,22 @@ use libc::c_uint; use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; +use rustc_session::config::DebugInfo; use rustc_span::symbol::sym; +use crate::debuginfo; use crate::llvm::{self, False, True}; use crate::ModuleLlvm; pub(crate) unsafe fn codegen( tcx: TyCtxt<'_>, - mods: &mut ModuleLlvm, + module_llvm: &mut ModuleLlvm, + module_name: &str, kind: AllocatorKind, has_alloc_error_handler: bool, ) { - let llcx = &*mods.llcx; - let llmod = mods.llmod(); + let llcx = &*module_llvm.llcx; + let llmod = module_llvm.llmod(); let usize = match tcx.sess.target.pointer_width { 16 => llvm::LLVMInt16TypeInContext(llcx), 32 => llvm::LLVMInt32TypeInContext(llcx), @@ -132,4 +135,10 @@ pub(crate) unsafe fn codegen( llvm::LLVMSetTailCall(ret, True); llvm::LLVMBuildRetVoid(llbuilder); llvm::LLVMDisposeBuilder(llbuilder); + + if tcx.sess.opts.debuginfo != DebugInfo::None { + let dbg_cx = debuginfo::CrateDebugContext::new(llmod); + debuginfo::metadata::compile_unit_metadata(tcx, module_name, &dbg_cx); + dbg_cx.finalize(tcx.sess); + } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 914376d58dd..f6953b8b50a 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -29,6 +29,7 @@ use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeFoldable}; use rustc_session::config::{self, DebugInfo}; +use rustc_session::Session; use rustc_span::symbol::Symbol; use rustc_span::{self, BytePos, Pos, SourceFile, SourceFileAndLine, Span}; use rustc_target::abi::{LayoutOf, Primitive, Size}; @@ -95,45 +96,52 @@ impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> { composite_types_completed: Default::default(), } } + + pub fn finalize(&self, sess: &Session) { + unsafe { + llvm::LLVMRustDIBuilderFinalize(self.builder); + + // Debuginfo generation in LLVM by default uses a higher + // version of dwarf than macOS currently understands. We can + // instruct LLVM to emit an older version of dwarf, however, + // for macOS to understand. For more info see #11352 + // This can be overridden using --llvm-opts -dwarf-version,N. + // Android has the same issue (#22398) + if let Some(version) = sess.target.dwarf_version { + llvm::LLVMRustAddModuleFlag(self.llmod, "Dwarf Version\0".as_ptr().cast(), version) + } + + // Indicate that we want CodeView debug information on MSVC + if sess.target.is_like_msvc { + llvm::LLVMRustAddModuleFlag(self.llmod, "CodeView\0".as_ptr().cast(), 1) + } + + // Prevent bitcode readers from deleting the debug info. + let ptr = "Debug Info Version\0".as_ptr(); + llvm::LLVMRustAddModuleFlag( + self.llmod, + ptr.cast(), + llvm::LLVMRustDebugMetadataVersion(), + ); + } + } } /// Creates any deferred debug metadata nodes pub fn finalize(cx: &CodegenCx<'_, '_>) { - if cx.dbg_cx.is_none() { - return; - } + if let Some(dbg_cx) = &cx.dbg_cx { + debug!("finalize"); - debug!("finalize"); - - if gdb::needs_gdb_debug_scripts_section(cx) { - // Add a .debug_gdb_scripts section to this compile-unit. This will - // cause GDB to try and load the gdb_load_rust_pretty_printers.py file, - // which activates the Rust pretty printers for binary this section is - // contained in. - gdb::get_or_insert_gdb_debug_scripts_section_global(cx); - } - - unsafe { - llvm::LLVMRustDIBuilderFinalize(DIB(cx)); - // Debuginfo generation in LLVM by default uses a higher - // version of dwarf than macOS currently understands. We can - // instruct LLVM to emit an older version of dwarf, however, - // for macOS to understand. For more info see #11352 - // This can be overridden using --llvm-opts -dwarf-version,N. - // Android has the same issue (#22398) - if let Some(version) = cx.sess().target.dwarf_version { - llvm::LLVMRustAddModuleFlag(cx.llmod, "Dwarf Version\0".as_ptr().cast(), version) + if gdb::needs_gdb_debug_scripts_section(cx) { + // Add a .debug_gdb_scripts section to this compile-unit. This will + // cause GDB to try and load the gdb_load_rust_pretty_printers.py file, + // which activates the Rust pretty printers for binary this section is + // contained in. + gdb::get_or_insert_gdb_debug_scripts_section_global(cx); } - // Indicate that we want CodeView debug information on MSVC - if cx.sess().target.is_like_msvc { - llvm::LLVMRustAddModuleFlag(cx.llmod, "CodeView\0".as_ptr().cast(), 1) - } - - // Prevent bitcode readers from deleting the debug info. - let ptr = "Debug Info Version\0".as_ptr(); - llvm::LLVMRustAddModuleFlag(cx.llmod, ptr.cast(), llvm::LLVMRustDebugMetadataVersion()); - }; + dbg_cx.finalize(cx.sess()); + } } impl DebugInfoBuilderMethods for Builder<'a, 'll, 'tcx> { diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 1e6e5252b25..1da14344b1d 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -92,11 +92,12 @@ impl ExtraBackendMethods for LlvmCodegenBackend { fn codegen_allocator<'tcx>( &self, tcx: TyCtxt<'tcx>, - mods: &mut ModuleLlvm, + module_llvm: &mut ModuleLlvm, + module_name: &str, kind: AllocatorKind, has_alloc_error_handler: bool, ) { - unsafe { allocator::codegen(tcx, mods, kind, has_alloc_error_handler) } + unsafe { allocator::codegen(tcx, module_llvm, module_name, kind, has_alloc_error_handler) } } fn compile_codegen_unit( &self, diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index a5143a755fe..f427dd76693 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -538,12 +538,18 @@ pub fn codegen_crate( } else if let Some(kind) = tcx.allocator_kind(()) { let llmod_id = cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string(); - let mut modules = backend.new_metadata(tcx, &llmod_id); + let mut module_llvm = backend.new_metadata(tcx, &llmod_id); tcx.sess.time("write_allocator_module", || { - backend.codegen_allocator(tcx, &mut modules, kind, tcx.lang_items().oom().is_some()) + backend.codegen_allocator( + tcx, + &mut module_llvm, + &llmod_id, + kind, + tcx.lang_items().oom().is_some(), + ) }); - Some(ModuleCodegen { name: llmod_id, module_llvm: modules, kind: ModuleKind::Allocator }) + Some(ModuleCodegen { name: llmod_id, module_llvm, kind: ModuleKind::Allocator }) } else { None }; diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 1393fc71d6b..96e53f51dac 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -120,7 +120,8 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se fn codegen_allocator<'tcx>( &self, tcx: TyCtxt<'tcx>, - mods: &mut Self::Module, + module_llvm: &mut Self::Module, + module_name: &str, kind: AllocatorKind, has_alloc_error_handler: bool, );