Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
c377ef8
wip [ci skip]
kripken Jan 14, 2020
6df8a92
update test
kripken Jan 14, 2020
e1bcd0a
wip phase 2[ci skip]
kripken Jan 14, 2020
1513554
wip phase 3 [ci skip]
kripken Jan 14, 2020
d395bb2
finish
kripken Jan 14, 2020
5394975
style
kripken Jan 14, 2020
9c09438
try to see if -O3 avoids the -O4 issue; -O3 is a more realistic opt l…
kripken Jan 15, 2020
48255c1
undo
kripken Jan 15, 2020
6fab0e5
normalize
kripken Jan 15, 2020
54ffc2a
update
kripken Jan 15, 2020
017443f
Merge remote-tracking branch 'origin/master' into floc
kripken Jan 15, 2020
62e12e4
restore
kripken Jan 15, 2020
0392c06
back and better than ever [ci skip]
kripken Jan 15, 2020
61ac3db
track func locs
kripken Jan 15, 2020
00e079a
tests
kripken Jan 15, 2020
5fd73e9
style
kripken Jan 15, 2020
e0c5a7c
DW_TAG_lexical_block too, which appears in the emscripten test suite
kripken Jan 15, 2020
ad17e8c
NEW [ci skip]
kripken Jan 15, 2020
8e47d78
wip [ci skip]
kripken Jan 15, 2020
960db12
update testcases with new llvm + https://reviews.llvm.org/D71681 on t…
kripken Jan 15, 2020
2ee0669
update testcases with new llvm + https://reviews.llvm.org/D71681 on t…
kripken Jan 15, 2020
40188a5
works [ci skip]
kripken Jan 16, 2020
89d14f0
style
kripken Jan 16, 2020
2401f66
use a named struct
kripken Jan 16, 2020
312fce0
style
kripken Jan 16, 2020
4e37151
[ci skip]
kripken Jan 16, 2020
64abe3b
merge
kripken Jan 16, 2020
65b3f31
style
kripken Jan 16, 2020
fcdf809
Merge remote-tracking branch 'origin/master' into floc2-postupdate
kripken Jan 16, 2020
8b496d7
final update
kripken Jan 16, 2020
bd388c4
Merge branch 'floc2-postupdate' into floc2-b
kripken Jan 16, 2020
6dc1ea7
update tests
kripken Jan 16, 2020
bc17baf
comment
kripken Jan 16, 2020
bb271c9
Update LLVM to support WASM_location (from https://github.com/llvm/ll…
kripken Jan 16, 2020
de17914
Merge branch 'wasmloc' into floc2-postupdate
kripken Jan 16, 2020
3f5edcc
[ci skip]
kripken Jan 16, 2020
a89d299
[ci skip]
kripken Jan 16, 2020
5b9180a
Merge remote-tracking branch 'origin/master' into floc2-postupdate
kripken Jan 16, 2020
6fa4189
Merge branch 'floc2-postupdate' into floc2-b
kripken Jan 16, 2020
ee3cd5c
update comment [ci skip]
kripken Jan 16, 2020
05c7fdf
Merge remote-tracking branch 'origin/master' into floc2-b
kripken Jan 16, 2020
0b22854
fix
kripken Jan 16, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/passes/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1443,8 +1443,8 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
auto iter = currFunction->expressionLocations.find(curr);
if (iter != currFunction->expressionLocations.end()) {
Colors::grey(o);
o << ";; code offset: 0x" << std::hex << iter->second << std::dec
<< '\n';
o << ";; code offset: 0x" << std::hex << iter->second.start
<< std::dec << '\n';
restoreNormalColor(o);
doIndent(o, indent);
}
Expand Down
1 change: 1 addition & 0 deletions src/wasm-binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,7 @@ class WasmBinaryWriter {
void writeSourceMapEpilog();
void writeDebugLocation(const Function::DebugLocation& loc);
void writeDebugLocation(Expression* curr, Function* func);
void writeDebugLocationEnd(Expression* curr, Function* func);

// helpers
void writeInlineString(const char* name);
Expand Down
3 changes: 3 additions & 0 deletions src/wasm-stack.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ class BinaryInstWriter : public OverriddenVisitor<BinaryInstWriter> {
parent.writeDebugLocation(curr, func);
}
OverriddenVisitor<BinaryInstWriter>::visit(curr);
if (func && !sourceMap) {
parent.writeDebugLocationEnd(curr, func);
}
}

void visitBlock(Block* curr);
Expand Down
4 changes: 2 additions & 2 deletions src/wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1167,7 +1167,7 @@ struct BinaryLocations {
struct Span {
uint32_t start, end;
};
std::unordered_map<Expression*, uint32_t> expressions;
std::unordered_map<Expression*, Span> expressions;
std::unordered_map<Function*, Span> functions;
};

Expand Down Expand Up @@ -1225,7 +1225,7 @@ class Function : public Importable {
std::set<DebugLocation> epilogLocation;

// General debugging info support: track instructions and the function itself.
std::unordered_map<Expression*, uint32_t> expressionLocations;
std::unordered_map<Expression*, BinaryLocations::Span> expressionLocations;
BinaryLocations::Span funcLocation;

size_t getNumParams();
Expand Down
22 changes: 18 additions & 4 deletions src/wasm/wasm-binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ void WasmBinaryWriter::finishSection(int32_t start) {
// We are relative to the section start.
auto totalAdjustment = adjustmentForLEBShrinking + body;
for (auto& pair : binaryLocations.expressions) {
pair.second -= totalAdjustment;
pair.second.start -= totalAdjustment;
pair.second.end -= totalAdjustment;
}
for (auto& pair : binaryLocations.functions) {
pair.second.start -= totalAdjustment;
Expand Down Expand Up @@ -339,7 +340,9 @@ void WasmBinaryWriter::writeFunctions() {
for (auto* curr : binaryLocationTrackedExpressionsForFunc) {
// We added the binary locations, adjust them: they must be relative
// to the code section.
binaryLocations.expressions[curr] -= adjustmentForLEBShrinking;
auto& span = binaryLocations.expressions[curr];
span.start -= adjustmentForLEBShrinking;
span.end -= adjustmentForLEBShrinking;
}
}
if (!binaryLocationTrackedExpressionsForFunc.empty()) {
Expand Down Expand Up @@ -708,11 +711,20 @@ void WasmBinaryWriter::writeDebugLocation(Expression* curr, Function* func) {
// If this is an instruction in a function, and if the original wasm had
// binary locations tracked, then track it in the output as well.
if (func && !func->expressionLocations.empty()) {
binaryLocations.expressions[curr] = o.size();
binaryLocations.expressions[curr] =
BinaryLocations::Span{uint32_t(o.size()), 0};
binaryLocationTrackedExpressionsForFunc.push_back(curr);
}
}

void WasmBinaryWriter::writeDebugLocationEnd(Expression* curr, Function* func) {
if (func && !func->expressionLocations.empty()) {
auto& span = binaryLocations.expressions.at(curr);
assert(span.end == 0);
span.end = o.size();
}
}

void WasmBinaryWriter::writeInlineString(const char* name) {
int32_t size = strlen(name);
o << U32LEB(size);
Expand Down Expand Up @@ -2293,7 +2305,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
currFunction->debugLocations[curr] = *currDebugLocation.begin();
}
if (DWARF && currFunction) {
currFunction->expressionLocations[curr] = startPos - codeSectionLocation;
currFunction->expressionLocations[curr] =
BinaryLocations::Span{uint32_t(startPos - codeSectionLocation),
uint32_t(pos - codeSectionLocation)};
}
}
BYN_TRACE("zz recurse from " << depth-- << " at " << pos << std::endl);
Expand Down
159 changes: 113 additions & 46 deletions src/wasm/wasm-debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,45 +328,59 @@ struct LineState {
}
};

// Represents a mapping of addresses to expressions.
// Represents a mapping of addresses to expressions. We track beginnings and
// endings of expressions separately, since the end of one (which is one past
// the end in DWARF notation) overlaps with the beginning of the next, and also
// to let us use contextual information (we may know we are looking up the end
// of an instruction).
struct AddrExprMap {
std::unordered_map<uint32_t, Expression*> map;
std::unordered_map<uint32_t, Expression*> startMap;
std::unordered_map<uint32_t, Expression*> endMap;

// Construct the map from the binaryLocations loaded from the wasm.
AddrExprMap(const Module& wasm) {
for (auto& func : wasm.functions) {
for (auto pair : func->expressionLocations) {
assert(map.count(pair.second) == 0);
map[pair.second] = pair.first;
add(pair.first, pair.second);
}
}
}

// Construct the map from new binaryLocations just written
AddrExprMap(const BinaryLocations& newLocations) {
for (auto pair : newLocations.expressions) {
assert(map.count(pair.second) == 0);
map[pair.second] = pair.first;
add(pair.first, pair.second);
}
}

Expression* get(uint32_t addr) const {
auto iter = map.find(addr);
if (iter != map.end()) {
Expression* getStart(uint32_t addr) const {
auto iter = startMap.find(addr);
if (iter != startMap.end()) {
return iter->second;
}
return nullptr;
}

void dump() const {
std::cout << " (size: " << map.size() << ")\n";
for (auto pair : map) {
std::cout << " " << pair.first << " => " << pair.second << '\n';
Expression* getEnd(uint32_t addr) const {
auto iter = endMap.find(addr);
if (iter != endMap.end()) {
return iter->second;
}
return nullptr;
}

private:
void add(Expression* expr, BinaryLocations::Span span) {
assert(startMap.count(span.start) == 0);
startMap[span.start] = expr;
assert(endMap.count(span.end) == 0);
endMap[span.end] = expr;
}
};

// Represents a mapping of addresses to expressions.
// Represents a mapping of addresses to expressions. Note that we use a single
// map for the start and end addresses, since there is no chance of a function's
// start overlapping with another's end (there is the size LEB in the middle).
struct FuncAddrMap {
std::unordered_map<uint32_t, Function*> map;

Expand Down Expand Up @@ -415,10 +429,6 @@ struct LocationUpdater {
// TODO: for memory efficiency, we may want to do this in a streaming manner,
// binary to binary, without YAML IR.

// TODO: apparently DWARF offsets may be into the middle of instructions...
// we may need to track their spans too
// https://github.com/WebAssembly/debugging/issues/9#issuecomment-567720872

LocationUpdater(Module& wasm, const BinaryLocations& newLocations)
: wasm(wasm), newLocations(newLocations), oldExprAddrMap(wasm),
newExprAddrMap(newLocations), oldFuncAddrMap(wasm) {}
Expand All @@ -427,10 +437,21 @@ struct LocationUpdater {
// address, or if there was but if that instruction no longer exists, return
// 0. Otherwise, return the new updated location.
uint32_t getNewExprAddr(uint32_t oldAddr) const {
if (auto* expr = oldExprAddrMap.get(oldAddr)) {
if (auto* expr = oldExprAddrMap.getStart(oldAddr)) {
auto iter = newLocations.expressions.find(expr);
if (iter != newLocations.expressions.end()) {
uint32_t newAddr = iter->second;
uint32_t newAddr = iter->second.start;
return newAddr;
}
}
return 0;
}

uint32_t getNewExprEndAddr(uint32_t oldAddr) const {
if (auto* expr = oldExprAddrMap.getEnd(oldAddr)) {
auto iter = newLocations.expressions.find(expr);
if (iter != newLocations.expressions.end()) {
uint32_t newAddr = iter->second.end;
return newAddr;
}
}
Expand Down Expand Up @@ -529,6 +550,76 @@ static void iterContextAndYAML(const T& contextList, U& yamlList, W func) {
assert(yamlValue == yamlList.end());
}

static void updateDIE(const llvm::DWARFDebugInfoEntry& DIE,
llvm::DWARFYAML::Entry& yamlEntry,
const llvm::DWARFAbbreviationDeclaration* abbrevDecl,
const LocationUpdater& locationUpdater) {
auto tag = DIE.getTag();
// Pairs of low/high_pc require some special handling, as the high
// may be an offset relative to the low. First, process the low_pcs.
uint32_t oldLowPC = 0, newLowPC = 0;
iterContextAndYAML(
abbrevDecl->attributes(),
yamlEntry.Values,
[&](const llvm::DWARFAbbreviationDeclaration::AttributeSpec& attrSpec,
llvm::DWARFYAML::FormValue& yamlValue) {
auto attr = attrSpec.Attr;
if (attr != llvm::dwarf::DW_AT_low_pc) {
return;
}
uint32_t oldValue = yamlValue.Value, newValue = 0;
if (tag == llvm::dwarf::DW_TAG_GNU_call_site ||
tag == llvm::dwarf::DW_TAG_inlined_subroutine ||
tag == llvm::dwarf::DW_TAG_lexical_block ||
tag == llvm::dwarf::DW_TAG_label) {
newValue = locationUpdater.getNewExprAddr(oldValue);
} else if (tag == llvm::dwarf::DW_TAG_compile_unit ||
tag == llvm::dwarf::DW_TAG_subprogram) {
newValue = locationUpdater.getNewFuncAddr(oldValue);
} else {
Fatal() << "unknown tag with low_pc "
<< llvm::dwarf::TagString(tag).str();
}
oldLowPC = oldValue;
newLowPC = newValue;
yamlValue.Value = newValue;
});
// Next, process the high_pcs.
// TODO: do this more efficiently, without a second traversal (but that's a
// little tricky given the special double-traversal we have).
iterContextAndYAML(
abbrevDecl->attributes(),
yamlEntry.Values,
[&](const llvm::DWARFAbbreviationDeclaration::AttributeSpec& attrSpec,
llvm::DWARFYAML::FormValue& yamlValue) {
auto attr = attrSpec.Attr;
if (attr != llvm::dwarf::DW_AT_high_pc) {
return;
}
uint32_t oldValue = yamlValue.Value, newValue = 0;
bool isRelative = attrSpec.Form == llvm::dwarf::DW_FORM_data4;
if (isRelative) {
oldValue += oldLowPC;
}
if (tag == llvm::dwarf::DW_TAG_GNU_call_site ||
tag == llvm::dwarf::DW_TAG_inlined_subroutine ||
tag == llvm::dwarf::DW_TAG_lexical_block ||
tag == llvm::dwarf::DW_TAG_label) {
newValue = locationUpdater.getNewExprEndAddr(oldValue);
} else if (tag == llvm::dwarf::DW_TAG_compile_unit ||
tag == llvm::dwarf::DW_TAG_subprogram) {
newValue = locationUpdater.getNewFuncAddr(oldValue);
} else {
Fatal() << "unknown tag with low_pc "
<< llvm::dwarf::TagString(tag).str();
}
if (isRelative) {
newValue -= newLowPC;
}
yamlValue.Value = newValue;
});
}

static void updateCompileUnits(const BinaryenDWARFInfo& info,
llvm::DWARFYAML::Data& yaml,
const LocationUpdater& locationUpdater) {
Expand All @@ -545,36 +636,12 @@ static void updateCompileUnits(const BinaryenDWARFInfo& info,
yamlUnit.Entries,
[&](const llvm::DWARFDebugInfoEntry& DIE,
llvm::DWARFYAML::Entry& yamlEntry) {
auto tag = DIE.getTag();
// Process the entries in each relevant DIE, looking for attributes to
// change.
auto abbrevDecl = DIE.getAbbreviationDeclarationPtr();
if (abbrevDecl) {
iterContextAndYAML(
abbrevDecl->attributes(),
yamlEntry.Values,
[&](const llvm::DWARFAbbreviationDeclaration::AttributeSpec&
attrSpec,
llvm::DWARFYAML::FormValue& yamlValue) {
if (attrSpec.Attr == llvm::dwarf::DW_AT_low_pc) {
if (tag == llvm::dwarf::DW_TAG_GNU_call_site ||
tag == llvm::dwarf::DW_TAG_inlined_subroutine ||
tag == llvm::dwarf::DW_TAG_lexical_block ||
tag == llvm::dwarf::DW_TAG_label) {
// low_pc in certain tags represent expressions.
yamlValue.Value =
locationUpdater.getNewExprAddr(yamlValue.Value);
} else if (tag == llvm::dwarf::DW_TAG_compile_unit ||
tag == llvm::dwarf::DW_TAG_subprogram) {
// low_pc in certain tags represent function.
yamlValue.Value =
locationUpdater.getNewFuncAddr(yamlValue.Value);
} else {
Fatal() << "unknown tag with low_pc "
<< llvm::dwarf::TagString(tag).str();
}
}
});
// This is relevant; look for things to update.
updateDIE(DIE, yamlEntry, abbrevDecl, locationUpdater);
}
});
});
Expand Down
4 changes: 2 additions & 2 deletions test/passes/dwarfdump_roundtrip_dwarfdump.bin.txt
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,11 @@ Abbrev table for offset: 0x00000000
DW_AT_stmt_list [DW_FORM_sec_offset] (0x00000000)
DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x0000009b] = "/usr/local/google/home/azakai/Dev/emscripten")
DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
DW_AT_high_pc [DW_FORM_data4] (0x00000002)
DW_AT_high_pc [DW_FORM_data4] (0x00000000)

0x00000026: DW_TAG_subprogram [2]
DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
DW_AT_high_pc [DW_FORM_data4] (0x00000002)
DW_AT_high_pc [DW_FORM_data4] (0x00000000)
DW_AT_linkage_name [DW_FORM_strp] ( .debug_str[0x000000c8] = "_Z3foov")
DW_AT_name [DW_FORM_strp] ( .debug_str[0x000000d0] = "foo")
DW_AT_decl_file [DW_FORM_data1] ("/usr/local/google/home/azakai/Dev/emscripten/a.cpp")
Expand Down
6 changes: 3 additions & 3 deletions test/passes/fannkuch3.bin.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2534,7 +2534,7 @@ Abbrev table for offset: 0x00000000

0x00000082: DW_TAG_subprogram [10] *
DW_AT_low_pc [DW_FORM_addr] (0x0000000000000006)
DW_AT_high_pc [DW_FORM_data4] (0x00000397)
DW_AT_high_pc [DW_FORM_data4] (0x00000383)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this means that Binaryen shrank the function? Is that expected for this test?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it shrinks it a little even without running optimizations, due to LEBs being compressed (which clang doesn't do in all places). I verified that size is correct.

DW_AT_frame_base [DW_FORM_exprloc] (DW_OP_WASM_location 0x1 +0, DW_OP_stack_value)
DW_AT_GNU_all_call_sites [DW_FORM_flag_present] (true)
DW_AT_linkage_name [DW_FORM_strp] ( .debug_str[0x00000166] = "_Z15fannkuch_workerPv")
Expand Down Expand Up @@ -2818,7 +2818,7 @@ Abbrev table for offset: 0x00000000

0x0000023b: DW_TAG_subprogram [23] *
DW_AT_low_pc [DW_FORM_addr] (0x000000000000038b)
DW_AT_high_pc [DW_FORM_data4] (0x00000342)
DW_AT_high_pc [DW_FORM_data4] (0x000002fb)
DW_AT_frame_base [DW_FORM_exprloc] (DW_OP_WASM_location 0x0 +2, DW_OP_stack_value)
DW_AT_GNU_all_call_sites [DW_FORM_flag_present] (true)
DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000018c] = "main")
Expand Down Expand Up @@ -2851,7 +2851,7 @@ Abbrev table for offset: 0x00000000
0x00000278: DW_TAG_inlined_subroutine [24] *
DW_AT_abstract_origin [DW_FORM_ref4] (cu + 0x01a8 => {0x000001a8} "_ZL8fannkuchi")
DW_AT_low_pc [DW_FORM_addr] (0x00000000000003c6)
DW_AT_high_pc [DW_FORM_data4] (0x000002c8)
DW_AT_high_pc [DW_FORM_data4] (0x0000026d)
DW_AT_call_file [DW_FORM_data1] ("/usr/local/google/home/azakai/Dev/emscripten/tests/fannkuch.cpp")
DW_AT_call_line [DW_FORM_data1] (159)
DW_AT_call_column [DW_FORM_data1] (0x29)
Expand Down
6 changes: 3 additions & 3 deletions test/passes/fannkuch3_manyopts.bin.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2534,7 +2534,7 @@ Abbrev table for offset: 0x00000000

0x00000082: DW_TAG_subprogram [10] *
DW_AT_low_pc [DW_FORM_addr] (0x0000000000000007)
DW_AT_high_pc [DW_FORM_data4] (0x00000397)
DW_AT_high_pc [DW_FORM_data4] (0x00000353)
DW_AT_frame_base [DW_FORM_exprloc] (DW_OP_WASM_location 0x1 +0, DW_OP_stack_value)
DW_AT_GNU_all_call_sites [DW_FORM_flag_present] (true)
DW_AT_linkage_name [DW_FORM_strp] ( .debug_str[0x00000166] = "_Z15fannkuch_workerPv")
Expand Down Expand Up @@ -2818,7 +2818,7 @@ Abbrev table for offset: 0x00000000

0x0000023b: DW_TAG_subprogram [23] *
DW_AT_low_pc [DW_FORM_addr] (0x000000000000035c)
DW_AT_high_pc [DW_FORM_data4] (0x00000342)
DW_AT_high_pc [DW_FORM_data4] (0x000002cf)
DW_AT_frame_base [DW_FORM_exprloc] (DW_OP_WASM_location 0x0 +2, DW_OP_stack_value)
DW_AT_GNU_all_call_sites [DW_FORM_flag_present] (true)
DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000018c] = "main")
Expand Down Expand Up @@ -2851,7 +2851,7 @@ Abbrev table for offset: 0x00000000
0x00000278: DW_TAG_inlined_subroutine [24] *
DW_AT_abstract_origin [DW_FORM_ref4] (cu + 0x01a8 => {0x000001a8} "_ZL8fannkuchi")
DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
DW_AT_high_pc [DW_FORM_data4] (0x000002c8)
DW_AT_high_pc [DW_FORM_data4] (0x00000000)
DW_AT_call_file [DW_FORM_data1] ("/usr/local/google/home/azakai/Dev/emscripten/tests/fannkuch.cpp")
DW_AT_call_line [DW_FORM_data1] (159)
DW_AT_call_column [DW_FORM_data1] (0x29)
Expand Down
Loading