diff --git a/src/backend.rs b/src/backend.rs index bfc9e2d4367..5077c77ec33 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -1,4 +1,4 @@ -use std::convert::TryFrom; +use std::convert::{TryFrom, TryInto}; use rustc_data_structures::fx::FxHashMap; use rustc_session::Session; @@ -45,7 +45,6 @@ pub(crate) trait WriteDebugInfo { fn add_debug_reloc( &mut self, section_map: &FxHashMap, - symbol_map: &indexmap::IndexMap, from: &Self::SectionId, reloc: &DebugReloc, ); @@ -75,7 +74,6 @@ impl WriteDebugInfo for ObjectProduct { fn add_debug_reloc( &mut self, section_map: &FxHashMap, - symbol_map: &indexmap::IndexMap, from: &Self::SectionId, reloc: &DebugReloc, ) { @@ -84,7 +82,7 @@ impl WriteDebugInfo for ObjectProduct { (section_map.get(&id).unwrap().1, 0) } DebugRelocName::Symbol(id) => { - let symbol_id = self.function_symbol(*symbol_map.get_index(id).unwrap().0); + let symbol_id = self.function_symbol(FuncId::from_u32(id.try_into().unwrap())); self.object.symbol_section_and_offset(symbol_id).expect("Debug reloc for undef sym???") } }; diff --git a/src/base.rs b/src/base.rs index b97279fb235..cbef8d288c8 100644 --- a/src/base.rs +++ b/src/base.rs @@ -124,10 +124,12 @@ pub(crate) fn trans_fn<'clif, 'tcx, B: Backend + 'static>( // Define debuginfo for function let isa = cx.module.isa(); + let unwind_context = &mut cx.unwind_context; tcx.sess.time("generate debug info", || { debug_context .as_mut() .map(|x| x.define(context, isa, &source_info_set, local_map)); + unwind_context.add_function(func_id, &context, isa); }); // Clear context to make it usable for the next function diff --git a/src/debuginfo/emit.rs b/src/debuginfo/emit.rs index e49e13a5be5..af93620fa8a 100644 --- a/src/debuginfo/emit.rs +++ b/src/debuginfo/emit.rs @@ -1,6 +1,6 @@ use rustc_data_structures::fx::FxHashMap; -use gimli::write::{Address, AttributeValue, EhFrame, EndianVec, Result, Sections, Writer, Section}; +use gimli::write::{Address, AttributeValue, EndianVec, Result, Sections, Writer}; use gimli::{RunTimeEndian, SectionId}; use crate::backend::WriteDebugInfo; @@ -17,12 +17,9 @@ impl DebugContext<'_> { AttributeValue::RangeListRef(unit_range_list_id), ); - let mut sections = Sections::new(WriterRelocate::new(self)); + let mut sections = Sections::new(WriterRelocate::new(self.endian)); self.dwarf.write(&mut sections).unwrap(); - let mut eh_frame = EhFrame::from(WriterRelocate::new(self)); - self.frame_table.write_eh_frame(&mut eh_frame).unwrap(); - let mut section_map = FxHashMap::default(); let _: Result<()> = sections.for_each_mut(|id, section| { if !section.writer.slice().is_empty() { @@ -35,21 +32,11 @@ impl DebugContext<'_> { let _: Result<()> = sections.for_each(|id, section| { if let Some(section_id) = section_map.get(&id) { for reloc in §ion.relocs { - product.add_debug_reloc(§ion_map, &self.symbols, section_id, reloc); + product.add_debug_reloc(§ion_map, section_id, reloc); } } Ok(()) }); - - if !eh_frame.0.writer.slice().is_empty() { - let id = eh_frame.id(); - let section_id = product.add_debug_section(id, eh_frame.0.writer.into_vec()); - section_map.insert(id, section_id); - - for reloc in &eh_frame.0.relocs { - product.add_debug_reloc(§ion_map, &self.symbols, §ion_id, reloc); - } - } } } @@ -68,16 +55,16 @@ pub(crate) enum DebugRelocName { } #[derive(Clone)] -struct WriterRelocate { - relocs: Vec, - writer: EndianVec, +pub(super) struct WriterRelocate { + pub(super) relocs: Vec, + pub(super) writer: EndianVec, } impl WriterRelocate { - fn new(ctx: &DebugContext<'_>) -> Self { + pub(super) fn new(endian: RunTimeEndian) -> Self { WriterRelocate { relocs: Vec::new(), - writer: EndianVec::new(ctx.endian), + writer: EndianVec::new(endian), } } } diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index fdc6cc911c7..2a360dd00c2 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -11,12 +11,13 @@ use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::ValueLocRange; use gimli::write::{ - self, Address, AttributeValue, CieId, DwarfUnit, Expression, FrameTable, LineProgram, + self, Address, AttributeValue, DwarfUnit, Expression, LineProgram, LineString, Location, LocationList, Range, RangeList, UnitEntryId, Writer, }; use gimli::{Encoding, Format, LineEncoding, RunTimeEndian, X86_64}; pub(crate) use emit::{DebugReloc, DebugRelocName}; +pub(crate) use unwind::UnwindContext; fn target_endian(tcx: TyCtxt<'_>) -> RunTimeEndian { use rustc_target::abi::Endian; @@ -31,13 +32,10 @@ pub(crate) struct DebugContext<'tcx> { tcx: TyCtxt<'tcx>, endian: RunTimeEndian, - symbols: indexmap::IndexMap, dwarf: DwarfUnit, unit_range_list: RangeList, - frame_table: FrameTable, - cie: CieId, clif_types: FxHashMap, types: FxHashMap, UnitEntryId>, } @@ -111,20 +109,14 @@ impl<'tcx> DebugContext<'tcx> { ); } - let mut frame_table = FrameTable::default(); - let cie = frame_table.add_cie(isa.create_systemv_cie().expect("SystemV unwind info CIE")); - DebugContext { tcx, endian: target_endian(tcx), - symbols: indexmap::IndexMap::new(), dwarf, unit_range_list: RangeList(Vec::new()), - frame_table, - cie, clif_types: FxHashMap::default(), types: FxHashMap::default(), } @@ -267,8 +259,6 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { ) -> Self { let mir = debug_context.tcx.instance_mir(instance.def); - let (symbol, _) = debug_context.symbols.insert_full(func_id, name.to_string()); - // FIXME: add to appropriate scope intead of root let scope = debug_context.dwarf.unit.root(); @@ -291,7 +281,7 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { FunctionDebugContext { debug_context, entry_id, - symbol, + symbol: func_id.as_u32() as usize, instance, mir, } @@ -320,8 +310,6 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { source_info_set: &indexmap::IndexSet, local_map: FxHashMap>, ) { - self.create_unwind_info(context, isa); - let end = self.create_debug_lines(context, isa, source_info_set); self.debug_context diff --git a/src/debuginfo/unwind.rs b/src/debuginfo/unwind.rs index c0d4eb5c0ed..987c4d8f3e8 100644 --- a/src/debuginfo/unwind.rs +++ b/src/debuginfo/unwind.rs @@ -1,15 +1,35 @@ use crate::prelude::*; -use cranelift_codegen::isa::unwind::UnwindInfo; +use cranelift_codegen::isa::{TargetIsa, unwind::UnwindInfo}; -use gimli::write::Address; +use gimli::write::{Address, CieId, EhFrame, FrameTable, Section}; -impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { - pub(super) fn create_unwind_info( - &mut self, - context: &Context, - isa: &dyn cranelift_codegen::isa::TargetIsa, - ) { +use crate::backend::WriteDebugInfo; + +pub(crate) struct UnwindContext<'tcx> { + tcx: TyCtxt<'tcx>, + frame_table: FrameTable, + cie_id: CieId, +} + +impl<'tcx> UnwindContext<'tcx> { + pub(crate) fn new( + tcx: TyCtxt<'tcx>, + module: &mut Module, + ) -> Self { + let mut frame_table = FrameTable::default(); + let cie = module.isa().create_systemv_cie().expect("SystemV unwind info CIE"); + + let cie_id = frame_table.add_cie(cie); + + UnwindContext { + tcx, + frame_table, + cie_id, + } + } + + pub(crate) fn add_function(&mut self, func_id: FuncId, context: &Context, isa: &dyn TargetIsa) { let unwind_info = if let Some(unwind_info) = context.create_unwind_info(isa).unwrap() { unwind_info } else { @@ -18,8 +38,8 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { match unwind_info { UnwindInfo::SystemV(unwind_info) => { - self.debug_context.frame_table.add_fde(self.debug_context.cie, unwind_info.to_fde(Address::Symbol { - symbol: self.symbol, + self.frame_table.add_fde(self.cie_id, unwind_info.to_fde(Address::Symbol { + symbol: func_id.as_u32() as usize, addend: 0, })); }, @@ -28,4 +48,20 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { } } } + + pub(crate) fn emit(self, product: &mut P) { + let mut eh_frame = EhFrame::from(super::emit::WriterRelocate::new(super::target_endian(self.tcx))); + self.frame_table.write_eh_frame(&mut eh_frame).unwrap(); + + if !eh_frame.0.writer.slice().is_empty() { + let id = eh_frame.id(); + let section_id = product.add_debug_section(id, eh_frame.0.writer.into_vec()); + let mut section_map = FxHashMap::default(); + section_map.insert(id, section_id); + + for reloc in &eh_frame.0.relocs { + product.add_debug_reloc(§ion_map, §ion_id, reloc); + } + } + } } diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 76bd614b164..9454f43f23a 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -32,6 +32,7 @@ fn emit_module( kind: ModuleKind, mut module: Module, debug: Option>, + unwind_context: UnwindContext<'_>, ) -> ModuleCodegenResult where B::Product: Emit + WriteDebugInfo, { @@ -42,6 +43,8 @@ fn emit_module( debug.emit(&mut product); } + unwind_context.emit(&mut product); + let tmp_file = tcx .output_filenames(LOCAL_CRATE) .temp_path(OutputType::Object, Some(&name)); @@ -125,7 +128,9 @@ fn module_codegen(tcx: TyCtxt<'_>, cgu_name: rustc_span::Symbol) -> ModuleCodege None }; - super::codegen_mono_items(tcx, &mut module, debug.as_mut(), mono_items); + let mut unwind_context = UnwindContext::new(tcx, &mut module); + + super::codegen_mono_items(tcx, &mut module, debug.as_mut(), &mut unwind_context, mono_items); crate::main_shim::maybe_create_entry_wrapper(tcx, &mut module); emit_module( @@ -134,6 +139,7 @@ fn module_codegen(tcx: TyCtxt<'_>, cgu_name: rustc_span::Symbol) -> ModuleCodege ModuleKind::Regular, module, debug, + unwind_context, ) } @@ -190,12 +196,16 @@ pub(super) fn run_aot( let created_alloc_shim = crate::allocator::codegen(tcx, &mut allocator_module); let allocator_module = if created_alloc_shim { + // FIXME create .eh_frame for allocator shim + let unwind_context = UnwindContext::new(tcx, &mut allocator_module); + let ModuleCodegenResult(module, work_product) = emit_module( tcx, "allocator_shim".to_string(), ModuleKind::Allocator, allocator_module, None, + unwind_context, ); if let Some((id, product)) = work_product { work_products.insert(id, product); diff --git a/src/driver/jit.rs b/src/driver/jit.rs index a5dca71c330..4d7ca34d1ba 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -52,8 +52,11 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>) -> ! { .into_iter() .collect::>(); + // FIXME register with unwind runtime + let mut unwind_context = UnwindContext::new(tcx, &mut jit_module); + super::time(tcx, "codegen mono items", || { - super::codegen_mono_items(tcx, &mut jit_module, None, mono_items); + super::codegen_mono_items(tcx, &mut jit_module, None, &mut unwind_context, mono_items); }); crate::main_shim::maybe_create_entry_wrapper(tcx, &mut jit_module); crate::allocator::codegen(tcx, &mut jit_module); diff --git a/src/driver/mod.rs b/src/driver/mod.rs index 6aa736d18ce..bf3241b8834 100644 --- a/src/driver/mod.rs +++ b/src/driver/mod.rs @@ -33,9 +33,10 @@ fn codegen_mono_items<'tcx>( tcx: TyCtxt<'tcx>, module: &mut Module, debug_context: Option<&mut DebugContext<'tcx>>, + unwind_context: &mut UnwindContext<'tcx>, mono_items: Vec<(MonoItem<'tcx>, (RLinkage, Visibility))>, ) { - let mut cx = CodegenCx::new(tcx, module, debug_context); + let mut cx = CodegenCx::new(tcx, module, debug_context, unwind_context); tcx.sess.time("predefine functions", || { for &(mono_item, (linkage, visibility)) in &mono_items { diff --git a/src/lib.rs b/src/lib.rs index d679b4d7930..8af309a22ba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -106,7 +106,7 @@ mod prelude { pub(crate) use crate::base::{trans_operand, trans_place}; pub(crate) use crate::cast::*; pub(crate) use crate::common::*; - pub(crate) use crate::debuginfo::{DebugContext, FunctionDebugContext}; + pub(crate) use crate::debuginfo::{DebugContext, FunctionDebugContext, UnwindContext}; pub(crate) use crate::pointer::Pointer; pub(crate) use crate::trap::*; pub(crate) use crate::value_and_place::{CPlace, CPlaceInner, CValue}; @@ -133,6 +133,7 @@ pub(crate) struct CodegenCx<'clif, 'tcx, B: Backend + 'static> { cached_context: Context, vtables: FxHashMap<(Ty<'tcx>, Option>), DataId>, debug_context: Option<&'clif mut DebugContext<'tcx>>, + unwind_context: &'clif mut UnwindContext<'tcx>, } impl<'clif, 'tcx, B: Backend + 'static> CodegenCx<'clif, 'tcx, B> { @@ -140,6 +141,7 @@ impl<'clif, 'tcx, B: Backend + 'static> CodegenCx<'clif, 'tcx, B> { tcx: TyCtxt<'tcx>, module: &'clif mut Module, debug_context: Option<&'clif mut DebugContext<'tcx>>, + unwind_context: &'clif mut UnwindContext<'tcx>, ) -> Self { CodegenCx { tcx, @@ -148,6 +150,7 @@ impl<'clif, 'tcx, B: Backend + 'static> CodegenCx<'clif, 'tcx, B> { cached_context: Context::new(), vtables: FxHashMap::default(), debug_context, + unwind_context, } }