Wasm: fix bugs in DWARF generator, emit DW_LNE_end_sequence after each function

This commit is contained in:
Alexey Andreev 2022-11-19 15:14:21 +01:00
parent 0604c6a613
commit f7768efd51
5 changed files with 57 additions and 19 deletions

View File

@ -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() {
}
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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();
}

View File

@ -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) {