Auto merge of #88550 - dpaoliello:dpaoliello/allocdebuginfo, r=estebank

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.
This commit is contained in:
bors 2021-09-04 12:27:45 +00:00
commit 226e181b80
5 changed files with 66 additions and 41 deletions

View File

@ -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);
}
}

View File

@ -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> {

View File

@ -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,

View File

@ -538,12 +538,18 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
} 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
};

View File

@ -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,
);