mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Wasm: add information about parameters and local variables to DWARF
This commit is contained in:
parent
13cc56feb5
commit
f938db798b
|
@ -446,7 +446,14 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
||||||
BinaryWriter binaryWriter = new BinaryWriter(256);
|
BinaryWriter binaryWriter = new BinaryWriter(256);
|
||||||
var names = new NameProviderWithSpecialNames(new WasmNameProvider(), controller.getUnprocessedClassSource());
|
var names = new NameProviderWithSpecialNames(new WasmNameProvider(), controller.getUnprocessedClassSource());
|
||||||
var metadataRequirements = new ClassMetadataRequirements(controller.getDependencyInfo());
|
var metadataRequirements = new ClassMetadataRequirements(controller.getDependencyInfo());
|
||||||
var dwarfClassGen = debugging ? new DwarfClassGenerator() : null;
|
|
||||||
|
var dwarfGenerator = debugging ? new DwarfGenerator() : null;
|
||||||
|
if (dwarfGenerator != null) {
|
||||||
|
dwarfGenerator.begin();
|
||||||
|
}
|
||||||
|
var dwarfClassGen = debugging
|
||||||
|
? new DwarfClassGenerator(dwarfGenerator.getInfoWriter(), dwarfGenerator.strings)
|
||||||
|
: null;
|
||||||
var classGenerator = new WasmClassGenerator(classes, controller.getUnprocessedClassSource(),
|
var classGenerator = new WasmClassGenerator(classes, controller.getUnprocessedClassSource(),
|
||||||
vtableProvider, tagRegistry, binaryWriter, names, metadataRequirements,
|
vtableProvider, tagRegistry, binaryWriter, names, metadataRequirements,
|
||||||
controller.getClassInitializerInfo(), characteristics, dwarfClassGen);
|
controller.getClassInitializerInfo(), characteristics, dwarfClassGen);
|
||||||
|
@ -496,10 +503,6 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
||||||
classGenerator, stringPool, obfuscated);
|
classGenerator, stringPool, obfuscated);
|
||||||
context.addIntrinsic(exceptionHandlingIntrinsic);
|
context.addIntrinsic(exceptionHandlingIntrinsic);
|
||||||
|
|
||||||
var dwarfGenerator = debugging ? new DwarfGenerator() : null;
|
|
||||||
if (dwarfGenerator != null) {
|
|
||||||
dwarfGenerator.begin();
|
|
||||||
}
|
|
||||||
var generator = new WasmGenerator(decompiler, classes, context, classGenerator, binaryWriter,
|
var generator = new WasmGenerator(decompiler, classes, context, classGenerator, binaryWriter,
|
||||||
asyncMethods::contains);
|
asyncMethods::contains);
|
||||||
|
|
||||||
|
@ -547,11 +550,8 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
||||||
}
|
}
|
||||||
|
|
||||||
var writer = new WasmBinaryWriter();
|
var writer = new WasmBinaryWriter();
|
||||||
if (dwarfClassGen != null) {
|
|
||||||
dwarfClassGen.write(dwarfGenerator.getInfoWriter(), dwarfGenerator.strings);
|
|
||||||
}
|
|
||||||
var renderer = new WasmBinaryRenderer(writer, version, obfuscated, dwarfGenerator, dwarfClassGen);
|
var renderer = new WasmBinaryRenderer(writer, version, obfuscated, dwarfGenerator, dwarfClassGen);
|
||||||
renderer.render(module, buildDwarf(dwarfGenerator));
|
renderer.render(module, buildDwarf(dwarfGenerator, dwarfClassGen));
|
||||||
|
|
||||||
try (OutputStream output = buildTarget.createResource(outputName)) {
|
try (OutputStream output = buildTarget.createResource(outputName)) {
|
||||||
output.write(writer.getData());
|
output.write(writer.getData());
|
||||||
|
@ -570,11 +570,13 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Supplier<Collection<? extends WasmCustomSection>> buildDwarf(DwarfGenerator generator) {
|
private Supplier<Collection<? extends WasmCustomSection>> buildDwarf(DwarfGenerator generator,
|
||||||
|
DwarfClassGenerator classGen) {
|
||||||
if (generator == null) {
|
if (generator == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return () -> {
|
return () -> {
|
||||||
|
classGen.write();
|
||||||
generator.end();
|
generator.end();
|
||||||
return generator.createSections();
|
return generator.createSections();
|
||||||
};
|
};
|
||||||
|
@ -781,6 +783,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
||||||
if (dwarfClassGen != null) {
|
if (dwarfClassGen != null) {
|
||||||
var dwarfClass = dwarfClassGen.getClass(method.getOwnerName());
|
var dwarfClass = dwarfClassGen.getClass(method.getOwnerName());
|
||||||
var dwarfSubprogram = dwarfClass.getSubprogram(method.getDescriptor());
|
var dwarfSubprogram = dwarfClass.getSubprogram(method.getDescriptor());
|
||||||
|
dwarfSubprogram.isStatic = method.hasModifier(ElementModifier.STATIC);
|
||||||
dwarfClassGen.registerSubprogram(context.names.forMethod(method.getReference()), dwarfSubprogram);
|
dwarfClassGen.registerSubprogram(context.names.forMethod(method.getReference()), dwarfSubprogram);
|
||||||
}
|
}
|
||||||
if (controller.wasCancelled()) {
|
if (controller.wasCancelled()) {
|
||||||
|
|
|
@ -21,20 +21,36 @@ public final class DwarfConstants {
|
||||||
public static final int DW_UT_COMPILE = 0x01;
|
public static final int DW_UT_COMPILE = 0x01;
|
||||||
|
|
||||||
public static final int DW_TAG_CLASS_TYPE = 0x02;
|
public static final int DW_TAG_CLASS_TYPE = 0x02;
|
||||||
|
public static final int DW_TAG_FORMAL_PARAMETER = 0x05;
|
||||||
public static final int DW_TAG_COMPILE_UNIT = 0x11;
|
public static final int DW_TAG_COMPILE_UNIT = 0x11;
|
||||||
|
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_NAMESPACE = 0x39;
|
public static final int DW_TAG_NAMESPACE = 0x39;
|
||||||
|
public static final int DW_TAG_UNSPECIFIED_TYPE = 0x3B;
|
||||||
|
|
||||||
|
public static final int DW_AT_LOCATION = 0x02;
|
||||||
public static final int DW_AT_NAME = 0x03;
|
public static final int DW_AT_NAME = 0x03;
|
||||||
|
public static final int DW_AT_BYTE_SIZE = 0x0B;
|
||||||
public static final int DW_AT_STMT_LIST = 0x10;
|
public static final int DW_AT_STMT_LIST = 0x10;
|
||||||
public static final int DW_AT_LOW_PC = 0x11;
|
public static final int DW_AT_LOW_PC = 0x11;
|
||||||
public static final int DW_AT_HIGH_PC = 0x12;
|
public static final int DW_AT_HIGH_PC = 0x12;
|
||||||
public static final int DW_AT_LANGUAGE = 0x13;
|
public static final int DW_AT_LANGUAGE = 0x13;
|
||||||
public static final int DW_AT_PRODUCER = 0x25;
|
public static final int DW_AT_PRODUCER = 0x25;
|
||||||
public static final int DW_AT_DECLARATION = 0x3c;
|
public static final int DW_AT_DECLARATION = 0x3C;
|
||||||
|
public static final int DW_AT_ENCODING = 0x3E;
|
||||||
public static final int DW_AT_SPECIFICATION = 0x47;
|
public static final int DW_AT_SPECIFICATION = 0x47;
|
||||||
|
public static final int DW_AT_TYPE = 0x49;
|
||||||
public static final int DW_AT_LINKAGE_NAME = 0x6E;
|
public static final int DW_AT_LINKAGE_NAME = 0x6E;
|
||||||
|
|
||||||
|
public static final int DW_ATE_ADDRESS = 0x01;
|
||||||
|
public static final int DW_ATE_BOOLEAN = 0x02;
|
||||||
|
public static final int DW_ATE_FLOAT = 0x04;
|
||||||
|
public static final int DW_ATE_SIGNED = 0x05;
|
||||||
|
public static final int DW_ATE_UNSIGNED = 0x07;
|
||||||
|
public static final int DW_ATE_UNSIGNED_CHAR = 0x08;
|
||||||
|
public static final int DW_ATE_UTF = 0x10;
|
||||||
|
|
||||||
public static final int DW_LANG_JAVA = 0x0b;
|
public static final int DW_LANG_JAVA = 0x0b;
|
||||||
|
|
||||||
public static final int DW_CHILDREN_YES = 1;
|
public static final int DW_CHILDREN_YES = 1;
|
||||||
|
@ -46,13 +62,17 @@ public final class DwarfConstants {
|
||||||
public static final int DW_FORM_ADDR = 0x01;
|
public static final int DW_FORM_ADDR = 0x01;
|
||||||
public static final int DW_FORM_DATA2 = 0x05;
|
public static final int DW_FORM_DATA2 = 0x05;
|
||||||
public static final int DW_FORM_DATA4 = 0x06;
|
public static final int DW_FORM_DATA4 = 0x06;
|
||||||
|
public static final int DW_FORM_DATA1 = 0x0B;
|
||||||
public static final int DW_FORM_FLAG = 0x0C;
|
public static final int DW_FORM_FLAG = 0x0C;
|
||||||
public static final int DW_FORM_STRP = 0x0E;
|
public static final int DW_FORM_STRP = 0x0E;
|
||||||
public static final int DW_FORM_REF4 = 0x13;
|
public static final int DW_FORM_REF4 = 0x13;
|
||||||
public static final int DW_FORM_SEC_OFFSET = 0x17;
|
public static final int DW_FORM_SEC_OFFSET = 0x17;
|
||||||
|
public static final int DW_FORM_EXPRLOC = 0x18;
|
||||||
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_WASM_LOCATION = 0xED;
|
||||||
|
|
||||||
public static final int DW_LNS_COPY = 0x01;
|
public static final int DW_LNS_COPY = 0x01;
|
||||||
public static final int DW_LNS_ADVANCE_PC = 0x02;
|
public static final int DW_LNS_ADVANCE_PC = 0x02;
|
||||||
public static final int DW_LNS_ADVANCE_LINE = 0x03;
|
public static final int DW_LNS_ADVANCE_LINE = 0x03;
|
||||||
|
|
|
@ -15,13 +15,22 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.wasm.generate;
|
package org.teavm.backend.wasm.generate;
|
||||||
|
|
||||||
|
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_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_NAME;
|
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_AT_NAME;
|
||||||
|
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_DATA1;
|
||||||
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_STRP;
|
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_STRP;
|
||||||
|
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_NAMESPACE;
|
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_NAMESPACE;
|
||||||
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 java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
@ -31,16 +40,36 @@ import org.teavm.backend.wasm.dwarf.DwarfAbbreviation;
|
||||||
import org.teavm.backend.wasm.dwarf.DwarfInfoWriter;
|
import org.teavm.backend.wasm.dwarf.DwarfInfoWriter;
|
||||||
import org.teavm.backend.wasm.dwarf.DwarfPlaceholder;
|
import org.teavm.backend.wasm.dwarf.DwarfPlaceholder;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
|
import org.teavm.model.PrimitiveType;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
import org.teavm.model.util.VariableType;
|
||||||
|
|
||||||
public class DwarfClassGenerator {
|
public class DwarfClassGenerator {
|
||||||
|
private static final ValueType objectType = ValueType.object("java.lang.Object");
|
||||||
final Namespace root = new Namespace(null);
|
final Namespace root = new Namespace(null);
|
||||||
final Map<String, Subprogram> subprogramsByFunctionName = new HashMap<>();
|
final Map<String, Subprogram> subprogramsByFunctionName = new HashMap<>();
|
||||||
final List<Subprogram> rootSubprograms = new ArrayList<>();
|
final List<Subprogram> rootSubprograms = new ArrayList<>();
|
||||||
private DwarfInfoWriter infoWriter;
|
private final DwarfInfoWriter writer;
|
||||||
private DwarfStrings strings;
|
private final DwarfStrings strings;
|
||||||
private DwarfAbbreviation nsAbbrev;
|
private DwarfAbbreviation nsAbbrev;
|
||||||
private DwarfAbbreviation classTypeAbbrev;
|
private DwarfAbbreviation classTypeAbbrev;
|
||||||
private DwarfAbbreviation methodAbbrev;
|
private DwarfAbbreviation methodAbbrev;
|
||||||
|
private DwarfPlaceholder[] primitiveTypes = new DwarfPlaceholder[PrimitiveType.values().length];
|
||||||
|
private DwarfPlaceholder unspecifiedType;
|
||||||
|
private DwarfAbbreviation baseTypeAbbrev;
|
||||||
|
private List<Runnable> postponedWrites = new ArrayList<>();
|
||||||
|
|
||||||
|
public DwarfClassGenerator(DwarfInfoWriter writer, DwarfStrings strings) {
|
||||||
|
this.writer = writer;
|
||||||
|
this.strings = strings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flushTypes() {
|
||||||
|
for (var postponedWrite : postponedWrites) {
|
||||||
|
postponedWrite.run();
|
||||||
|
}
|
||||||
|
postponedWrites.clear();
|
||||||
|
}
|
||||||
|
|
||||||
public ClassType getClass(String fullName) {
|
public ClassType getClass(String fullName) {
|
||||||
var index = 0;
|
var index = 0;
|
||||||
|
@ -64,21 +93,16 @@ public class DwarfClassGenerator {
|
||||||
return subprogramsByFunctionName.get(functionName);
|
return subprogramsByFunctionName.get(functionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(DwarfInfoWriter infoWriter, DwarfStrings strings) {
|
public void write() {
|
||||||
this.infoWriter = infoWriter;
|
|
||||||
this.strings = strings;
|
|
||||||
root.writeChildren();
|
root.writeChildren();
|
||||||
for (var subprogram : rootSubprograms) {
|
for (var subprogram : rootSubprograms) {
|
||||||
subprogram.write();
|
subprogram.write();
|
||||||
}
|
}
|
||||||
this.infoWriter = null;
|
|
||||||
this.strings = null;
|
|
||||||
methodAbbrev = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private DwarfAbbreviation getMethodAbbrev() {
|
private DwarfAbbreviation getMethodAbbrev() {
|
||||||
if (methodAbbrev == null) {
|
if (methodAbbrev == null) {
|
||||||
methodAbbrev = infoWriter.abbreviation(DW_TAG_SUBPROGRAM, true, data -> {
|
methodAbbrev = writer.abbreviation(DW_TAG_SUBPROGRAM, true, data -> {
|
||||||
data.writeLEB(DW_AT_NAME).writeLEB(DW_FORM_STRP);
|
data.writeLEB(DW_AT_NAME).writeLEB(DW_FORM_STRP);
|
||||||
data.writeLEB(DW_AT_DECLARATION).writeLEB(DW_FORM_FLAG_PRESENT);
|
data.writeLEB(DW_AT_DECLARATION).writeLEB(DW_FORM_FLAG_PRESENT);
|
||||||
});
|
});
|
||||||
|
@ -88,7 +112,7 @@ public class DwarfClassGenerator {
|
||||||
|
|
||||||
private DwarfAbbreviation getNsAbbrev() {
|
private DwarfAbbreviation getNsAbbrev() {
|
||||||
if (nsAbbrev == null) {
|
if (nsAbbrev == null) {
|
||||||
nsAbbrev = infoWriter.abbreviation(DW_TAG_NAMESPACE, true, data -> {
|
nsAbbrev = writer.abbreviation(DW_TAG_NAMESPACE, true, data -> {
|
||||||
data.writeLEB(DW_AT_NAME).writeLEB(DW_FORM_STRP);
|
data.writeLEB(DW_AT_NAME).writeLEB(DW_FORM_STRP);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -97,13 +121,127 @@ public class DwarfClassGenerator {
|
||||||
|
|
||||||
private DwarfAbbreviation getClassTypeAbbrev() {
|
private DwarfAbbreviation getClassTypeAbbrev() {
|
||||||
if (classTypeAbbrev == null) {
|
if (classTypeAbbrev == null) {
|
||||||
classTypeAbbrev = infoWriter.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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return classTypeAbbrev;
|
return classTypeAbbrev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DwarfPlaceholder getTypePtr(VariableType type) {
|
||||||
|
switch (type) {
|
||||||
|
case INT:
|
||||||
|
return getPrimitivePtr(ValueType.Primitive.INTEGER);
|
||||||
|
case LONG:
|
||||||
|
return getPrimitivePtr(ValueType.Primitive.LONG);
|
||||||
|
case FLOAT:
|
||||||
|
return getPrimitivePtr(ValueType.Primitive.FLOAT);
|
||||||
|
case DOUBLE:
|
||||||
|
return getPrimitivePtr(ValueType.Primitive.DOUBLE);
|
||||||
|
default:
|
||||||
|
return getTypePtr(objectType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DwarfPlaceholder getTypePtr(ValueType type) {
|
||||||
|
if (type instanceof ValueType.Primitive) {
|
||||||
|
return getPrimitivePtr((ValueType.Primitive) type);
|
||||||
|
} else if (type instanceof ValueType.Object) {
|
||||||
|
return getClassType(((ValueType.Object) type).getClassName());
|
||||||
|
}
|
||||||
|
return getClassType("java.lang.Object");
|
||||||
|
}
|
||||||
|
|
||||||
|
private DwarfPlaceholder getUnspecifiedType() {
|
||||||
|
if (unspecifiedType == null) {
|
||||||
|
unspecifiedType = writer.placeholder(4);
|
||||||
|
var abbrev = writer.abbreviation(DW_TAG_UNSPECIFIED_TYPE, false, blob -> {
|
||||||
|
blob.writeInt(DW_AT_NAME).writeInt(DW_FORM_STRP);
|
||||||
|
});
|
||||||
|
writer.mark(unspecifiedType).tag(abbrev).writeInt(strings.stringRef("<unspecified>"));
|
||||||
|
}
|
||||||
|
return unspecifiedType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DwarfPlaceholder getClassType(String name) {
|
||||||
|
return getClass(name).ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DwarfPlaceholder getPrimitivePtr(ValueType.Primitive type) {
|
||||||
|
var result = primitiveTypes[type.getKind().ordinal()];
|
||||||
|
if (result == null) {
|
||||||
|
String name;
|
||||||
|
int byteSize;
|
||||||
|
int encoding;
|
||||||
|
switch (type.getKind()) {
|
||||||
|
case BOOLEAN:
|
||||||
|
name = "boolean";
|
||||||
|
byteSize = 1;
|
||||||
|
encoding = DW_ATE_BOOLEAN;
|
||||||
|
break;
|
||||||
|
case BYTE:
|
||||||
|
name = "byte";
|
||||||
|
byteSize = 1;
|
||||||
|
encoding = DW_ATE_SIGNED;
|
||||||
|
break;
|
||||||
|
case SHORT:
|
||||||
|
name = "short";
|
||||||
|
byteSize = 2;
|
||||||
|
encoding = DW_ATE_SIGNED;
|
||||||
|
break;
|
||||||
|
case CHARACTER:
|
||||||
|
name = "char";
|
||||||
|
byteSize = 2;
|
||||||
|
encoding = DW_ATE_UTF;
|
||||||
|
break;
|
||||||
|
case INTEGER:
|
||||||
|
name = "int";
|
||||||
|
byteSize = 4;
|
||||||
|
encoding = DW_ATE_SIGNED;
|
||||||
|
break;
|
||||||
|
case LONG:
|
||||||
|
name = "long";
|
||||||
|
byteSize = 8;
|
||||||
|
encoding = DW_ATE_SIGNED;
|
||||||
|
break;
|
||||||
|
case FLOAT:
|
||||||
|
name = "float";
|
||||||
|
encoding = DW_ATE_FLOAT;
|
||||||
|
byteSize = 4;
|
||||||
|
break;
|
||||||
|
case DOUBLE:
|
||||||
|
name = "double";
|
||||||
|
encoding = DW_ATE_FLOAT;
|
||||||
|
byteSize = 8;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
var ptr = writer.placeholder(4);
|
||||||
|
postponedWrites.add(() -> {
|
||||||
|
writer.mark(ptr).tag(getBaseTypeAbbrev());
|
||||||
|
writer.writeInt(strings.stringRef(name));
|
||||||
|
writer.writeByte(byteSize);
|
||||||
|
writer.writeByte(encoding);
|
||||||
|
});
|
||||||
|
result = ptr;
|
||||||
|
primitiveTypes[type.getKind().ordinal()] = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DwarfAbbreviation getBaseTypeAbbrev() {
|
||||||
|
if (baseTypeAbbrev == null) {
|
||||||
|
baseTypeAbbrev = writer.abbreviation(DW_TAG_BASE_TYPE, false, blob -> {
|
||||||
|
blob.writeLEB(DW_AT_NAME).writeLEB(DW_FORM_STRP);
|
||||||
|
blob.writeLEB(DW_AT_BYTE_SIZE).writeLEB(DW_FORM_DATA1);
|
||||||
|
blob.writeLEB(DW_AT_ENCODING).writeLEB(DW_FORM_DATA1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return baseTypeAbbrev;
|
||||||
|
}
|
||||||
|
|
||||||
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<>();
|
||||||
|
@ -118,10 +256,10 @@ public class DwarfClassGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void write() {
|
private void write() {
|
||||||
infoWriter.tag(getNsAbbrev());
|
writer.tag(getNsAbbrev());
|
||||||
infoWriter.writeInt(strings.stringRef(name));
|
writer.writeInt(strings.stringRef(name));
|
||||||
writeChildren();
|
writeChildren();
|
||||||
infoWriter.emptyTag();
|
writer.emptyTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeChildren() {
|
private void writeChildren() {
|
||||||
|
@ -140,39 +278,44 @@ public class DwarfClassGenerator {
|
||||||
|
|
||||||
public class ClassType {
|
public class ClassType {
|
||||||
public final String name;
|
public final String name;
|
||||||
|
final DwarfPlaceholder ptr;
|
||||||
final Map<MethodDescriptor, Subprogram> subprograms = new LinkedHashMap<>();
|
final Map<MethodDescriptor, Subprogram> subprograms = new LinkedHashMap<>();
|
||||||
|
|
||||||
private ClassType(String name) {
|
private ClassType(String name) {
|
||||||
|
ptr = writer.placeholder(4);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Subprogram getSubprogram(MethodDescriptor desc) {
|
public Subprogram getSubprogram(MethodDescriptor desc) {
|
||||||
return subprograms.computeIfAbsent(desc, d -> new Subprogram(d.getName()));
|
return subprograms.computeIfAbsent(desc, d -> new Subprogram(d.getName(), desc));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void write() {
|
private void write() {
|
||||||
infoWriter.tag(getClassTypeAbbrev());
|
writer.mark(ptr).tag(getClassTypeAbbrev());
|
||||||
infoWriter.writeInt(strings.stringRef(name));
|
writer.writeInt(strings.stringRef(name));
|
||||||
for (var child : subprograms.values()) {
|
for (var child : subprograms.values()) {
|
||||||
child.write();
|
child.write();
|
||||||
}
|
}
|
||||||
infoWriter.emptyTag();
|
writer.emptyTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Subprogram {
|
public class Subprogram {
|
||||||
public final String name;
|
public final String name;
|
||||||
public DwarfPlaceholder ref;
|
public boolean isStatic;
|
||||||
|
public final MethodDescriptor descriptor;
|
||||||
|
public final DwarfPlaceholder ref;
|
||||||
|
|
||||||
private Subprogram(String name) {
|
private Subprogram(String name, MethodDescriptor descriptor) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.descriptor = descriptor;
|
||||||
|
ref = writer.placeholder(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void write() {
|
private void write() {
|
||||||
ref = infoWriter.placeholder(4);
|
writer.mark(ref).tag(getMethodAbbrev());
|
||||||
infoWriter.mark(ref).tag(getMethodAbbrev());
|
writer.writeInt(strings.stringRef(name));
|
||||||
infoWriter.writeInt(strings.stringRef(name));
|
writer.emptyTag();
|
||||||
infoWriter.emptyTag();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,184 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
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_LOCATION;
|
||||||
|
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_AT_TYPE;
|
||||||
|
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_REF4;
|
||||||
|
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_FORM_STRP;
|
||||||
|
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_SUBPROGRAM;
|
||||||
|
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_VARIABLE;
|
||||||
|
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.model.WasmFunction;
|
||||||
|
|
||||||
|
public class DwarfFunctionGenerator {
|
||||||
|
private DwarfClassGenerator classGen;
|
||||||
|
private DwarfGenerator generator;
|
||||||
|
private WasmFunction function;
|
||||||
|
private int offset;
|
||||||
|
private Marker endProgramMarker;
|
||||||
|
private DwarfAbbreviation methodAbbrev;
|
||||||
|
private DwarfAbbreviation functionAbbrev;
|
||||||
|
private DwarfAbbreviation parameterAbbrev;
|
||||||
|
private DwarfAbbreviation variableAbbrev;
|
||||||
|
private DwarfClassGenerator.Subprogram subprogram;
|
||||||
|
|
||||||
|
public DwarfFunctionGenerator(DwarfClassGenerator classGen, DwarfGenerator generator) {
|
||||||
|
this.classGen = classGen;
|
||||||
|
this.generator = generator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void begin(WasmFunction function, int offset) {
|
||||||
|
if (function.getName() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
subprogram = classGen.getSubprogram(function.getName());
|
||||||
|
var writer = generator.getInfoWriter();
|
||||||
|
var strings = generator.strings;
|
||||||
|
writer.tag(subprogram != null ? getMethodAbbrev() : getFunctionAbbrev());
|
||||||
|
if (subprogram != null) {
|
||||||
|
writer.ref(subprogram.ref, Blob::writeInt);
|
||||||
|
} else {
|
||||||
|
writer.writeInt(strings.stringRef(subprogram != null ? subprogram.name : function.getName()));
|
||||||
|
}
|
||||||
|
writer.writeInt(offset);
|
||||||
|
endProgramMarker = writer.marker();
|
||||||
|
writer.skip(4);
|
||||||
|
|
||||||
|
this.function = function;
|
||||||
|
this.offset = offset;
|
||||||
|
|
||||||
|
writeLocals();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeLocals() {
|
||||||
|
if (subprogram == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var descriptor = subprogram.descriptor;
|
||||||
|
if (descriptor == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var writer = generator.getInfoWriter();
|
||||||
|
var strings = generator.strings;
|
||||||
|
var offset = subprogram.isStatic ? 0 : 1;
|
||||||
|
int count = Math.min(function.getLocalVariables().size() - offset, descriptor.parameterCount());
|
||||||
|
for (var i = 0; i < count; ++i) {
|
||||||
|
var local = function.getLocalVariables().get(i + offset);
|
||||||
|
if (local.getName() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
writer.tag(getParameterAbbrev());
|
||||||
|
writer.writeInt(strings.stringRef(local.getName()));
|
||||||
|
writer.ref(classGen.getTypePtr(descriptor.parameterType(i)), Blob::writeInt);
|
||||||
|
|
||||||
|
var operations = new Blob();
|
||||||
|
operations.writeByte(DW_OP_WASM_LOCATION).writeByte(0).writeLEB(i + 1);
|
||||||
|
writer.writeLEB(operations.size());
|
||||||
|
operations.newReader(writer::write).readRemaining();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = count + offset; i < function.getLocalVariables().size(); ++i) {
|
||||||
|
var local = function.getLocalVariables().get(i);
|
||||||
|
if (local.getName() == null || local.getJavaType() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
writer.tag(getVariableAbbrev());
|
||||||
|
writer.writeInt(strings.stringRef(local.getName()));
|
||||||
|
writer.ref(classGen.getTypePtr(local.getJavaType()), Blob::writeInt);
|
||||||
|
|
||||||
|
var operations = new Blob();
|
||||||
|
operations.writeByte(DW_OP_WASM_LOCATION).writeByte(0).writeLEB(i + 1);
|
||||||
|
writer.writeLEB(operations.size());
|
||||||
|
operations.newReader(writer::write).readRemaining();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void end(int size) {
|
||||||
|
if (function == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var writer = generator.getInfoWriter();
|
||||||
|
if (endProgramMarker != null) {
|
||||||
|
var backup = writer.marker();
|
||||||
|
endProgramMarker.rewind();
|
||||||
|
writer.writeInt(offset + size);
|
||||||
|
backup.rewind();
|
||||||
|
}
|
||||||
|
writer.emptyTag();
|
||||||
|
classGen.flushTypes();
|
||||||
|
subprogram = null;
|
||||||
|
endProgramMarker = null;
|
||||||
|
function = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DwarfAbbreviation getMethodAbbrev() {
|
||||||
|
if (methodAbbrev == null) {
|
||||||
|
methodAbbrev = generator.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 = generator.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DwarfAbbreviation getParameterAbbrev() {
|
||||||
|
if (parameterAbbrev == null) {
|
||||||
|
parameterAbbrev = generator.getInfoWriter().abbreviation(DW_TAG_FORMAL_PARAMETER, false, data -> {
|
||||||
|
data.writeLEB(DW_AT_NAME).writeLEB(DW_FORM_STRP);
|
||||||
|
data.writeLEB(DW_AT_TYPE).writeLEB(DW_FORM_REF4);
|
||||||
|
data.writeLEB(DW_AT_LOCATION).writeLEB(DW_FORM_EXPRLOC);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return parameterAbbrev;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DwarfAbbreviation getVariableAbbrev() {
|
||||||
|
if (variableAbbrev == null) {
|
||||||
|
variableAbbrev = generator.getInfoWriter().abbreviation(DW_TAG_VARIABLE, false, data -> {
|
||||||
|
data.writeLEB(DW_AT_NAME).writeLEB(DW_FORM_STRP);
|
||||||
|
data.writeLEB(DW_AT_TYPE).writeLEB(DW_FORM_REF4);
|
||||||
|
data.writeLEB(DW_AT_LOCATION).writeLEB(DW_FORM_EXPRLOC);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return variableAbbrev;
|
||||||
|
}
|
||||||
|
}
|
|
@ -85,7 +85,9 @@ public class WasmGenerator {
|
||||||
WasmType type = variable.getType() != null
|
WasmType type = variable.getType() != null
|
||||||
? WasmGeneratorUtil.mapType(variable.getType())
|
? WasmGeneratorUtil.mapType(variable.getType())
|
||||||
: WasmType.INT32;
|
: WasmType.INT32;
|
||||||
function.add(new WasmLocal(type, variable.getName()));
|
var local = new WasmLocal(type, variable.getName());
|
||||||
|
local.setJavaType(variable.getType());
|
||||||
|
function.add(local);
|
||||||
}
|
}
|
||||||
|
|
||||||
WasmGenerationVisitor visitor = new WasmGenerationVisitor(context, classGenerator, binaryWriter, function,
|
WasmGenerationVisitor visitor = new WasmGenerationVisitor(context, classGenerator, binaryWriter, function,
|
||||||
|
|
|
@ -16,12 +16,14 @@
|
||||||
package org.teavm.backend.wasm.model;
|
package org.teavm.backend.wasm.model;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import org.teavm.model.util.VariableType;
|
||||||
|
|
||||||
public class WasmLocal {
|
public class WasmLocal {
|
||||||
WasmFunction function;
|
WasmFunction function;
|
||||||
int index;
|
int index;
|
||||||
private String name;
|
private String name;
|
||||||
private WasmType type;
|
private WasmType type;
|
||||||
|
private VariableType javaType;
|
||||||
|
|
||||||
public WasmLocal(WasmType type, String name) {
|
public WasmLocal(WasmType type, String name) {
|
||||||
Objects.requireNonNull(type);
|
Objects.requireNonNull(type);
|
||||||
|
@ -57,4 +59,12 @@ public class WasmLocal {
|
||||||
public int getIndex() {
|
public int getIndex() {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setJavaType(VariableType javaType) {
|
||||||
|
this.javaType = javaType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VariableType getJavaType() {
|
||||||
|
return javaType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.wasm.render;
|
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.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -31,14 +23,11 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
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.DwarfClassGenerator;
|
||||||
|
import org.teavm.backend.wasm.generate.DwarfFunctionGenerator;
|
||||||
import org.teavm.backend.wasm.generate.DwarfGenerator;
|
import org.teavm.backend.wasm.generate.DwarfGenerator;
|
||||||
import org.teavm.backend.wasm.model.WasmCustomSection;
|
import org.teavm.backend.wasm.model.WasmCustomSection;
|
||||||
import org.teavm.backend.wasm.model.WasmFunction;
|
import org.teavm.backend.wasm.model.WasmFunction;
|
||||||
import org.teavm.backend.wasm.model.WasmLocal;
|
|
||||||
import org.teavm.backend.wasm.model.WasmMemorySegment;
|
import org.teavm.backend.wasm.model.WasmMemorySegment;
|
||||||
import org.teavm.backend.wasm.model.WasmModule;
|
import org.teavm.backend.wasm.model.WasmModule;
|
||||||
import org.teavm.backend.wasm.model.WasmType;
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
|
@ -67,9 +56,7 @@ public class WasmBinaryRenderer {
|
||||||
private Map<String, Integer> functionIndexes = new HashMap<>();
|
private Map<String, Integer> functionIndexes = new HashMap<>();
|
||||||
private boolean obfuscated;
|
private boolean obfuscated;
|
||||||
private DwarfGenerator dwarfGenerator;
|
private DwarfGenerator dwarfGenerator;
|
||||||
private DwarfClassGenerator dwarfClassGen;
|
private DwarfFunctionGenerator dwarfFunctionGen;
|
||||||
private DwarfAbbreviation methodAbbrev;
|
|
||||||
private DwarfAbbreviation functionAbbrev;
|
|
||||||
|
|
||||||
public WasmBinaryRenderer(WasmBinaryWriter output, WasmBinaryVersion version, boolean obfuscated,
|
public WasmBinaryRenderer(WasmBinaryWriter output, WasmBinaryVersion version, boolean obfuscated,
|
||||||
DwarfGenerator dwarfGenerator, DwarfClassGenerator dwarfClassGen) {
|
DwarfGenerator dwarfGenerator, DwarfClassGenerator dwarfClassGen) {
|
||||||
|
@ -77,7 +64,7 @@ public class WasmBinaryRenderer {
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.obfuscated = obfuscated;
|
this.obfuscated = obfuscated;
|
||||||
this.dwarfGenerator = dwarfGenerator;
|
this.dwarfGenerator = dwarfGenerator;
|
||||||
this.dwarfClassGen = dwarfClassGen;
|
dwarfFunctionGen = dwarfClassGen != null ? new DwarfFunctionGenerator(dwarfClassGen, dwarfGenerator) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render(WasmModule module) {
|
public void render(WasmModule module) {
|
||||||
|
@ -299,35 +286,21 @@ public class WasmBinaryRenderer {
|
||||||
private byte[] renderFunction(WasmFunction function, int offset) {
|
private byte[] renderFunction(WasmFunction function, int offset) {
|
||||||
var code = new WasmBinaryWriter();
|
var code = new WasmBinaryWriter();
|
||||||
|
|
||||||
Marker endProgramMarker;
|
if (dwarfFunctionGen != null) {
|
||||||
if (dwarfClassGen != null && function.getName() != null) {
|
dwarfFunctionGen.begin(function, offset);
|
||||||
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();
|
var localVariables = function.getLocalVariables();
|
||||||
int parameterCount = Math.min(function.getParameters().size(), localVariables.size());
|
int parameterCount = Math.min(function.getParameters().size(), localVariables.size());
|
||||||
localVariables = localVariables.subList(parameterCount, localVariables.size());
|
localVariables = localVariables.subList(parameterCount, localVariables.size());
|
||||||
if (localVariables.isEmpty()) {
|
if (localVariables.isEmpty()) {
|
||||||
code.writeLEB(0);
|
code.writeLEB(0);
|
||||||
} else {
|
} else {
|
||||||
List<LocalEntry> localEntries = new ArrayList<>();
|
var localEntries = new ArrayList<LocalEntry>();
|
||||||
LocalEntry currentEntry = new LocalEntry(localVariables.get(0).getType());
|
var currentEntry = new LocalEntry(localVariables.get(0).getType());
|
||||||
for (int i = 1; i < localVariables.size(); ++i) {
|
for (int i = 1; i < localVariables.size(); ++i) {
|
||||||
WasmType type = localVariables.get(i).getType();
|
var type = localVariables.get(i).getType();
|
||||||
if (currentEntry.type == type) {
|
if (currentEntry.type == type) {
|
||||||
currentEntry.count++;
|
currentEntry.count++;
|
||||||
} else {
|
} else {
|
||||||
|
@ -338,7 +311,7 @@ public class WasmBinaryRenderer {
|
||||||
localEntries.add(currentEntry);
|
localEntries.add(currentEntry);
|
||||||
|
|
||||||
code.writeLEB(localEntries.size());
|
code.writeLEB(localEntries.size());
|
||||||
for (LocalEntry entry : localEntries) {
|
for (var entry : localEntries) {
|
||||||
code.writeLEB(entry.count);
|
code.writeLEB(entry.count);
|
||||||
code.writeType(entry.type, version);
|
code.writeType(entry.type, version);
|
||||||
}
|
}
|
||||||
|
@ -347,7 +320,7 @@ public class WasmBinaryRenderer {
|
||||||
var importIndexes = this.functionIndexes;
|
var importIndexes = this.functionIndexes;
|
||||||
var visitor = new WasmBinaryRenderingVisitor(code, version, functionIndexes, importIndexes,
|
var visitor = new WasmBinaryRenderingVisitor(code, version, functionIndexes, importIndexes,
|
||||||
signatureIndexes, dwarfGenerator, offset);
|
signatureIndexes, dwarfGenerator, offset);
|
||||||
for (WasmExpression part : function.getBody()) {
|
for (var part : function.getBody()) {
|
||||||
part.acceptVisitor(visitor);
|
part.acceptVisitor(visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,13 +330,8 @@ public class WasmBinaryRenderer {
|
||||||
|
|
||||||
code.writeByte(0x0B);
|
code.writeByte(0x0B);
|
||||||
|
|
||||||
if (endProgramMarker != null) {
|
if (dwarfFunctionGen != null) {
|
||||||
var dwarfWriter = dwarfGenerator.getInfoWriter();
|
dwarfFunctionGen.end(code.getPosition());
|
||||||
var backup = dwarfWriter.marker();
|
|
||||||
endProgramMarker.rewind();
|
|
||||||
dwarfWriter.writeInt(offset + code.getPosition());
|
|
||||||
backup.rewind();
|
|
||||||
dwarfWriter.emptyTag();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return code.getData();
|
return code.getData();
|
||||||
|
@ -465,27 +433,4 @@ public class WasmBinaryRenderer {
|
||||||
|
|
||||||
output.writeBytes(data);
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user