summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/passes/Print.cpp21
-rw-r--r--src/support/small_vector.h24
-rw-r--r--src/wasm-binary.h8
-rw-r--r--src/wasm.h21
-rw-r--r--src/wasm/wasm-binary.cpp44
-rw-r--r--src/wasm/wasm-debug.cpp5
-rw-r--r--src/wasm/wasm-stack.cpp7
7 files changed, 85 insertions, 45 deletions
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 53049943a..7b35701d4 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -1902,6 +1902,21 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
}
}
+ // Prints debug info for a delimiter in an expression.
+ void printDebugDelimiterLocation(Expression* curr, Index i) {
+ if (currFunction && debugInfo) {
+ auto iter = currFunction->delimiterLocations.find(curr);
+ if (iter != currFunction->delimiterLocations.end()) {
+ auto& locations = iter->second;
+ Colors::grey(o);
+ o << ";; code offset: 0x" << std::hex << locations[i] << std::dec
+ << '\n';
+ restoreNormalColor(o);
+ doIndent(o, indent);
+ }
+ }
+ }
+
void visit(Expression* curr) {
printDebugLocation(curr);
OverriddenVisitor<PrintSExpression>::visit(curr);
@@ -2020,6 +2035,10 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
printFullLine(curr->condition);
maybePrintImplicitBlock(curr->ifTrue, false);
if (curr->ifFalse) {
+ // Note: debug info here is not used as LLVM does not emit ifs, and since
+ // LLVM is the main source of DWARF, effectively we never encounter ifs
+ // with DWARF.
+ printDebugDelimiterLocation(curr, BinaryLocations::Else);
maybePrintImplicitBlock(curr->ifFalse, false);
}
decIndent();
@@ -2380,6 +2399,7 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
o << "\n";
for (size_t i = 0; i < curr->catchEvents.size(); i++) {
doIndent(o, indent);
+ printDebugDelimiterLocation(curr, i);
o << "(catch ";
printName(curr->catchEvents[i], o);
incIndent();
@@ -2389,6 +2409,7 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
}
if (curr->hasCatchAll()) {
doIndent(o, indent);
+ printDebugDelimiterLocation(curr, curr->catchEvents.size());
o << "(catch_all";
incIndent();
maybePrintImplicitBlock(curr->catchBodies.back(), true);
diff --git a/src/support/small_vector.h b/src/support/small_vector.h
index 2e65eda41..8ab10c05b 100644
--- a/src/support/small_vector.h
+++ b/src/support/small_vector.h
@@ -181,6 +181,30 @@ public:
ConstIterator end() const { return ConstIterator(this, size()); }
};
+// A SmallVector for which some values may be read before they are written, and
+// in that case they have the value zero.
+template<typename T, size_t N>
+struct ZeroInitSmallVector : public SmallVector<T, N> {
+ T& operator[](size_t i) {
+ if (i >= this->size()) {
+ resize(i + 1);
+ }
+ return SmallVector<T, N>::operator[](i);
+ }
+
+ const T& operator[](size_t i) const {
+ return const_cast<ZeroInitSmallVector<T, N>&>(*this)[i];
+ }
+
+ void resize(size_t newSize) {
+ auto oldSize = this->size();
+ SmallVector<T, N>::resize(newSize);
+ for (size_t i = oldSize; i < this->size(); i++) {
+ (*this)[i] = 0;
+ }
+ }
+};
+
} // namespace wasm
#endif // wasm_support_small_vector_h
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 8f4946786..a495300dc 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -1177,9 +1177,7 @@ public:
void writeDebugLocation(const Function::DebugLocation& loc);
void writeDebugLocation(Expression* curr, Function* func);
void writeDebugLocationEnd(Expression* curr, Function* func);
- void writeExtraDebugLocation(Expression* curr,
- Function* func,
- BinaryLocations::DelimiterId id);
+ void writeExtraDebugLocation(Expression* curr, Function* func, size_t id);
// helpers
void writeInlineString(const char* name);
@@ -1406,10 +1404,6 @@ public:
// Called when we parse the beginning of a control flow structure.
void startControlFlow(Expression* curr);
- // Called when we parse a later part of a control flow structure, like "end"
- // or "else".
- void continueControlFlow(BinaryLocations::DelimiterId id, BinaryLocation pos);
-
// set when we know code is unreachable in the sense of the wasm spec: we are
// in a block and after an unreachable element. this helps parse stacky wasm
// code, which can be unsuitable for our IR when unreachable.
diff --git a/src/wasm.h b/src/wasm.h
index 0b7a09a3c..7090aeff1 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -1530,20 +1530,15 @@ struct BinaryLocations {
// Track the extra delimiter positions that some instructions, in particular
// control flow, have, like 'end' for loop and block. We keep these in a
// separate map because they are rare and we optimize for the storage space
- // for the common type of instruction which just needs a Span. We implement
- // this as a simple array with one element at the moment (more elements may
- // be necessary in the future).
- // TODO: If we are sure we won't need more, make this a single value?
- struct DelimiterLocations : public std::array<BinaryLocation, 1> {
- DelimiterLocations() {
- // Ensure zero-initialization.
- for (auto& item : *this) {
- item = 0;
- }
- }
- };
+ // for the common type of instruction which just needs a Span.
+ // For "else" (from an if) we use index 0, and for catch (from a try) we use
+ // indexes 0 and above.
+ // We use automatic zero-initialization here because that indicates a "null"
+ // debug value, indicating the information is not present.
+ using DelimiterLocations = ZeroInitSmallVector<BinaryLocation, 1>;
+
+ enum DelimiterId : size_t { Else = 0, Invalid = size_t(-1) };
- enum DelimiterId { Else = 0, Catch = 0, Invalid = -1 };
std::unordered_map<Expression*, DelimiterLocations> delimiters;
// DWARF debug info can refer to multiple interesting positions in a function.
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index cc289e7ec..bf71d3a4d 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -915,8 +915,9 @@ void WasmBinaryWriter::writeDebugLocationEnd(Expression* curr, Function* func) {
}
}
-void WasmBinaryWriter::writeExtraDebugLocation(
- Expression* curr, Function* func, BinaryLocations::DelimiterId id) {
+void WasmBinaryWriter::writeExtraDebugLocation(Expression* curr,
+ Function* func,
+ size_t id) {
if (func && !func->expressionLocations.empty()) {
binaryLocations.delimiters[curr][id] = o.size();
}
@@ -2836,13 +2837,30 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
}
break;
case BinaryConsts::Else:
+ case BinaryConsts::Catch: {
curr = nullptr;
- continueControlFlow(BinaryLocations::Else, startPos);
- break;
- case BinaryConsts::Catch:
- curr = nullptr;
- continueControlFlow(BinaryLocations::Catch, startPos);
+ if (DWARF && currFunction) {
+ assert(!controlFlowStack.empty());
+ auto currControlFlow = controlFlowStack.back();
+ BinaryLocation delimiterId;
+ // Else and CatchAll have the same binary ID, so differentiate them
+ // using the control flow stack.
+ static_assert(BinaryConsts::CatchAll == BinaryConsts::Else,
+ "Else and CatchAll should have identical codes");
+ if (currControlFlow->is<If>()) {
+ delimiterId = BinaryLocations::Else;
+ } else {
+ // Both Catch and CatchAll can simply append to the list as we go, as
+ // we visit them in the right order in the binary, and like the binary
+ // we store the CatchAll at the end.
+ delimiterId =
+ currFunction->delimiterLocations[currControlFlow].size();
+ }
+ currFunction->delimiterLocations[currControlFlow][delimiterId] =
+ startPos - codeSectionLocation;
+ }
break;
+ }
case BinaryConsts::RefNull:
visitRefNull((curr = allocator.alloc<RefNull>())->cast<RefNull>());
break;
@@ -3102,18 +3120,6 @@ void WasmBinaryBuilder::startControlFlow(Expression* curr) {
}
}
-void WasmBinaryBuilder::continueControlFlow(BinaryLocations::DelimiterId id,
- BinaryLocation pos) {
- if (DWARF && currFunction) {
- assert(!controlFlowStack.empty());
- auto currControlFlow = controlFlowStack.back();
- // We are called after parsing the byte, so we need to subtract one to
- // get its position.
- currFunction->delimiterLocations[currControlFlow][id] =
- pos - codeSectionLocation;
- }
-}
-
void WasmBinaryBuilder::pushBlockElements(Block* curr,
Type type,
size_t start) {
diff --git a/src/wasm/wasm-debug.cpp b/src/wasm/wasm-debug.cpp
index 52baaf24d..2c5ed9515 100644
--- a/src/wasm/wasm-debug.cpp
+++ b/src/wasm/wasm-debug.cpp
@@ -361,7 +361,7 @@ struct AddrExprMap {
// bloat the common case which is represented in the earlier maps.
struct DelimiterInfo {
Expression* expr;
- BinaryLocations::DelimiterId id;
+ size_t id;
};
std::unordered_map<BinaryLocation, DelimiterInfo> delimiterMap;
@@ -414,8 +414,7 @@ private:
for (Index i = 0; i < delimiter.size(); i++) {
if (delimiter[i] != 0) {
assert(delimiterMap.count(delimiter[i]) == 0);
- delimiterMap[delimiter[i]] =
- DelimiterInfo{expr, BinaryLocations::DelimiterId(i)};
+ delimiterMap[delimiter[i]] = DelimiterInfo{expr, i};
}
}
}
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 8a5726f1f..fae9da140 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -1887,9 +1887,8 @@ void BinaryInstWriter::emitCatch(Try* curr, Index i) {
assert(!breakStack.empty());
breakStack.pop_back();
breakStack.emplace_back(IMPOSSIBLE_CONTINUE);
- // TODO Fix handling of BinaryLocations for the new EH spec
if (func && !sourceMap) {
- parent.writeExtraDebugLocation(curr, func, BinaryLocations::Catch);
+ parent.writeExtraDebugLocation(curr, func, i);
}
o << int8_t(BinaryConsts::Catch)
<< U32LEB(parent.getEventIndex(curr->catchEvents[i]));
@@ -1899,7 +1898,9 @@ void BinaryInstWriter::emitCatchAll(Try* curr) {
assert(!breakStack.empty());
breakStack.pop_back();
breakStack.emplace_back(IMPOSSIBLE_CONTINUE);
- // TODO Fix handling of BinaryLocations for the new EH spec
+ if (func && !sourceMap) {
+ parent.writeExtraDebugLocation(curr, func, curr->catchBodies.size());
+ }
o << int8_t(BinaryConsts::CatchAll);
}