summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-binary.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm/wasm-binary.cpp')
-rw-r--r--src/wasm/wasm-binary.cpp80
1 files changed, 65 insertions, 15 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 71dd0fc21..fa90532d9 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -72,6 +72,14 @@ void WasmBinaryWriter::write() {
writeSourceMapEpilog();
}
+#ifdef BUILD_LLVM_DWARF
+ // Update DWARF user sections after writing the data referred to by them
+ // (function bodies), and before writing the user sections themselves.
+ if (Debug::hasDWARFSections(*wasm)) {
+ Debug::writeDWARFSections(*wasm, binaryLocations);
+ }
+#endif
+
writeLateUserSections();
writeFeaturesSection();
@@ -109,6 +117,7 @@ template<typename T> int32_t WasmBinaryWriter::startSection(T code) {
if (sourceMap) {
sourceMapLocationsSizeAtSectionStart = sourceMapLocations.size();
}
+ binaryLocationsSizeAtSectionStart = binaryLocations.size();
return writeU32LEBPlaceholder(); // section size to be filled in later
}
@@ -116,22 +125,44 @@ void WasmBinaryWriter::finishSection(int32_t start) {
// section size does not include the reserved bytes of the size field itself
int32_t size = o.size() - start - MaxLEB32Bytes;
auto sizeFieldSize = o.writeAt(start, U32LEB(size));
- if (sizeFieldSize != MaxLEB32Bytes) {
+ // We can move things back if the actual LEB for the size doesn't use the
+ // maximum 5 bytes. In that case we need to adjust offsets after we move
+ // things backwards.
+ auto adjustmentForLEBShrinking = MaxLEB32Bytes - sizeFieldSize;
+ if (adjustmentForLEBShrinking) {
// we can save some room, nice
assert(sizeFieldSize < MaxLEB32Bytes);
std::move(&o[start] + MaxLEB32Bytes,
&o[start] + MaxLEB32Bytes + size,
&o[start] + sizeFieldSize);
- auto adjustment = MaxLEB32Bytes - sizeFieldSize;
- o.resize(o.size() - adjustment);
+ o.resize(o.size() - adjustmentForLEBShrinking);
if (sourceMap) {
for (auto i = sourceMapLocationsSizeAtSectionStart;
i < sourceMapLocations.size();
++i) {
- sourceMapLocations[i].first -= adjustment;
+ sourceMapLocations[i].first -= adjustmentForLEBShrinking;
}
}
}
+
+ if (binaryLocationsSizeAtSectionStart != binaryLocations.size()) {
+ // We added the binary locations, adjust them: they must be relative
+ // to the code section.
+ assert(binaryLocationsSizeAtSectionStart == 0);
+ // The section type byte is right before the LEB for the size; we want
+ // offsets that are relative to the body, which is after that section type
+ // byte and the the size LEB.
+ auto body = start + sizeFieldSize;
+ for (auto& pair : binaryLocations) {
+ // Offsets are relative to the body of the code section: after the
+ // section type byte and the size.
+ // Everything was moved by the adjustment, track that. After this,
+ // we are at the right absolute address.
+ pair.second -= adjustmentForLEBShrinking;
+ // We are relative to the section start.
+ pair.second -= body;
+ }
+ }
}
int32_t
@@ -266,6 +297,7 @@ void WasmBinaryWriter::writeFunctions() {
auto start = startSection(BinaryConsts::Section::Code);
o << U32LEB(importInfo->getNumDefinedFunctions());
ModuleUtils::iterDefinedFunctions(*wasm, [&](Function* func) {
+ assert(binaryLocationTrackedExpressionsForFunc.empty());
size_t sourceMapLocationsSizeAtFunctionStart = sourceMapLocations.size();
BYN_TRACE("write one at" << o.size() << std::endl);
size_t sizePos = writeU32LEBPlaceholder();
@@ -284,22 +316,31 @@ void WasmBinaryWriter::writeFunctions() {
BYN_TRACE("body size: " << size << ", writing at " << sizePos
<< ", next starts at " << o.size() << "\n");
auto sizeFieldSize = o.writeAt(sizePos, U32LEB(size));
- if (sizeFieldSize != MaxLEB32Bytes) {
+ // We can move things back if the actual LEB for the size doesn't use the
+ // maximum 5 bytes. In that case we need to adjust offsets after we move
+ // things backwards.
+ auto adjustmentForLEBShrinking = MaxLEB32Bytes - sizeFieldSize;
+ if (adjustmentForLEBShrinking) {
// we can save some room, nice
assert(sizeFieldSize < MaxLEB32Bytes);
std::move(&o[start], &o[start] + size, &o[sizePos] + sizeFieldSize);
- auto adjustment = MaxLEB32Bytes - sizeFieldSize;
- o.resize(o.size() - adjustment);
+ o.resize(o.size() - adjustmentForLEBShrinking);
if (sourceMap) {
for (auto i = sourceMapLocationsSizeAtFunctionStart;
i < sourceMapLocations.size();
++i) {
- sourceMapLocations[i].first -= adjustment;
+ sourceMapLocations[i].first -= adjustmentForLEBShrinking;
}
}
+ for (auto* curr : binaryLocationTrackedExpressionsForFunc) {
+ // We added the binary locations, adjust them: they must be relative
+ // to the code section.
+ binaryLocations[curr] -= adjustmentForLEBShrinking;
+ }
}
tableOfContents.functionBodies.emplace_back(
func->name, sizePos + sizeFieldSize, size);
+ binaryLocationTrackedExpressionsForFunc.clear();
});
finishSection(start);
}
@@ -649,10 +690,19 @@ void WasmBinaryWriter::writeDebugLocation(const Function::DebugLocation& loc) {
}
void WasmBinaryWriter::writeDebugLocation(Expression* curr, Function* func) {
- auto& debugLocations = func->debugLocations;
- auto iter = debugLocations.find(curr);
- if (iter != debugLocations.end()) {
- writeDebugLocation(iter->second);
+ if (sourceMap) {
+ auto& debugLocations = func->debugLocations;
+ auto iter = debugLocations.find(curr);
+ if (iter != debugLocations.end()) {
+ writeDebugLocation(iter->second);
+ }
+ }
+ // TODO: remove source map debugging support and refactor this method
+ // to something that directly thinks about DWARF, instead of indirectly
+ // looking at func->binaryLocations as a proxy for that etc.
+ if (func && !func->binaryLocations.empty()) {
+ binaryLocations[curr] = o.size();
+ binaryLocationTrackedExpressionsForFunc.push_back(curr);
}
}
@@ -809,6 +859,9 @@ void WasmBinaryBuilder::read() {
readFunctionSignatures();
break;
case BinaryConsts::Section::Code:
+ if (DWARF) {
+ codeSectionLocation = pos;
+ }
readFunctions();
break;
case BinaryConsts::Section::Export:
@@ -1288,9 +1341,6 @@ void WasmBinaryBuilder::readFunctionSignatures() {
void WasmBinaryBuilder::readFunctions() {
BYN_TRACE("== readFunctions\n");
- if (DWARF) {
- codeSectionLocation = pos;
- }
size_t total = getU32LEB();
if (total != functionSignatures.size()) {
throwError("invalid function section size, must equal types");