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:
parent
6cfa773583
commit
77a96ed564
5 changed files with 66 additions and 41 deletions
|
@ -3,19 +3,22 @@ use libc::c_uint;
|
||||||
use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
|
use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
use rustc_session::config::DebugInfo;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
|
use crate::debuginfo;
|
||||||
use crate::llvm::{self, False, True};
|
use crate::llvm::{self, False, True};
|
||||||
use crate::ModuleLlvm;
|
use crate::ModuleLlvm;
|
||||||
|
|
||||||
pub(crate) unsafe fn codegen(
|
pub(crate) unsafe fn codegen(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
mods: &mut ModuleLlvm,
|
module_llvm: &mut ModuleLlvm,
|
||||||
|
module_name: &str,
|
||||||
kind: AllocatorKind,
|
kind: AllocatorKind,
|
||||||
has_alloc_error_handler: bool,
|
has_alloc_error_handler: bool,
|
||||||
) {
|
) {
|
||||||
let llcx = &*mods.llcx;
|
let llcx = &*module_llvm.llcx;
|
||||||
let llmod = mods.llmod();
|
let llmod = module_llvm.llmod();
|
||||||
let usize = match tcx.sess.target.pointer_width {
|
let usize = match tcx.sess.target.pointer_width {
|
||||||
16 => llvm::LLVMInt16TypeInContext(llcx),
|
16 => llvm::LLVMInt16TypeInContext(llcx),
|
||||||
32 => llvm::LLVMInt32TypeInContext(llcx),
|
32 => llvm::LLVMInt32TypeInContext(llcx),
|
||||||
|
@ -132,4 +135,10 @@ pub(crate) unsafe fn codegen(
|
||||||
llvm::LLVMSetTailCall(ret, True);
|
llvm::LLVMSetTailCall(ret, True);
|
||||||
llvm::LLVMBuildRetVoid(llbuilder);
|
llvm::LLVMBuildRetVoid(llbuilder);
|
||||||
llvm::LLVMDisposeBuilder(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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ use rustc_middle::ty::layout::HasTyCtxt;
|
||||||
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
||||||
use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeFoldable};
|
use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeFoldable};
|
||||||
use rustc_session::config::{self, DebugInfo};
|
use rustc_session::config::{self, DebugInfo};
|
||||||
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_span::{self, BytePos, Pos, SourceFile, SourceFileAndLine, Span};
|
use rustc_span::{self, BytePos, Pos, SourceFile, SourceFileAndLine, Span};
|
||||||
use rustc_target::abi::{LayoutOf, Primitive, Size};
|
use rustc_target::abi::{LayoutOf, Primitive, Size};
|
||||||
|
@ -95,45 +96,52 @@ impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> {
|
||||||
composite_types_completed: Default::default(),
|
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
|
/// Creates any deferred debug metadata nodes
|
||||||
pub fn finalize(cx: &CodegenCx<'_, '_>) {
|
pub fn finalize(cx: &CodegenCx<'_, '_>) {
|
||||||
if cx.dbg_cx.is_none() {
|
if let Some(dbg_cx) = &cx.dbg_cx {
|
||||||
return;
|
debug!("finalize");
|
||||||
}
|
|
||||||
|
|
||||||
debug!("finalize");
|
if gdb::needs_gdb_debug_scripts_section(cx) {
|
||||||
|
// Add a .debug_gdb_scripts section to this compile-unit. This will
|
||||||
if gdb::needs_gdb_debug_scripts_section(cx) {
|
// cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
|
||||||
// Add a .debug_gdb_scripts section to this compile-unit. This will
|
// which activates the Rust pretty printers for binary this section is
|
||||||
// cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
|
// contained in.
|
||||||
// which activates the Rust pretty printers for binary this section is
|
gdb::get_or_insert_gdb_debug_scripts_section_global(cx);
|
||||||
// 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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indicate that we want CodeView debug information on MSVC
|
dbg_cx.finalize(cx.sess());
|
||||||
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());
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DebugInfoBuilderMethods for Builder<'a, 'll, 'tcx> {
|
impl DebugInfoBuilderMethods for Builder<'a, 'll, 'tcx> {
|
||||||
|
|
|
@ -92,11 +92,12 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
|
||||||
fn codegen_allocator<'tcx>(
|
fn codegen_allocator<'tcx>(
|
||||||
&self,
|
&self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
mods: &mut ModuleLlvm,
|
module_llvm: &mut ModuleLlvm,
|
||||||
|
module_name: &str,
|
||||||
kind: AllocatorKind,
|
kind: AllocatorKind,
|
||||||
has_alloc_error_handler: bool,
|
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(
|
fn compile_codegen_unit(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -538,12 +538,18 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||||
} else if let Some(kind) = tcx.allocator_kind(()) {
|
} else if let Some(kind) = tcx.allocator_kind(()) {
|
||||||
let llmod_id =
|
let llmod_id =
|
||||||
cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
|
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", || {
|
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 {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
|
@ -120,7 +120,8 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se
|
||||||
fn codegen_allocator<'tcx>(
|
fn codegen_allocator<'tcx>(
|
||||||
&self,
|
&self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
mods: &mut Self::Module,
|
module_llvm: &mut Self::Module,
|
||||||
|
module_name: &str,
|
||||||
kind: AllocatorKind,
|
kind: AllocatorKind,
|
||||||
has_alloc_error_handler: bool,
|
has_alloc_error_handler: bool,
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue