mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Wasm: generate DWARF line numbers
Despite generated DWARF sections pass different verifications, they don't work in chrome or wasmtime.
This commit is contained in:
parent
c5011ebf69
commit
f06ba832d7
|
@ -545,7 +545,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
||||||
}
|
}
|
||||||
|
|
||||||
var writer = new WasmBinaryWriter();
|
var writer = new WasmBinaryWriter();
|
||||||
var renderer = new WasmBinaryRenderer(writer, version, obfuscated);
|
var renderer = new WasmBinaryRenderer(writer, version, obfuscated, dwarfGenerator);
|
||||||
renderer.render(module, buildDwarf(dwarfGenerator));
|
renderer.render(module, buildDwarf(dwarfGenerator));
|
||||||
|
|
||||||
try (OutputStream output = buildTarget.createResource(outputName)) {
|
try (OutputStream output = buildTarget.createResource(outputName)) {
|
||||||
|
|
|
@ -22,9 +22,38 @@ public final class DwarfConstants {
|
||||||
|
|
||||||
public static final int DW_TAG_COMPILE_UNIT = 0x11;
|
public static final int DW_TAG_COMPILE_UNIT = 0x11;
|
||||||
|
|
||||||
|
public static final int DW_AT_NAME = 0x03;
|
||||||
|
public static final int DW_AT_STMT_LIST = 0x10;
|
||||||
|
public static final int DW_AT_LOW_PC = 0x11;
|
||||||
|
public static final int DW_AT_HIGH_PC = 0x12;
|
||||||
|
public static final int DW_AT_PRODUCER = 0x25;
|
||||||
|
|
||||||
public static final int DW_CHILDREN_YES = 1;
|
public static final int DW_CHILDREN_YES = 1;
|
||||||
public static final int DW_CHILDREN_NO = 0;
|
public static final int DW_CHILDREN_NO = 0;
|
||||||
|
|
||||||
|
public static final int DW_LNCT_PATH = 0x1;
|
||||||
|
public static final int DW_LNCT_DIRECTORY_INDEX = 0x2;
|
||||||
|
|
||||||
|
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_STRP = 0x0E;
|
||||||
|
public static final int DW_FORM_SEC_OFFSET = 0x17;
|
||||||
|
public static final int DW_FORM_LINE_STRP = 0x1F;
|
||||||
|
|
||||||
|
public static final int DW_LNS_COPY = 0x01;
|
||||||
|
public static final int DW_LNS_ADVANCE_PC = 0x02;
|
||||||
|
public static final int DW_LNS_ADVANCE_LINE = 0x03;
|
||||||
|
public static final int DW_LNS_SET_FILE = 0x04;
|
||||||
|
public static final int DW_LNS_SET_COLUMN = 0x05;
|
||||||
|
public static final int DW_LNS_NEGATE_STMT = 0x06;
|
||||||
|
public static final int DW_LNS_SET_BASIC_BLOCK = 0x07;
|
||||||
|
public static final int DW_LNS_CONST_ADD_PC = 0x08;
|
||||||
|
public static final int DW_LNS_FIXED_ADVANCE_PC = 0x09;
|
||||||
|
public static final int DW_LNS_SET_PROLOGUE_END = 0x0A;
|
||||||
|
public static final int DW_LNS_SET_EPILOGUE_BEGIN = 0x0B;
|
||||||
|
public static final int DW_LNS_SET_ISA = 0x0C;
|
||||||
|
|
||||||
private DwarfConstants() {
|
private DwarfConstants() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,15 @@ public class DwarfInfoWriter {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DwarfInfoWriter skip(int count) {
|
||||||
|
output.skip(count);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Marker marker() {
|
||||||
|
return output.marker();
|
||||||
|
}
|
||||||
|
|
||||||
public DwarfAbbreviation abbreviation(int tag, boolean hasChildren, Consumer<Blob> blob) {
|
public DwarfAbbreviation abbreviation(int tag, boolean hasChildren, Consumer<Blob> blob) {
|
||||||
var abbr = new DwarfAbbreviation(tag, hasChildren, blob);
|
var abbr = new DwarfAbbreviation(tag, hasChildren, blob);
|
||||||
abbreviations.add(abbr);
|
abbreviations.add(abbr);
|
||||||
|
|
|
@ -100,12 +100,30 @@ public class Blob {
|
||||||
var buffer = this.buffer;
|
var buffer = this.buffer;
|
||||||
while ((value & 0x7F) != value) {
|
while ((value & 0x7F) != value) {
|
||||||
buffer[ptr++] = (byte) ((value & 0x7F) | 0x80);
|
buffer[ptr++] = (byte) ((value & 0x7F) | 0x80);
|
||||||
value >>= 7;
|
value >>>= 7;
|
||||||
}
|
}
|
||||||
buffer[ptr++] = (byte) (value & 0x7F);
|
buffer[ptr++] = (byte) (value & 0x7F);
|
||||||
return write(buffer, 0, ptr);
|
return write(buffer, 0, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Blob writeSLEB(int value) {
|
||||||
|
var ptr = 0;
|
||||||
|
var buffer = this.buffer;
|
||||||
|
var sign = value >>> 31;
|
||||||
|
while (true) {
|
||||||
|
var digit = value & 0x7F;
|
||||||
|
value >>= 7;
|
||||||
|
var more = value != 0 && value != -1 || digit >> 6 != sign;
|
||||||
|
if (more) {
|
||||||
|
buffer[ptr++] = (byte) (digit | 0x80);
|
||||||
|
} else {
|
||||||
|
buffer[ptr++] = (byte) digit;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return write(buffer, 0, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
private void nextChunkIfNeeded() {
|
private void nextChunkIfNeeded() {
|
||||||
if (posInChunk < currentChunk.length) {
|
if (posInChunk < currentChunk.length) {
|
||||||
return;
|
return;
|
||||||
|
@ -127,6 +145,10 @@ public class Blob {
|
||||||
return new BlobReader(this, consumer);
|
return new BlobReader(this, consumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BinaryDataConsumer writer() {
|
||||||
|
return this::write;
|
||||||
|
}
|
||||||
|
|
||||||
public Marker marker() {
|
public Marker marker() {
|
||||||
return new Marker(this, chunkIndex, posInChunk, ptr);
|
return new Marker(this, chunkIndex, posInChunk, ptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,14 +16,14 @@
|
||||||
package org.teavm.backend.wasm.dwarf.blob;
|
package org.teavm.backend.wasm.dwarf.blob;
|
||||||
|
|
||||||
public class BlobReader {
|
public class BlobReader {
|
||||||
private Blob output;
|
private Blob blob;
|
||||||
private BinaryDataConsumer consumer;
|
private BinaryDataConsumer consumer;
|
||||||
private int ptr;
|
private int ptr;
|
||||||
private int currentChunk;
|
private int currentChunk;
|
||||||
private int offsetInChunk;
|
private int offsetInChunk;
|
||||||
|
|
||||||
BlobReader(Blob output, BinaryDataConsumer consumer) {
|
BlobReader(Blob blob, BinaryDataConsumer consumer) {
|
||||||
this.output = output;
|
this.blob = blob;
|
||||||
this.consumer = consumer;
|
this.consumer = consumer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,8 +31,12 @@ public class BlobReader {
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void readRemaining() {
|
||||||
|
advance(blob.size());
|
||||||
|
}
|
||||||
|
|
||||||
public void advance(int to) {
|
public void advance(int to) {
|
||||||
if (to < ptr || to > output.size()) {
|
if (to < ptr || to > blob.size()) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
if (to == ptr) {
|
if (to == ptr) {
|
||||||
|
@ -43,7 +47,7 @@ public class BlobReader {
|
||||||
var currentChunk = this.currentChunk;
|
var currentChunk = this.currentChunk;
|
||||||
var offsetInChunk = this.offsetInChunk;
|
var offsetInChunk = this.offsetInChunk;
|
||||||
while (ptr < to) {
|
while (ptr < to) {
|
||||||
var chunk = output.chunkAt(currentChunk);
|
var chunk = blob.chunkAt(currentChunk);
|
||||||
var limit = Math.min(ptr + chunk.length, to);
|
var limit = Math.min(ptr + chunk.length, to);
|
||||||
var bytesToWrite = limit - ptr;
|
var bytesToWrite = limit - ptr;
|
||||||
consumer.accept(chunk, offsetInChunk, offsetInChunk + bytesToWrite);
|
consumer.accept(chunk, offsetInChunk, offsetInChunk + bytesToWrite);
|
||||||
|
|
|
@ -40,4 +40,8 @@ public class Marker {
|
||||||
posInChunk = blob.posInChunk;
|
posInChunk = blob.posInChunk;
|
||||||
ptr = blob.ptr;
|
ptr = blob.ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int ptr() {
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,19 +18,26 @@ package org.teavm.backend.wasm.generate;
|
||||||
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DWARF_VERSION;
|
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DWARF_VERSION;
|
||||||
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_COMPILE_UNIT;
|
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_COMPILE_UNIT;
|
||||||
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_UT_COMPILE;
|
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_UT_COMPILE;
|
||||||
import java.util.Arrays;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import org.teavm.backend.wasm.dwarf.DwarfConstants;
|
||||||
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.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.model.WasmCustomSection;
|
import org.teavm.backend.wasm.model.WasmCustomSection;
|
||||||
|
|
||||||
public class DwarfGenerator {
|
public class DwarfGenerator {
|
||||||
private DwarfInfoWriter infoWriter = new DwarfInfoWriter();
|
private DwarfInfoWriter infoWriter = new DwarfInfoWriter();
|
||||||
private DwarfPlaceholder endOfSection;
|
private DwarfPlaceholder endOfSection;
|
||||||
|
private DwarfStrings strings = new DwarfStrings();
|
||||||
|
private DwarfStrings lineStrings = new DwarfStrings();
|
||||||
|
private DwarfLinesGenerator lines = new DwarfLinesGenerator(lineStrings);
|
||||||
|
private Marker highPcMarker;
|
||||||
|
|
||||||
public void begin() {
|
public void begin() {
|
||||||
endOfSection = infoWriter.placeholder(4);
|
endOfSection = infoWriter.placeholder(4);
|
||||||
|
lines.begin();
|
||||||
emitUnitHeader();
|
emitUnitHeader();
|
||||||
compilationUnit();
|
compilationUnit();
|
||||||
}
|
}
|
||||||
|
@ -56,28 +63,60 @@ public class DwarfGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void compilationUnit() {
|
private void compilationUnit() {
|
||||||
infoWriter.tag(infoWriter.abbreviation(DW_TAG_COMPILE_UNIT, true, data -> { }));
|
infoWriter.tag(infoWriter.abbreviation(DW_TAG_COMPILE_UNIT, true, data -> {
|
||||||
|
data.writeLEB(DwarfConstants.DW_AT_PRODUCER).writeLEB(DwarfConstants.DW_FORM_STRP);
|
||||||
|
data.writeLEB(DwarfConstants.DW_AT_NAME).writeLEB(DwarfConstants.DW_FORM_STRP);
|
||||||
|
data.writeLEB(DwarfConstants.DW_AT_STMT_LIST).writeLEB(DwarfConstants.DW_FORM_SEC_OFFSET);
|
||||||
|
data.writeLEB(DwarfConstants.DW_AT_LOW_PC).writeLEB(DwarfConstants.DW_FORM_ADDR);
|
||||||
|
data.writeLEB(DwarfConstants.DW_AT_HIGH_PC).writeLEB(DwarfConstants.DW_FORM_ADDR);
|
||||||
|
}));
|
||||||
|
infoWriter.writeInt(strings.stringRef("TeaVM"));
|
||||||
|
infoWriter.writeInt(strings.stringRef("classes.wasm"));
|
||||||
|
infoWriter.writeInt(0);
|
||||||
|
infoWriter.writeInt(0);
|
||||||
|
highPcMarker = infoWriter.marker();
|
||||||
|
infoWriter.skip(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void end() {
|
public void end() {
|
||||||
closeTag(); // compilation unit
|
closeTag(); // compilation unit
|
||||||
infoWriter.mark(endOfSection);
|
infoWriter.mark(endOfSection);
|
||||||
|
lines.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void closeTag() {
|
private void closeTag() {
|
||||||
infoWriter.writeByte(0);
|
infoWriter.writeByte(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCodeSize(int codeSize) {
|
||||||
|
highPcMarker.rewind();
|
||||||
|
infoWriter.writeInt(codeSize);
|
||||||
|
}
|
||||||
|
|
||||||
public Collection<? extends WasmCustomSection> createSections() {
|
public Collection<? extends WasmCustomSection> createSections() {
|
||||||
|
var sections = new ArrayList<WasmCustomSection>();
|
||||||
|
|
||||||
var abbreviations = new Blob();
|
var abbreviations = new Blob();
|
||||||
infoWriter.buildAbbreviations(abbreviations);
|
infoWriter.buildAbbreviations(abbreviations);
|
||||||
|
sections.add(new WasmCustomSection(".debug_abbrev", abbreviations.toArray()));
|
||||||
|
|
||||||
var info = new Blob();
|
var info = new Blob();
|
||||||
infoWriter.build(info);
|
infoWriter.build(info);
|
||||||
|
sections.add(new WasmCustomSection(".debug_info", info.toArray()));
|
||||||
|
|
||||||
return Arrays.asList(
|
if (strings.blob.size() > 0) {
|
||||||
new WasmCustomSection(".debug_abbrev", abbreviations.toArray()),
|
sections.add(new WasmCustomSection(".debug_str", strings.blob.toArray()));
|
||||||
new WasmCustomSection(".debug_info", info.toArray())
|
}
|
||||||
);
|
if (lineStrings.blob.size() > 0) {
|
||||||
|
sections.add(new WasmCustomSection(".debug_line_str", lineStrings.blob.toArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
sections.add(new WasmCustomSection(".debug_line", lines.blob.toArray()));
|
||||||
|
|
||||||
|
return sections;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void lineNumber(int address, String fileName, int lineNumber) {
|
||||||
|
lines.lineNumber(address, fileName, lineNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,207 @@
|
||||||
|
/*
|
||||||
|
* 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_FORM_DATA2;
|
||||||
|
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_PATH;
|
||||||
|
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_COPY;
|
||||||
|
import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_LNS_SET_FILE;
|
||||||
|
import com.carrotsearch.hppc.ObjectIntHashMap;
|
||||||
|
import com.carrotsearch.hppc.ObjectIntMap;
|
||||||
|
import org.teavm.backend.wasm.dwarf.blob.Blob;
|
||||||
|
import org.teavm.backend.wasm.dwarf.blob.Marker;
|
||||||
|
|
||||||
|
class DwarfLinesGenerator {
|
||||||
|
private static final int MIN_INSN_LEN = 1;
|
||||||
|
private static final int LINE_BASE = -3;
|
||||||
|
private static final int LINE_RANGE = 8;
|
||||||
|
private static final int OPCODE_BASE = 13;
|
||||||
|
|
||||||
|
Blob blob = new Blob();
|
||||||
|
private DwarfStrings strings;
|
||||||
|
private Blob instructionsBlob = new Blob();
|
||||||
|
private Marker unitLengthMarker;
|
||||||
|
private Marker headerLengthMarker;
|
||||||
|
private Blob filesBlob = new Blob();
|
||||||
|
private ObjectIntMap<String> fileIndexes = new ObjectIntHashMap<>();
|
||||||
|
private Blob dirsBlob = new Blob();
|
||||||
|
private ObjectIntMap<String> dirIndexes = new ObjectIntHashMap<>();
|
||||||
|
private int address;
|
||||||
|
private int file = 1;
|
||||||
|
private int line = 1;
|
||||||
|
|
||||||
|
DwarfLinesGenerator(DwarfStrings strings) {
|
||||||
|
this.strings = strings;
|
||||||
|
}
|
||||||
|
|
||||||
|
void begin() {
|
||||||
|
emitLinesHeader();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void emitLinesHeader() {
|
||||||
|
// length
|
||||||
|
unitLengthMarker = blob.marker();
|
||||||
|
blob.skip(4);
|
||||||
|
|
||||||
|
// version
|
||||||
|
blob.writeShort(5);
|
||||||
|
|
||||||
|
// address_size
|
||||||
|
blob.writeByte(4);
|
||||||
|
|
||||||
|
// segment_selector_size
|
||||||
|
blob.writeByte(0);
|
||||||
|
|
||||||
|
// header_length
|
||||||
|
headerLengthMarker = blob.marker();
|
||||||
|
blob.skip(4);
|
||||||
|
|
||||||
|
// minimum_instruction_length
|
||||||
|
blob.writeByte(MIN_INSN_LEN);
|
||||||
|
|
||||||
|
// maximum_operations_per_instruction
|
||||||
|
blob.writeByte(1);
|
||||||
|
|
||||||
|
// default_is_stmt
|
||||||
|
blob.writeByte(1);
|
||||||
|
|
||||||
|
blob.writeByte(LINE_BASE).writeByte(LINE_RANGE).writeByte(OPCODE_BASE);
|
||||||
|
|
||||||
|
// standard_opcode_lengths
|
||||||
|
|
||||||
|
blob.writeByte(0); // DW_LNS_COPY
|
||||||
|
blob.writeByte(1); // DW_LNS_ADVANCE_PC
|
||||||
|
blob.writeByte(1); // DW_LNS_ADVANCE_LINE
|
||||||
|
blob.writeByte(1); // DW_LNS_SET_FILE
|
||||||
|
blob.writeByte(1); // DW_LNS_SET_COLUMN
|
||||||
|
blob.writeByte(0); // DW_LNS_NEGATE_STMT
|
||||||
|
blob.writeByte(0); // DW_LNS_SET_BASIC_BLOCK
|
||||||
|
blob.writeByte(0); // DW_LNS_CONST_ADD_PC
|
||||||
|
blob.writeByte(1); // DW_LNS_FIXED_ADVANCE_PC
|
||||||
|
blob.writeByte(0); // DW_LNS_SET_PROLOGUE_END
|
||||||
|
blob.writeByte(0); // DW_LNS_SET_EPILOGUE_BEGIN
|
||||||
|
blob.writeByte(1); // DW_LNS_SET_ISA
|
||||||
|
}
|
||||||
|
|
||||||
|
void end() {
|
||||||
|
emitDirsAndFiles();
|
||||||
|
finishHeader();
|
||||||
|
|
||||||
|
instructionsBlob.newReader(blob.writer()).readRemaining();
|
||||||
|
|
||||||
|
var length = blob.ptr() - unitLengthMarker.ptr() - 4;
|
||||||
|
unitLengthMarker.rewind();
|
||||||
|
blob.writeInt(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void emitDirsAndFiles() {
|
||||||
|
blob.writeByte(1); // directory_entry_format_count
|
||||||
|
blob.writeByte(DW_LNCT_PATH);
|
||||||
|
blob.writeByte(DW_FORM_LINE_STRP);
|
||||||
|
blob.writeLEB(dirIndexes.size());
|
||||||
|
dirsBlob.newReader(blob.writer()).readRemaining();
|
||||||
|
|
||||||
|
blob.writeByte(2); // file_name_entry_format_count
|
||||||
|
blob.writeByte(DW_LNCT_DIRECTORY_INDEX);
|
||||||
|
blob.writeByte(DW_FORM_DATA2);
|
||||||
|
blob.writeByte(DW_LNCT_PATH);
|
||||||
|
blob.writeByte(DW_FORM_LINE_STRP);
|
||||||
|
blob.writeLEB(fileIndexes.size());
|
||||||
|
filesBlob.newReader(blob.writer()).readRemaining();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void finishHeader() {
|
||||||
|
var marker = blob.marker();
|
||||||
|
var headerLength = blob.ptr() - headerLengthMarker.ptr() - 4;
|
||||||
|
headerLengthMarker.rewind();
|
||||||
|
blob.writeInt(headerLength);
|
||||||
|
marker.rewind();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int fileRef(String path) {
|
||||||
|
var ref = fileIndexes.getOrDefault(path, -1);
|
||||||
|
if (ref < 0) {
|
||||||
|
var nameIndex = path.lastIndexOf('/') + 1;
|
||||||
|
var name = path.substring(nameIndex);
|
||||||
|
var dir = path.substring(0, Math.max(0, nameIndex - 1));
|
||||||
|
|
||||||
|
var dirPtr = dirRef(dir);
|
||||||
|
ref = fileIndexes.size();
|
||||||
|
fileIndexes.put(path, ref);
|
||||||
|
|
||||||
|
filesBlob.writeShort(dirPtr);
|
||||||
|
filesBlob.writeInt(strings.stringRef(name));
|
||||||
|
}
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int dirRef(String path) {
|
||||||
|
var ref = dirIndexes.getOrDefault(path, -1);
|
||||||
|
if (ref < 0) {
|
||||||
|
ref = dirIndexes.size();
|
||||||
|
dirIndexes.put(path, ref);
|
||||||
|
dirsBlob.writeInt(strings.stringRef(path));
|
||||||
|
}
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lineNumber(int address, String file, int line) {
|
||||||
|
var changed = false;
|
||||||
|
var fileRef = fileRef(file);
|
||||||
|
if (fileRef != this.file) {
|
||||||
|
this.file = fileRef;
|
||||||
|
instructionsBlob.writeByte(DW_LNS_SET_FILE);
|
||||||
|
instructionsBlob.writeLEB(fileRef);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (address != this.address || line != this.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;
|
||||||
|
this.line = line;
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
instructionsBlob.writeByte(DW_LNS_COPY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean tryEmitSpecial(int lineIncrement, int addressIncrement) {
|
||||||
|
if (lineIncrement < LINE_BASE || lineIncrement >= LINE_BASE + LINE_RANGE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int opcode = lineIncrement - LINE_BASE + (LINE_RANGE * addressIncrement) + OPCODE_BASE;
|
||||||
|
if (opcode <= OPCODE_BASE || opcode > 255) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
instructionsBlob.writeByte(opcode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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 com.carrotsearch.hppc.ObjectIntHashMap;
|
||||||
|
import com.carrotsearch.hppc.ObjectIntMap;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import org.teavm.backend.wasm.dwarf.blob.Blob;
|
||||||
|
|
||||||
|
class DwarfStrings {
|
||||||
|
final Blob blob = new Blob();
|
||||||
|
private ObjectIntMap<String> offsets = new ObjectIntHashMap<>();
|
||||||
|
|
||||||
|
int stringRef(String s) {
|
||||||
|
int ptr = offsets.getOrDefault(s, -1);
|
||||||
|
if (ptr < 0) {
|
||||||
|
ptr = blob.size();
|
||||||
|
offsets.put(s, ptr);
|
||||||
|
var bytes = s.getBytes(StandardCharsets.UTF_8);
|
||||||
|
blob.write(bytes);
|
||||||
|
blob.writeByte(0);
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ 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.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.WasmLocal;
|
||||||
|
@ -53,11 +54,14 @@ public class WasmBinaryRenderer {
|
||||||
private Map<WasmSignature, Integer> signatureIndexes = new HashMap<>();
|
private Map<WasmSignature, Integer> signatureIndexes = new HashMap<>();
|
||||||
private Map<String, Integer> functionIndexes = new HashMap<>();
|
private Map<String, Integer> functionIndexes = new HashMap<>();
|
||||||
private boolean obfuscated;
|
private boolean obfuscated;
|
||||||
|
private DwarfGenerator dwarfGenerator;
|
||||||
|
|
||||||
public WasmBinaryRenderer(WasmBinaryWriter output, WasmBinaryVersion version, boolean obfuscated) {
|
public WasmBinaryRenderer(WasmBinaryWriter output, WasmBinaryVersion version, boolean obfuscated,
|
||||||
|
DwarfGenerator dwarfGenerator) {
|
||||||
this.output = output;
|
this.output = output;
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.obfuscated = obfuscated;
|
this.obfuscated = obfuscated;
|
||||||
|
this.dwarfGenerator = dwarfGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render(WasmModule module) {
|
public void render(WasmModule module) {
|
||||||
|
@ -256,24 +260,28 @@ public class WasmBinaryRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderCode(WasmModule module) {
|
private void renderCode(WasmModule module) {
|
||||||
WasmBinaryWriter section = new WasmBinaryWriter();
|
var section = new WasmBinaryWriter();
|
||||||
|
|
||||||
List<WasmFunction> functions = module.getFunctions().values().stream()
|
var functions = module.getFunctions().values().stream()
|
||||||
.filter(function -> function.getImportName() == null)
|
.filter(function -> function.getImportName() == null)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
section.writeLEB(functions.size());
|
section.writeLEB(functions.size());
|
||||||
for (WasmFunction function : functions) {
|
for (var function : functions) {
|
||||||
byte[] body = renderFunction(function);
|
var body = renderFunction(function, section.getPosition());
|
||||||
section.writeLEB(body.length);
|
section.writeLEB(body.length);
|
||||||
section.writeBytes(body);
|
section.writeBytes(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dwarfGenerator != null) {
|
||||||
|
dwarfGenerator.setCodeSize(section.getPosition());
|
||||||
|
}
|
||||||
|
|
||||||
writeSection(SECTION_CODE, "code", section.getData());
|
writeSection(SECTION_CODE, "code", section.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] renderFunction(WasmFunction function) {
|
private byte[] renderFunction(WasmFunction function, int offset) {
|
||||||
WasmBinaryWriter code = new WasmBinaryWriter();
|
var code = new WasmBinaryWriter();
|
||||||
|
|
||||||
List<WasmLocal> localVariables = function.getLocalVariables();
|
List<WasmLocal> localVariables = function.getLocalVariables();
|
||||||
int parameterCount = Math.min(function.getParameters().size(), localVariables.size());
|
int parameterCount = Math.min(function.getParameters().size(), localVariables.size());
|
||||||
|
@ -301,9 +309,9 @@ public class WasmBinaryRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Integer> importIndexes = this.functionIndexes;
|
var importIndexes = this.functionIndexes;
|
||||||
WasmBinaryRenderingVisitor visitor = new WasmBinaryRenderingVisitor(code, version, functionIndexes,
|
var visitor = new WasmBinaryRenderingVisitor(code, version, functionIndexes, importIndexes,
|
||||||
importIndexes, signatureIndexes);
|
signatureIndexes, dwarfGenerator, offset);
|
||||||
for (WasmExpression part : function.getBody()) {
|
for (WasmExpression part : function.getBody()) {
|
||||||
part.acceptVisitor(visitor);
|
part.acceptVisitor(visitor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package org.teavm.backend.wasm.render;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.teavm.backend.wasm.generate.DwarfGenerator;
|
||||||
import org.teavm.backend.wasm.model.WasmType;
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmBlock;
|
import org.teavm.backend.wasm.model.expression.WasmBlock;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
||||||
|
@ -57,16 +58,21 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
private Map<String, Integer> functionIndexes;
|
private Map<String, Integer> functionIndexes;
|
||||||
private Map<String, Integer> importedIndexes;
|
private Map<String, Integer> importedIndexes;
|
||||||
private Map<WasmSignature, Integer> signatureIndexes;
|
private Map<WasmSignature, Integer> signatureIndexes;
|
||||||
|
private DwarfGenerator dwarfGenerator;
|
||||||
|
private int addressOffset;
|
||||||
private int depth;
|
private int depth;
|
||||||
private Map<WasmBlock, Integer> blockDepths = new HashMap<>();
|
private Map<WasmBlock, Integer> blockDepths = new HashMap<>();
|
||||||
|
|
||||||
WasmBinaryRenderingVisitor(WasmBinaryWriter writer, WasmBinaryVersion version, Map<String, Integer> functionIndexes,
|
WasmBinaryRenderingVisitor(WasmBinaryWriter writer, WasmBinaryVersion version, Map<String, Integer> functionIndexes,
|
||||||
Map<String, Integer> importedIndexes, Map<WasmSignature, Integer> signatureIndexes) {
|
Map<String, Integer> importedIndexes, Map<WasmSignature, Integer> signatureIndexes,
|
||||||
|
DwarfGenerator dwarfGenerator, int addressOffset) {
|
||||||
this.writer = writer;
|
this.writer = writer;
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.functionIndexes = functionIndexes;
|
this.functionIndexes = functionIndexes;
|
||||||
this.importedIndexes = importedIndexes;
|
this.importedIndexes = importedIndexes;
|
||||||
this.signatureIndexes = signatureIndexes;
|
this.signatureIndexes = signatureIndexes;
|
||||||
|
this.dwarfGenerator = dwarfGenerator;
|
||||||
|
this.addressOffset = addressOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -95,6 +101,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
}
|
}
|
||||||
expression.getCondition().acceptVisitor(this);
|
expression.getCondition().acceptVisitor(this);
|
||||||
|
|
||||||
|
emitLocation(expression);
|
||||||
writer.writeByte(0x0D);
|
writer.writeByte(0x0D);
|
||||||
|
|
||||||
writeLabel(expression.getTarget());
|
writeLabel(expression.getTarget());
|
||||||
|
@ -106,6 +113,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
expression.getResult().acceptVisitor(this);
|
expression.getResult().acceptVisitor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emitLocation(expression);
|
||||||
writer.writeByte(0x0C);
|
writer.writeByte(0x0C);
|
||||||
|
|
||||||
writeLabel(expression.getTarget());
|
writeLabel(expression.getTarget());
|
||||||
|
@ -115,6 +123,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
public void visit(WasmSwitch expression) {
|
public void visit(WasmSwitch expression) {
|
||||||
expression.getSelector().acceptVisitor(this);
|
expression.getSelector().acceptVisitor(this);
|
||||||
|
|
||||||
|
emitLocation(expression);
|
||||||
writer.writeByte(0x0E);
|
writer.writeByte(0x0E);
|
||||||
|
|
||||||
writer.writeLEB(expression.getTargets().size());
|
writer.writeLEB(expression.getTargets().size());
|
||||||
|
@ -132,6 +141,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmConditional expression) {
|
public void visit(WasmConditional expression) {
|
||||||
expression.getCondition().acceptVisitor(this);
|
expression.getCondition().acceptVisitor(this);
|
||||||
|
emitLocation(expression);
|
||||||
writer.writeByte(0x04);
|
writer.writeByte(0x04);
|
||||||
writeBlockType(expression.getType());
|
writeBlockType(expression.getType());
|
||||||
|
|
||||||
|
@ -160,40 +170,47 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
if (expression.getValue() != null) {
|
if (expression.getValue() != null) {
|
||||||
expression.getValue().acceptVisitor(this);
|
expression.getValue().acceptVisitor(this);
|
||||||
}
|
}
|
||||||
|
emitLocation(expression);
|
||||||
writer.writeByte(0x0F);
|
writer.writeByte(0x0F);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmUnreachable expression) {
|
public void visit(WasmUnreachable expression) {
|
||||||
|
emitLocation(expression);
|
||||||
writer.writeByte(0x0);
|
writer.writeByte(0x0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmInt32Constant expression) {
|
public void visit(WasmInt32Constant expression) {
|
||||||
|
emitLocation(expression);
|
||||||
writer.writeByte(0x41);
|
writer.writeByte(0x41);
|
||||||
writer.writeSignedLEB(expression.getValue());
|
writer.writeSignedLEB(expression.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmInt64Constant expression) {
|
public void visit(WasmInt64Constant expression) {
|
||||||
|
emitLocation(expression);
|
||||||
writer.writeByte(0x42);
|
writer.writeByte(0x42);
|
||||||
writer.writeSignedLEB(expression.getValue());
|
writer.writeSignedLEB(expression.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmFloat32Constant expression) {
|
public void visit(WasmFloat32Constant expression) {
|
||||||
|
emitLocation(expression);
|
||||||
writer.writeByte(0x43);
|
writer.writeByte(0x43);
|
||||||
writer.writeFixed(Float.floatToRawIntBits(expression.getValue()));
|
writer.writeFixed(Float.floatToRawIntBits(expression.getValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmFloat64Constant expression) {
|
public void visit(WasmFloat64Constant expression) {
|
||||||
|
emitLocation(expression);
|
||||||
writer.writeByte(0x44);
|
writer.writeByte(0x44);
|
||||||
writer.writeFixed(Double.doubleToRawLongBits(expression.getValue()));
|
writer.writeFixed(Double.doubleToRawLongBits(expression.getValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmGetLocal expression) {
|
public void visit(WasmGetLocal expression) {
|
||||||
|
emitLocation(expression);
|
||||||
writer.writeByte(0x20);
|
writer.writeByte(0x20);
|
||||||
writer.writeLEB(expression.getLocal().getIndex());
|
writer.writeLEB(expression.getLocal().getIndex());
|
||||||
}
|
}
|
||||||
|
@ -201,6 +218,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmSetLocal expression) {
|
public void visit(WasmSetLocal expression) {
|
||||||
expression.getValue().acceptVisitor(this);
|
expression.getValue().acceptVisitor(this);
|
||||||
|
emitLocation(expression);
|
||||||
writer.writeByte(0x21);
|
writer.writeByte(0x21);
|
||||||
writer.writeLEB(expression.getLocal().getIndex());
|
writer.writeLEB(expression.getLocal().getIndex());
|
||||||
}
|
}
|
||||||
|
@ -209,6 +227,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
public void visit(WasmIntBinary expression) {
|
public void visit(WasmIntBinary expression) {
|
||||||
expression.getFirst().acceptVisitor(this);
|
expression.getFirst().acceptVisitor(this);
|
||||||
expression.getSecond().acceptVisitor(this);
|
expression.getSecond().acceptVisitor(this);
|
||||||
|
emitLocation(expression);
|
||||||
render0xD(expression);
|
render0xD(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,6 +398,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
public void visit(WasmFloatBinary expression) {
|
public void visit(WasmFloatBinary expression) {
|
||||||
expression.getFirst().acceptVisitor(this);
|
expression.getFirst().acceptVisitor(this);
|
||||||
expression.getSecond().acceptVisitor(this);
|
expression.getSecond().acceptVisitor(this);
|
||||||
|
emitLocation(expression);
|
||||||
render0xD(expression);
|
render0xD(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,6 +523,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmFloatUnary expression) {
|
public void visit(WasmFloatUnary expression) {
|
||||||
expression.getOperand().acceptVisitor(this);
|
expression.getOperand().acceptVisitor(this);
|
||||||
|
emitLocation(expression);
|
||||||
render0xD(expression);
|
render0xD(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,6 +591,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmConversion expression) {
|
public void visit(WasmConversion expression) {
|
||||||
expression.getOperand().acceptVisitor(this);
|
expression.getOperand().acceptVisitor(this);
|
||||||
|
emitLocation(expression);
|
||||||
switch (expression.getSourceType()) {
|
switch (expression.getSourceType()) {
|
||||||
case INT32:
|
case INT32:
|
||||||
switch (expression.getTargetType()) {
|
switch (expression.getTargetType()) {
|
||||||
|
@ -658,6 +680,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
Integer functionIndex = !expression.isImported()
|
Integer functionIndex = !expression.isImported()
|
||||||
? functionIndexes.get(expression.getFunctionName())
|
? functionIndexes.get(expression.getFunctionName())
|
||||||
: importedIndexes.get(expression.getFunctionName());
|
: importedIndexes.get(expression.getFunctionName());
|
||||||
|
emitLocation(expression);
|
||||||
if (functionIndex == null) {
|
if (functionIndex == null) {
|
||||||
writer.writeByte(0x00);
|
writer.writeByte(0x00);
|
||||||
return;
|
return;
|
||||||
|
@ -688,12 +711,14 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmDrop expression) {
|
public void visit(WasmDrop expression) {
|
||||||
expression.getOperand().acceptVisitor(this);
|
expression.getOperand().acceptVisitor(this);
|
||||||
|
emitLocation(expression);
|
||||||
writer.writeByte(0x1A);
|
writer.writeByte(0x1A);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmLoadInt32 expression) {
|
public void visit(WasmLoadInt32 expression) {
|
||||||
expression.getIndex().acceptVisitor(this);
|
expression.getIndex().acceptVisitor(this);
|
||||||
|
emitLocation(expression);
|
||||||
switch (expression.getConvertFrom()) {
|
switch (expression.getConvertFrom()) {
|
||||||
case INT8:
|
case INT8:
|
||||||
writer.writeByte(0x2C);
|
writer.writeByte(0x2C);
|
||||||
|
@ -718,6 +743,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmLoadInt64 expression) {
|
public void visit(WasmLoadInt64 expression) {
|
||||||
expression.getIndex().acceptVisitor(this);
|
expression.getIndex().acceptVisitor(this);
|
||||||
|
emitLocation(expression);
|
||||||
switch (expression.getConvertFrom()) {
|
switch (expression.getConvertFrom()) {
|
||||||
case INT8:
|
case INT8:
|
||||||
writer.writeByte(0x30);
|
writer.writeByte(0x30);
|
||||||
|
@ -748,6 +774,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmLoadFloat32 expression) {
|
public void visit(WasmLoadFloat32 expression) {
|
||||||
expression.getIndex().acceptVisitor(this);
|
expression.getIndex().acceptVisitor(this);
|
||||||
|
emitLocation(expression);
|
||||||
writer.writeByte(0x2A);
|
writer.writeByte(0x2A);
|
||||||
writer.writeByte(alignment(expression.getAlignment()));
|
writer.writeByte(alignment(expression.getAlignment()));
|
||||||
writer.writeLEB(expression.getOffset());
|
writer.writeLEB(expression.getOffset());
|
||||||
|
@ -756,6 +783,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmLoadFloat64 expression) {
|
public void visit(WasmLoadFloat64 expression) {
|
||||||
expression.getIndex().acceptVisitor(this);
|
expression.getIndex().acceptVisitor(this);
|
||||||
|
emitLocation(expression);
|
||||||
writer.writeByte(0x2B);
|
writer.writeByte(0x2B);
|
||||||
writer.writeByte(alignment(expression.getAlignment()));
|
writer.writeByte(alignment(expression.getAlignment()));
|
||||||
writer.writeLEB(expression.getOffset());
|
writer.writeLEB(expression.getOffset());
|
||||||
|
@ -765,6 +793,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
public void visit(WasmStoreInt32 expression) {
|
public void visit(WasmStoreInt32 expression) {
|
||||||
expression.getIndex().acceptVisitor(this);
|
expression.getIndex().acceptVisitor(this);
|
||||||
expression.getValue().acceptVisitor(this);
|
expression.getValue().acceptVisitor(this);
|
||||||
|
emitLocation(expression);
|
||||||
switch (expression.getConvertTo()) {
|
switch (expression.getConvertTo()) {
|
||||||
case INT8:
|
case INT8:
|
||||||
case UINT8:
|
case UINT8:
|
||||||
|
@ -786,6 +815,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
public void visit(WasmStoreInt64 expression) {
|
public void visit(WasmStoreInt64 expression) {
|
||||||
expression.getIndex().acceptVisitor(this);
|
expression.getIndex().acceptVisitor(this);
|
||||||
expression.getValue().acceptVisitor(this);
|
expression.getValue().acceptVisitor(this);
|
||||||
|
emitLocation(expression);
|
||||||
switch (expression.getConvertTo()) {
|
switch (expression.getConvertTo()) {
|
||||||
case INT8:
|
case INT8:
|
||||||
case UINT8:
|
case UINT8:
|
||||||
|
@ -811,6 +841,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
public void visit(WasmStoreFloat32 expression) {
|
public void visit(WasmStoreFloat32 expression) {
|
||||||
expression.getIndex().acceptVisitor(this);
|
expression.getIndex().acceptVisitor(this);
|
||||||
expression.getValue().acceptVisitor(this);
|
expression.getValue().acceptVisitor(this);
|
||||||
|
emitLocation(expression);
|
||||||
writer.writeByte(0x38);
|
writer.writeByte(0x38);
|
||||||
writer.writeByte(alignment(expression.getAlignment()));
|
writer.writeByte(alignment(expression.getAlignment()));
|
||||||
writer.writeLEB(expression.getOffset());
|
writer.writeLEB(expression.getOffset());
|
||||||
|
@ -820,6 +851,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
public void visit(WasmStoreFloat64 expression) {
|
public void visit(WasmStoreFloat64 expression) {
|
||||||
expression.getIndex().acceptVisitor(this);
|
expression.getIndex().acceptVisitor(this);
|
||||||
expression.getValue().acceptVisitor(this);
|
expression.getValue().acceptVisitor(this);
|
||||||
|
emitLocation(expression);
|
||||||
writer.writeByte(0x39);
|
writer.writeByte(0x39);
|
||||||
writer.writeByte(alignment(expression.getAlignment()));
|
writer.writeByte(alignment(expression.getAlignment()));
|
||||||
writer.writeLEB(expression.getOffset());
|
writer.writeLEB(expression.getOffset());
|
||||||
|
@ -828,6 +860,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmMemoryGrow expression) {
|
public void visit(WasmMemoryGrow expression) {
|
||||||
expression.getAmount().acceptVisitor(this);
|
expression.getAmount().acceptVisitor(this);
|
||||||
|
emitLocation(expression);
|
||||||
writer.writeByte(0x40);
|
writer.writeByte(0x40);
|
||||||
writer.writeByte(0);
|
writer.writeByte(0);
|
||||||
}
|
}
|
||||||
|
@ -840,4 +873,12 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
int blockDepth = blockDepths.get(target);
|
int blockDepth = blockDepths.get(target);
|
||||||
writer.writeLEB(depth - blockDepth);
|
writer.writeLEB(depth - blockDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void emitLocation(WasmExpression expression) {
|
||||||
|
if (dwarfGenerator == null || expression.getLocation() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dwarfGenerator.lineNumber(writer.getPosition() + addressOffset, expression.getLocation().getFileName(),
|
||||||
|
expression.getLocation().getLine());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user