187c33c29SAlex Crichton use super::address_transform::AddressTransform;
290ac295eSAlex Crichton use super::attr::{EntryAttributesContext, clone_die_attributes};
392cc0ad7SSingleAccretion use super::debug_transform_logging::{
492cc0ad7SSingleAccretion     dbi_log, log_begin_input_die, log_end_output_die, log_end_output_die_skipped,
592cc0ad7SSingleAccretion     log_get_cu_summary,
692cc0ad7SSingleAccretion };
787c33c29SAlex Crichton use super::expression::compile_expression;
887c33c29SAlex Crichton use super::line_program::clone_line_program;
987c33c29SAlex Crichton use super::range_info_builder::RangeInfoBuilder;
10af476a51SSingleAccretion use super::synthetic::ModuleSyntheticUnit;
110b2c9d72SSingleAccretion use super::utils::{append_vmctx_info, resolve_die_ref};
12dd8c48b3SAlex Crichton use crate::debug::{Compilation, Reader};
1387c33c29SAlex Crichton use cranelift_codegen::ir::Endianness;
1487c33c29SAlex Crichton use cranelift_codegen::isa::TargetIsa;
15*c4a38d67SPhilip Craig use gimli::AttributeValue;
1687c33c29SAlex Crichton use gimli::write;
1787c33c29SAlex Crichton use std::collections::HashSet;
18dd8c48b3SAlex Crichton use wasmtime_environ::StaticModuleIndex;
19c7cab275SNick Fitzgerald use wasmtime_environ::error::{Context, Error};
20ca90650cSAdam Petro use wasmtime_versioned_export_macros::versioned_stringify_ident;
2187c33c29SAlex Crichton 
220b2c9d72SSingleAccretion #[derive(Debug)]
230b2c9d72SSingleAccretion pub struct InheritedAttr<T> {
24*c4a38d67SPhilip Craig     stack: Vec<(isize, T)>,
2587c33c29SAlex Crichton }
2687c33c29SAlex Crichton 
2787c33c29SAlex Crichton impl<T> InheritedAttr<T> {
new() -> Self2887c33c29SAlex Crichton     fn new() -> Self {
2987c33c29SAlex Crichton         InheritedAttr { stack: Vec::new() }
3087c33c29SAlex Crichton     }
3187c33c29SAlex Crichton 
update(&mut self, depth: isize)32*c4a38d67SPhilip Craig     fn update(&mut self, depth: isize) {
3387c33c29SAlex Crichton         while !self.stack.is_empty() && self.stack.last().unwrap().0 >= depth {
3487c33c29SAlex Crichton             self.stack.pop();
3587c33c29SAlex Crichton         }
3687c33c29SAlex Crichton     }
3787c33c29SAlex Crichton 
push(&mut self, depth: isize, value: T)38*c4a38d67SPhilip Craig     pub fn push(&mut self, depth: isize, value: T) {
3987c33c29SAlex Crichton         self.stack.push((depth, value));
4087c33c29SAlex Crichton     }
4187c33c29SAlex Crichton 
top(&self) -> Option<&T>420b2c9d72SSingleAccretion     pub fn top(&self) -> Option<&T> {
4387c33c29SAlex Crichton         self.stack.last().map(|entry| &entry.1)
4487c33c29SAlex Crichton     }
4587c33c29SAlex Crichton 
top_with_depth_mut(&mut self, depth: isize) -> Option<&mut T>46*c4a38d67SPhilip Craig     pub fn top_with_depth_mut(&mut self, depth: isize) -> Option<&mut T> {
470b2c9d72SSingleAccretion         self.stack
480b2c9d72SSingleAccretion             .last_mut()
490b2c9d72SSingleAccretion             .filter(|entry| entry.0 == depth)
500b2c9d72SSingleAccretion             .map(|entry| &mut entry.1)
510b2c9d72SSingleAccretion     }
520b2c9d72SSingleAccretion 
is_empty(&self) -> bool5387c33c29SAlex Crichton     fn is_empty(&self) -> bool {
5487c33c29SAlex Crichton         self.stack.is_empty()
5587c33c29SAlex Crichton     }
5687c33c29SAlex Crichton }
5787c33c29SAlex Crichton 
get_base_type_name(type_entry: &write::ConvertUnitEntry<Reader<'_>>) -> Result<String, Error>58*c4a38d67SPhilip Craig fn get_base_type_name(type_entry: &write::ConvertUnitEntry<Reader<'_>>) -> Result<String, Error> {
5987c33c29SAlex Crichton     // FIXME remove recursion.
607ee620a5SPhilip Craig     if let Some(die_ref) = type_entry.attr_value(gimli::DW_AT_type) {
61*c4a38d67SPhilip Craig         if let Some(ref die) = resolve_die_ref(type_entry.read_unit, &die_ref)? {
627ee620a5SPhilip Craig             if let Some(value) = die.attr_value(gimli::DW_AT_name) {
63*c4a38d67SPhilip Craig                 return Ok(String::from(die.read_unit.attr_string(value)?.to_string()?));
6487c33c29SAlex Crichton             }
65*c4a38d67SPhilip Craig             match die.tag {
6687c33c29SAlex Crichton                 gimli::DW_TAG_const_type => {
67*c4a38d67SPhilip Craig                     return Ok(format!("const {}", get_base_type_name(die)?));
6887c33c29SAlex Crichton                 }
6987c33c29SAlex Crichton                 gimli::DW_TAG_pointer_type => {
70*c4a38d67SPhilip Craig                     return Ok(format!("{}*", get_base_type_name(die)?));
7187c33c29SAlex Crichton                 }
7287c33c29SAlex Crichton                 gimli::DW_TAG_reference_type => {
73*c4a38d67SPhilip Craig                     return Ok(format!("{}&", get_base_type_name(die)?));
7487c33c29SAlex Crichton                 }
7587c33c29SAlex Crichton                 gimli::DW_TAG_array_type => {
76*c4a38d67SPhilip Craig                     return Ok(format!("{}[]", get_base_type_name(die)?));
7787c33c29SAlex Crichton                 }
7887c33c29SAlex Crichton                 _ => (),
7987c33c29SAlex Crichton             }
8087c33c29SAlex Crichton         }
8187c33c29SAlex Crichton     }
8287c33c29SAlex Crichton     Ok(String::from("??"))
8387c33c29SAlex Crichton }
8487c33c29SAlex Crichton 
8587c33c29SAlex Crichton enum WebAssemblyPtrKind {
8687c33c29SAlex Crichton     Reference,
8787c33c29SAlex Crichton     Pointer,
8887c33c29SAlex Crichton }
8987c33c29SAlex Crichton 
9087c33c29SAlex Crichton /// Replaces WebAssembly pointer type DIE with the wrapper
9187c33c29SAlex Crichton /// which natively represented by offset in a Wasm memory.
9287c33c29SAlex Crichton ///
9387c33c29SAlex Crichton /// `pointer_type_entry` is a DW_TAG_pointer_type entry (e.g. `T*`),
9487c33c29SAlex Crichton /// which refers its base type (e.g. `T`), or is a
9587c33c29SAlex Crichton /// DW_TAG_reference_type (e.g. `T&`).
9687c33c29SAlex Crichton ///
9787c33c29SAlex Crichton /// The generated wrapper is a structure that contains only the
9887c33c29SAlex Crichton /// `__ptr` field. The utility operators overloads is added to
9987c33c29SAlex Crichton /// provide better debugging experience.
10087c33c29SAlex Crichton ///
10187c33c29SAlex Crichton /// Wrappers of pointer and reference types are identical except for
10287c33c29SAlex Crichton /// their name -- they are formatted and accessed from a debugger
10387c33c29SAlex Crichton /// the same way.
10487c33c29SAlex Crichton ///
10587c33c29SAlex Crichton /// Notice that "resolve_vmctx_memory_ptr" is external/builtin
10687c33c29SAlex Crichton /// subprogram that is not part of Wasm code.
replace_pointer_type<'a>( wrapper_die_id: write::UnitEntryId, parent_id: write::UnitEntryId, kind: WebAssemblyPtrKind, wasm_ptr_die_ref: write::DebugInfoRef, pointer_type_entry: &write::ConvertUnitEntry<Reader<'a>>, unit: &mut write::ConvertUnit<'_, Reader<'a>>, ) -> Result<(), Error>107bd7b59daSPhilip Craig fn replace_pointer_type<'a>(
108*c4a38d67SPhilip Craig     wrapper_die_id: write::UnitEntryId,
10987c33c29SAlex Crichton     parent_id: write::UnitEntryId,
11087c33c29SAlex Crichton     kind: WebAssemblyPtrKind,
1117ee620a5SPhilip Craig     wasm_ptr_die_ref: write::DebugInfoRef,
112*c4a38d67SPhilip Craig     pointer_type_entry: &write::ConvertUnitEntry<Reader<'a>>,
113*c4a38d67SPhilip Craig     unit: &mut write::ConvertUnit<'_, Reader<'a>>,
114*c4a38d67SPhilip Craig ) -> Result<(), Error> {
11587c33c29SAlex Crichton     const WASM_PTR_LEN: u8 = 4;
11687c33c29SAlex Crichton 
11787c33c29SAlex Crichton     macro_rules! add_tag {
11887c33c29SAlex Crichton         ($parent_id:ident, $tag:expr => $die:ident as $die_id:ident { $($a:path = $v:expr),* }) => {
119*c4a38d67SPhilip Craig             let $die_id = unit.unit.add($parent_id, $tag);
12045b60bd6SAlex Crichton             #[allow(unused_variables, reason = "sometimes not used below")]
121*c4a38d67SPhilip Craig             let $die = unit.unit.get_mut($die_id);
12287c33c29SAlex Crichton             $( $die.set($a, $v); )*
12387c33c29SAlex Crichton         };
12487c33c29SAlex Crichton     }
12587c33c29SAlex Crichton 
12687c33c29SAlex Crichton     // Build DW_TAG_structure_type for the wrapper:
12787c33c29SAlex Crichton     //  .. DW_AT_name = "WebAssemblyPtrWrapper<T>",
12887c33c29SAlex Crichton     //  .. DW_AT_byte_size = 4,
12987c33c29SAlex Crichton     let name = match kind {
13087c33c29SAlex Crichton         WebAssemblyPtrKind::Pointer => format!(
13187c33c29SAlex Crichton             "WebAssemblyPtrWrapper<{}>",
132*c4a38d67SPhilip Craig             get_base_type_name(pointer_type_entry)?
13387c33c29SAlex Crichton         ),
13487c33c29SAlex Crichton         WebAssemblyPtrKind::Reference => format!(
13587c33c29SAlex Crichton             "WebAssemblyRefWrapper<{}>",
136*c4a38d67SPhilip Craig             get_base_type_name(pointer_type_entry)?
13787c33c29SAlex Crichton         ),
13887c33c29SAlex Crichton     };
139*c4a38d67SPhilip Craig     unit.unit
140*c4a38d67SPhilip Craig         .add_reserved(wrapper_die_id, parent_id, gimli::DW_TAG_structure_type);
141*c4a38d67SPhilip Craig     let wrapper_die = unit.unit.get_mut(wrapper_die_id);
142*c4a38d67SPhilip Craig     wrapper_die.set(
143*c4a38d67SPhilip Craig         gimli::DW_AT_name,
144*c4a38d67SPhilip Craig         write::AttributeValue::StringRef(unit.strings.add(name.as_str())),
145*c4a38d67SPhilip Craig     );
146*c4a38d67SPhilip Craig     wrapper_die.set(
147*c4a38d67SPhilip Craig         gimli::DW_AT_byte_size,
148*c4a38d67SPhilip Craig         write::AttributeValue::Data1(WASM_PTR_LEN),
149*c4a38d67SPhilip Craig     );
15087c33c29SAlex Crichton 
15187c33c29SAlex Crichton     // Build DW_TAG_pointer_type for `WebAssemblyPtrWrapper<T>*`:
15287c33c29SAlex Crichton     //  .. DW_AT_type = <wrapper_die>
15387c33c29SAlex Crichton     add_tag!(parent_id, gimli::DW_TAG_pointer_type => wrapper_ptr_type as wrapper_ptr_type_id {
15487c33c29SAlex Crichton         gimli::DW_AT_type = write::AttributeValue::UnitRef(wrapper_die_id)
15587c33c29SAlex Crichton     });
15687c33c29SAlex Crichton 
157*c4a38d67SPhilip Craig     let base_type = pointer_type_entry.attr_value(gimli::DW_AT_type);
158*c4a38d67SPhilip Craig     let base_type_id = if let Some(AttributeValue::UnitRef(offset)) = base_type {
159*c4a38d67SPhilip Craig         unit.convert_unit_ref(offset).ok()
160*c4a38d67SPhilip Craig     } else {
161*c4a38d67SPhilip Craig         None
162*c4a38d67SPhilip Craig     };
163*c4a38d67SPhilip Craig 
16487c33c29SAlex Crichton     // Build DW_TAG_reference_type for `T&`:
16587c33c29SAlex Crichton     //  .. DW_AT_type = <base_type>
16687c33c29SAlex Crichton     add_tag!(parent_id, gimli::DW_TAG_reference_type => ref_type as ref_type_id {});
167*c4a38d67SPhilip Craig     if let Some(base_type_id) = base_type_id {
168*c4a38d67SPhilip Craig         ref_type.set(
169*c4a38d67SPhilip Craig             gimli::DW_AT_type,
170*c4a38d67SPhilip Craig             write::AttributeValue::UnitRef(base_type_id),
171*c4a38d67SPhilip Craig         );
17287c33c29SAlex Crichton     }
17387c33c29SAlex Crichton 
17487c33c29SAlex Crichton     // Build DW_TAG_pointer_type for `T*`:
17587c33c29SAlex Crichton     //  .. DW_AT_type = <base_type>
17687c33c29SAlex Crichton     add_tag!(parent_id, gimli::DW_TAG_pointer_type => ptr_type as ptr_type_id {});
177*c4a38d67SPhilip Craig     if let Some(base_type_id) = base_type_id {
178*c4a38d67SPhilip Craig         ptr_type.set(
179*c4a38d67SPhilip Craig             gimli::DW_AT_type,
180*c4a38d67SPhilip Craig             write::AttributeValue::UnitRef(base_type_id),
181*c4a38d67SPhilip Craig         );
18287c33c29SAlex Crichton     }
18387c33c29SAlex Crichton 
18487c33c29SAlex Crichton     // Build wrapper_die's DW_TAG_template_type_parameter:
18587c33c29SAlex Crichton     //  .. DW_AT_name = "T"
18687c33c29SAlex Crichton     //  .. DW_AT_type = <base_type>
18787c33c29SAlex Crichton     add_tag!(wrapper_die_id, gimli::DW_TAG_template_type_parameter => t_param_die as t_param_die_id {
188*c4a38d67SPhilip Craig         gimli::DW_AT_name = write::AttributeValue::StringRef(unit.strings.add("T"))
18987c33c29SAlex Crichton     });
190*c4a38d67SPhilip Craig     if let Some(base_type_id) = base_type_id {
191*c4a38d67SPhilip Craig         t_param_die.set(
192*c4a38d67SPhilip Craig             gimli::DW_AT_type,
193*c4a38d67SPhilip Craig             write::AttributeValue::UnitRef(base_type_id),
194*c4a38d67SPhilip Craig         );
19587c33c29SAlex Crichton     }
19687c33c29SAlex Crichton 
19787c33c29SAlex Crichton     // Build wrapper_die's DW_TAG_member for `__ptr`:
19887c33c29SAlex Crichton     //  .. DW_AT_name = "__ptr"
19987c33c29SAlex Crichton     //  .. DW_AT_type = <wp_die>
20087c33c29SAlex Crichton     //  .. DW_AT_location = 0
20187c33c29SAlex Crichton     add_tag!(wrapper_die_id, gimli::DW_TAG_member => m_die as m_die_id {
202*c4a38d67SPhilip Craig         gimli::DW_AT_name = write::AttributeValue::StringRef(unit.strings.add("__ptr")),
203af476a51SSingleAccretion         gimli::DW_AT_type = write::AttributeValue::DebugInfoRef(wasm_ptr_die_ref),
20487c33c29SAlex Crichton         gimli::DW_AT_data_member_location = write::AttributeValue::Data1(0)
20587c33c29SAlex Crichton     });
20687c33c29SAlex Crichton 
20787c33c29SAlex Crichton     // Build wrapper_die's DW_TAG_subprogram for `ptr()`:
2088e4f0cd3SSingleAccretion     //  .. DW_AT_linkage_name = "wasmtime_resolve_vmctx_memory_ptr"
20987c33c29SAlex Crichton     //  .. DW_AT_name = "ptr"
21087c33c29SAlex Crichton     //  .. DW_AT_type = <ptr_type>
21187c33c29SAlex Crichton     //  .. DW_TAG_formal_parameter
21287c33c29SAlex Crichton     //  ..  .. DW_AT_type = <wrapper_ptr_type>
21387c33c29SAlex Crichton     //  ..  .. DW_AT_artificial = 1
21487c33c29SAlex Crichton     add_tag!(wrapper_die_id, gimli::DW_TAG_subprogram => deref_op_die as deref_op_die_id {
215*c4a38d67SPhilip Craig         gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(unit.strings.add(versioned_stringify_ident!(wasmtime_resolve_vmctx_memory_ptr))),
216*c4a38d67SPhilip Craig         gimli::DW_AT_name = write::AttributeValue::StringRef(unit.strings.add("ptr")),
21787c33c29SAlex Crichton         gimli::DW_AT_type = write::AttributeValue::UnitRef(ptr_type_id)
21887c33c29SAlex Crichton     });
21987c33c29SAlex Crichton     add_tag!(deref_op_die_id, gimli::DW_TAG_formal_parameter => deref_op_this_param as deref_op_this_param_id {
22087c33c29SAlex Crichton         gimli::DW_AT_type = write::AttributeValue::UnitRef(wrapper_ptr_type_id),
22187c33c29SAlex Crichton         gimli::DW_AT_artificial = write::AttributeValue::Flag(true)
22287c33c29SAlex Crichton     });
22387c33c29SAlex Crichton 
22487c33c29SAlex Crichton     // Build wrapper_die's DW_TAG_subprogram for `operator*`:
2258e4f0cd3SSingleAccretion     //  .. DW_AT_linkage_name = "wasmtime_resolve_vmctx_memory_ptr"
22687c33c29SAlex Crichton     //  .. DW_AT_name = "operator*"
22787c33c29SAlex Crichton     //  .. DW_AT_type = <ref_type>
22887c33c29SAlex Crichton     //  .. DW_TAG_formal_parameter
22987c33c29SAlex Crichton     //  ..  .. DW_AT_type = <wrapper_ptr_type>
23087c33c29SAlex Crichton     //  ..  .. DW_AT_artificial = 1
23187c33c29SAlex Crichton     add_tag!(wrapper_die_id, gimli::DW_TAG_subprogram => deref_op_die as deref_op_die_id {
232*c4a38d67SPhilip Craig         gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(unit.strings.add(versioned_stringify_ident!(wasmtime_resolve_vmctx_memory_ptr))),
233*c4a38d67SPhilip Craig         gimli::DW_AT_name = write::AttributeValue::StringRef(unit.strings.add("operator*")),
23487c33c29SAlex Crichton         gimli::DW_AT_type = write::AttributeValue::UnitRef(ref_type_id)
23587c33c29SAlex Crichton     });
23687c33c29SAlex Crichton     add_tag!(deref_op_die_id, gimli::DW_TAG_formal_parameter => deref_op_this_param as deref_op_this_param_id {
23787c33c29SAlex Crichton         gimli::DW_AT_type = write::AttributeValue::UnitRef(wrapper_ptr_type_id),
23887c33c29SAlex Crichton         gimli::DW_AT_artificial = write::AttributeValue::Flag(true)
23987c33c29SAlex Crichton     });
24087c33c29SAlex Crichton 
24187c33c29SAlex Crichton     // Build wrapper_die's DW_TAG_subprogram for `operator->`:
2428e4f0cd3SSingleAccretion     //  .. DW_AT_linkage_name = "wasmtime_resolve_vmctx_memory_ptr"
24387c33c29SAlex Crichton     //  .. DW_AT_name = "operator->"
24487c33c29SAlex Crichton     //  .. DW_AT_type = <ptr_type>
24587c33c29SAlex Crichton     //  .. DW_TAG_formal_parameter
24687c33c29SAlex Crichton     //  ..  .. DW_AT_type = <wrapper_ptr_type>
24787c33c29SAlex Crichton     //  ..  .. DW_AT_artificial = 1
24887c33c29SAlex Crichton     add_tag!(wrapper_die_id, gimli::DW_TAG_subprogram => deref_op_die as deref_op_die_id {
249*c4a38d67SPhilip Craig         gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(unit.strings.add(versioned_stringify_ident!(wasmtime_resolve_vmctx_memory_ptr))),
250*c4a38d67SPhilip Craig         gimli::DW_AT_name = write::AttributeValue::StringRef(unit.strings.add("operator->")),
25187c33c29SAlex Crichton         gimli::DW_AT_type = write::AttributeValue::UnitRef(ptr_type_id)
25287c33c29SAlex Crichton     });
25387c33c29SAlex Crichton     add_tag!(deref_op_die_id, gimli::DW_TAG_formal_parameter => deref_op_this_param as deref_op_this_param_id {
25487c33c29SAlex Crichton         gimli::DW_AT_type = write::AttributeValue::UnitRef(wrapper_ptr_type_id),
25587c33c29SAlex Crichton         gimli::DW_AT_artificial = write::AttributeValue::Flag(true)
25687c33c29SAlex Crichton     });
25787c33c29SAlex Crichton 
258*c4a38d67SPhilip Craig     Ok(())
25987c33c29SAlex Crichton }
26087c33c29SAlex Crichton 
clone_unit<'a>( compilation: &mut Compilation<'_>, module: StaticModuleIndex, unit: &mut write::ConvertUnit<'_, Reader<'a>>, root_entry: &write::ConvertUnitEntry<Reader<'a>>, skeleton_root_entry: Option<&write::ConvertUnitEntry<Reader<'a>>>, addr_tr: &AddressTransform, out_module_synthetic_unit: &ModuleSyntheticUnit, translated: &mut HashSet<usize>, isa: &dyn TargetIsa, ) -> Result<(), Error>261bd7b59daSPhilip Craig pub(crate) fn clone_unit<'a>(
262dd8c48b3SAlex Crichton     compilation: &mut Compilation<'_>,
263dd8c48b3SAlex Crichton     module: StaticModuleIndex,
264*c4a38d67SPhilip Craig     unit: &mut write::ConvertUnit<'_, Reader<'a>>,
265*c4a38d67SPhilip Craig     root_entry: &write::ConvertUnitEntry<Reader<'a>>,
266*c4a38d67SPhilip Craig     skeleton_root_entry: Option<&write::ConvertUnitEntry<Reader<'a>>>,
267dd8c48b3SAlex Crichton     addr_tr: &AddressTransform,
268af476a51SSingleAccretion     out_module_synthetic_unit: &ModuleSyntheticUnit,
269dd8c48b3SAlex Crichton     translated: &mut HashSet<usize>,
27087c33c29SAlex Crichton     isa: &dyn TargetIsa,
271*c4a38d67SPhilip Craig ) -> Result<(), Error> {
27287c33c29SAlex Crichton     let mut current_frame_base = InheritedAttr::new();
27387c33c29SAlex Crichton     let mut current_value_range = InheritedAttr::new();
27487c33c29SAlex Crichton     let mut current_scope_ranges = InheritedAttr::new();
2750b2c9d72SSingleAccretion     let mut current_subprogram = InheritedAttr::new();
27692cc0ad7SSingleAccretion 
277*c4a38d67SPhilip Craig     dbi_log!("Cloning CU {:?}", log_get_cu_summary(unit.read_unit));
278*c4a38d67SPhilip Craig 
279*c4a38d67SPhilip Craig     if let Some(convert_program) = unit.read_line_program(Some(unit.unit.encoding()), None)? {
280*c4a38d67SPhilip Craig         let (program, files) = clone_line_program(convert_program, addr_tr)?;
281*c4a38d67SPhilip Craig         unit.set_line_program(program, files);
282*c4a38d67SPhilip Craig     }
283*c4a38d67SPhilip Craig 
284*c4a38d67SPhilip Craig     if root_entry.tag == gimli::DW_TAG_compile_unit {
285*c4a38d67SPhilip Craig         log_begin_input_die(root_entry);
286*c4a38d67SPhilip Craig 
287*c4a38d67SPhilip Craig         let out_root_id = unit.unit.root();
288*c4a38d67SPhilip Craig         clone_die_attributes(
289*c4a38d67SPhilip Craig             unit,
290*c4a38d67SPhilip Craig             root_entry,
291*c4a38d67SPhilip Craig             addr_tr,
292*c4a38d67SPhilip Craig             None,
293*c4a38d67SPhilip Craig             out_root_id,
294*c4a38d67SPhilip Craig             None,
295*c4a38d67SPhilip Craig             None,
296*c4a38d67SPhilip Craig             EntryAttributesContext {
297*c4a38d67SPhilip Craig                 subprograms: &mut current_subprogram,
298*c4a38d67SPhilip Craig                 frame_base: None,
299*c4a38d67SPhilip Craig             },
300*c4a38d67SPhilip Craig             isa,
301*c4a38d67SPhilip Craig         )?;
302*c4a38d67SPhilip Craig 
303*c4a38d67SPhilip Craig         if let Some(skeleton_root_entry) = skeleton_root_entry {
304*c4a38d67SPhilip Craig             clone_die_attributes(
305*c4a38d67SPhilip Craig                 unit,
306*c4a38d67SPhilip Craig                 skeleton_root_entry,
307*c4a38d67SPhilip Craig                 addr_tr,
308*c4a38d67SPhilip Craig                 None,
309*c4a38d67SPhilip Craig                 out_root_id,
310*c4a38d67SPhilip Craig                 None,
311*c4a38d67SPhilip Craig                 None,
312*c4a38d67SPhilip Craig                 EntryAttributesContext {
313*c4a38d67SPhilip Craig                     subprograms: &mut current_subprogram,
314*c4a38d67SPhilip Craig                     frame_base: None,
315*c4a38d67SPhilip Craig                 },
316*c4a38d67SPhilip Craig                 isa,
317*c4a38d67SPhilip Craig             )?;
318*c4a38d67SPhilip Craig         }
319*c4a38d67SPhilip Craig 
320*c4a38d67SPhilip Craig         log_end_output_die(out_root_id, root_entry, unit);
321*c4a38d67SPhilip Craig     } else {
322*c4a38d67SPhilip Craig         // Can happen when the DWARF is split and we dont have the package/dwo files.
323*c4a38d67SPhilip Craig         // This is a better user experience than errorring.
324*c4a38d67SPhilip Craig         dbi_log!("... skipped: split DW_TAG_compile_unit entry missing");
325*c4a38d67SPhilip Craig         return Ok(()); // empty:
326*c4a38d67SPhilip Craig     }
327*c4a38d67SPhilip Craig 
328*c4a38d67SPhilip Craig     let mut entry = write::ConvertUnitEntry::null(unit.read_unit);
329*c4a38d67SPhilip Craig     while let Some(entry_id) = unit.read_entry(&mut entry)? {
330*c4a38d67SPhilip Craig         log_begin_input_die(&entry);
331*c4a38d67SPhilip Craig         let (Some(out_die_id), Some(parent)) = (entry_id, entry.parent) else {
332*c4a38d67SPhilip Craig             log_end_output_die_skipped(&entry, "unreachable");
33387c33c29SAlex Crichton             continue;
334*c4a38d67SPhilip Craig         };
33587c33c29SAlex Crichton 
336*c4a38d67SPhilip Craig         let new_stack_len = entry.depth;
33787c33c29SAlex Crichton         current_frame_base.update(new_stack_len);
33887c33c29SAlex Crichton         current_scope_ranges.update(new_stack_len);
33987c33c29SAlex Crichton         current_value_range.update(new_stack_len);
3400b2c9d72SSingleAccretion         current_subprogram.update(new_stack_len);
341*c4a38d67SPhilip Craig         let range_builder = if entry.tag == gimli::DW_TAG_subprogram {
342*c4a38d67SPhilip Craig             let range_builder = RangeInfoBuilder::from_subprogram_die(&entry, addr_tr)?;
343dd8c48b3SAlex Crichton             if let RangeInfoBuilder::Function(func) = range_builder {
344dd8c48b3SAlex Crichton                 let frame_info = compilation.function_frame_info(module, func);
34587c33c29SAlex Crichton                 current_value_range.push(new_stack_len, frame_info);
346dd8c48b3SAlex Crichton                 let (symbol, _) = compilation.function(module, func);
347dd8c48b3SAlex Crichton                 translated.insert(symbol);
34887c33c29SAlex Crichton                 current_scope_ranges.push(new_stack_len, range_builder.get_ranges(addr_tr));
34987c33c29SAlex Crichton                 Some(range_builder)
35087c33c29SAlex Crichton             } else {
35187c33c29SAlex Crichton                 // FIXME current_scope_ranges.push()
35287c33c29SAlex Crichton                 None
35387c33c29SAlex Crichton             }
35487c33c29SAlex Crichton         } else {
355*c4a38d67SPhilip Craig             if entry.has_attr(gimli::DW_AT_high_pc) || entry.has_attr(gimli::DW_AT_ranges) {
356*c4a38d67SPhilip Craig                 let range_builder = RangeInfoBuilder::from(&entry)?;
35787c33c29SAlex Crichton                 current_scope_ranges.push(new_stack_len, range_builder.get_ranges(addr_tr));
35887c33c29SAlex Crichton                 Some(range_builder)
35987c33c29SAlex Crichton             } else {
36087c33c29SAlex Crichton                 None
36187c33c29SAlex Crichton             }
36287c33c29SAlex Crichton         };
36387c33c29SAlex Crichton 
3647ee620a5SPhilip Craig         if let Some(AttributeValue::Exprloc(expr)) = entry.attr_value(gimli::DW_AT_frame_base) {
365*c4a38d67SPhilip Craig             if let Some(expr) = compile_expression(&expr, unit.unit.encoding(), None)? {
36687c33c29SAlex Crichton                 current_frame_base.push(new_stack_len, expr);
36787c33c29SAlex Crichton             }
36887c33c29SAlex Crichton         }
36987c33c29SAlex Crichton 
370*c4a38d67SPhilip Craig         if entry.tag == gimli::DW_TAG_pointer_type || entry.tag == gimli::DW_TAG_reference_type {
37187c33c29SAlex Crichton             // Wrap pointer types.
372*c4a38d67SPhilip Craig             let pointer_kind = match entry.tag {
37387c33c29SAlex Crichton                 gimli::DW_TAG_pointer_type => WebAssemblyPtrKind::Pointer,
37487c33c29SAlex Crichton                 gimli::DW_TAG_reference_type => WebAssemblyPtrKind::Reference,
37587c33c29SAlex Crichton                 _ => panic!(),
37687c33c29SAlex Crichton             };
377*c4a38d67SPhilip Craig             replace_pointer_type(
378*c4a38d67SPhilip Craig                 out_die_id,
379*c4a38d67SPhilip Craig                 parent,
38087c33c29SAlex Crichton                 pointer_kind,
381af476a51SSingleAccretion                 out_module_synthetic_unit.wasm_ptr_die_ref(),
382*c4a38d67SPhilip Craig                 &entry,
383c7756bd2SPhilip Craig                 unit,
38487c33c29SAlex Crichton             )?;
385*c4a38d67SPhilip Craig             log_end_output_die(out_die_id, &entry, unit);
38687c33c29SAlex Crichton             continue;
38787c33c29SAlex Crichton         }
38887c33c29SAlex Crichton 
389*c4a38d67SPhilip Craig         unit.unit.add_reserved(out_die_id, parent, entry.tag);
39087c33c29SAlex Crichton 
39187c33c29SAlex Crichton         clone_die_attributes(
392bd7b59daSPhilip Craig             unit,
393*c4a38d67SPhilip Craig             &entry,
39487c33c29SAlex Crichton             addr_tr,
39587c33c29SAlex Crichton             current_value_range.top(),
39692cc0ad7SSingleAccretion             out_die_id,
39787c33c29SAlex Crichton             range_builder,
39887c33c29SAlex Crichton             current_scope_ranges.top(),
399*c4a38d67SPhilip Craig             EntryAttributesContext {
4000b2c9d72SSingleAccretion                 subprograms: &mut current_subprogram,
40187c33c29SAlex Crichton                 frame_base: current_frame_base.top(),
40287c33c29SAlex Crichton             },
40387c33c29SAlex Crichton             isa,
40487c33c29SAlex Crichton         )?;
40587c33c29SAlex Crichton 
40687c33c29SAlex Crichton         // Data in WebAssembly memory always uses little-endian byte order.
40787c33c29SAlex Crichton         // If the native architecture is big-endian, we need to mark all
40887c33c29SAlex Crichton         // base types used to refer to WebAssembly memory as little-endian
40987c33c29SAlex Crichton         // using the DW_AT_endianity attribute, so that the debugger will
41087c33c29SAlex Crichton         // be able to correctly access them.
411*c4a38d67SPhilip Craig         if entry.tag == gimli::DW_TAG_base_type && isa.endianness() == Endianness::Big {
412*c4a38d67SPhilip Craig             let current_scope = unit.unit.get_mut(out_die_id);
41387c33c29SAlex Crichton             current_scope.set(
41487c33c29SAlex Crichton                 gimli::DW_AT_endianity,
41587c33c29SAlex Crichton                 write::AttributeValue::Endianity(gimli::DW_END_little),
41687c33c29SAlex Crichton             );
41787c33c29SAlex Crichton         }
41887c33c29SAlex Crichton 
419*c4a38d67SPhilip Craig         if entry.tag == gimli::DW_TAG_subprogram && !current_scope_ranges.is_empty() {
42087c33c29SAlex Crichton             append_vmctx_info(
421*c4a38d67SPhilip Craig                 unit.unit,
42292cc0ad7SSingleAccretion                 out_die_id,
423af476a51SSingleAccretion                 out_module_synthetic_unit.vmctx_ptr_die_ref(),
42487c33c29SAlex Crichton                 addr_tr,
42587c33c29SAlex Crichton                 current_value_range.top(),
42687c33c29SAlex Crichton                 current_scope_ranges.top().context("range")?,
427*c4a38d67SPhilip Craig                 unit.strings,
42887c33c29SAlex Crichton                 isa,
42987c33c29SAlex Crichton             )?;
43087c33c29SAlex Crichton         }
43192cc0ad7SSingleAccretion 
432*c4a38d67SPhilip Craig         log_end_output_die(out_die_id, &entry, unit);
43387c33c29SAlex Crichton     }
434*c4a38d67SPhilip Craig     Ok(())
43587c33c29SAlex Crichton }
436