2020-09-23 15:13:49 +02:00
//! Handling of everything related to debuginfo.
2019-11-12 20:52:32 +01:00
mod emit ;
2019-11-12 21:08:08 +01:00
mod line_info ;
2020-04-25 18:23:31 +02:00
mod unwind ;
2019-01-17 18:07:27 +01:00
2019-11-12 20:52:32 +01:00
use crate ::prelude ::* ;
2019-10-16 21:21:20 +02:00
2020-09-16 18:45:19 +02:00
use rustc_index ::vec ::IndexVec ;
2020-06-27 11:58:44 +02:00
use cranelift_codegen ::entity ::EntityRef ;
2019-12-24 12:40:18 +01:00
use cranelift_codegen ::ir ::{ StackSlots , ValueLabel , ValueLoc } ;
2020-04-01 14:12:46 +02:00
use cranelift_codegen ::isa ::TargetIsa ;
2019-12-24 12:40:18 +01:00
use cranelift_codegen ::ValueLocRange ;
2019-11-11 21:43:57 +01:00
2019-01-17 18:07:27 +01:00
use gimli ::write ::{
2020-08-28 12:10:48 +02:00
Address , AttributeValue , DwarfUnit , Expression , LineProgram , LineString , Location ,
LocationList , Range , RangeList , UnitEntryId ,
2019-01-17 18:07:27 +01:00
} ;
2020-04-01 14:12:46 +02:00
use gimli ::{ Encoding , Format , LineEncoding , RunTimeEndian , X86_64 } ;
2019-11-12 20:52:32 +01:00
2020-03-27 12:14:45 +01:00
pub ( crate ) use emit ::{ DebugReloc , DebugRelocName } ;
2020-05-01 19:21:29 +02:00
pub ( crate ) use unwind ::UnwindContext ;
2019-01-17 18:07:27 +01:00
2020-04-05 13:48:26 +02:00
fn target_endian ( tcx : TyCtxt < '_ > ) -> RunTimeEndian {
2020-04-03 11:54:18 +02:00
use rustc_target ::abi ::Endian ;
2019-01-17 18:07:27 +01:00
match tcx . data_layout . endian {
Endian ::Big = > RunTimeEndian ::Big ,
Endian ::Little = > RunTimeEndian ::Little ,
}
}
2019-01-19 12:07:42 +01:00
2020-03-27 12:14:45 +01:00
pub ( crate ) struct DebugContext < ' tcx > {
2019-11-09 18:40:11 +01:00
tcx : TyCtxt < ' tcx > ,
2019-01-17 18:07:27 +01:00
endian : RunTimeEndian ,
2019-01-19 12:18:39 +01:00
2019-02-09 17:15:15 +10:00
dwarf : DwarfUnit ,
2019-01-19 12:00:51 +01:00
unit_range_list : RangeList ,
2019-01-17 18:07:27 +01:00
2020-04-22 14:48:56 +02:00
clif_types : FxHashMap < Type , UnitEntryId > ,
2020-04-05 14:01:02 +02:00
types : FxHashMap < Ty < ' tcx > , UnitEntryId > ,
2019-01-17 18:07:27 +01:00
}
2019-06-16 11:13:49 +02:00
impl < ' tcx > DebugContext < ' tcx > {
2020-04-25 18:23:31 +02:00
pub ( crate ) fn new ( tcx : TyCtxt < ' tcx > , isa : & dyn TargetIsa ) -> Self {
2019-01-26 12:37:49 +01:00
let encoding = Encoding {
format : Format ::Dwarf32 ,
// TODO: this should be configurable
// macOS doesn't seem to support DWARF > 3
2020-04-18 14:56:04 +03:00
// 5 version is required for md5 file hash
2020-11-08 14:27:51 +03:00
version : if tcx . sess . target . is_like_osx {
2020-04-18 16:05:20 +03:00
3
} else {
2020-04-21 12:13:50 +02:00
// FIXME change to version 5 once the gdb and lldb shipping with the latest debian
// support it.
4
2020-04-18 16:05:20 +03:00
} ,
2020-04-25 18:23:31 +02:00
address_size : isa . frontend_config ( ) . pointer_bytes ( ) ,
2019-01-26 12:37:49 +01:00
} ;
2019-01-17 18:07:27 +01:00
2019-02-09 17:15:15 +10:00
let mut dwarf = DwarfUnit ::new ( encoding ) ;
2019-01-17 18:07:27 +01:00
// FIXME: how to get version when building out of tree?
// Normally this would use option_env!("CFG_VERSION").
2020-03-21 16:52:02 +01:00
let producer = format! ( " cg_clif (rustc {} ) " , " unknown version " ) ;
2019-01-17 18:07:27 +01:00
let comp_dir = tcx . sess . working_dir . 0. to_string_lossy ( ) . into_owned ( ) ;
2020-04-18 17:43:00 +03:00
let ( name , file_info ) = match tcx . sess . local_crate_source_file . clone ( ) {
2020-04-18 14:56:04 +03:00
Some ( path ) = > {
let name = path . to_string_lossy ( ) . into_owned ( ) ;
2020-06-04 19:57:12 +02:00
( name , None )
2020-08-28 12:10:48 +02:00
}
2020-04-18 14:56:04 +03:00
None = > ( tcx . crate_name ( LOCAL_CRATE ) . to_string ( ) , None ) ,
2019-01-17 18:07:27 +01:00
} ;
2020-04-18 14:56:04 +03:00
let mut line_program = LineProgram ::new (
2019-01-26 12:37:49 +01:00
encoding ,
2019-02-18 18:32:40 +01:00
LineEncoding ::default ( ) ,
2019-02-09 17:15:15 +10:00
LineString ::new ( comp_dir . as_bytes ( ) , encoding , & mut dwarf . line_strings ) ,
LineString ::new ( name . as_bytes ( ) , encoding , & mut dwarf . line_strings ) ,
2020-04-18 17:43:00 +03:00
file_info ,
2019-02-09 17:15:15 +10:00
) ;
2020-04-18 17:43:00 +03:00
line_program . file_has_md5 = file_info . is_some ( ) ;
2020-04-18 14:56:04 +03:00
2019-02-09 17:15:15 +10:00
dwarf . unit . line_program = line_program ;
2019-01-17 18:07:27 +01:00
{
2020-03-07 11:27:49 +01:00
let name = dwarf . strings . add ( name ) ;
let comp_dir = dwarf . strings . add ( comp_dir ) ;
2019-01-17 18:07:27 +01:00
2019-02-09 17:15:15 +10:00
let root = dwarf . unit . root ( ) ;
let root = dwarf . unit . get_mut ( root ) ;
2019-01-17 18:07:27 +01:00
root . set (
gimli ::DW_AT_producer ,
2019-02-09 17:15:15 +10:00
AttributeValue ::StringRef ( dwarf . strings . add ( producer ) ) ,
2019-01-17 18:07:27 +01:00
) ;
root . set (
gimli ::DW_AT_language ,
AttributeValue ::Language ( gimli ::DW_LANG_Rust ) ,
) ;
root . set ( gimli ::DW_AT_name , AttributeValue ::StringRef ( name ) ) ;
root . set ( gimli ::DW_AT_comp_dir , AttributeValue ::StringRef ( comp_dir ) ) ;
root . set (
gimli ::DW_AT_low_pc ,
2019-05-04 16:20:43 +02:00
AttributeValue ::Address ( Address ::Constant ( 0 ) ) ,
2019-01-17 18:07:27 +01:00
) ;
}
2019-02-21 15:06:09 +01:00
DebugContext {
2019-11-09 18:40:11 +01:00
tcx ,
2019-01-17 18:07:27 +01:00
endian : target_endian ( tcx ) ,
2019-01-19 12:18:39 +01:00
2019-02-09 17:15:15 +10:00
dwarf ,
2019-01-19 12:00:51 +01:00
unit_range_list : RangeList ( Vec ::new ( ) ) ,
2019-01-19 12:18:39 +01:00
2020-04-22 14:48:56 +02:00
clif_types : FxHashMap ::default ( ) ,
2020-04-05 14:01:02 +02:00
types : FxHashMap ::default ( ) ,
2019-01-17 18:07:27 +01:00
}
}
2020-04-22 14:48:56 +02:00
fn dwarf_ty_for_clif_ty ( & mut self , ty : Type ) -> UnitEntryId {
if let Some ( type_id ) = self . clif_types . get ( & ty ) {
return * type_id ;
}
let new_entry = | dwarf : & mut DwarfUnit , tag | dwarf . unit . add ( dwarf . unit . root ( ) , tag ) ;
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 type_id = if ty . is_bool ( ) {
primitive ( & mut self . dwarf , gimli ::DW_ATE_boolean )
} else if ty . is_int ( ) {
primitive ( & mut self . dwarf , gimli ::DW_ATE_address )
} else if ty . is_float ( ) {
primitive ( & mut self . dwarf , gimli ::DW_ATE_float )
} else {
new_entry ( & mut self . dwarf , gimli ::DW_TAG_structure_type )
} ;
let type_entry = self . dwarf . unit . get_mut ( type_id ) ;
2020-08-28 12:10:48 +02:00
type_entry . set (
gimli ::DW_AT_name ,
AttributeValue ::String ( format! ( " {} " , ty ) . replace ( 'i' , " u " ) . into_bytes ( ) ) ,
) ;
2020-04-22 14:48:56 +02:00
type_entry . set (
gimli ::DW_AT_byte_size ,
AttributeValue ::Udata ( u64 ::from ( ty . bytes ( ) ) ) ,
) ;
type_id
}
2019-11-09 18:40:11 +01:00
fn dwarf_ty ( & mut self , ty : Ty < ' tcx > ) -> UnitEntryId {
if let Some ( type_id ) = self . types . get ( ty ) {
return * type_id ;
}
2019-11-12 21:13:15 +01:00
let new_entry = | dwarf : & mut DwarfUnit , tag | dwarf . unit . add ( dwarf . unit . root ( ) , tag ) ;
2019-11-09 18:40:11 +01:00
2019-11-15 21:32:52 +01:00
let primitive = | dwarf : & mut DwarfUnit , ate | {
2019-11-09 18:40:11 +01:00
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
} ;
2019-11-15 21:32:52 +01:00
let name = format! ( " {} " , ty ) ;
let layout = self . tcx . layout_of ( ParamEnv ::reveal_all ( ) . and ( ty ) ) . unwrap ( ) ;
2020-09-05 10:38:49 +02:00
let type_id = match ty . kind ( ) {
2019-11-15 21:32:52 +01:00
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 ) ,
2020-02-22 15:17:30 +01:00
ty ::Ref ( _ , pointee_ty , _mutbl )
2019-11-12 21:13:15 +01:00
| ty ::RawPtr ( ty ::TypeAndMut {
ty : pointee_ty ,
2020-02-22 15:17:30 +01:00
mutbl : _mutbl ,
2019-11-12 21:13:15 +01:00
} ) = > {
2019-11-09 18:40:11 +01:00
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 ) ;
2020-01-09 17:43:10 +01:00
//type_entry.set(gimli::DW_AT_mutable, AttributeValue::Flag(mutbl == rustc_hir::Mutability::Mut));
2020-06-05 12:40:33 +02:00
type_entry . set ( gimli ::DW_AT_type , AttributeValue ::UnitRef ( pointee ) ) ;
2019-11-09 18:40:11 +01:00
type_id
}
2019-11-15 21:32:52 +01:00
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 ) ;
2020-08-28 12:10:48 +02:00
let field_layout = layout
. field (
& layout ::LayoutCx {
tcx : self . tcx ,
param_env : ParamEnv ::reveal_all ( ) ,
} ,
field_idx ,
)
. unwrap ( ) ;
2019-11-15 21:32:52 +01:00
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 ) ;
2020-08-28 12:10:48 +02:00
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 ( ) ) ,
) ;
2020-06-05 12:40:33 +02:00
field_entry . set ( gimli ::DW_AT_type , AttributeValue ::UnitRef ( field_type ) ) ;
2019-11-15 21:32:52 +01:00
}
type_id
}
2019-11-09 18:40:11 +01:00
_ = > new_entry ( & mut self . dwarf , gimli ::DW_TAG_structure_type ) ,
} ;
let type_entry = self . dwarf . unit . get_mut ( type_id ) ;
type_entry . set ( gimli ::DW_AT_name , AttributeValue ::String ( name . into_bytes ( ) ) ) ;
2019-11-12 21:13:15 +01:00
type_entry . set (
gimli ::DW_AT_byte_size ,
AttributeValue ::Udata ( layout . size . bytes ( ) ) ,
) ;
2019-11-09 18:40:11 +01:00
self . types . insert ( ty , type_id ) ;
type_id
}
2019-01-17 18:07:27 +01:00
2020-06-13 17:03:34 +02:00
fn define_local ( & mut self , scope : UnitEntryId , name : String , ty : Ty < ' tcx > ) -> UnitEntryId {
let dw_ty = self . dwarf_ty ( ty ) ;
2020-08-28 12:10:48 +02:00
let var_id = self . dwarf . unit . add ( scope , gimli ::DW_TAG_variable ) ;
2020-06-13 17:03:34 +02:00
let var_entry = self . 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 ::UnitRef ( dw_ty ) ) ;
2019-01-17 18:07:27 +01:00
2020-06-13 17:03:34 +02:00
var_id
}
pub ( crate ) fn define_function (
& mut self ,
2019-11-11 20:49:20 +01:00
instance : Instance < ' tcx > ,
2019-10-16 21:21:20 +02:00
func_id : FuncId ,
2019-01-17 18:07:27 +01:00
name : & str ,
2020-06-13 17:03:34 +02:00
isa : & dyn TargetIsa ,
context : & Context ,
source_info_set : & indexmap ::IndexSet < SourceInfo > ,
2020-09-16 18:45:19 +02:00
local_map : IndexVec < mir ::Local , CPlace < ' tcx > > ,
2020-06-13 17:03:34 +02:00
) {
let symbol = func_id . as_u32 ( ) as usize ;
let mir = self . tcx . instance_mir ( instance . def ) ;
2019-11-11 20:49:20 +01:00
2020-06-13 17:03:34 +02:00
// FIXME: add to appropriate scope instead of root
let scope = self . dwarf . unit . root ( ) ;
2019-01-17 18:07:27 +01:00
2020-08-28 12:10:48 +02:00
let entry_id = self . dwarf . unit . add ( scope , gimli ::DW_TAG_subprogram ) ;
2020-06-13 17:03:34 +02:00
let entry = self . dwarf . unit . get_mut ( entry_id ) ;
let name_id = self . dwarf . strings . add ( name ) ;
2020-04-23 16:44:12 +02:00
// Gdb requires DW_AT_name. Otherwise the DW_TAG_subprogram is skipped.
2020-08-28 12:10:48 +02:00
entry . set ( gimli ::DW_AT_name , AttributeValue ::StringRef ( name_id ) ) ;
2019-01-17 18:07:27 +01:00
entry . set (
gimli ::DW_AT_linkage_name ,
AttributeValue ::StringRef ( name_id ) ,
) ;
2020-08-28 12:10:48 +02:00
let end =
self . create_debug_lines ( isa , symbol , entry_id , context , mir . span , source_info_set ) ;
2019-11-12 21:10:51 +01:00
2020-08-28 12:10:48 +02:00
self . unit_range_list . 0. push ( Range ::StartLength {
begin : Address ::Symbol { symbol , addend : 0 } ,
length : u64 ::from ( end ) ,
} ) ;
2019-01-19 16:16:30 +01:00
2020-04-25 14:17:09 +02:00
if isa . get_mach_backend ( ) . is_some ( ) {
return ; // Not yet implemented for the AArch64 backend.
}
2020-06-13 17:03:34 +02:00
let func_entry = self . dwarf . unit . get_mut ( entry_id ) ;
2020-04-23 16:44:12 +02:00
// Gdb requires both DW_AT_low_pc and DW_AT_high_pc. Otherwise the DW_TAG_subprogram is skipped.
2020-08-28 12:10:48 +02:00
func_entry . set (
gimli ::DW_AT_low_pc ,
AttributeValue ::Address ( Address ::Symbol { symbol , addend : 0 } ) ,
) ;
2020-04-23 16:44:12 +02:00
// Using Udata for DW_AT_high_pc requires at least DWARF4
func_entry . set ( gimli ::DW_AT_high_pc , AttributeValue ::Udata ( u64 ::from ( end ) ) ) ;
2020-04-22 14:48:56 +02:00
// FIXME Remove once actual debuginfo for locals works.
2020-08-28 12:10:48 +02:00
for ( i , ( param , & val ) ) in context
. func
. signature
. params
. iter ( )
. zip (
context
. func
. dfg
. block_params ( context . func . layout . entry_block ( ) . unwrap ( ) ) ,
)
. enumerate ( )
{
2020-04-22 14:48:56 +02:00
use cranelift_codegen ::ir ::ArgumentPurpose ;
let base_name = match param . purpose {
ArgumentPurpose ::Normal = > " arg " ,
2020-04-20 17:13:43 +02:00
ArgumentPurpose ::StructArgument ( _ ) = > " struct_arg " ,
2020-04-22 14:48:56 +02:00
ArgumentPurpose ::StructReturn = > " sret " ,
2020-08-28 12:10:48 +02:00
ArgumentPurpose ::Link
| ArgumentPurpose ::FramePointer
| ArgumentPurpose ::CalleeSaved = > continue ,
ArgumentPurpose ::VMContext
| ArgumentPurpose ::SignatureId
2020-10-01 10:38:23 +02:00
| ArgumentPurpose ::CallerTLS
| ArgumentPurpose ::CalleeTLS
2020-08-28 12:10:48 +02:00
| ArgumentPurpose ::StackLimit = > unreachable! ( ) ,
2020-04-22 14:48:56 +02:00
} ;
let name = format! ( " {} {} " , base_name , i ) ;
2020-06-13 17:03:34 +02:00
let dw_ty = self . dwarf_ty_for_clif_ty ( param . value_type ) ;
2020-08-28 12:10:48 +02:00
let loc =
translate_loc ( isa , context . func . locations [ val ] , & context . func . stack_slots ) . unwrap ( ) ;
2020-04-22 14:48:56 +02:00
2020-08-28 12:10:48 +02:00
let arg_id = self
. dwarf
. unit
. add ( entry_id , gimli ::DW_TAG_formal_parameter ) ;
2020-06-13 17:03:34 +02:00
let var_entry = self . dwarf . unit . get_mut ( arg_id ) ;
2020-04-22 14:48:56 +02:00
var_entry . set ( gimli ::DW_AT_name , AttributeValue ::String ( name . into_bytes ( ) ) ) ;
2020-06-05 12:40:33 +02:00
var_entry . set ( gimli ::DW_AT_type , AttributeValue ::UnitRef ( dw_ty ) ) ;
2020-04-22 14:48:56 +02:00
var_entry . set ( gimli ::DW_AT_location , AttributeValue ::Exprloc ( loc ) ) ;
}
2019-12-16 12:12:51 +01:00
// 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 ( ) ;
2020-06-13 17:03:34 +02:00
for ( local , _local_decl ) in mir . local_decls . iter_enumerated ( ) {
let ty = self . tcx . subst_and_normalize_erasing_regions (
instance . substs ,
2020-04-22 14:48:56 +02:00
ty ::ParamEnv ::reveal_all ( ) ,
2020-10-28 08:25:06 +01:00
mir . local_decls [ local ] . ty ,
2020-04-22 14:48:56 +02:00
) ;
2020-06-13 17:03:34 +02:00
let var_id = self . define_local ( entry_id , format! ( " {:?} " , local ) , ty ) ;
2019-12-16 12:12:51 +01:00
let location = place_location (
self ,
2020-03-17 15:30:32 +01:00
isa ,
2020-06-13 17:03:34 +02:00
symbol ,
2019-12-16 12:12:51 +01:00
context ,
& local_map ,
& value_labels_ranges ,
Place {
2020-01-13 21:38:46 +01:00
local ,
2019-12-16 12:12:51 +01:00
projection : ty ::List ::empty ( ) ,
} ,
) ;
2020-06-13 17:03:34 +02:00
let var_entry = self . dwarf . unit . get_mut ( var_id ) ;
2019-12-16 12:12:51 +01:00
var_entry . set ( gimli ::DW_AT_location , location ) ;
}
2019-11-09 16:42:21 +01:00
}
2019-11-28 21:35:03 +01:00
// FIXME create locals for all entries in mir.var_debug_info
2019-01-17 18:07:27 +01:00
}
}
2020-06-13 17:03:34 +02:00
fn place_location < ' tcx > (
debug_context : & mut DebugContext < ' tcx > ,
2020-03-17 15:30:32 +01:00
isa : & dyn TargetIsa ,
2020-06-13 17:03:34 +02:00
symbol : usize ,
2019-11-28 21:35:03 +01:00
context : & Context ,
2020-09-16 18:45:19 +02:00
local_map : & IndexVec < mir ::Local , CPlace < ' tcx > > ,
2020-08-28 12:10:48 +02:00
#[ allow(rustc::default_hash_types) ] value_labels_ranges : & std ::collections ::HashMap <
ValueLabel ,
Vec < ValueLocRange > ,
> ,
2019-11-28 21:35:03 +01:00
place : Place < ' tcx > ,
) -> AttributeValue {
assert! ( place . projection . is_empty ( ) ) ; // FIXME implement them
2020-09-16 18:45:19 +02:00
match local_map [ place . local ] . inner ( ) {
2020-06-27 11:58:44 +02:00
CPlaceInner ::Var ( _local , var ) = > {
let value_label = cranelift_codegen ::ir ::ValueLabel ::new ( var . index ( ) ) ;
2019-11-28 21:35:03 +01:00
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 {
2020-06-13 17:03:34 +02:00
symbol ,
2019-11-28 21:35:03 +01:00
addend : i64 ::from ( value_loc_range . start ) ,
} ,
end : Address ::Symbol {
2020-06-13 17:03:34 +02:00
symbol ,
2019-11-28 21:35:03 +01:00
addend : i64 ::from ( value_loc_range . end ) ,
} ,
2020-08-28 12:10:48 +02:00
data : translate_loc (
isa ,
value_loc_range . loc ,
& context . func . stack_slots ,
)
. unwrap ( ) ,
2019-11-28 21:35:03 +01:00
} )
. collect ( ) ,
) ;
2020-06-13 17:03:34 +02:00
let loc_list_id = debug_context . dwarf . unit . locations . add ( loc_list ) ;
2019-11-28 21:35:03 +01:00
AttributeValue ::LocationListRef ( loc_list_id )
} else {
// FIXME set value labels for unused locals
2020-06-05 12:40:33 +02:00
AttributeValue ::Exprloc ( Expression ::new ( ) )
2019-11-28 21:35:03 +01:00
}
}
2020-07-02 19:23:21 -03:00
CPlaceInner ::VarPair ( _ , _ , _ ) = > {
// FIXME implement this
AttributeValue ::Exprloc ( Expression ::new ( ) )
}
2020-03-28 15:21:58 +01:00
CPlaceInner ::VarLane ( _ , _ , _ ) = > {
// FIXME implement this
AttributeValue ::Exprloc ( Expression ::new ( ) )
}
2019-11-28 21:35:03 +01:00
CPlaceInner ::Addr ( _ , _ ) = > {
// FIXME implement this (used by arguments and returns)
2019-11-11 21:43:57 +01:00
2020-06-05 12:40:33 +02:00
AttributeValue ::Exprloc ( Expression ::new ( ) )
2019-12-20 22:00:12 +01:00
// For PointerBase::Stack:
2020-06-05 12:40:33 +02:00
//AttributeValue::Exprloc(translate_loc(ValueLoc::Stack(*stack_slot), &context.func.stack_slots).unwrap())
2019-11-28 21:35:03 +01:00
}
}
}
2019-11-11 21:43:57 +01:00
2020-03-17 15:30:32 +01:00
// Adapted from https://github.com/CraneStation/wasmtime/blob/5a1845b4caf7a5dba8eda1fef05213a532ed4259/crates/debug/src/transform/expression.rs#L59-L137
2020-08-28 12:10:48 +02:00
fn translate_loc (
isa : & dyn TargetIsa ,
loc : ValueLoc ,
stack_slots : & StackSlots ,
) -> Option < Expression > {
2019-11-11 21:43:57 +01:00
match loc {
ValueLoc ::Reg ( reg ) = > {
2020-04-13 12:52:53 +02:00
let machine_reg = isa . map_dwarf_register ( reg ) . unwrap ( ) ;
2020-06-05 12:40:33 +02:00
let mut expr = Expression ::new ( ) ;
expr . op_reg ( gimli ::Register ( machine_reg ) ) ;
Some ( expr )
2019-11-11 21:43:57 +01:00
}
ValueLoc ::Stack ( ss ) = > {
if let Some ( ss_offset ) = stack_slots [ ss ] . offset {
2020-06-05 12:40:33 +02:00
let mut expr = Expression ::new ( ) ;
2020-07-14 16:38:50 +02:00
expr . op_breg ( X86_64 ::RBP , i64 ::from ( ss_offset ) + 16 ) ;
2020-06-05 12:40:33 +02:00
Some ( expr )
} else {
None
2019-11-11 21:43:57 +01:00
}
}
_ = > None ,
}
}