Wasm: split declarations and specifications of methods in DWARF

This commit is contained in:
Alexey Andreev 2022-11-21 16:00:27 +01:00
parent 8fac3237ba
commit 13cc56feb5
4 changed files with 81 additions and 28 deletions

View File

@ -547,8 +547,11 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
}
var writer = new WasmBinaryWriter();
if (dwarfClassGen != null) {
dwarfClassGen.write(dwarfGenerator.getInfoWriter(), dwarfGenerator.strings);
}
var renderer = new WasmBinaryRenderer(writer, version, obfuscated, dwarfGenerator, dwarfClassGen);
renderer.render(module, buildDwarf(dwarfGenerator, dwarfClassGen));
renderer.render(module, buildDwarf(dwarfGenerator));
try (OutputStream output = buildTarget.createResource(outputName)) {
output.write(writer.getData());
@ -567,13 +570,11 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
}
}
private Supplier<Collection<? extends WasmCustomSection>> buildDwarf(DwarfGenerator generator,
DwarfClassGenerator classGen) {
private Supplier<Collection<? extends WasmCustomSection>> buildDwarf(DwarfGenerator generator) {
if (generator == null) {
return null;
}
return () -> {
classGen.write(generator.getInfoWriter(), generator.strings);
generator.end();
return generator.createSections();
};

View File

@ -31,6 +31,9 @@ public final class DwarfConstants {
public static final int DW_AT_HIGH_PC = 0x12;
public static final int DW_AT_LANGUAGE = 0x13;
public static final int DW_AT_PRODUCER = 0x25;
public static final int DW_AT_DECLARATION = 0x3c;
public static final int DW_AT_SPECIFICATION = 0x47;
public static final int DW_AT_LINKAGE_NAME = 0x6E;
public static final int DW_LANG_JAVA = 0x0b;
@ -43,8 +46,11 @@ public final class DwarfConstants {
public static final int DW_FORM_ADDR = 0x01;
public static final int DW_FORM_DATA2 = 0x05;
public static final int DW_FORM_DATA4 = 0x06;
public static final int DW_FORM_FLAG = 0x0C;
public static final int DW_FORM_STRP = 0x0E;
public static final int DW_FORM_REF4 = 0x13;
public static final int DW_FORM_SEC_OFFSET = 0x17;
public static final int DW_FORM_FLAG_PRESENT = 0x19;
public static final int DW_FORM_LINE_STRP = 0x1F;
public static final int DW_LNS_COPY = 0x01;

View File

@ -15,10 +15,9 @@
*/
package org.teavm.backend.wasm.generate;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_HIGH_PC;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_LOW_PC;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_DECLARATION;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_NAME;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_ADDR;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_FLAG_PRESENT;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_STRP;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_CLASS_TYPE;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_NAMESPACE;
@ -30,6 +29,7 @@ import java.util.List;
import java.util.Map;
import org.teavm.backend.wasm.dwarf.DwarfAbbreviation;
import org.teavm.backend.wasm.dwarf.DwarfInfoWriter;
import org.teavm.backend.wasm.dwarf.DwarfPlaceholder;
import org.teavm.model.MethodDescriptor;
public class DwarfClassGenerator {
@ -64,13 +64,6 @@ public class DwarfClassGenerator {
return subprogramsByFunctionName.get(functionName);
}
public Subprogram createSubprogram(String functionName) {
var subprogram = new Subprogram(functionName);
subprogramsByFunctionName.put(functionName, subprogram);
rootSubprograms.add(subprogram);
return subprogram;
}
public void write(DwarfInfoWriter infoWriter, DwarfStrings strings) {
this.infoWriter = infoWriter;
this.strings = strings;
@ -87,8 +80,7 @@ public class DwarfClassGenerator {
if (methodAbbrev == null) {
methodAbbrev = infoWriter.abbreviation(DW_TAG_SUBPROGRAM, true, data -> {
data.writeLEB(DW_AT_NAME).writeLEB(DW_FORM_STRP);
data.writeLEB(DW_AT_LOW_PC).writeLEB(DW_FORM_ADDR);
data.writeLEB(DW_AT_HIGH_PC).writeLEB(DW_FORM_ADDR);
data.writeLEB(DW_AT_DECLARATION).writeLEB(DW_FORM_FLAG_PRESENT);
});
}
return methodAbbrev;
@ -170,18 +162,16 @@ public class DwarfClassGenerator {
public class Subprogram {
public final String name;
public int startAddress;
public int endAddress;
public DwarfPlaceholder ref;
private Subprogram(String name) {
this.name = name;
}
private void write() {
infoWriter.tag(getMethodAbbrev());
ref = infoWriter.placeholder(4);
infoWriter.mark(ref).tag(getMethodAbbrev());
infoWriter.writeInt(strings.stringRef(name));
infoWriter.writeInt(startAddress);
infoWriter.writeInt(endAddress);
infoWriter.emptyTag();
}
}

View File

@ -15,6 +15,14 @@
*/
package org.teavm.backend.wasm.render;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_HIGH_PC;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_LOW_PC;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_NAME;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_SPECIFICATION;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_ADDR;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_REF4;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_STRP;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_SUBPROGRAM;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@ -23,6 +31,9 @@ import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.teavm.backend.wasm.dwarf.DwarfAbbreviation;
import org.teavm.backend.wasm.dwarf.blob.Blob;
import org.teavm.backend.wasm.dwarf.blob.Marker;
import org.teavm.backend.wasm.generate.DwarfClassGenerator;
import org.teavm.backend.wasm.generate.DwarfGenerator;
import org.teavm.backend.wasm.model.WasmCustomSection;
@ -57,6 +68,8 @@ public class WasmBinaryRenderer {
private boolean obfuscated;
private DwarfGenerator dwarfGenerator;
private DwarfClassGenerator dwarfClassGen;
private DwarfAbbreviation methodAbbrev;
private DwarfAbbreviation functionAbbrev;
public WasmBinaryRenderer(WasmBinaryWriter output, WasmBinaryVersion version, boolean obfuscated,
DwarfGenerator dwarfGenerator, DwarfClassGenerator dwarfClassGen) {
@ -286,6 +299,25 @@ public class WasmBinaryRenderer {
private byte[] renderFunction(WasmFunction function, int offset) {
var code = new WasmBinaryWriter();
Marker endProgramMarker;
if (dwarfClassGen != null && function.getName() != null) {
var dwarfSubprogram = dwarfClassGen.getSubprogram(function.getName());
var writer = dwarfGenerator.getInfoWriter();
var strings = dwarfGenerator.strings;
writer.tag(dwarfSubprogram != null ? getMethodAbbrev() : getFunctionAbbrev());
if (dwarfSubprogram != null) {
writer.ref(dwarfSubprogram.ref, Blob::writeInt);
} else {
writer.writeInt(strings.stringRef(
dwarfSubprogram != null ? dwarfSubprogram.name : function.getName()));
}
writer.writeInt(offset);
endProgramMarker = writer.marker();
writer.skip(4);
} else {
endProgramMarker = null;
}
List<WasmLocal> localVariables = function.getLocalVariables();
int parameterCount = Math.min(function.getParameters().size(), localVariables.size());
localVariables = localVariables.subList(parameterCount, localVariables.size());
@ -324,13 +356,14 @@ public class WasmBinaryRenderer {
}
code.writeByte(0x0B);
if (dwarfClassGen != null && function.getName() != null) {
var dwarfSubprogram = dwarfClassGen.getSubprogram(function.getName());
if (dwarfSubprogram == null) {
dwarfSubprogram = dwarfClassGen.createSubprogram(function.getName());
}
dwarfSubprogram.startAddress = offset;
dwarfSubprogram.endAddress = offset + code.getPosition();
if (endProgramMarker != null) {
var dwarfWriter = dwarfGenerator.getInfoWriter();
var backup = dwarfWriter.marker();
endProgramMarker.rewind();
dwarfWriter.writeInt(offset + code.getPosition());
backup.rewind();
dwarfWriter.emptyTag();
}
return code.getData();
@ -432,4 +465,27 @@ public class WasmBinaryRenderer {
output.writeBytes(data);
}
private DwarfAbbreviation getMethodAbbrev() {
if (methodAbbrev == null) {
methodAbbrev = dwarfGenerator.getInfoWriter().abbreviation(DW_TAG_SUBPROGRAM, true, data -> {
data.writeLEB(DW_AT_SPECIFICATION).writeLEB(DW_FORM_REF4);
data.writeLEB(DW_AT_LOW_PC).writeLEB(DW_FORM_ADDR);
data.writeLEB(DW_AT_HIGH_PC).writeLEB(DW_FORM_ADDR);
});
}
return methodAbbrev;
}
private DwarfAbbreviation getFunctionAbbrev() {
if (functionAbbrev == null) {
functionAbbrev = dwarfGenerator.getInfoWriter().abbreviation(DW_TAG_SUBPROGRAM, true, data -> {
data.writeLEB(DW_AT_NAME).writeLEB(DW_FORM_STRP);
data.writeLEB(DW_AT_LOW_PC).writeLEB(DW_FORM_ADDR);
data.writeLEB(DW_AT_HIGH_PC).writeLEB(DW_FORM_ADDR);
});
}
return functionAbbrev;
}
}