Support reference types in the DWARF transform (#1986)

This commit is contained in:
Yury Delendik
2020-07-07 09:43:03 -05:00
committed by GitHub
parent 70cef0a433
commit 9900641674
4 changed files with 105 additions and 7 deletions

View File

@@ -82,20 +82,31 @@ where
Ok(String::from("??")) Ok(String::from("??"))
} }
enum WebAssemblyPtrKind {
Reference,
Pointer,
}
/// Replaces WebAssembly pointer type DIE with the wrapper /// Replaces WebAssembly pointer type DIE with the wrapper
/// which natively represented by offset in a Wasm memory. /// which natively represented by offset in a Wasm memory.
/// ///
/// `pointer_type_entry` is an DW_TAG_pointer_type entry (e.g. `T*`), /// `pointer_type_entry` is a DW_TAG_pointer_type entry (e.g. `T*`),
/// which refers its base type (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 /// The generated wrapper is a structure that contains only the
/// `__ptr` field. The utility operators overloads is added to /// `__ptr` field. The utility operators overloads is added to
/// provide better debugging experience. /// 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 /// Notice that "resolve_vmctx_memory_ptr" is external/builtin
/// subprogram that is not part of Wasm code. /// subprogram that is not part of Wasm code.
fn replace_pointer_type<R>( fn replace_pointer_type<R>(
parent_id: write::UnitEntryId, parent_id: write::UnitEntryId,
kind: WebAssemblyPtrKind,
comp_unit: &mut write::Unit, comp_unit: &mut write::Unit,
wp_die_id: write::UnitEntryId, wp_die_id: write::UnitEntryId,
pointer_type_entry: &DebuggingInformationEntry<R>, pointer_type_entry: &DebuggingInformationEntry<R>,
@@ -121,11 +132,18 @@ where
// Build DW_TAG_structure_type for the wrapper: // Build DW_TAG_structure_type for the wrapper:
// .. DW_AT_name = "WebAssemblyPtrWrapper<T>", // .. DW_AT_name = "WebAssemblyPtrWrapper<T>",
// .. DW_AT_byte_size = 4, // .. DW_AT_byte_size = 4,
add_tag!(parent_id, gimli::DW_TAG_structure_type => wrapper_die as wrapper_die_id { let name = match kind {
gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add(format!( WebAssemblyPtrKind::Pointer => format!(
"WebAssemblyPtrWrapper<{}>", "WebAssemblyPtrWrapper<{}>",
get_base_type_name(pointer_type_entry, unit, context)? 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) gimli::DW_AT_byte_size = write::AttributeValue::Data1(WASM_PTR_LEN)
}); });
@@ -393,11 +411,17 @@ where
let parent = stack.last().unwrap(); 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. // 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( let die_id = replace_pointer_type(
*parent, *parent,
pointer_kind,
comp_unit, comp_unit,
wp_die_id, wp_die_id,
entry, entry,

View File

@@ -166,3 +166,37 @@ check: resuming
)?; )?;
Ok(()) 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(())
}

View File

@@ -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);
}

Binary file not shown.