Wasm: write more info about classes in DWARF

This commit is contained in:
Alexey Andreev 2022-11-23 22:04:26 +01:00
parent 646c8ec488
commit 7e95e935d1
5 changed files with 86 additions and 5 deletions

View File

@ -24,6 +24,7 @@ public final class DwarfConstants {
public static final int DW_TAG_FORMAL_PARAMETER = 0x05; public static final int DW_TAG_FORMAL_PARAMETER = 0x05;
public static final int DW_TAG_POINTER_TYPE = 0x0F; public static final int DW_TAG_POINTER_TYPE = 0x0F;
public static final int DW_TAG_COMPILE_UNIT = 0x11; public static final int DW_TAG_COMPILE_UNIT = 0x11;
public static final int DW_TAG_INHERITANCE = 0x1C;
public static final int DW_TAG_BASE_TYPE = 0x24; public static final int DW_TAG_BASE_TYPE = 0x24;
public static final int DW_TAG_SUBPROGRAM = 0x2E; public static final int DW_TAG_SUBPROGRAM = 0x2E;
public static final int DW_TAG_VARIABLE = 0x34; public static final int DW_TAG_VARIABLE = 0x34;
@ -72,6 +73,8 @@ public final class DwarfConstants {
public static final int DW_FORM_FLAG_PRESENT = 0x19; public static final int DW_FORM_FLAG_PRESENT = 0x19;
public static final int DW_FORM_LINE_STRP = 0x1F; public static final int DW_FORM_LINE_STRP = 0x1F;
public static final int DW_OP_ADDR = 0x03;
public static final int DW_OP_STACK_VALUE = 0x9F;
public static final int DW_OP_WASM_LOCATION = 0xED; public static final int DW_OP_WASM_LOCATION = 0xED;
public static final int DW_LNS_COPY = 0x01; public static final int DW_LNS_COPY = 0x01;

View File

@ -20,6 +20,7 @@ import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_CHILDREN_YES;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.teavm.backend.wasm.dwarf.blob.BinaryDataConsumer; import org.teavm.backend.wasm.dwarf.blob.BinaryDataConsumer;
import org.teavm.backend.wasm.dwarf.blob.Blob; import org.teavm.backend.wasm.dwarf.blob.Blob;
@ -115,6 +116,7 @@ public class DwarfInfoWriter {
} }
public DwarfInfoWriter mark(DwarfPlaceholder placeholder) { public DwarfInfoWriter mark(DwarfPlaceholder placeholder) {
Objects.requireNonNull(placeholder);
placements.add(new Placement(output.ptr()) { placements.add(new Placement(output.ptr()) {
@Override @Override
void write(Blob blob) { void write(Blob blob) {

View File

@ -22,18 +22,25 @@ import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_ATE_UTF;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_BYTE_SIZE; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_BYTE_SIZE;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_DECLARATION; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_DECLARATION;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_ENCODING; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_ENCODING;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_LOCATION;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_NAME; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_NAME;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_TYPE; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_TYPE;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_DATA1; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_DATA1;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_DATA2;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_EXPRLOC;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_FLAG_PRESENT; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_FLAG_PRESENT;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_REF4; 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_FORM_STRP;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_OP_ADDR;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_OP_STACK_VALUE;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_BASE_TYPE; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_BASE_TYPE;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_CLASS_TYPE; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_CLASS_TYPE;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_INHERITANCE;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_NAMESPACE; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_NAMESPACE;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_POINTER_TYPE; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_POINTER_TYPE;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_SUBPROGRAM; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_SUBPROGRAM;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_UNSPECIFIED_TYPE; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_UNSPECIFIED_TYPE;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_VARIABLE;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -57,12 +64,15 @@ public class DwarfClassGenerator {
private final DwarfStrings strings; private final DwarfStrings strings;
private DwarfAbbreviation nsAbbrev; private DwarfAbbreviation nsAbbrev;
private DwarfAbbreviation classTypeAbbrev; private DwarfAbbreviation classTypeAbbrev;
private DwarfAbbreviation inheritanceAbbrev;
private DwarfAbbreviation methodAbbrev; private DwarfAbbreviation methodAbbrev;
private DwarfPlaceholder[] primitiveTypes = new DwarfPlaceholder[PrimitiveType.values().length]; private DwarfPlaceholder[] primitiveTypes = new DwarfPlaceholder[PrimitiveType.values().length];
private DwarfPlaceholder unspecifiedType; private DwarfPlaceholder unspecifiedType;
private DwarfAbbreviation baseTypeAbbrev; private DwarfAbbreviation baseTypeAbbrev;
private DwarfAbbreviation pointerAbbrev; private DwarfAbbreviation pointerAbbrev;
private DwarfAbbreviation variableAbbrev;
private List<Runnable> postponedWrites = new ArrayList<>(); private List<Runnable> postponedWrites = new ArrayList<>();
private ClassType classClass;
public DwarfClassGenerator(DwarfInfoWriter writer, DwarfStrings strings) { public DwarfClassGenerator(DwarfInfoWriter writer, DwarfStrings strings) {
this.writer = writer; this.writer = writer;
@ -99,10 +109,12 @@ public class DwarfClassGenerator {
} }
public void write() { public void write() {
classClass = getClass("java.lang.Class");
root.writeChildren(); root.writeChildren();
for (var subprogram : rootSubprograms) { for (var subprogram : rootSubprograms) {
subprogram.write(); subprogram.write();
} }
flushTypes();
} }
private DwarfAbbreviation getMethodAbbrev() { private DwarfAbbreviation getMethodAbbrev() {
@ -128,11 +140,21 @@ public class DwarfClassGenerator {
if (classTypeAbbrev == null) { if (classTypeAbbrev == null) {
classTypeAbbrev = writer.abbreviation(DW_TAG_CLASS_TYPE, true, data -> { classTypeAbbrev = writer.abbreviation(DW_TAG_CLASS_TYPE, true, data -> {
data.writeLEB(DW_AT_NAME).writeLEB(DW_FORM_STRP); data.writeLEB(DW_AT_NAME).writeLEB(DW_FORM_STRP);
data.writeLEB(DW_AT_BYTE_SIZE).writeLEB(DW_FORM_DATA2);
}); });
} }
return classTypeAbbrev; return classTypeAbbrev;
} }
private DwarfAbbreviation getInheritanceAbbrev() {
if (inheritanceAbbrev == null) {
inheritanceAbbrev = writer.abbreviation(DW_TAG_INHERITANCE, false, data -> {
data.writeLEB(DW_AT_TYPE).writeLEB(DW_FORM_REF4);
});
}
return inheritanceAbbrev;
}
public DwarfPlaceholder getTypePtr(VariableType type) { public DwarfPlaceholder getTypePtr(VariableType type) {
switch (type) { switch (type) {
case INT: case INT:
@ -169,7 +191,7 @@ public class DwarfClassGenerator {
} }
private DwarfPlaceholder getClassType(String name) { private DwarfPlaceholder getClassType(String name) {
return getClass(name).getPointerPtr(); return getClass(name).ptr;
} }
private DwarfPlaceholder getPrimitivePtr(ValueType.Primitive type) { private DwarfPlaceholder getPrimitivePtr(ValueType.Primitive type) {
@ -256,6 +278,17 @@ public class DwarfClassGenerator {
return pointerAbbrev; return pointerAbbrev;
} }
private DwarfAbbreviation getVariableAbbrev() {
if (variableAbbrev == null) {
variableAbbrev = writer.abbreviation(DW_TAG_VARIABLE, false, blob -> {
blob.writeLEB(DW_AT_NAME).writeLEB(DW_FORM_STRP);
blob.writeLEB(DW_AT_TYPE).writeLEB(DW_FORM_REF4);
blob.writeLEB(DW_AT_LOCATION).writeLEB(DW_FORM_EXPRLOC);
});
}
return variableAbbrev;
}
public class Namespace { public class Namespace {
public final String name; public final String name;
final Map<String, Namespace> namespaces = new LinkedHashMap<>(); final Map<String, Namespace> namespaces = new LinkedHashMap<>();
@ -295,16 +328,31 @@ public class DwarfClassGenerator {
final DwarfPlaceholder ptr; final DwarfPlaceholder ptr;
private DwarfPlaceholder pointerPtr; private DwarfPlaceholder pointerPtr;
final Map<MethodDescriptor, Subprogram> subprograms = new LinkedHashMap<>(); final Map<MethodDescriptor, Subprogram> subprograms = new LinkedHashMap<>();
private ClassType superclass;
private int size;
private int pointer = -1;
private ClassType(String name) { private ClassType(String name) {
ptr = writer.placeholder(4); ptr = writer.placeholder(4);
this.name = name; this.name = name;
} }
public void setSuperclass(ClassType superclass) {
this.superclass = superclass;
}
public Subprogram getSubprogram(MethodDescriptor desc) { public Subprogram getSubprogram(MethodDescriptor desc) {
return subprograms.computeIfAbsent(desc, d -> new Subprogram(d.getName(), desc)); return subprograms.computeIfAbsent(desc, d -> new Subprogram(d.getName(), desc));
} }
public void setSize(int size) {
this.size = size;
}
public void setPointer(int pointer) {
this.pointer = pointer;
}
public DwarfPlaceholder getPointerPtr() { public DwarfPlaceholder getPointerPtr() {
if (pointerPtr == null) { if (pointerPtr == null) {
pointerPtr = writer.placeholder(4); pointerPtr = writer.placeholder(4);
@ -315,6 +363,10 @@ public class DwarfClassGenerator {
private void write() { private void write() {
writer.mark(ptr).tag(getClassTypeAbbrev()); writer.mark(ptr).tag(getClassTypeAbbrev());
writer.writeInt(strings.stringRef(name)); writer.writeInt(strings.stringRef(name));
writer.writeShort(size);
if (superclass != null) {
writer.tag(getInheritanceAbbrev()).ref(superclass.ptr, Blob::writeInt);
}
for (var child : subprograms.values()) { for (var child : subprograms.values()) {
child.write(); child.write();
} }
@ -322,6 +374,15 @@ public class DwarfClassGenerator {
writer.mark(pointerPtr).tag(getPointerAbbrev()); writer.mark(pointerPtr).tag(getPointerAbbrev());
writer.ref(ptr, Blob::writeInt); writer.ref(ptr, Blob::writeInt);
} }
if (pointer >= 0) {
writer.tag(getVariableAbbrev());
writer.writeInt(strings.stringRef("__class__"));
writer.ref(classClass.ptr, Blob::writeInt);
var ops = new Blob();
ops.writeByte(DW_OP_ADDR).writeInt(pointer).writeByte(DW_OP_STACK_VALUE);
writer.writeLEB(ops.size());
ops.newReader(writer::write).readRemaining();
}
writer.emptyTag(); writer.emptyTag();
} }
} }

View File

@ -25,6 +25,7 @@ import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_ADDR;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_EXPRLOC; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_EXPRLOC;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_REF4; 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_FORM_STRP;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_OP_STACK_VALUE;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_OP_WASM_LOCATION; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_OP_WASM_LOCATION;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_FORMAL_PARAMETER; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_FORMAL_PARAMETER;
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_SUBPROGRAM; import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_SUBPROGRAM;
@ -33,6 +34,7 @@ import org.teavm.backend.wasm.dwarf.DwarfAbbreviation;
import org.teavm.backend.wasm.dwarf.blob.Blob; import org.teavm.backend.wasm.dwarf.blob.Blob;
import org.teavm.backend.wasm.dwarf.blob.Marker; import org.teavm.backend.wasm.dwarf.blob.Marker;
import org.teavm.backend.wasm.model.WasmFunction; import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.model.util.VariableType;
public class DwarfFunctionGenerator { public class DwarfFunctionGenerator {
private DwarfClassGenerator classGen; private DwarfClassGenerator classGen;
@ -114,6 +116,9 @@ public class DwarfFunctionGenerator {
var operations = new Blob(); var operations = new Blob();
operations.writeByte(DW_OP_WASM_LOCATION).writeByte(0).writeLEB(i + 1); operations.writeByte(DW_OP_WASM_LOCATION).writeByte(0).writeLEB(i + 1);
if (local.getJavaType() == VariableType.OBJECT) {
operations.writeByte(DW_OP_STACK_VALUE);
}
writer.writeLEB(operations.size()); writer.writeLEB(operations.size());
operations.newReader(writer::write).readRemaining(); operations.newReader(writer::write).readRemaining();
} }

View File

@ -179,12 +179,22 @@ public class WasmClassGenerator {
var cls = classSource.get(className); var cls = classSource.get(className);
if (cls != null) { if (cls != null) {
calculateLayout(cls, binaryData); DwarfClassGenerator.ClassType dwarfClass;
if (dwarfClassGenerator != null) {
dwarfClass = dwarfClassGenerator.getClass(className);
dwarfClass.setSuperclass(cls.getParent() != null
? dwarfClassGenerator.getClass(cls.getParent())
: null);
} else {
dwarfClass = null;
}
calculateLayout(cls, binaryData, dwarfClass);
if (binaryData.start >= 0) { if (binaryData.start >= 0) {
binaryData.start = binaryWriter.append(createStructure(binaryData)); binaryData.start = binaryWriter.append(createStructure(binaryData));
} }
if (dwarfClassGenerator != null) { if (dwarfClass != null) {
dwarfClassGenerator.getClass(className); dwarfClass.setSize(binaryData.size);
dwarfClass.setPointer(binaryData.start);
} }
} }
} else if (type instanceof ValueType.Array) { } else if (type instanceof ValueType.Array) {
@ -486,7 +496,7 @@ public class WasmClassGenerator {
return binaryDataMap.get(type).function; return binaryDataMap.get(type).function;
} }
private void calculateLayout(ClassReader cls, ClassBinaryData data) { private void calculateLayout(ClassReader cls, ClassBinaryData data, DwarfClassGenerator.ClassType dwarfClass) {
if (cls.getName().equals(Structure.class.getName()) || cls.getName().equals(Address.class.getName())) { if (cls.getName().equals(Structure.class.getName()) || cls.getName().equals(Address.class.getName())) {
data.size = 0; data.size = 0;
data.start = -1; data.start = -1;