mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
wasm: generate field description in DWARF
This commit is contained in:
parent
fed6a2d0ef
commit
cacf09dca8
|
@ -22,6 +22,7 @@ public final class DwarfConstants {
|
|||
|
||||
public static final int DW_TAG_CLASS_TYPE = 0x02;
|
||||
public static final int DW_TAG_FORMAL_PARAMETER = 0x05;
|
||||
public static final int DW_TAG_MEMBER = 0x0d;
|
||||
public static final int DW_TAG_POINTER_TYPE = 0x0F;
|
||||
public static final int DW_TAG_COMPILE_UNIT = 0x11;
|
||||
public static final int DW_TAG_INHERITANCE = 0x1C;
|
||||
|
@ -38,7 +39,11 @@ public final class DwarfConstants {
|
|||
public static final int DW_AT_LOW_PC = 0x11;
|
||||
public static final int DW_AT_HIGH_PC = 0x12;
|
||||
public static final int DW_AT_LANGUAGE = 0x13;
|
||||
public static final int DW_AT_CONTAINING_TYPE = 0x1D;
|
||||
public static final int DW_AT_PRODUCER = 0x25;
|
||||
public static final int DW_AT_ACCESSIBILITY = 0x32;
|
||||
public static final int DW_AT_CALLING_CONVENTION = 0x36;
|
||||
public static final int DW_AT_DATA_MEMBER_LOCATION = 0x38;
|
||||
public static final int DW_AT_DECLARATION = 0x3C;
|
||||
public static final int DW_AT_ENCODING = 0x3E;
|
||||
public static final int DW_AT_SPECIFICATION = 0x47;
|
||||
|
@ -75,6 +80,10 @@ public final class DwarfConstants {
|
|||
public static final int DW_FORM_LINE_STRP = 0x1F;
|
||||
|
||||
public static final int DW_OP_ADDR = 0x03;
|
||||
public static final int DW_OP_DEREF = 0x06;
|
||||
public static final int DW_OP_SHL = 0x24;
|
||||
public static final int DW_OP_LIT0 = 0x30;
|
||||
public static final int DW_OP_LIT3 = 0x33;
|
||||
public static final int DW_OP_STACK_VALUE = 0x9F;
|
||||
public static final int DW_OP_WASM_LOCATION = 0xED;
|
||||
|
||||
|
@ -93,6 +102,10 @@ public final class DwarfConstants {
|
|||
|
||||
public static final int DW_LNE_END_SEQUENCE = 0x01;
|
||||
|
||||
public static final int DW_ACCESS_PUBLIC = 0x01;
|
||||
|
||||
public static final int DW_CC_PASS_BY_REFERENCE = 0x04;
|
||||
|
||||
private DwarfConstants() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,25 +15,34 @@
|
|||
*/
|
||||
package org.teavm.backend.wasm.generate;
|
||||
|
||||
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_ACCESS_PUBLIC;
|
||||
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_ATE_BOOLEAN;
|
||||
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_ATE_FLOAT;
|
||||
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_ATE_SIGNED;
|
||||
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_ATE_UTF;
|
||||
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_ACCESSIBILITY;
|
||||
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_BYTE_SIZE;
|
||||
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_CALLING_CONVENTION;
|
||||
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_CONTAINING_TYPE;
|
||||
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_DATA_MEMBER_LOCATION;
|
||||
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_TYPE;
|
||||
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_CC_PASS_BY_REFERENCE;
|
||||
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_REF4;
|
||||
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_OP_DEREF;
|
||||
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_OP_LIT3;
|
||||
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_OP_SHL;
|
||||
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_INHERITANCE;
|
||||
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_MEMBER;
|
||||
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_UNSPECIFIED_TYPE;
|
||||
|
@ -63,6 +72,8 @@ public class DwarfClassGenerator {
|
|||
private DwarfAbbreviation nsAbbrev;
|
||||
private DwarfAbbreviation classTypeAbbrev;
|
||||
private DwarfAbbreviation inheritanceAbbrev;
|
||||
private DwarfAbbreviation immutableMemberAbbrev;
|
||||
private DwarfAbbreviation memberAbbrev;
|
||||
private DwarfPlaceholder[] primitiveTypes = new DwarfPlaceholder[PrimitiveType.values().length];
|
||||
private DwarfPlaceholder unspecifiedType;
|
||||
private DwarfAbbreviation baseTypeAbbrev;
|
||||
|
@ -96,7 +107,11 @@ public class DwarfClassGenerator {
|
|||
ns = ns.getNamespace(fullName.substring(index, next));
|
||||
index = next + 1;
|
||||
}
|
||||
return ns.getClass(fullName.substring(index));
|
||||
var cls = ns.getClass(fullName.substring(index));
|
||||
if (fullName.equals("java.lang.Object")) {
|
||||
cls.isRoot = true;
|
||||
}
|
||||
return cls;
|
||||
}
|
||||
|
||||
public void registerSubprogram(String functionName, Subprogram subprogram) {
|
||||
|
@ -129,7 +144,9 @@ public class DwarfClassGenerator {
|
|||
if (classTypeAbbrev == null) {
|
||||
classTypeAbbrev = writer.abbreviation(DW_TAG_CLASS_TYPE, true, data -> {
|
||||
data.writeLEB(DW_AT_NAME).writeLEB(DW_FORM_STRP);
|
||||
data.writeLEB(DW_AT_CONTAINING_TYPE).writeLEB(DW_FORM_REF4);
|
||||
data.writeLEB(DW_AT_BYTE_SIZE).writeLEB(DW_FORM_DATA2);
|
||||
data.writeLEB(DW_AT_CALLING_CONVENTION).writeLEB(DW_FORM_DATA1);
|
||||
});
|
||||
}
|
||||
return classTypeAbbrev;
|
||||
|
@ -144,6 +161,30 @@ public class DwarfClassGenerator {
|
|||
return inheritanceAbbrev;
|
||||
}
|
||||
|
||||
private DwarfAbbreviation getImmutableMemberAbbrev() {
|
||||
if (immutableMemberAbbrev == null) {
|
||||
immutableMemberAbbrev = writer.abbreviation(DW_TAG_MEMBER, false, data -> {
|
||||
data.writeLEB(DW_AT_NAME).writeLEB(DW_FORM_STRP);
|
||||
data.writeLEB(DW_AT_TYPE).writeLEB(DW_FORM_REF4);
|
||||
data.writeLEB(DW_AT_DATA_MEMBER_LOCATION).writeLEB(DW_FORM_EXPRLOC);
|
||||
data.writeLEB(DW_AT_ACCESSIBILITY).writeLEB(DW_FORM_DATA1);
|
||||
});
|
||||
}
|
||||
return immutableMemberAbbrev;
|
||||
}
|
||||
|
||||
private DwarfAbbreviation getMemberAbbrev() {
|
||||
if (memberAbbrev == null) {
|
||||
memberAbbrev = writer.abbreviation(DW_TAG_MEMBER, false, data -> {
|
||||
data.writeLEB(DW_AT_NAME).writeLEB(DW_FORM_STRP);
|
||||
data.writeLEB(DW_AT_TYPE).writeLEB(DW_FORM_REF4);
|
||||
data.writeLEB(DW_AT_DATA_MEMBER_LOCATION).writeLEB(DW_FORM_DATA2);
|
||||
data.writeLEB(DW_AT_ACCESSIBILITY).writeLEB(DW_FORM_DATA1);
|
||||
});
|
||||
}
|
||||
return memberAbbrev;
|
||||
}
|
||||
|
||||
public DwarfPlaceholder getTypePtr(VariableType type) {
|
||||
switch (type) {
|
||||
case INT:
|
||||
|
@ -180,7 +221,7 @@ public class DwarfClassGenerator {
|
|||
}
|
||||
|
||||
private DwarfPlaceholder getClassType(String name) {
|
||||
return getClass(name).ptr;
|
||||
return getClass(name).getPointerPtr();
|
||||
}
|
||||
|
||||
private DwarfPlaceholder getPrimitivePtr(ValueType.Primitive type) {
|
||||
|
@ -314,9 +355,11 @@ public class DwarfClassGenerator {
|
|||
|
||||
public class ClassType {
|
||||
public final String name;
|
||||
boolean isRoot;
|
||||
final DwarfPlaceholder ptr;
|
||||
private DwarfPlaceholder pointerPtr;
|
||||
final Map<MethodDescriptor, Subprogram> subprograms = new LinkedHashMap<>();
|
||||
List<Field> fields;
|
||||
private ClassType superclass;
|
||||
private int size;
|
||||
private int pointer = -1;
|
||||
|
@ -342,6 +385,21 @@ public class DwarfClassGenerator {
|
|||
this.pointer = pointer;
|
||||
}
|
||||
|
||||
public void registerField(String name, ValueType type, int offset) {
|
||||
addField(new InstanceField(name, type, offset));
|
||||
}
|
||||
|
||||
public void registerStaticField(String name, ValueType type, int address) {
|
||||
addField(new StaticField(name, type, address));
|
||||
}
|
||||
|
||||
private void addField(Field field) {
|
||||
if (fields == null) {
|
||||
fields = new ArrayList<>();
|
||||
}
|
||||
fields.add(field);
|
||||
}
|
||||
|
||||
public DwarfPlaceholder getPointerPtr() {
|
||||
if (pointerPtr == null) {
|
||||
pointerPtr = writer.placeholder(4);
|
||||
|
@ -352,7 +410,9 @@ public class DwarfClassGenerator {
|
|||
private void write() {
|
||||
writer.mark(ptr).tag(getClassTypeAbbrev());
|
||||
writer.writeInt(strings.stringRef(name));
|
||||
writer.ref(ptr, Blob::writeInt);
|
||||
writer.writeShort(size);
|
||||
writer.writeByte(DW_CC_PASS_BY_REFERENCE);
|
||||
if (superclass != null) {
|
||||
writer.tag(getInheritanceAbbrev()).ref(superclass.ptr, Blob::writeInt);
|
||||
}
|
||||
|
@ -365,15 +425,38 @@ public class DwarfClassGenerator {
|
|||
}
|
||||
if (pointer >= 0) {
|
||||
writer.tag(getVariableAbbrev());
|
||||
writer.writeInt(strings.stringRef("__class__"));
|
||||
writer.ref(classClass.ptr, Blob::writeInt);
|
||||
writer.writeInt(strings.stringRef("__classData__"));
|
||||
writer.ref(classClass.getPointerPtr(), Blob::writeInt);
|
||||
var ops = new Blob();
|
||||
ops.writeByte(DW_OP_ADDR).writeInt(pointer).writeByte(DW_OP_STACK_VALUE);
|
||||
ops.writeByte(DW_OP_ADDR).writeInt(pointer);
|
||||
writer.writeLEB(ops.size());
|
||||
ops.newReader(writer::write).readRemaining();
|
||||
}
|
||||
if (isRoot) {
|
||||
writeClassPointerField();
|
||||
}
|
||||
writeFields();
|
||||
writer.emptyTag();
|
||||
}
|
||||
|
||||
private void writeClassPointerField() {
|
||||
writer.tag(getImmutableMemberAbbrev());
|
||||
writer.writeInt(strings.stringRef("__class__"));
|
||||
writer.ref(classClass.ptr, Blob::writeInt);
|
||||
var ops = new Blob();
|
||||
ops.writeByte(DW_OP_DEREF).writeByte(DW_OP_LIT3).writeByte(DW_OP_SHL);
|
||||
writer.writeLEB(ops.size());
|
||||
ops.newReader(writer::write).readRemaining();
|
||||
writer.writeByte(DW_ACCESS_PUBLIC);
|
||||
}
|
||||
|
||||
private void writeFields() {
|
||||
if (fields != null) {
|
||||
for (var field : fields) {
|
||||
field.write();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Subprogram {
|
||||
|
@ -395,4 +478,50 @@ public class DwarfClassGenerator {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract static class Field {
|
||||
String name;
|
||||
ValueType type;
|
||||
int offset;
|
||||
|
||||
Field(String name, ValueType type, int offset) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
abstract void write();
|
||||
}
|
||||
|
||||
class InstanceField extends Field {
|
||||
InstanceField(String name, ValueType type, int offset) {
|
||||
super(name, type, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
void write() {
|
||||
writer.tag(getMemberAbbrev());
|
||||
writer.writeInt(strings.stringRef(name));
|
||||
writer.ref(getTypePtr(type), Blob::writeInt);
|
||||
writer.writeShort(offset);
|
||||
writer.writeByte(DW_ACCESS_PUBLIC);
|
||||
}
|
||||
}
|
||||
|
||||
class StaticField extends Field {
|
||||
StaticField(String name, ValueType type, int offset) {
|
||||
super(name, type, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
void write() {
|
||||
writer.tag(getVariableAbbrev());
|
||||
writer.writeInt(strings.stringRef(name));
|
||||
writer.ref(getTypePtr(type), Blob::writeInt);
|
||||
var ops = new Blob();
|
||||
ops.writeByte(DW_OP_ADDR).writeInt(offset);
|
||||
writer.writeLEB(ops.size());
|
||||
ops.newReader(writer::write).readRemaining();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,6 +83,9 @@ public class DwarfFunctionGenerator {
|
|||
|
||||
var operations = new Blob();
|
||||
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());
|
||||
operations.newReader(writer::write).readRemaining();
|
||||
}
|
||||
|
|
|
@ -545,11 +545,20 @@ public class WasmClassGenerator {
|
|||
if (field.getInitialValue() != null) {
|
||||
setInitialValue(field.getType(), value, field.getInitialValue());
|
||||
}
|
||||
data.fieldLayout.put(field.getName(), binaryWriter.append(value));
|
||||
var address = binaryWriter.append(value);
|
||||
data.fieldLayout.put(field.getName(), address);
|
||||
if (dwarfClass != null) {
|
||||
dwarfClass.registerStaticField(field.getName(), field.getType(), address);
|
||||
dwarfClassGenerator.getTypePtr(field.getType());
|
||||
}
|
||||
} else {
|
||||
int offset = align(data.size, desiredAlignment);
|
||||
data.fieldLayout.put(field.getName(), offset);
|
||||
data.size = offset + desiredAlignment;
|
||||
if (dwarfClass != null) {
|
||||
dwarfClass.registerField(field.getName(), field.getType(), offset);
|
||||
dwarfClassGenerator.getTypePtr(field.getType());
|
||||
}
|
||||
}
|
||||
if (data.alignment == 0) {
|
||||
data.alignment = desiredAlignment;
|
||||
|
@ -720,7 +729,6 @@ public class WasmClassGenerator {
|
|||
} else if (data.type instanceof ValueType.Object) {
|
||||
var className = ((ValueType.Object) data.type).getClassName();
|
||||
if (className.equals("java.lang.Class")) {
|
||||
int headerSize = 8;
|
||||
debug.startClass(className, indexes.get(ValueType.object("java.lang.Object")), data.start, 60);
|
||||
debug.instanceField("size", 8, FieldType.INT);
|
||||
debug.instanceField("flags", 12, FieldType.INT);
|
||||
|
|
Loading…
Reference in New Issue
Block a user