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_EPILOGUE_BEGIN = 0x0B;
public static final int DW_LNS_SET_ISA = 0x0C; public static final int DW_LNS_SET_ISA = 0x0C;
public static final int DW_LNE_END_SEQUENCE = 0x01;
private DwarfConstants() { private DwarfConstants() {
} }
} }

View File

@ -122,6 +122,10 @@ public class DwarfGenerator {
lines.lineNumber(address, fileName, lineNumber); lines.lineNumber(address, fileName, lineNumber);
} }
public void endLineNumberSequence(int address) {
lines.endLineNumberSequence(address);
}
public DwarfInfoWriter getInfoWriter() { public DwarfInfoWriter getInfoWriter() {
return infoWriter; 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_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_DIRECTORY_INDEX;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_LNCT_PATH; 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_LINE;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_LNS_ADVANCE_PC; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_LNS_ADVANCE_PC;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_LNS_COPY; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_LNS_COPY;
@ -171,28 +172,45 @@ class DwarfLinesGenerator {
instructionsBlob.writeLEB(fileRef); instructionsBlob.writeLEB(fileRef);
changed = true; changed = true;
} }
if (address != this.address || line != this.line) { if (advanceTo(address, 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);
}
}
changed = true; changed = true;
this.line = line;
this.address = address;
} }
if (changed) { if (changed) {
instructionsBlob.writeByte(DW_LNS_COPY); 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) { private boolean tryEmitSpecial(int lineIncrement, int addressIncrement) {
if (lineIncrement < LINE_BASE || lineIncrement >= LINE_BASE + LINE_RANGE) { if (lineIncrement < LINE_BASE || lineIncrement >= LINE_BASE + LINE_RANGE) {
return false; return false;

View File

@ -275,8 +275,8 @@ public class WasmBinaryRenderer {
section.writeLEB(functions.size()); section.writeLEB(functions.size());
for (var function : functions) { for (var function : functions) {
var body = renderFunction(function, section.getPosition()); var body = renderFunction(function, section.getPosition() + 4);
section.writeLEB(body.length); section.writeLEB4(body.length);
section.writeBytes(body); section.writeBytes(body);
} }
@ -322,12 +322,16 @@ public class WasmBinaryRenderer {
for (WasmExpression part : function.getBody()) { for (WasmExpression part : function.getBody()) {
part.acceptVisitor(visitor); part.acceptVisitor(visitor);
} }
code.writeByte(0x0B);
if (dwarfGenerator != null) {
dwarfGenerator.endLineNumberSequence(offset + code.getPosition());
}
code.writeByte(0x0B);
if (dwarfGenerator != null && function.getName() != null) { if (dwarfGenerator != null && function.getName() != null) {
infoWriter.tag(getMethodAbbrev()); infoWriter.tag(getMethodAbbrev());
infoWriter.writeInt(dwarfGenerator.strings.stringRef(function.getName())); infoWriter.writeInt(dwarfGenerator.strings.stringRef(function.getName()));
infoWriter.writeInt(offset); infoWriter.writeInt(offset - 4);
infoWriter.writeInt(offset + code.getPosition()); infoWriter.writeInt(offset + code.getPosition());
infoWriter.emptyTag(); 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) { public void writeSignedLEB(int v) {
alloc(5); alloc(5);
while (true) { while (true) {