Support reference types in the DWARF transform (#1986)
This commit is contained in:
@@ -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<R>(
|
||||
parent_id: write::UnitEntryId,
|
||||
kind: WebAssemblyPtrKind,
|
||||
comp_unit: &mut write::Unit,
|
||||
wp_die_id: write::UnitEntryId,
|
||||
pointer_type_entry: &DebuggingInformationEntry<R>,
|
||||
@@ -121,11 +132,18 @@ where
|
||||
// Build DW_TAG_structure_type for the wrapper:
|
||||
// .. DW_AT_name = "WebAssemblyPtrWrapper<T>",
|
||||
// .. 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,
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
40
tests/all/debug/testsuite/fraction-norm.cc
Normal file
40
tests/all/debug/testsuite/fraction-norm.cc
Normal 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);
|
||||
}
|
||||
BIN
tests/all/debug/testsuite/fraction-norm.wasm
Executable file
BIN
tests/all/debug/testsuite/fraction-norm.wasm
Executable file
Binary file not shown.
Reference in New Issue
Block a user