From c0aedfef96b62302a2c2410d0214d94da5dff647 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 9 Nov 2019 16:42:21 +0100 Subject: [PATCH 01/21] [WIP] debuginfo for locals --- src/base.rs | 1 + src/debuginfo.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ src/value_and_place.rs | 6 +++++- 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/base.rs b/src/base.rs index 705629888..91c258733 100644 --- a/src/base.rs +++ b/src/base.rs @@ -21,6 +21,7 @@ pub fn trans_fn<'clif, 'tcx, B: Backend + 'static>( // Make FunctionBuilder let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig); + func.collect_debug_info(); let mut func_ctx = FunctionBuilderContext::new(); let mut bcx = FunctionBuilder::new(&mut func, &mut func_ctx); diff --git a/src/debuginfo.rs b/src/debuginfo.rs index e6d133c64..0998236e5 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -305,6 +305,48 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { let entry = self.debug_context.dwarf.unit.get_mut(self.entry_id); entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(end as u64)); + { + let value_labels_ranges = context.build_value_labels_ranges(isa).unwrap(); + + for (value_label, value_loc_ranges) in value_labels_ranges.iter() { + let live_ranges = RangeList( + Some(Range::BaseAddress { + address: Address::Symbol { + symbol: self.symbol, + addend: 0, + }, + }) + .into_iter() + .chain( + value_loc_ranges + .iter() + .map(|val_loc_range| Range::OffsetPair { + begin: u64::from(val_loc_range.start), + end: u64::from(val_loc_range.end), + }), + ) + .collect(), + ); + let live_ranges_id = self.debug_context.dwarf.unit.ranges.add(live_ranges); + + let var_id = self + .debug_context + .dwarf + .unit + .add(self.entry_id, gimli::DW_TAG_variable); + let var_entry = self.debug_context.dwarf.unit.get_mut(var_id); + + var_entry.set( + gimli::DW_AT_ranges, + AttributeValue::RangeListRef(live_ranges_id), + ); + var_entry.set( + gimli::DW_AT_name, + AttributeValue::String(format!("{:?}", value_label).into_bytes()), + ); + } + } + self.debug_context .unit_range_list .0 diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 142795a91..8016a802d 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -299,7 +299,11 @@ impl<'tcx> CPlace<'tcx> { pub fn to_cvalue(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> CValue<'tcx> { let layout = self.layout(); match self.inner { - CPlaceInner::Var(var) => CValue::by_val(fx.bcx.use_var(mir_var(var)), layout), + CPlaceInner::Var(var) => { + let val = fx.bcx.use_var(mir_var(var)); + fx.bcx.set_val_label(val, cranelift::codegen::ir::ValueLabel::from_u32(var.as_u32())); + CValue::by_val(val, layout) + } CPlaceInner::Addr(addr, extra) => { assert!(extra.is_none(), "unsized values are not yet supported"); CValue::by_ref(addr, layout) From a962835685d0cc02b9749bd8f1f89236796f55a9 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 9 Nov 2019 18:40:11 +0100 Subject: [PATCH 02/21] [WIP] debuginfo: Add types for locals --- src/base.rs | 2 +- src/debuginfo.rs | 77 +++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/src/base.rs b/src/base.rs index 91c258733..bb0ffb51b 100644 --- a/src/base.rs +++ b/src/base.rs @@ -17,7 +17,7 @@ pub fn trans_fn<'clif, 'tcx, B: Backend + 'static>( let mut debug_context = cx .debug_context .as_mut() - .map(|debug_context| FunctionDebugContext::new(tcx, debug_context, mir, func_id, &name, &sig)); + .map(|debug_context| FunctionDebugContext::new(debug_context, mir, func_id, &name, &sig)); // Make FunctionBuilder let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig); diff --git a/src/debuginfo.rs b/src/debuginfo.rs index 0998236e5..b3de6449f 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -70,13 +70,15 @@ pub enum DebugRelocName { } pub struct DebugContext<'tcx> { + tcx: TyCtxt<'tcx>, + endian: RunTimeEndian, symbols: indexmap::IndexMap, dwarf: DwarfUnit, unit_range_list: RangeList, - _dummy: PhantomData<&'tcx ()>, + types: HashMap, UnitEntryId>, } impl<'tcx> DebugContext<'tcx> { @@ -132,18 +134,20 @@ impl<'tcx> DebugContext<'tcx> { } DebugContext { + tcx, + endian: target_endian(tcx), symbols: indexmap::IndexMap::new(), dwarf, unit_range_list: RangeList(Vec::new()), - _dummy: PhantomData, + types: HashMap::new(), } } - fn emit_location(&mut self, tcx: TyCtxt<'tcx>, entry_id: UnitEntryId, span: Span) { - let loc = tcx.sess.source_map().lookup_char_pos(span.lo()); + fn emit_location(&mut self, entry_id: UnitEntryId, span: Span) { + let loc = self.tcx.sess.source_map().lookup_char_pos(span.lo()); let file_id = line_program_add_file( &mut self.dwarf.unit.line_program, @@ -168,6 +172,58 @@ impl<'tcx> DebugContext<'tcx> { ); } + fn dwarf_ty(&mut self, ty: Ty<'tcx>) -> UnitEntryId { + if let Some(type_id) = self.types.get(ty) { + return *type_id; + } + + let new_entry = |dwarf: &mut DwarfUnit, tag| { + dwarf.unit.add(dwarf.unit.root(), tag) + }; + + let primtive = |dwarf: &mut DwarfUnit, ate| { + let type_id = new_entry(dwarf, gimli::DW_TAG_base_type); + let type_entry = dwarf.unit.get_mut(type_id); + type_entry.set(gimli::DW_AT_encoding, AttributeValue::Encoding(ate)); + type_id + }; + + let type_id = match ty.kind { + ty::Bool => primtive(&mut self.dwarf, gimli::DW_ATE_boolean), + ty::Char => primtive(&mut self.dwarf, gimli::DW_ATE_UTF), + ty::Uint(_) => primtive(&mut self.dwarf, gimli::DW_ATE_unsigned), + ty::Int(_) => primtive(&mut self.dwarf, gimli::DW_ATE_signed), + ty::Float(_) => primtive(&mut self.dwarf, gimli::DW_ATE_float), + ty::Ref(_, pointee_ty, mutbl) | ty::RawPtr(ty::TypeAndMut { ty: pointee_ty, mutbl }) => { + let type_id = new_entry(&mut self.dwarf, gimli::DW_TAG_pointer_type); + + // Ensure that type is inserted before recursing to avoid duplicates + self.types.insert(ty, type_id); + + let pointee = self.dwarf_ty(pointee_ty); + + let type_entry = self.dwarf.unit.get_mut(type_id); + + //type_entry.set(gimli::DW_AT_mutable, AttributeValue::Flag(mutbl == rustc::hir::Mutability::MutMutable)); + type_entry.set(gimli::DW_AT_type, AttributeValue::ThisUnitEntryRef(pointee)); + + type_id + } + _ => new_entry(&mut self.dwarf, gimli::DW_TAG_structure_type), + }; + let name = format!("{}", ty); + let layout = self.tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap(); + + let type_entry = self.dwarf.unit.get_mut(type_id); + + type_entry.set(gimli::DW_AT_name, AttributeValue::String(name.into_bytes())); + type_entry.set(gimli::DW_AT_byte_size, AttributeValue::Udata(layout.size.bytes())); + + self.types.insert(ty, type_id); + + type_id + } + pub fn emit(&mut self, product: &mut P) { let unit_range_list_id = self.dwarf.unit.ranges.add(self.unit_range_list.clone()); let root = self.dwarf.unit.root(); @@ -205,13 +261,13 @@ pub struct FunctionDebugContext<'a, 'tcx> { entry_id: UnitEntryId, symbol: usize, mir_span: Span, + local_decls: rustc_index::vec::IndexVec>, } impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { pub fn new( - tcx: TyCtxt<'tcx>, debug_context: &'a mut DebugContext<'tcx>, - mir: &Body, + mir: &'tcx Body, func_id: FuncId, name: &str, _sig: &Signature, @@ -237,13 +293,14 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { AttributeValue::Address(Address::Symbol { symbol, addend: 0 }), ); - debug_context.emit_location(tcx, entry_id, mir.span); + debug_context.emit_location(entry_id, mir.span); FunctionDebugContext { debug_context, entry_id, symbol, mir_span: mir.span, + local_decls: mir.local_decls.clone(), } } @@ -329,6 +386,8 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { ); let live_ranges_id = self.debug_context.dwarf.unit.ranges.add(live_ranges); + let local_type = self.debug_context.dwarf_ty(self.local_decls[mir::Local::from_u32(value_label.as_u32())].ty); + let var_id = self .debug_context .dwarf @@ -344,6 +403,10 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { gimli::DW_AT_name, AttributeValue::String(format!("{:?}", value_label).into_bytes()), ); + var_entry.set( + gimli::DW_AT_type, + AttributeValue::ThisUnitEntryRef(local_type), + ); } } From 21f0dfd014fc5996b6f88b9565656f63b2f65c99 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 11 Nov 2019 20:49:20 +0100 Subject: [PATCH 03/21] Monomorphize locals --- src/base.rs | 4 ++-- src/debuginfo.rs | 24 ++++++++++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/base.rs b/src/base.rs index bb0ffb51b..ed587bf73 100644 --- a/src/base.rs +++ b/src/base.rs @@ -17,7 +17,7 @@ pub fn trans_fn<'clif, 'tcx, B: Backend + 'static>( let mut debug_context = cx .debug_context .as_mut() - .map(|debug_context| FunctionDebugContext::new(debug_context, mir, func_id, &name, &sig)); + .map(|debug_context| FunctionDebugContext::new(debug_context, instance, func_id, &name, &sig)); // Make FunctionBuilder let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig); @@ -92,7 +92,7 @@ pub fn trans_fn<'clif, 'tcx, B: Backend + 'static>( let isa = cx.module.isa(); debug_context .as_mut() - .map(|x| x.define(tcx, context, isa, &source_info_set)); + .map(|x| x.define(context, isa, &source_info_set)); // Clear context to make it usable for the next function context.clear(); diff --git a/src/debuginfo.rs b/src/debuginfo.rs index b3de6449f..8de7ab673 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -260,18 +260,20 @@ pub struct FunctionDebugContext<'a, 'tcx> { debug_context: &'a mut DebugContext<'tcx>, entry_id: UnitEntryId, symbol: usize, - mir_span: Span, - local_decls: rustc_index::vec::IndexVec>, + instance: Instance<'tcx>, + mir: &'tcx mir::Body<'tcx>, } impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { pub fn new( debug_context: &'a mut DebugContext<'tcx>, - mir: &'tcx Body, + instance: Instance<'tcx>, func_id: FuncId, name: &str, _sig: &Signature, ) -> 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 @@ -299,18 +301,19 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { debug_context, entry_id, symbol, - mir_span: mir.span, - local_decls: mir.local_decls.clone(), + instance, + mir, } } pub fn define( &mut self, - tcx: TyCtxt, context: &Context, isa: &dyn cranelift::codegen::isa::TargetIsa, source_info_set: &indexmap::IndexSet<(Span, mir::SourceScope)>, ) { + let tcx = self.debug_context.tcx; + let line_program = &mut self.debug_context.dwarf.unit.line_program; line_program.begin_sequence(Some(Address::Symbol { @@ -351,7 +354,7 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { let source_info = *source_info_set.get_index(srcloc.bits() as usize).unwrap(); create_row_for_span(line_program, source_info.0); } else { - create_row_for_span(line_program, self.mir_span); + create_row_for_span(line_program, self.mir.span); } end = offset + size; } @@ -386,7 +389,12 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { ); let live_ranges_id = self.debug_context.dwarf.unit.ranges.add(live_ranges); - let local_type = self.debug_context.dwarf_ty(self.local_decls[mir::Local::from_u32(value_label.as_u32())].ty); + let local_ty = tcx.subst_and_normalize_erasing_regions( + self.instance.substs, + ty::ParamEnv::reveal_all(), + &self.mir.local_decls[mir::Local::from_u32(value_label.as_u32())].ty, + ); + let local_type = self.debug_context.dwarf_ty(local_ty); let var_id = self .debug_context From 3fed8800575297814370e4a16ff7edbf7746dba6 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 11 Nov 2019 21:43:57 +0100 Subject: [PATCH 04/21] [WIP] Set local DW_AT_location --- src/debuginfo.rs | 128 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 122 insertions(+), 6 deletions(-) diff --git a/src/debuginfo.rs b/src/debuginfo.rs index 8de7ab673..7530c7c21 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -6,11 +6,15 @@ use std::marker::PhantomData; use syntax::source_map::FileName; +use cranelift::codegen::ir::{StackSlots, ValueLoc}; +use cranelift::codegen::isa::RegUnit; + use gimli::write::{ - Address, AttributeValue, DwarfUnit, EndianVec, FileId, LineProgram, LineString, - LineStringTable, Range, RangeList, Result, Sections, UnitEntryId, Writer, + self, Address, AttributeValue, DwarfUnit, EndianVec, Expression, FileId, LineProgram, + LineString, LineStringTable, Location, LocationList, Range, RangeList, Result, Sections, + UnitEntryId, Writer, }; -use gimli::{Encoding, Format, LineEncoding, RunTimeEndian, SectionId}; +use gimli::{Encoding, Format, LineEncoding, Register, RunTimeEndian, SectionId, X86_64}; fn target_endian(tcx: TyCtxt) -> RunTimeEndian { use rustc::ty::layout::Endian; @@ -380,9 +384,9 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { .chain( value_loc_ranges .iter() - .map(|val_loc_range| Range::OffsetPair { - begin: u64::from(val_loc_range.start), - end: u64::from(val_loc_range.end), + .map(|value_loc_range| Range::OffsetPair { + begin: u64::from(value_loc_range.start), + end: u64::from(value_loc_range.end), }), ) .collect(), @@ -415,6 +419,34 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { gimli::DW_AT_type, AttributeValue::ThisUnitEntryRef(local_type), ); + + + let loc_list = LocationList( + Some(Location::BaseAddress { + address: Address::Symbol { + symbol: self.symbol, + addend: 0, + }, + }) + .into_iter() + .chain( + value_loc_ranges + .iter() + .map(|value_loc_range| Location::OffsetPair { + begin: u64::from(value_loc_range.start), + end: u64::from(value_loc_range.end), + data: Expression(translate_loc(value_loc_range.loc, &context.func.stack_slots).unwrap()), + }), + ) + .collect(), + ); + let loc_list_id = self.debug_context.dwarf.unit.locations.add(loc_list); + + let var_entry = self.debug_context.dwarf.unit.get_mut(var_id); + var_entry.set( + gimli::DW_AT_location, + AttributeValue::LocationListRef(loc_list_id), + ); } } @@ -510,3 +542,87 @@ impl Writer for WriterRelocate { self.write_udata_at(offset, 0, size) } } + + + + + + +// Adapted from https://github.com/CraneStation/wasmtime/blob/5a1845b4caf7a5dba8eda1fef05213a532ed4259/crates/debug/src/transform/expression.rs#L59-L137 + +fn map_reg(reg: RegUnit) -> Register { + static mut REG_X86_MAP: Option> = None; + // FIXME lazy initialization? + unsafe { + if REG_X86_MAP.is_none() { + REG_X86_MAP = Some(HashMap::new()); + } + if let Some(val) = REG_X86_MAP.as_mut().unwrap().get(®) { + return *val; + } + let result = match reg { + 0 => X86_64::RAX, + 1 => X86_64::RCX, + 2 => X86_64::RDX, + 3 => X86_64::RBX, + 4 => X86_64::RSP, + 5 => X86_64::RBP, + 6 => X86_64::RSI, + 7 => X86_64::RDI, + 8 => X86_64::R8, + 9 => X86_64::R9, + 10 => X86_64::R10, + 11 => X86_64::R11, + 12 => X86_64::R12, + 13 => X86_64::R13, + 14 => X86_64::R14, + 15 => X86_64::R15, + 16 => X86_64::XMM0, + 17 => X86_64::XMM1, + 18 => X86_64::XMM2, + 19 => X86_64::XMM3, + 20 => X86_64::XMM4, + 21 => X86_64::XMM5, + 22 => X86_64::XMM6, + 23 => X86_64::XMM7, + 24 => X86_64::XMM8, + 25 => X86_64::XMM9, + 26 => X86_64::XMM10, + 27 => X86_64::XMM11, + 28 => X86_64::XMM12, + 29 => X86_64::XMM13, + 30 => X86_64::XMM14, + 31 => X86_64::XMM15, + _ => panic!("unknown x86_64 register {}", reg), + }; + REG_X86_MAP.as_mut().unwrap().insert(reg, result); + result + } +} + +fn translate_loc(loc: ValueLoc, stack_slots: &StackSlots) -> Option> { + match loc { + ValueLoc::Reg(reg) => { + let machine_reg = map_reg(reg).0 as u8; + assert!(machine_reg <= 32); // FIXME + Some(vec![gimli::constants::DW_OP_reg0.0 + machine_reg]) + } + ValueLoc::Stack(ss) => { + if let Some(ss_offset) = stack_slots[ss].offset { + let endian = gimli::RunTimeEndian::Little; + let mut writer = write::EndianVec::new(endian); + writer + .write_u8(gimli::constants::DW_OP_breg0.0 + X86_64::RBP.0 as u8) + .expect("bp wr"); + writer.write_sleb128(ss_offset as i64 + 16).expect("ss wr"); + writer + .write_u8(gimli::constants::DW_OP_deref.0 as u8) + .expect("bp wr"); + let buf = writer.into_vec(); + return Some(buf); + } + None + } + _ => None, + } +} From 50f7110cb69458fa996ed88f17e1210ff0fc24f3 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 12 Nov 2019 20:31:53 +0100 Subject: [PATCH 05/21] Fix local value reading LLDB doesn't understand base address entries --- src/debuginfo.rs | 56 +++++++++++++----------------------------------- 1 file changed, 15 insertions(+), 41 deletions(-) diff --git a/src/debuginfo.rs b/src/debuginfo.rs index 7530c7c21..d67171579 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -373,26 +373,6 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { let value_labels_ranges = context.build_value_labels_ranges(isa).unwrap(); for (value_label, value_loc_ranges) in value_labels_ranges.iter() { - let live_ranges = RangeList( - Some(Range::BaseAddress { - address: Address::Symbol { - symbol: self.symbol, - addend: 0, - }, - }) - .into_iter() - .chain( - value_loc_ranges - .iter() - .map(|value_loc_range| Range::OffsetPair { - begin: u64::from(value_loc_range.start), - end: u64::from(value_loc_range.end), - }), - ) - .collect(), - ); - let live_ranges_id = self.debug_context.dwarf.unit.ranges.add(live_ranges); - let local_ty = tcx.subst_and_normalize_erasing_regions( self.instance.substs, ty::ParamEnv::reveal_all(), @@ -407,10 +387,6 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { .add(self.entry_id, gimli::DW_TAG_variable); let var_entry = self.debug_context.dwarf.unit.get_mut(var_id); - var_entry.set( - gimli::DW_AT_ranges, - AttributeValue::RangeListRef(live_ranges_id), - ); var_entry.set( gimli::DW_AT_name, AttributeValue::String(format!("{:?}", value_label).into_bytes()), @@ -420,25 +396,23 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { AttributeValue::ThisUnitEntryRef(local_type), ); - let loc_list = LocationList( - Some(Location::BaseAddress { - address: Address::Symbol { - symbol: self.symbol, - addend: 0, - }, - }) - .into_iter() - .chain( - value_loc_ranges - .iter() - .map(|value_loc_range| Location::OffsetPair { - begin: u64::from(value_loc_range.start), - end: u64::from(value_loc_range.end), + value_loc_ranges + .iter() + .map(|value_loc_range| { + Location::StartEnd { + begin: Address::Symbol { + symbol: self.symbol, + addend: i64::from(value_loc_range.start), + }, + end: Address::Symbol { + symbol: self.symbol, + addend: i64::from(value_loc_range.end), + }, data: Expression(translate_loc(value_loc_range.loc, &context.func.stack_slots).unwrap()), - }), - ) - .collect(), + } + }) + .collect(), ); let loc_list_id = self.debug_context.dwarf.unit.locations.add(loc_list); From 62c3ca28e1e7d69541a3884e57ec33df7836c936 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 12 Nov 2019 20:43:34 +0100 Subject: [PATCH 06/21] Extract local definition from FunctionDebugContext::define --- src/debuginfo.rs | 60 +++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/src/debuginfo.rs b/src/debuginfo.rs index d67171579..63a95e7e0 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -2,8 +2,6 @@ use crate::prelude::*; use crate::backend::WriteDebugInfo; -use std::marker::PhantomData; - use syntax::source_map::FileName; use cranelift::codegen::ir::{StackSlots, ValueLoc}; @@ -310,6 +308,41 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { } } + fn define_local(&mut self, local: mir::Local) -> UnitEntryId { + let local_decl = &self.mir.local_decls[local]; + + let ty = self.debug_context.tcx.subst_and_normalize_erasing_regions( + self.instance.substs, + ty::ParamEnv::reveal_all(), + &local_decl.ty, + ); + let dw_ty = self.debug_context.dwarf_ty(ty); + + let name = if let Some(name) = local_decl.name { + format!("{}{:?}", name.as_str(), local) + } else { + format!("{:?}", local) + }; + + let var_id = self + .debug_context + .dwarf + .unit + .add(self.entry_id, gimli::DW_TAG_variable); + let var_entry = self.debug_context.dwarf.unit.get_mut(var_id); + + var_entry.set( + gimli::DW_AT_name, + AttributeValue::String(name.into_bytes()), + ); + var_entry.set( + gimli::DW_AT_type, + AttributeValue::ThisUnitEntryRef(dw_ty), + ); + + var_id + } + pub fn define( &mut self, context: &Context, @@ -373,28 +406,7 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { let value_labels_ranges = context.build_value_labels_ranges(isa).unwrap(); for (value_label, value_loc_ranges) in value_labels_ranges.iter() { - let local_ty = tcx.subst_and_normalize_erasing_regions( - self.instance.substs, - ty::ParamEnv::reveal_all(), - &self.mir.local_decls[mir::Local::from_u32(value_label.as_u32())].ty, - ); - let local_type = self.debug_context.dwarf_ty(local_ty); - - let var_id = self - .debug_context - .dwarf - .unit - .add(self.entry_id, gimli::DW_TAG_variable); - let var_entry = self.debug_context.dwarf.unit.get_mut(var_id); - - var_entry.set( - gimli::DW_AT_name, - AttributeValue::String(format!("{:?}", value_label).into_bytes()), - ); - var_entry.set( - gimli::DW_AT_type, - AttributeValue::ThisUnitEntryRef(local_type), - ); + let var_id = self.define_local(mir::Local::from_u32(value_label.as_u32())); let loc_list = LocationList( value_loc_ranges From d07fe816af78de1578e9f915012b6485c2928f38 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 12 Nov 2019 20:44:20 +0100 Subject: [PATCH 07/21] Move debuginfo.rs to debuginfo/mod.rs --- src/{debuginfo.rs => debuginfo/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{debuginfo.rs => debuginfo/mod.rs} (100%) diff --git a/src/debuginfo.rs b/src/debuginfo/mod.rs similarity index 100% rename from src/debuginfo.rs rename to src/debuginfo/mod.rs From ed758912d31c159c26768a4603db55372f948b82 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 12 Nov 2019 20:52:32 +0100 Subject: [PATCH 08/21] Split debuginfo/emit.rs part out of debuginfo/mod.rs --- src/debuginfo/emit.rs | 135 +++++++++++++++++++++++++++++++++++++++++ src/debuginfo/mod.rs | 137 +++--------------------------------------- 2 files changed, 142 insertions(+), 130 deletions(-) create mode 100644 src/debuginfo/emit.rs diff --git a/src/debuginfo/emit.rs b/src/debuginfo/emit.rs new file mode 100644 index 000000000..2b6dc9f66 --- /dev/null +++ b/src/debuginfo/emit.rs @@ -0,0 +1,135 @@ +use std::collections::HashMap; + +use gimli::write::{Address, AttributeValue, EndianVec, Result, Sections, Writer}; +use gimli::{RunTimeEndian, SectionId}; + +use crate::backend::WriteDebugInfo; + +use super::DebugContext; + +impl DebugContext<'_> { + pub fn emit(&mut self, product: &mut P) { + let unit_range_list_id = self.dwarf.unit.ranges.add(self.unit_range_list.clone()); + let root = self.dwarf.unit.root(); + let root = self.dwarf.unit.get_mut(root); + root.set( + gimli::DW_AT_ranges, + AttributeValue::RangeListRef(unit_range_list_id), + ); + + let mut sections = Sections::new(WriterRelocate::new(self)); + self.dwarf.write(&mut sections).unwrap(); + + let mut section_map = HashMap::new(); + let _: Result<()> = sections.for_each_mut(|id, section| { + if !section.writer.slice().is_empty() { + let section_id = product.add_debug_section(id, section.writer.take()); + section_map.insert(id, section_id); + } + Ok(()) + }); + + 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); + } + } + Ok(()) + }); + } +} + +#[derive(Clone)] +pub struct DebugReloc { + pub offset: u32, + pub size: u8, + pub name: DebugRelocName, + pub addend: i64, +} + +#[derive(Clone)] +pub enum DebugRelocName { + Section(SectionId), + Symbol(usize), +} + +#[derive(Clone)] +struct WriterRelocate { + relocs: Vec, + writer: EndianVec, +} + +impl WriterRelocate { + fn new(ctx: &DebugContext) -> Self { + WriterRelocate { + relocs: Vec::new(), + writer: EndianVec::new(ctx.endian), + } + } +} + +impl Writer for WriterRelocate { + type Endian = RunTimeEndian; + + fn endian(&self) -> Self::Endian { + self.writer.endian() + } + + fn len(&self) -> usize { + self.writer.len() + } + + fn write(&mut self, bytes: &[u8]) -> Result<()> { + self.writer.write(bytes) + } + + fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()> { + self.writer.write_at(offset, bytes) + } + + fn write_address(&mut self, address: Address, size: u8) -> Result<()> { + match address { + Address::Constant(val) => self.write_udata(val, size), + Address::Symbol { symbol, addend } => { + let offset = self.len() as u64; + self.relocs.push(DebugReloc { + offset: offset as u32, + size, + name: DebugRelocName::Symbol(symbol), + addend: addend as i64, + }); + self.write_udata(0, size) + } + } + } + + // TODO: implement write_eh_pointer + + fn write_offset(&mut self, val: usize, section: SectionId, size: u8) -> Result<()> { + let offset = self.len() as u32; + self.relocs.push(DebugReloc { + offset, + size, + name: DebugRelocName::Section(section), + addend: val as i64, + }); + self.write_udata(0, size) + } + + fn write_offset_at( + &mut self, + offset: usize, + val: usize, + section: SectionId, + size: u8, + ) -> Result<()> { + self.relocs.push(DebugReloc { + offset: offset as u32, + size, + name: DebugRelocName::Section(section), + addend: val as i64, + }); + self.write_udata_at(offset, 0, size) + } +} diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 63a95e7e0..3ab03a411 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -1,6 +1,6 @@ -use crate::prelude::*; +mod emit; -use crate::backend::WriteDebugInfo; +use crate::prelude::*; use syntax::source_map::FileName; @@ -8,11 +8,12 @@ use cranelift::codegen::ir::{StackSlots, ValueLoc}; use cranelift::codegen::isa::RegUnit; use gimli::write::{ - self, Address, AttributeValue, DwarfUnit, EndianVec, Expression, FileId, LineProgram, - LineString, LineStringTable, Location, LocationList, Range, RangeList, Result, Sections, - UnitEntryId, Writer, + self, Address, AttributeValue, DwarfUnit, Expression, FileId, LineProgram, LineString, + LineStringTable, Location, LocationList, Range, RangeList, UnitEntryId, Writer, }; -use gimli::{Encoding, Format, LineEncoding, Register, RunTimeEndian, SectionId, X86_64}; +use gimli::{Encoding, Format, LineEncoding, Register, RunTimeEndian, X86_64}; + +pub use emit::{DebugReloc, DebugRelocName}; fn target_endian(tcx: TyCtxt) -> RunTimeEndian { use rustc::ty::layout::Endian; @@ -57,20 +58,6 @@ fn line_program_add_file( } } -#[derive(Clone)] -pub struct DebugReloc { - pub offset: u32, - pub size: u8, - pub name: DebugRelocName, - pub addend: i64, -} - -#[derive(Clone)] -pub enum DebugRelocName { - Section(SectionId), - Symbol(usize), -} - pub struct DebugContext<'tcx> { tcx: TyCtxt<'tcx>, @@ -225,37 +212,6 @@ impl<'tcx> DebugContext<'tcx> { type_id } - - pub fn emit(&mut self, product: &mut P) { - let unit_range_list_id = self.dwarf.unit.ranges.add(self.unit_range_list.clone()); - let root = self.dwarf.unit.root(); - let root = self.dwarf.unit.get_mut(root); - root.set( - gimli::DW_AT_ranges, - AttributeValue::RangeListRef(unit_range_list_id), - ); - - let mut sections = Sections::new(WriterRelocate::new(self)); - self.dwarf.write(&mut sections).unwrap(); - - let mut section_map = HashMap::new(); - let _: Result<()> = sections.for_each_mut(|id, section| { - if !section.writer.slice().is_empty() { - let section_id = product.add_debug_section(id, section.writer.take()); - section_map.insert(id, section_id); - } - Ok(()) - }); - - 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); - } - } - Ok(()) - }); - } } pub struct FunctionDebugContext<'a, 'tcx> { @@ -449,85 +405,6 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { } } -#[derive(Clone)] -struct WriterRelocate { - relocs: Vec, - writer: EndianVec, -} - -impl WriterRelocate { - fn new(ctx: &DebugContext) -> Self { - WriterRelocate { - relocs: Vec::new(), - writer: EndianVec::new(ctx.endian), - } - } -} - -impl Writer for WriterRelocate { - type Endian = RunTimeEndian; - - fn endian(&self) -> Self::Endian { - self.writer.endian() - } - - fn len(&self) -> usize { - self.writer.len() - } - - fn write(&mut self, bytes: &[u8]) -> Result<()> { - self.writer.write(bytes) - } - - fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()> { - self.writer.write_at(offset, bytes) - } - - fn write_address(&mut self, address: Address, size: u8) -> Result<()> { - match address { - Address::Constant(val) => self.write_udata(val, size), - Address::Symbol { symbol, addend } => { - let offset = self.len() as u64; - self.relocs.push(DebugReloc { - offset: offset as u32, - size, - name: DebugRelocName::Symbol(symbol), - addend: addend as i64, - }); - self.write_udata(0, size) - } - } - } - - // TODO: implement write_eh_pointer - - fn write_offset(&mut self, val: usize, section: SectionId, size: u8) -> Result<()> { - let offset = self.len() as u32; - self.relocs.push(DebugReloc { - offset, - size, - name: DebugRelocName::Section(section), - addend: val as i64, - }); - self.write_udata(0, size) - } - - fn write_offset_at( - &mut self, - offset: usize, - val: usize, - section: SectionId, - size: u8, - ) -> Result<()> { - self.relocs.push(DebugReloc { - offset: offset as u32, - size, - name: DebugRelocName::Section(section), - addend: val as i64, - }); - self.write_udata_at(offset, 0, size) - } -} From beda7870fb0f813e69e7803c612f865079625235 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 12 Nov 2019 21:08:08 +0100 Subject: [PATCH 09/21] Split debuginfo/line_info.rs from debuginfo/mod.rs --- src/debuginfo/line_info.rs | 149 +++++++++++++++++++++++++++++++++++++ src/debuginfo/mod.rs | 138 +--------------------------------- 2 files changed, 153 insertions(+), 134 deletions(-) create mode 100644 src/debuginfo/line_info.rs diff --git a/src/debuginfo/line_info.rs b/src/debuginfo/line_info.rs new file mode 100644 index 000000000..dc380c623 --- /dev/null +++ b/src/debuginfo/line_info.rs @@ -0,0 +1,149 @@ +use crate::prelude::*; + +use syntax::source_map::FileName; + +use gimli::write::{ + Address, AttributeValue, FileId, LineProgram, LineString, + LineStringTable, Range, UnitEntryId, +}; + +fn line_program_add_file( + line_program: &mut LineProgram, + line_strings: &mut LineStringTable, + file: &FileName, +) -> FileId { + match file { + FileName::Real(path) => { + let dir_name = path.parent().unwrap().to_str().unwrap().as_bytes(); + let dir_id = if !dir_name.is_empty() { + let dir_name = LineString::new(dir_name, line_program.encoding(), line_strings); + line_program.add_directory(dir_name) + } else { + line_program.default_directory() + }; + let file_name = LineString::new( + path.file_name().unwrap().to_str().unwrap().as_bytes(), + line_program.encoding(), + line_strings, + ); + line_program.add_file(file_name, dir_id, None) + } + // FIXME give more appropriate file names + _ => { + let dir_id = line_program.default_directory(); + let dummy_file_name = LineString::new( + file.to_string().into_bytes(), + line_program.encoding(), + line_strings, + ); + line_program.add_file(dummy_file_name, dir_id, None) + } + } +} + +impl<'tcx> DebugContext<'tcx> { + pub(super) fn emit_location(&mut self, entry_id: UnitEntryId, span: Span) { + let loc = self.tcx.sess.source_map().lookup_char_pos(span.lo()); + + let file_id = line_program_add_file( + &mut self.dwarf.unit.line_program, + &mut self.dwarf.line_strings, + &loc.file.name, + ); + + let entry = self.dwarf.unit.get_mut(entry_id); + + entry.set( + gimli::DW_AT_decl_file, + AttributeValue::FileIndex(Some(file_id)), + ); + entry.set( + gimli::DW_AT_decl_line, + AttributeValue::Udata(loc.line as u64), + ); + // FIXME: probably omit this + entry.set( + gimli::DW_AT_decl_column, + AttributeValue::Udata(loc.col.to_usize() as u64), + ); + } +} + +impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { + pub(crate) fn create_debug_lines( + &mut self, + context: &Context, + isa: &dyn cranelift::codegen::isa::TargetIsa, + source_info_set: &indexmap::IndexSet<(Span, mir::SourceScope)>, + ) { + let tcx = self.debug_context.tcx; + + let line_program = &mut self.debug_context.dwarf.unit.line_program; + + line_program.begin_sequence(Some(Address::Symbol { + symbol: self.symbol, + addend: 0, + })); + + let encinfo = isa.encoding_info(); + let func = &context.func; + let mut ebbs = func.layout.ebbs().collect::>(); + ebbs.sort_by_key(|ebb| func.offsets[*ebb]); // Ensure inst offsets always increase + + let line_strings = &mut self.debug_context.dwarf.line_strings; + let mut create_row_for_span = |line_program: &mut LineProgram, span: Span| { + let loc = tcx.sess.source_map().lookup_char_pos(span.lo()); + let file_id = line_program_add_file(line_program, line_strings, &loc.file.name); + + /*println!( + "srcloc {:>04X} {}:{}:{}", + line_program.row().address_offset, + file.display(), + loc.line, + loc.col.to_u32() + );*/ + + line_program.row().file = file_id; + line_program.row().line = loc.line as u64; + line_program.row().column = loc.col.to_u32() as u64 + 1; + line_program.generate_row(); + }; + + let mut end = 0; + for ebb in ebbs { + for (offset, inst, size) in func.inst_offsets(ebb, &encinfo) { + let srcloc = func.srclocs[inst]; + line_program.row().address_offset = offset as u64; + if !srcloc.is_default() { + let source_info = *source_info_set.get_index(srcloc.bits() as usize).unwrap(); + create_row_for_span(line_program, source_info.0); + } else { + create_row_for_span(line_program, self.mir.span); + } + end = offset + size; + } + } + + line_program.end_sequence(end as u64); + + let entry = self.debug_context.dwarf.unit.get_mut(self.entry_id); + entry.set( + gimli::DW_AT_low_pc, + AttributeValue::Address(Address::Symbol { symbol: self.symbol, addend: 0 }), + ); + entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(end as u64)); + + self.debug_context.emit_location(self.entry_id, self.mir.span); + + self.debug_context + .unit_range_list + .0 + .push(Range::StartLength { + begin: Address::Symbol { + symbol: self.symbol, + addend: 0, + }, + length: end as u64, + }); + } +} diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 3ab03a411..f710f90e7 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -1,15 +1,14 @@ mod emit; +mod line_info; use crate::prelude::*; -use syntax::source_map::FileName; - use cranelift::codegen::ir::{StackSlots, ValueLoc}; use cranelift::codegen::isa::RegUnit; use gimli::write::{ - self, Address, AttributeValue, DwarfUnit, Expression, FileId, LineProgram, LineString, - LineStringTable, Location, LocationList, Range, RangeList, UnitEntryId, Writer, + self, Address, AttributeValue, DwarfUnit, Expression, LineProgram, LineString, + Location, LocationList, RangeList, UnitEntryId, Writer, }; use gimli::{Encoding, Format, LineEncoding, Register, RunTimeEndian, X86_64}; @@ -24,40 +23,6 @@ fn target_endian(tcx: TyCtxt) -> RunTimeEndian { } } -fn line_program_add_file( - line_program: &mut LineProgram, - line_strings: &mut LineStringTable, - file: &FileName, -) -> FileId { - match file { - FileName::Real(path) => { - let dir_name = path.parent().unwrap().to_str().unwrap().as_bytes(); - let dir_id = if !dir_name.is_empty() { - let dir_name = LineString::new(dir_name, line_program.encoding(), line_strings); - line_program.add_directory(dir_name) - } else { - line_program.default_directory() - }; - let file_name = LineString::new( - path.file_name().unwrap().to_str().unwrap().as_bytes(), - line_program.encoding(), - line_strings, - ); - line_program.add_file(file_name, dir_id, None) - } - // FIXME give more appropriate file names - _ => { - let dir_id = line_program.default_directory(); - let dummy_file_name = LineString::new( - file.to_string().into_bytes(), - line_program.encoding(), - line_strings, - ); - line_program.add_file(dummy_file_name, dir_id, None) - } - } -} - pub struct DebugContext<'tcx> { tcx: TyCtxt<'tcx>, @@ -135,32 +100,6 @@ impl<'tcx> DebugContext<'tcx> { } } - fn emit_location(&mut self, entry_id: UnitEntryId, span: Span) { - let loc = self.tcx.sess.source_map().lookup_char_pos(span.lo()); - - let file_id = line_program_add_file( - &mut self.dwarf.unit.line_program, - &mut self.dwarf.line_strings, - &loc.file.name, - ); - - let entry = self.dwarf.unit.get_mut(entry_id); - - entry.set( - gimli::DW_AT_decl_file, - AttributeValue::FileIndex(Some(file_id)), - ); - entry.set( - gimli::DW_AT_decl_line, - AttributeValue::Udata(loc.line as u64), - ); - // FIXME: probably omit this - entry.set( - gimli::DW_AT_decl_column, - AttributeValue::Udata(loc.col.to_usize() as u64), - ); - } - fn dwarf_ty(&mut self, ty: Ty<'tcx>) -> UnitEntryId { if let Some(type_id) = self.types.get(ty) { return *type_id; @@ -248,13 +187,6 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { AttributeValue::StringRef(name_id), ); - entry.set( - gimli::DW_AT_low_pc, - AttributeValue::Address(Address::Symbol { symbol, addend: 0 }), - ); - - debug_context.emit_location(entry_id, mir.span); - FunctionDebugContext { debug_context, entry_id, @@ -305,58 +237,7 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { isa: &dyn cranelift::codegen::isa::TargetIsa, source_info_set: &indexmap::IndexSet<(Span, mir::SourceScope)>, ) { - let tcx = self.debug_context.tcx; - - let line_program = &mut self.debug_context.dwarf.unit.line_program; - - line_program.begin_sequence(Some(Address::Symbol { - symbol: self.symbol, - addend: 0, - })); - - let encinfo = isa.encoding_info(); - let func = &context.func; - let mut ebbs = func.layout.ebbs().collect::>(); - ebbs.sort_by_key(|ebb| func.offsets[*ebb]); // Ensure inst offsets always increase - - let line_strings = &mut self.debug_context.dwarf.line_strings; - let mut create_row_for_span = |line_program: &mut LineProgram, span: Span| { - let loc = tcx.sess.source_map().lookup_char_pos(span.lo()); - let file_id = line_program_add_file(line_program, line_strings, &loc.file.name); - - /*println!( - "srcloc {:>04X} {}:{}:{}", - line_program.row().address_offset, - file.display(), - loc.line, - loc.col.to_u32() - );*/ - - line_program.row().file = file_id; - line_program.row().line = loc.line as u64; - line_program.row().column = loc.col.to_u32() as u64 + 1; - line_program.generate_row(); - }; - - let mut end = 0; - for ebb in ebbs { - for (offset, inst, size) in func.inst_offsets(ebb, &encinfo) { - let srcloc = func.srclocs[inst]; - line_program.row().address_offset = offset as u64; - if !srcloc.is_default() { - let source_info = *source_info_set.get_index(srcloc.bits() as usize).unwrap(); - create_row_for_span(line_program, source_info.0); - } else { - create_row_for_span(line_program, self.mir.span); - } - end = offset + size; - } - } - - line_program.end_sequence(end as u64); - - let entry = self.debug_context.dwarf.unit.get_mut(self.entry_id); - entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(end as u64)); + self.create_debug_lines(context, isa, source_info_set); { let value_labels_ranges = context.build_value_labels_ranges(isa).unwrap(); @@ -391,17 +272,6 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { ); } } - - self.debug_context - .unit_range_list - .0 - .push(Range::StartLength { - begin: Address::Symbol { - symbol: self.symbol, - addend: 0, - }, - length: end as u64, - }); } } From c5c6ce87d239c0599c87e73481983b9ec6680cb1 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 12 Nov 2019 21:10:51 +0100 Subject: [PATCH 10/21] Small change --- src/debuginfo/line_info.rs | 15 ++++----------- src/debuginfo/mod.rs | 15 +++++++++++++-- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/debuginfo/line_info.rs b/src/debuginfo/line_info.rs index dc380c623..8eef76146 100644 --- a/src/debuginfo/line_info.rs +++ b/src/debuginfo/line_info.rs @@ -2,6 +2,8 @@ use crate::prelude::*; use syntax::source_map::FileName; +use cranelift::codegen::binemit::CodeOffset; + use gimli::write::{ Address, AttributeValue, FileId, LineProgram, LineString, LineStringTable, Range, UnitEntryId, @@ -75,7 +77,7 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { context: &Context, isa: &dyn cranelift::codegen::isa::TargetIsa, source_info_set: &indexmap::IndexSet<(Span, mir::SourceScope)>, - ) { + ) -> CodeOffset { let tcx = self.debug_context.tcx; let line_program = &mut self.debug_context.dwarf.unit.line_program; @@ -135,15 +137,6 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { self.debug_context.emit_location(self.entry_id, self.mir.span); - self.debug_context - .unit_range_list - .0 - .push(Range::StartLength { - begin: Address::Symbol { - symbol: self.symbol, - addend: 0, - }, - length: end as u64, - }); + end } } diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index f710f90e7..c62dad9c3 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -8,7 +8,7 @@ use cranelift::codegen::isa::RegUnit; use gimli::write::{ self, Address, AttributeValue, DwarfUnit, Expression, LineProgram, LineString, - Location, LocationList, RangeList, UnitEntryId, Writer, + Location, LocationList, Range, RangeList, UnitEntryId, Writer, }; use gimli::{Encoding, Format, LineEncoding, Register, RunTimeEndian, X86_64}; @@ -237,7 +237,18 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { isa: &dyn cranelift::codegen::isa::TargetIsa, source_info_set: &indexmap::IndexSet<(Span, mir::SourceScope)>, ) { - self.create_debug_lines(context, isa, source_info_set); + let end = self.create_debug_lines(context, isa, source_info_set); + + self.debug_context + .unit_range_list + .0 + .push(Range::StartLength { + begin: Address::Symbol { + symbol: self.symbol, + addend: 0, + }, + length: end as u64, + }); { let value_labels_ranges = context.build_value_labels_ranges(isa).unwrap(); From d8e9148c2e07be8c2d65d87d84a88e9fd5a63c39 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 12 Nov 2019 21:13:15 +0100 Subject: [PATCH 11/21] Rustfmt debuginfo --- src/debuginfo/line_info.rs | 11 +++-- src/debuginfo/mod.rs | 91 ++++++++++++++++++-------------------- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/src/debuginfo/line_info.rs b/src/debuginfo/line_info.rs index 8eef76146..174cf0b93 100644 --- a/src/debuginfo/line_info.rs +++ b/src/debuginfo/line_info.rs @@ -5,8 +5,7 @@ use syntax::source_map::FileName; use cranelift::codegen::binemit::CodeOffset; use gimli::write::{ - Address, AttributeValue, FileId, LineProgram, LineString, - LineStringTable, Range, UnitEntryId, + Address, AttributeValue, FileId, LineProgram, LineString, LineStringTable, Range, UnitEntryId, }; fn line_program_add_file( @@ -131,11 +130,15 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { let entry = self.debug_context.dwarf.unit.get_mut(self.entry_id); entry.set( gimli::DW_AT_low_pc, - AttributeValue::Address(Address::Symbol { symbol: self.symbol, addend: 0 }), + AttributeValue::Address(Address::Symbol { + symbol: self.symbol, + addend: 0, + }), ); entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(end as u64)); - self.debug_context.emit_location(self.entry_id, self.mir.span); + self.debug_context + .emit_location(self.entry_id, self.mir.span); end } diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index c62dad9c3..e8b3cbe36 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -7,8 +7,8 @@ use cranelift::codegen::ir::{StackSlots, ValueLoc}; use cranelift::codegen::isa::RegUnit; use gimli::write::{ - self, Address, AttributeValue, DwarfUnit, Expression, LineProgram, LineString, - Location, LocationList, Range, RangeList, UnitEntryId, Writer, + self, Address, AttributeValue, DwarfUnit, Expression, LineProgram, LineString, Location, + LocationList, Range, RangeList, UnitEntryId, Writer, }; use gimli::{Encoding, Format, LineEncoding, Register, RunTimeEndian, X86_64}; @@ -105,9 +105,7 @@ impl<'tcx> DebugContext<'tcx> { return *type_id; } - let new_entry = |dwarf: &mut DwarfUnit, tag| { - dwarf.unit.add(dwarf.unit.root(), tag) - }; + let new_entry = |dwarf: &mut DwarfUnit, tag| dwarf.unit.add(dwarf.unit.root(), tag); let primtive = |dwarf: &mut DwarfUnit, ate| { let type_id = new_entry(dwarf, gimli::DW_TAG_base_type); @@ -122,7 +120,11 @@ impl<'tcx> DebugContext<'tcx> { ty::Uint(_) => primtive(&mut self.dwarf, gimli::DW_ATE_unsigned), ty::Int(_) => primtive(&mut self.dwarf, gimli::DW_ATE_signed), ty::Float(_) => primtive(&mut self.dwarf, gimli::DW_ATE_float), - ty::Ref(_, pointee_ty, mutbl) | ty::RawPtr(ty::TypeAndMut { ty: pointee_ty, mutbl }) => { + ty::Ref(_, pointee_ty, mutbl) + | ty::RawPtr(ty::TypeAndMut { + ty: pointee_ty, + mutbl, + }) => { let type_id = new_entry(&mut self.dwarf, gimli::DW_TAG_pointer_type); // Ensure that type is inserted before recursing to avoid duplicates @@ -145,7 +147,10 @@ impl<'tcx> DebugContext<'tcx> { let type_entry = self.dwarf.unit.get_mut(type_id); type_entry.set(gimli::DW_AT_name, AttributeValue::String(name.into_bytes())); - type_entry.set(gimli::DW_AT_byte_size, AttributeValue::Udata(layout.size.bytes())); + type_entry.set( + gimli::DW_AT_byte_size, + AttributeValue::Udata(layout.size.bytes()), + ); self.types.insert(ty, type_id); @@ -219,14 +224,8 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { .add(self.entry_id, gimli::DW_TAG_variable); let var_entry = self.debug_context.dwarf.unit.get_mut(var_id); - var_entry.set( - gimli::DW_AT_name, - AttributeValue::String(name.into_bytes()), - ); - var_entry.set( - gimli::DW_AT_type, - AttributeValue::ThisUnitEntryRef(dw_ty), - ); + var_entry.set(gimli::DW_AT_name, AttributeValue::String(name.into_bytes())); + var_entry.set(gimli::DW_AT_type, AttributeValue::ThisUnitEntryRef(dw_ty)); var_id } @@ -250,38 +249,36 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { length: end as u64, }); - { - let value_labels_ranges = context.build_value_labels_ranges(isa).unwrap(); - - for (value_label, value_loc_ranges) in value_labels_ranges.iter() { - let var_id = self.define_local(mir::Local::from_u32(value_label.as_u32())); - - let loc_list = LocationList( - value_loc_ranges - .iter() - .map(|value_loc_range| { - Location::StartEnd { - begin: Address::Symbol { - symbol: self.symbol, - addend: i64::from(value_loc_range.start), - }, - end: Address::Symbol { - symbol: self.symbol, - addend: i64::from(value_loc_range.end), - }, - data: Expression(translate_loc(value_loc_range.loc, &context.func.stack_slots).unwrap()), - } - }) - .collect(), - ); - let loc_list_id = self.debug_context.dwarf.unit.locations.add(loc_list); - - let var_entry = self.debug_context.dwarf.unit.get_mut(var_id); - var_entry.set( - gimli::DW_AT_location, - AttributeValue::LocationListRef(loc_list_id), - ); - } + let value_labels_ranges = context.build_value_labels_ranges(isa).unwrap(); + + for (value_label, value_loc_ranges) in value_labels_ranges.iter() { + let var_id = self.define_local(mir::Local::from_u32(value_label.as_u32())); + + let loc_list = LocationList( + value_loc_ranges + .iter() + .map(|value_loc_range| Location::StartEnd { + begin: Address::Symbol { + symbol: self.symbol, + addend: i64::from(value_loc_range.start), + }, + end: Address::Symbol { + symbol: self.symbol, + addend: i64::from(value_loc_range.end), + }, + data: Expression( + translate_loc(value_loc_range.loc, &context.func.stack_slots).unwrap(), + ), + }) + .collect(), + ); + let loc_list_id = self.debug_context.dwarf.unit.locations.add(loc_list); + + let var_entry = self.debug_context.dwarf.unit.get_mut(var_id); + var_entry.set( + gimli::DW_AT_location, + AttributeValue::LocationListRef(loc_list_id), + ); } } } From 8edbbc45f7d2ec2d61a9a7a5d9b4d968810cbce6 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 12 Nov 2019 21:36:31 +0100 Subject: [PATCH 12/21] Implement local reading for locals on stack --- src/base.rs | 5 +-- src/debuginfo/line_info.rs | 2 +- src/debuginfo/mod.rs | 73 ++++++++++++++++++++++++-------------- 3 files changed, 50 insertions(+), 30 deletions(-) diff --git a/src/base.rs b/src/base.rs index ed587bf73..441d875ef 100644 --- a/src/base.rs +++ b/src/base.rs @@ -17,7 +17,7 @@ pub fn trans_fn<'clif, 'tcx, B: Backend + 'static>( let mut debug_context = cx .debug_context .as_mut() - .map(|debug_context| FunctionDebugContext::new(debug_context, instance, func_id, &name, &sig)); + .map(|debug_context| FunctionDebugContext::new(debug_context, instance, func_id, &name)); // Make FunctionBuilder let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig); @@ -61,6 +61,7 @@ pub fn trans_fn<'clif, 'tcx, B: Backend + 'static>( let instance = fx.instance; let clif_comments = fx.clif_comments; let source_info_set = fx.source_info_set; + let local_map = fx.local_map; #[cfg(debug_assertions)] crate::pretty_clif::write_clif_file(cx.tcx, "unopt", instance, &func, &clif_comments, None); @@ -92,7 +93,7 @@ pub fn trans_fn<'clif, 'tcx, B: Backend + 'static>( let isa = cx.module.isa(); debug_context .as_mut() - .map(|x| x.define(context, isa, &source_info_set)); + .map(|x| x.define(context, isa, &source_info_set, local_map)); // Clear context to make it usable for the next function context.clear(); diff --git a/src/debuginfo/line_info.rs b/src/debuginfo/line_info.rs index 174cf0b93..e64344bfe 100644 --- a/src/debuginfo/line_info.rs +++ b/src/debuginfo/line_info.rs @@ -5,7 +5,7 @@ use syntax::source_map::FileName; use cranelift::codegen::binemit::CodeOffset; use gimli::write::{ - Address, AttributeValue, FileId, LineProgram, LineString, LineStringTable, Range, UnitEntryId, + Address, AttributeValue, FileId, LineProgram, LineString, LineStringTable, UnitEntryId, }; fn line_program_add_file( diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index e8b3cbe36..1c1e5762b 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -172,7 +172,6 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { instance: Instance<'tcx>, func_id: FuncId, name: &str, - _sig: &Signature, ) -> Self { let mir = debug_context.tcx.instance_mir(instance.def); @@ -235,6 +234,7 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { context: &Context, isa: &dyn cranelift::codegen::isa::TargetIsa, source_info_set: &indexmap::IndexSet<(Span, mir::SourceScope)>, + local_map: HashMap>, ) { let end = self.create_debug_lines(context, isa, source_info_set); @@ -251,34 +251,53 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { let value_labels_ranges = context.build_value_labels_ranges(isa).unwrap(); - for (value_label, value_loc_ranges) in value_labels_ranges.iter() { - let var_id = self.define_local(mir::Local::from_u32(value_label.as_u32())); - - let loc_list = LocationList( - value_loc_ranges - .iter() - .map(|value_loc_range| Location::StartEnd { - begin: Address::Symbol { - symbol: self.symbol, - addend: i64::from(value_loc_range.start), - }, - end: Address::Symbol { - symbol: self.symbol, - addend: i64::from(value_loc_range.end), - }, - data: Expression( - translate_loc(value_loc_range.loc, &context.func.stack_slots).unwrap(), - ), - }) - .collect(), - ); - let loc_list_id = self.debug_context.dwarf.unit.locations.add(loc_list); + for (local, _local_decl) in self.mir.local_decls.iter_enumerated() { + let var_id = self.define_local(local); + let value_label = cranelift::codegen::ir::ValueLabel::from_u32(local.as_u32()); + + let location = match local_map[&local].inner() { + CPlaceInner::Var(_) => { + if let Some(value_loc_ranges) = value_labels_ranges.get(&value_label) { + let loc_list = LocationList( + value_loc_ranges + .iter() + .map(|value_loc_range| Location::StartEnd { + begin: Address::Symbol { + symbol: self.symbol, + addend: i64::from(value_loc_range.start), + }, + end: Address::Symbol { + symbol: self.symbol, + addend: i64::from(value_loc_range.end), + }, + data: Expression( + translate_loc(value_loc_range.loc, &context.func.stack_slots).unwrap(), + ), + }) + .collect(), + ); + let loc_list_id = self.debug_context.dwarf.unit.locations.add(loc_list); + + AttributeValue::LocationListRef(loc_list_id) + } else { + // FIXME set value labels for unused locals + + AttributeValue::Exprloc(Expression(vec![])) + } + } + CPlaceInner::Addr(_, _) => { + // FIXME implement this (used by arguments and returns) + + AttributeValue::Exprloc(Expression(vec![])) + } + CPlaceInner::Stack(stack_slot) => { + AttributeValue::Exprloc(Expression(translate_loc(ValueLoc::Stack(*stack_slot), &context.func.stack_slots).unwrap())) + } + CPlaceInner::NoPlace => AttributeValue::Exprloc(Expression(vec![])), + }; let var_entry = self.debug_context.dwarf.unit.get_mut(var_id); - var_entry.set( - gimli::DW_AT_location, - AttributeValue::LocationListRef(loc_list_id), - ); + var_entry.set(gimli::DW_AT_location, location); } } } From 4826320680e2b5545f1920f2a6209fbffc9b0547 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 16 Dec 2019 12:06:52 +0100 Subject: [PATCH 13/21] Add debuginfo test --- test.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test.sh b/test.sh index 05ba16ea3..cae3955e5 100755 --- a/test.sh +++ b/test.sh @@ -31,11 +31,16 @@ $RUSTC example/mini_core.rs --crate-name mini_core --crate-type lib,dylib echo "[BUILD] example" $RUSTC example/example.rs --crate-type lib -JIT_ARGS="abc bcd" jit mini_core_hello_world example/mini_core_hello_world.rs +#JIT_ARGS="abc bcd" jit mini_core_hello_world example/mini_core_hello_world.rs echo "[AOT] mini_core_hello_world" -$RUSTC example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin +$RUSTC example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g ./target/out/mini_core_hello_world abc bcd +if lldb -v; then +(echo "break set -n main"; echo "run"; sleep 1; echo "si -c 21"; sleep 1; echo "frame variable") | lldb -- ./target/out/mini_core_hello_world abc bcd +fi + +exit 1 echo "[AOT] arbitrary_self_types_pointers_and_wrappers" $RUSTC example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin From 0244d19ebbc286940cb454769394637b50d9c73b Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 15 Nov 2019 21:07:18 +0100 Subject: [PATCH 14/21] Fix translate_loc for ValueLoc::Stack --- src/debuginfo/mod.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 1c1e5762b..59c5c9ac1 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -375,9 +375,6 @@ fn translate_loc(loc: ValueLoc, stack_slots: &StackSlots) -> Option> { .write_u8(gimli::constants::DW_OP_breg0.0 + X86_64::RBP.0 as u8) .expect("bp wr"); writer.write_sleb128(ss_offset as i64 + 16).expect("ss wr"); - writer - .write_u8(gimli::constants::DW_OP_deref.0 as u8) - .expect("bp wr"); let buf = writer.into_vec(); return Some(buf); } From ab7ad2caebff43356df1b2060021945dfc6ced4e Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 15 Nov 2019 21:07:54 +0100 Subject: [PATCH 15/21] Use set_val_label before every def_var --- src/intrinsics.rs | 2 ++ src/value_and_place.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/src/intrinsics.rs b/src/intrinsics.rs index 4ad6ae91f..840b4bf0d 100644 --- a/src/intrinsics.rs +++ b/src/intrinsics.rs @@ -625,6 +625,7 @@ pub fn codegen_intrinsic_call<'tcx>( } _ => panic!("clif_type returned {}", clif_ty), }; + fx.bcx.set_val_label(val, cranelift::codegen::ir::ValueLabel::from_u32(var.as_u32())); fx.bcx.def_var(mir_var(var), val); } _ => { @@ -656,6 +657,7 @@ pub fn codegen_intrinsic_call<'tcx>( } _ => panic!("clif_type returned {}", clif_ty), }; + fx.bcx.set_val_label(val, cranelift::codegen::ir::ValueLabel::from_u32(var.as_u32())); fx.bcx.def_var(mir_var(var), val); } CPlaceInner::Addr(_, _) | CPlaceInner::Stack(_) => { diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 8016a802d..64fd30def 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -423,6 +423,7 @@ impl<'tcx> CPlace<'tcx> { let addr = match self.inner { CPlaceInner::Var(var) => { let data = from.load_scalar(fx); + fx.bcx.set_val_label(data, cranelift::codegen::ir::ValueLabel::from_u32(var.as_u32())); fx.bcx.def_var(mir_var(var), data); return; } From 08217d1bdeaa9de9d72f718036ca5ac93e4a5c4e Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 15 Nov 2019 21:32:52 +0100 Subject: [PATCH 16/21] Emit DW_TAG_structure_type including fields for structs --- src/debuginfo/mod.rs | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 59c5c9ac1..c636906af 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -107,19 +107,22 @@ impl<'tcx> DebugContext<'tcx> { let new_entry = |dwarf: &mut DwarfUnit, tag| dwarf.unit.add(dwarf.unit.root(), tag); - let primtive = |dwarf: &mut DwarfUnit, ate| { + let primitive = |dwarf: &mut DwarfUnit, ate| { let type_id = new_entry(dwarf, gimli::DW_TAG_base_type); let type_entry = dwarf.unit.get_mut(type_id); type_entry.set(gimli::DW_AT_encoding, AttributeValue::Encoding(ate)); type_id }; + let name = format!("{}", ty); + let layout = self.tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap(); + let type_id = match ty.kind { - ty::Bool => primtive(&mut self.dwarf, gimli::DW_ATE_boolean), - ty::Char => primtive(&mut self.dwarf, gimli::DW_ATE_UTF), - ty::Uint(_) => primtive(&mut self.dwarf, gimli::DW_ATE_unsigned), - ty::Int(_) => primtive(&mut self.dwarf, gimli::DW_ATE_signed), - ty::Float(_) => primtive(&mut self.dwarf, gimli::DW_ATE_float), + ty::Bool => primitive(&mut self.dwarf, gimli::DW_ATE_boolean), + ty::Char => primitive(&mut self.dwarf, gimli::DW_ATE_UTF), + ty::Uint(_) => primitive(&mut self.dwarf, gimli::DW_ATE_unsigned), + ty::Int(_) => primitive(&mut self.dwarf, gimli::DW_ATE_signed), + ty::Float(_) => primitive(&mut self.dwarf, gimli::DW_ATE_float), ty::Ref(_, pointee_ty, mutbl) | ty::RawPtr(ty::TypeAndMut { ty: pointee_ty, @@ -139,10 +142,35 @@ impl<'tcx> DebugContext<'tcx> { type_id } + ty::Adt(adt_def, _substs) if adt_def.is_struct() && !layout.is_unsized() => { + let type_id = new_entry(&mut self.dwarf, gimli::DW_TAG_structure_type); + + // Ensure that type is inserted before recursing to avoid duplicates + self.types.insert(ty, type_id); + + let variant = adt_def.non_enum_variant(); + + for (field_idx, field_def) in variant.fields.iter().enumerate() { + let field_offset = layout.fields.offset(field_idx); + let field_layout = layout.field(&layout::LayoutCx { + tcx: self.tcx, + param_env: ParamEnv::reveal_all(), + }, field_idx).unwrap(); + + let field_type = self.dwarf_ty(field_layout.ty); + + let field_id = self.dwarf.unit.add(type_id, gimli::DW_TAG_member); + let field_entry = self.dwarf.unit.get_mut(field_id); + + field_entry.set(gimli::DW_AT_name, AttributeValue::String(field_def.ident.as_str().to_string().into_bytes())); + field_entry.set(gimli::DW_AT_data_member_location, AttributeValue::Udata(field_offset.bytes())); + field_entry.set(gimli::DW_AT_type, AttributeValue::ThisUnitEntryRef(field_type)); + } + + type_id + } _ => new_entry(&mut self.dwarf, gimli::DW_TAG_structure_type), }; - let name = format!("{}", ty); - let layout = self.tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap(); let type_entry = self.dwarf.unit.get_mut(type_id); From c84ff8504a6a6ba630abc7f67dad2552f1984006 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 15 Nov 2019 21:58:47 +0100 Subject: [PATCH 17/21] Change test script --- test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test.sh b/test.sh index cae3955e5..7c7803af0 100755 --- a/test.sh +++ b/test.sh @@ -37,7 +37,7 @@ echo "[AOT] mini_core_hello_world" $RUSTC example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g ./target/out/mini_core_hello_world abc bcd if lldb -v; then -(echo "break set -n main"; echo "run"; sleep 1; echo "si -c 21"; sleep 1; echo "frame variable") | lldb -- ./target/out/mini_core_hello_world abc bcd +(echo "break set -n main"; echo "run"; sleep 1; echo "si -c 35"; sleep 1; echo "frame variable") | lldb -- ./target/out/mini_core_hello_world abc bcd fi exit 1 From b86eb2e8ba3f442a2168406fc75e1f41cdc9ccc7 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 28 Nov 2019 20:34:55 +0100 Subject: [PATCH 18/21] Some optimizations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Only format global _comments when debug_assertions are enabled * Only call build_value_labels_ranges in base.rs when debug_assertions are enabled Benchmark #1: CHANNEL='pre' ../cargo.sh build Time (mean ± σ): 17.657 s ± 1.050 s [User: 31.871 s, System: 3.014 s] Range (min … max): 16.907 s … 20.394 s 10 runs Benchmark #2: ../cargo.sh build Time (mean ± σ): 16.640 s ± 0.255 s [User: 30.238 s, System: 2.965 s] Range (min … max): 16.413 s … 17.186 s 10 runs Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet PC without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options. Summary '../cargo.sh build' ran 1.06 ± 0.07 times faster than 'CHANNEL='pre' ../cargo.sh build' --- src/base.rs | 26 ++++++++++++++------------ src/pretty_clif.rs | 12 +++++++++--- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/base.rs b/src/base.rs index 441d875ef..243852f1d 100644 --- a/src/base.rs +++ b/src/base.rs @@ -74,20 +74,22 @@ pub fn trans_fn<'clif, 'tcx, B: Backend + 'static>( context.func = func; cx.module.define_function(func_id, context).unwrap(); - let value_ranges = context - .build_value_labels_ranges(cx.module.isa()) - .expect("value location ranges"); - // Write optimized function to file for debugging #[cfg(debug_assertions)] - crate::pretty_clif::write_clif_file( - cx.tcx, - "opt", - instance, - &context.func, - &clif_comments, - Some(&value_ranges), - ); + { + let value_ranges = context + .build_value_labels_ranges(cx.module.isa()) + .expect("value location ranges"); + + crate::pretty_clif::write_clif_file( + cx.tcx, + "opt", + instance, + &context.func, + &clif_comments, + Some(&value_ranges), + ); + } // Define debuginfo for function let isa = cx.module.isa(); diff --git a/src/pretty_clif.rs b/src/pretty_clif.rs index f595d384f..64359f389 100644 --- a/src/pretty_clif.rs +++ b/src/pretty_clif.rs @@ -74,8 +74,8 @@ pub struct CommentWriter { impl CommentWriter { pub fn new<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { - CommentWriter { - global_comments: vec![ + let mut global_comments = if cfg!(debug_assertions) { + vec![ format!("symbol {}", tcx.symbol_name(instance).name.as_str()), format!("instance {:?}", instance), format!( @@ -86,7 +86,13 @@ impl CommentWriter { ) ), String::new(), - ], + ] + } else { + vec![] + }; + + CommentWriter { + global_comments, entity_comments: HashMap::new(), inst_comments: HashMap::new(), } From 7a4fe12d31a72d956a63f69bf945f7e9e5898e52 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 28 Nov 2019 21:35:03 +0100 Subject: [PATCH 19/21] Rustup to rustc 1.41.0-nightly (e87a205c2 2019-11-27) --- src/debuginfo/mod.rs | 126 ++++++++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 54 deletions(-) diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index c636906af..50cae4d46 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -3,8 +3,9 @@ mod line_info; use crate::prelude::*; -use cranelift::codegen::ir::{StackSlots, ValueLoc}; +use cranelift::codegen::ir::{StackSlots, ValueLabel, ValueLoc}; use cranelift::codegen::isa::RegUnit; +use cranelift::codegen::ValueLocRange; use gimli::write::{ self, Address, AttributeValue, DwarfUnit, Expression, LineProgram, LineString, Location, @@ -228,22 +229,14 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { } } - fn define_local(&mut self, local: mir::Local) -> UnitEntryId { - let local_decl = &self.mir.local_decls[local]; - + fn define_local(&mut self, name: String, ty: Ty<'tcx>) -> UnitEntryId { let ty = self.debug_context.tcx.subst_and_normalize_erasing_regions( self.instance.substs, ty::ParamEnv::reveal_all(), - &local_decl.ty, + &ty, ); let dw_ty = self.debug_context.dwarf_ty(ty); - let name = if let Some(name) = local_decl.name { - format!("{}{:?}", name.as_str(), local) - } else { - format!("{:?}", local) - }; - let var_id = self .debug_context .dwarf @@ -280,57 +273,82 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { let value_labels_ranges = context.build_value_labels_ranges(isa).unwrap(); for (local, _local_decl) in self.mir.local_decls.iter_enumerated() { - let var_id = self.define_local(local); - let value_label = cranelift::codegen::ir::ValueLabel::from_u32(local.as_u32()); - - let location = match local_map[&local].inner() { - CPlaceInner::Var(_) => { - if let Some(value_loc_ranges) = value_labels_ranges.get(&value_label) { - let loc_list = LocationList( - value_loc_ranges - .iter() - .map(|value_loc_range| Location::StartEnd { - begin: Address::Symbol { - symbol: self.symbol, - addend: i64::from(value_loc_range.start), - }, - end: Address::Symbol { - symbol: self.symbol, - addend: i64::from(value_loc_range.end), - }, - data: Expression( - translate_loc(value_loc_range.loc, &context.func.stack_slots).unwrap(), - ), - }) - .collect(), - ); - let loc_list_id = self.debug_context.dwarf.unit.locations.add(loc_list); - - AttributeValue::LocationListRef(loc_list_id) - } else { - // FIXME set value labels for unused locals - - AttributeValue::Exprloc(Expression(vec![])) - } - } - CPlaceInner::Addr(_, _) => { - // FIXME implement this (used by arguments and returns) - - AttributeValue::Exprloc(Expression(vec![])) - } - CPlaceInner::Stack(stack_slot) => { - AttributeValue::Exprloc(Expression(translate_loc(ValueLoc::Stack(*stack_slot), &context.func.stack_slots).unwrap())) - } - CPlaceInner::NoPlace => AttributeValue::Exprloc(Expression(vec![])), - }; + let var_id = self.define_local(format!("{:?}", local), &self.mir.local_decls[local].ty); + + let location = place_location( + self, + context, + &local_map, + &value_labels_ranges, + Place { + base: PlaceBase::Local(local), + projection: ty::List::empty(), + }, + ); let var_entry = self.debug_context.dwarf.unit.get_mut(var_id); var_entry.set(gimli::DW_AT_location, location); } + + // FIXME create locals for all entries in mir.var_debug_info } } +fn place_location<'a, 'tcx>( + func_debug_ctx: &mut FunctionDebugContext<'a, 'tcx>, + context: &Context, + local_map: &HashMap>, + value_labels_ranges: &HashMap>, + place: Place<'tcx>, +) -> AttributeValue { + assert!(place.projection.is_empty()); // FIXME implement them + let cplace = match place.base { + PlaceBase::Local(local) => local_map[&local], + PlaceBase::Static(_) => bug!("Unenforced invariant that the place is based on a Local violated: {:?}", place), + }; + + match cplace.inner() { + CPlaceInner::Var(local) => { + let value_label = cranelift::codegen::ir::ValueLabel::from_u32(local.as_u32()); + if let Some(value_loc_ranges) = value_labels_ranges.get(&value_label) { + let loc_list = LocationList( + value_loc_ranges + .iter() + .map(|value_loc_range| Location::StartEnd { + begin: Address::Symbol { + symbol: func_debug_ctx.symbol, + addend: i64::from(value_loc_range.start), + }, + end: Address::Symbol { + symbol: func_debug_ctx.symbol, + addend: i64::from(value_loc_range.end), + }, + data: Expression( + translate_loc(value_loc_range.loc, &context.func.stack_slots).unwrap(), + ), + }) + .collect(), + ); + let loc_list_id = func_debug_ctx.debug_context.dwarf.unit.locations.add(loc_list); + + AttributeValue::LocationListRef(loc_list_id) + } else { + // FIXME set value labels for unused locals + + AttributeValue::Exprloc(Expression(vec![])) + } + } + CPlaceInner::Addr(_, _) => { + // FIXME implement this (used by arguments and returns) + AttributeValue::Exprloc(Expression(vec![])) + } + CPlaceInner::Stack(stack_slot) => { + AttributeValue::Exprloc(Expression(translate_loc(ValueLoc::Stack(*stack_slot), &context.func.stack_slots).unwrap())) + } + CPlaceInner::NoPlace => AttributeValue::Exprloc(Expression(vec![])), + } +} From 74ca55d23091565444ce64fe4c8dbd6fc0783f56 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 16 Dec 2019 12:11:14 +0100 Subject: [PATCH 20/21] Rustup --- src/debuginfo/mod.rs | 2 +- test.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 50cae4d46..9e04566a2 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -202,7 +202,7 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { func_id: FuncId, name: &str, ) -> Self { - let mir = debug_context.tcx.instance_mir(instance.def); + let mir = *debug_context.tcx.instance_mir(instance.def); let (symbol, _) = debug_context.symbols.insert_full(func_id, name.to_string()); diff --git a/test.sh b/test.sh index 7c7803af0..4f393ad17 100755 --- a/test.sh +++ b/test.sh @@ -37,7 +37,7 @@ echo "[AOT] mini_core_hello_world" $RUSTC example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g ./target/out/mini_core_hello_world abc bcd if lldb -v; then -(echo "break set -n main"; echo "run"; sleep 1; echo "si -c 35"; sleep 1; echo "frame variable") | lldb -- ./target/out/mini_core_hello_world abc bcd +(echo "break set -n main"; echo "run"; sleep 1; echo "si -c 10"; sleep 1; echo "frame variable") | lldb -- ./target/out/mini_core_hello_world abc bcd fi exit 1 From beda104a2b828616ce5691577bf0d8750c641ce0 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 16 Dec 2019 12:12:51 +0100 Subject: [PATCH 21/21] Disable local debuginfo for now --- src/debuginfo/mod.rs | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 9e04566a2..bb3f26f9f 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -270,24 +270,27 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> { length: end as u64, }); - let value_labels_ranges = context.build_value_labels_ranges(isa).unwrap(); - - for (local, _local_decl) in self.mir.local_decls.iter_enumerated() { - let var_id = self.define_local(format!("{:?}", local), &self.mir.local_decls[local].ty); - - let location = place_location( - self, - context, - &local_map, - &value_labels_ranges, - Place { - base: PlaceBase::Local(local), - projection: ty::List::empty(), - }, - ); + // FIXME make it more reliable and implement scopes before re-enabling this. + if false { + let value_labels_ranges = context.build_value_labels_ranges(isa).unwrap(); + + for (local, _local_decl) in self.mir.local_decls.iter_enumerated() { + let var_id = self.define_local(format!("{:?}", local), &self.mir.local_decls[local].ty); + + let location = place_location( + self, + context, + &local_map, + &value_labels_ranges, + Place { + base: PlaceBase::Local(local), + projection: ty::List::empty(), + }, + ); - let var_entry = self.debug_context.dwarf.unit.get_mut(var_id); - var_entry.set(gimli::DW_AT_location, location); + let var_entry = self.debug_context.dwarf.unit.get_mut(var_id); + var_entry.set(gimli::DW_AT_location, location); + } } // FIXME create locals for all entries in mir.var_debug_info