Support reference types in the DWARF transform (#1986)
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
@@ -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(())
|
||||||
|
}
|
||||||
|
|||||||
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