From f7768efd51d84e9263e3daf94f474fe651090b40 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Sat, 19 Nov 2022 15:14:21 +0100 Subject: [PATCH] Wasm: fix bugs in DWARF generator, emit DW_LNE_end_sequence after each function --- .../backend/wasm/dwarf/DwarfConstants.java | 2 + .../backend/wasm/generate/DwarfGenerator.java | 4 ++ .../wasm/generate/DwarfLinesGenerator.java | 48 +++++++++++++------ .../wasm/render/WasmBinaryRenderer.java | 12 +++-- .../backend/wasm/render/WasmBinaryWriter.java | 10 ++++ 5 files changed, 57 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/org/teavm/backend/wasm/dwarf/DwarfConstants.java b/core/src/main/java/org/teavm/backend/wasm/dwarf/DwarfConstants.java index 0716711f1..b3d951b75 100644 --- a/core/src/main/java/org/teavm/backend/wasm/dwarf/DwarfConstants.java +++ b/core/src/main/java/org/teavm/backend/wasm/dwarf/DwarfConstants.java @@ -55,6 +55,8 @@ public final class DwarfConstants { public static final int DW_LNS_SET_EPILOGUE_BEGIN = 0x0B; public static final int DW_LNS_SET_ISA = 0x0C; + public static final int DW_LNE_END_SEQUENCE = 0x01; + private DwarfConstants() { } } diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/DwarfGenerator.java b/core/src/main/java/org/teavm/backend/wasm/generate/DwarfGenerator.java index 60144bd54..3f97ff8d5 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/DwarfGenerator.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/DwarfGenerator.java @@ -122,6 +122,10 @@ public class DwarfGenerator { lines.lineNumber(address, fileName, lineNumber); } + public void endLineNumberSequence(int address) { + lines.endLineNumberSequence(address); + } + public DwarfInfoWriter getInfoWriter() { return infoWriter; } diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/DwarfLinesGenerator.java b/core/src/main/java/org/teavm/backend/wasm/generate/DwarfLinesGenerator.java index 717fde85a..709bde180 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/DwarfLinesGenerator.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/DwarfLinesGenerator.java @@ -19,6 +19,7 @@ import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_DATA2; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_LINE_STRP; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_LNCT_DIRECTORY_INDEX; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_LNCT_PATH; +import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_LNE_END_SEQUENCE; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_LNS_ADVANCE_LINE; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_LNS_ADVANCE_PC; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_LNS_COPY; @@ -171,28 +172,45 @@ class DwarfLinesGenerator { instructionsBlob.writeLEB(fileRef); changed = true; } - if (address != this.address || line != this.line) { - int lineIncrement = line - this.line; - int addressIncrement = address - this.address; - if (!tryEmitSpecial(lineIncrement, addressIncrement)) { - if (lineIncrement != 0) { - instructionsBlob.writeByte(DW_LNS_ADVANCE_LINE); - instructionsBlob.writeSLEB(lineIncrement); - } - if (addressIncrement != 0) { - instructionsBlob.writeByte(DW_LNS_ADVANCE_PC); - instructionsBlob.writeSLEB(addressIncrement); - } - } + if (advanceTo(address, line)) { changed = true; - this.line = line; - this.address = address; } if (changed) { instructionsBlob.writeByte(DW_LNS_COPY); } } + void endLineNumberSequence(int address) { + advanceTo(address, line); + instructionsBlob.writeByte(0); + instructionsBlob.writeByte(1); + instructionsBlob.writeByte(DW_LNE_END_SEQUENCE); + this.line = 1; + this.file = 0; + this.address = 0; + } + + private boolean advanceTo(int address, int line) { + if (address == this.address && line == this.line) { + return false; + } + int lineIncrement = line - this.line; + int addressIncrement = address - this.address; + if (!tryEmitSpecial(lineIncrement, addressIncrement)) { + if (lineIncrement != 0) { + instructionsBlob.writeByte(DW_LNS_ADVANCE_LINE); + instructionsBlob.writeSLEB(lineIncrement); + } + if (addressIncrement != 0) { + instructionsBlob.writeByte(DW_LNS_ADVANCE_PC); + instructionsBlob.writeLEB(addressIncrement); + } + } + this.line = line; + this.address = address; + return true; + } + private boolean tryEmitSpecial(int lineIncrement, int addressIncrement) { if (lineIncrement < LINE_BASE || lineIncrement >= LINE_BASE + LINE_RANGE) { return false; diff --git a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderer.java b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderer.java index ac1e33d2d..ac8dd6914 100644 --- a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderer.java +++ b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderer.java @@ -275,8 +275,8 @@ public class WasmBinaryRenderer { section.writeLEB(functions.size()); for (var function : functions) { - var body = renderFunction(function, section.getPosition()); - section.writeLEB(body.length); + var body = renderFunction(function, section.getPosition() + 4); + section.writeLEB4(body.length); section.writeBytes(body); } @@ -322,12 +322,16 @@ public class WasmBinaryRenderer { for (WasmExpression part : function.getBody()) { part.acceptVisitor(visitor); } - code.writeByte(0x0B); + if (dwarfGenerator != null) { + dwarfGenerator.endLineNumberSequence(offset + code.getPosition()); + } + + code.writeByte(0x0B); if (dwarfGenerator != null && function.getName() != null) { infoWriter.tag(getMethodAbbrev()); infoWriter.writeInt(dwarfGenerator.strings.stringRef(function.getName())); - infoWriter.writeInt(offset); + infoWriter.writeInt(offset - 4); infoWriter.writeInt(offset + code.getPosition()); infoWriter.emptyTag(); } diff --git a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryWriter.java b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryWriter.java index 7c823c62d..7f1b39b6c 100644 --- a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryWriter.java +++ b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryWriter.java @@ -92,6 +92,16 @@ public class WasmBinaryWriter { } } + public void writeLEB4(int v) { + alloc(4); + for (int i = 0; i < 3; ++i) { + int digit = v & 0x7F; + data[pointer++] = (byte) (digit | 0x80); + v >>>= 7; + } + data[pointer++] = (byte) (v & 0x7F); + } + public void writeSignedLEB(int v) { alloc(5); while (true) {