From 9900641674dc9828b12b98445f71c01850557d33 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 7 Jul 2020 09:43:03 -0500 Subject: [PATCH] Support reference types in the DWARF transform (#1986) --- crates/debug/src/transform/unit.rs | 38 ++++++++++++++---- tests/all/debug/lldb.rs | 34 ++++++++++++++++ tests/all/debug/testsuite/fraction-norm.cc | 40 +++++++++++++++++++ tests/all/debug/testsuite/fraction-norm.wasm | Bin 0 -> 2065 bytes 4 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 tests/all/debug/testsuite/fraction-norm.cc create mode 100755 tests/all/debug/testsuite/fraction-norm.wasm diff --git a/crates/debug/src/transform/unit.rs b/crates/debug/src/transform/unit.rs index 01835ccdf7..d8711b5f1e 100644 --- a/crates/debug/src/transform/unit.rs +++ b/crates/debug/src/transform/unit.rs @@ -82,20 +82,31 @@ where Ok(String::from("??")) } +enum WebAssemblyPtrKind { + Reference, + Pointer, +} + /// Replaces WebAssembly pointer type DIE with the wrapper /// which natively represented by offset in a Wasm memory. /// -/// `pointer_type_entry` is an DW_TAG_pointer_type entry (e.g. `T*`), -/// which refers its base type (e.g. `T`). +/// `pointer_type_entry` is a DW_TAG_pointer_type entry (e.g. `T*`), +/// which refers its base type (e.g. `T`), or is a +/// DW_TAG_reference_type (e.g. `T&`). /// /// The generated wrapper is a structure that contains only the /// `__ptr` field. The utility operators overloads is added to /// provide better debugging experience. /// +/// Wrappers of pointer and reference types are identical except for +/// their name -- they are formatted and accessed from a debugger +/// the same way. +/// /// Notice that "resolve_vmctx_memory_ptr" is external/builtin /// subprogram that is not part of Wasm code. fn replace_pointer_type( parent_id: write::UnitEntryId, + kind: WebAssemblyPtrKind, comp_unit: &mut write::Unit, wp_die_id: write::UnitEntryId, pointer_type_entry: &DebuggingInformationEntry, @@ -121,11 +132,18 @@ where // Build DW_TAG_structure_type for the wrapper: // .. DW_AT_name = "WebAssemblyPtrWrapper", // .. DW_AT_byte_size = 4, - add_tag!(parent_id, gimli::DW_TAG_structure_type => wrapper_die as wrapper_die_id { - gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add(format!( + let name = match kind { + WebAssemblyPtrKind::Pointer => format!( "WebAssemblyPtrWrapper<{}>", get_base_type_name(pointer_type_entry, unit, context)? - ).as_str())), + ), + WebAssemblyPtrKind::Reference => format!( + "WebAssemblyRefWrapper<{}>", + get_base_type_name(pointer_type_entry, unit, context)? + ), + }; + add_tag!(parent_id, gimli::DW_TAG_structure_type => wrapper_die as wrapper_die_id { + gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add(name.as_str())), gimli::DW_AT_byte_size = write::AttributeValue::Data1(WASM_PTR_LEN) }); @@ -393,11 +411,17 @@ where let parent = stack.last().unwrap(); - if entry.tag() == gimli::DW_TAG_pointer_type { + if entry.tag() == gimli::DW_TAG_pointer_type || entry.tag() == gimli::DW_TAG_reference_type + { // Wrap pointer types. - // TODO reference types? + let pointer_kind = match entry.tag() { + gimli::DW_TAG_pointer_type => WebAssemblyPtrKind::Pointer, + gimli::DW_TAG_reference_type => WebAssemblyPtrKind::Reference, + _ => panic!(), + }; let die_id = replace_pointer_type( *parent, + pointer_kind, comp_unit, wp_die_id, entry, diff --git a/tests/all/debug/lldb.rs b/tests/all/debug/lldb.rs index 6677acfb44..c29e757b31 100644 --- a/tests/all/debug/lldb.rs +++ b/tests/all/debug/lldb.rs @@ -166,3 +166,37 @@ check: resuming )?; Ok(()) } + +#[test] +#[ignore] +#[cfg(all( + any(target_os = "linux", target_os = "macos"), + target_pointer_width = "64" +))] +pub fn test_debug_dwarf_ref() -> Result<()> { + let output = lldb_with_script( + &[ + "-g", + "--opt-level", + "0", + "tests/all/debug/testsuite/fraction-norm.wasm", + ], + r#"b fraction-norm.cc:26 +r +p __vmctx->set(),n->denominator +c"#, + )?; + + check_lldb_output( + &output, + r#" +check: Breakpoint 1: no locations (pending) +check: stop reason = breakpoint 1.1 +check: frame #0 +sameln: norm(n=(__ptr = +check: = 27 +check: resuming +"#, + )?; + Ok(()) +} diff --git a/tests/all/debug/testsuite/fraction-norm.cc b/tests/all/debug/testsuite/fraction-norm.cc new file mode 100644 index 0000000000..c896c38238 --- /dev/null +++ b/tests/all/debug/testsuite/fraction-norm.cc @@ -0,0 +1,40 @@ +// Compile with: +// clang++ --target=wasm32 fraction-norm.cc -o fraction-norm.wasm -g \ +// -O0 -nostdlib -fdebug-prefix-map=$PWD=. + +struct Fraction { + long numerator; + long denominator; +}; + +inline long abs(long x) +{ + return x >= 0 ? x : -x; +} + +extern "C" +void norm(Fraction &n) +{ + long a = abs(n.numerator), b = abs(n.denominator); + if (a == 0 || b == 0) return; + do { + a %= b; + if (a == 0) break; + b %= a; + } while (b > 0); + long gcd = a + b; + if (n.denominator > 0) { + n.numerator /= gcd; + n.denominator /= gcd; + } else { + n.numerator /= -gcd; + n.denominator /= -gcd; + } +} + +extern "C" +void _start() +{ + Fraction c = {6, 27}; + norm(c); +} diff --git a/tests/all/debug/testsuite/fraction-norm.wasm b/tests/all/debug/testsuite/fraction-norm.wasm new file mode 100755 index 0000000000000000000000000000000000000000..23f34181a512f2750d7d2b224e7803a85c866644 GIT binary patch literal 2065 zcmcIl&2Jk;6n`_bvtE1G>rLFmNzDvvuj61aAmD|GwbVq; z3|2e7@Q@x*Y{yd^8S+CVP%K446bKdWpvZGa8EE7=D2dX06nU7WHY?nU)d@`GxuGny z#_A-glND}gwWU&gTmLZiW*W4_P&V3WW;@L0+hRKwMUgC(#xy#8^VHA5Kk*2sOsuGpx!` z6@6D1@ggpFRUTI`KSl(#8k=0gOB(nxUdGj~x`LPR3gu7NL3yod6Ho;6BF+!i!LCE7AEh+ojvKRqx-6yxQ=w3k4yb@4^;*;%CXT= z9(ozOB@)N%0iOg1%8nr*JESS(adtZvjUq>Jpl44>%E?4?l|Ou}=QV*66I;|K=|!_j z{uUWq2b5QGQk|V)u=CKeEfWA1Xu)61F0_KiXn(ie+w1>I5<`o@(C-u|XzPuh_v0<1 zT+qfi8T|(0*$0~O1b^au8J&J2YVar4x0;*&KIV+?UgqEj&CP2aNJ&8V=n#QDqQl3u zSV}83=#M8H@CRhtBA!h7v(L3+Nk`HV*~-sE!Tf}XG!mMzZfB?FU0$m_b2wP9M_J0iV-4dA?v12fxu61b5jKTXwTjxL$6-onr6i0C<6f z)8_V^aIe{~*ssr19TNDMy`H5AoBv?t#G&WLF4wc#$y@^AzGmAtK*9s#rNJ(Vk=%!l%PC>Ni~ggKHfX{NrGiBNRwa$eAXOt&DDrkFu# znqN!HwB9BQZ%-UV;+z(TqHWcsV~V+YIAMgHB+nT-zL2L(OG&9i zg>sf4qjNTtLc@z@LC%jY6~EUGH@6#$@ei&_4*8VS$ubD%OgA zwOp*!HvDR(+-x?AwNg;t^IO$sv*d47w>C>#o3--lzx!7J-AUNJS@s*l4iJG(pK@vU zLKuJIde9qngMlCR2ha+7{cgJ#o!=VI0{GB?{bq~aMw$m@^!#qXP75$JGD{Ll1U6C5&X2E$>{T5H^AGP