mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 00:04:10 -08:00
wasm gc: support emitting disassembly in HTML with link references, add setting to emit disassembly in JUnit tests
This commit is contained in:
parent
a8b999f8d9
commit
31d89ebec2
|
@ -102,23 +102,33 @@ public abstract class BaseDisassemblyListener {
|
|||
}
|
||||
|
||||
protected void writeGlobalRef(int index) {
|
||||
writer.startLink("g" + index);
|
||||
writeRef(nameProvider.global(index), index);
|
||||
writer.endLink();
|
||||
}
|
||||
|
||||
protected void writeFunctionRef(int index) {
|
||||
writer.startLink("f" + index);
|
||||
writeRef(nameProvider.function(index), index);
|
||||
writer.endLink();
|
||||
}
|
||||
|
||||
protected void writeTypeRef(int index) {
|
||||
writer.startLink("t" + index);
|
||||
writeRef(nameProvider.type(index), index);
|
||||
writer.endLink();
|
||||
}
|
||||
|
||||
protected void writeFieldRef(int typeIndex, int index) {
|
||||
writer.startLink("f" + typeIndex + "." + index);
|
||||
writeRef(nameProvider.field(typeIndex, index), index);
|
||||
writer.endLink();
|
||||
}
|
||||
|
||||
protected void writeLocalRef(int functionIndex, int index) {
|
||||
writer.startLink("l" + functionIndex + "." + index);
|
||||
writeRef(nameProvider.local(functionIndex, index), index);
|
||||
writer.endLink();
|
||||
}
|
||||
|
||||
private void writeRef(String name, int index) {
|
||||
|
|
|
@ -16,10 +16,9 @@
|
|||
package org.teavm.backend.wasm.disasm;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
import java.nio.file.Files;
|
||||
import java.util.function.Consumer;
|
||||
import org.teavm.backend.wasm.parser.AddressListener;
|
||||
|
@ -35,12 +34,10 @@ import org.teavm.common.AsyncInputStream;
|
|||
import org.teavm.common.ByteArrayAsyncInputStream;
|
||||
|
||||
public final class Disassembler {
|
||||
private PrintWriter out;
|
||||
private DisassemblyWriter writer;
|
||||
|
||||
public Disassembler(Writer writer) {
|
||||
out = new PrintWriter(writer);
|
||||
this.writer = new DisassemblyWriter(out, true);
|
||||
public Disassembler(DisassemblyWriter writer) {
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
public void startModule() {
|
||||
|
@ -52,9 +49,11 @@ public final class Disassembler {
|
|||
}
|
||||
|
||||
public void disassemble(byte[] bytes) {
|
||||
writer.prologue();
|
||||
startModule();
|
||||
read(bytes);
|
||||
endModule();
|
||||
writer.epilogue();
|
||||
}
|
||||
|
||||
public void read(byte[] bytes) {
|
||||
|
@ -97,12 +96,12 @@ public final class Disassembler {
|
|||
};
|
||||
if (code == 1) {
|
||||
return bytes -> {
|
||||
writer.write("(; type section size: " + bytes.length + " ;)");
|
||||
writer.write("(; type section size: " + bytes.length + " ;)").eol();
|
||||
var typeWriter = new DisassemblyTypeSectionListener(writer, nameProvider);
|
||||
writer.setAddressOffset(pos);
|
||||
var sectionParser = new TypeSectionParser(typeWriter);
|
||||
sectionParser.parse(writer.addressListener, bytes);
|
||||
out.flush();
|
||||
writer.flush();
|
||||
};
|
||||
} else if (code == 2) {
|
||||
return bytes -> {
|
||||
|
@ -111,23 +110,23 @@ public final class Disassembler {
|
|||
};
|
||||
} else if (code == 6) {
|
||||
return bytes -> {
|
||||
writer.write("(; global section size: " + bytes.length + " ;)");
|
||||
writer.write("(; global section size: " + bytes.length + " ;)").eol();
|
||||
var globalWriter = new DisassemblyGlobalSectionListener(writer, nameProvider);
|
||||
writer.setAddressOffset(pos);
|
||||
var sectionParser = new GlobalSectionParser(globalWriter);
|
||||
sectionParser.setFunctionIndexOffset(importListener.count);
|
||||
sectionParser.parse(writer.addressListener, bytes);
|
||||
out.flush();
|
||||
writer.flush();
|
||||
};
|
||||
} else if (code == 10) {
|
||||
return bytes -> {
|
||||
var disassembler = new DisassemblyCodeSectionListener(writer, nameProvider);
|
||||
writer.setAddressOffset(pos);
|
||||
writer.write("(; code section size: " + bytes.length + " ;)");
|
||||
writer.write("(; code section size: " + bytes.length + " ;)").eol();
|
||||
var sectionParser = new CodeSectionParser(disassembler);
|
||||
sectionParser.setFunctionIndexOffset(importListener.count);
|
||||
sectionParser.parse(writer.addressListener, bytes);
|
||||
out.flush();
|
||||
writer.flush();
|
||||
};
|
||||
} else {
|
||||
return null;
|
||||
|
@ -146,9 +145,34 @@ public final class Disassembler {
|
|||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
var file = new File(args[0]);
|
||||
String fileName = null;
|
||||
String outFileName = null;
|
||||
var htmlMode = false;
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
var arg = args[i];
|
||||
if (arg.equals("--html")) {
|
||||
htmlMode = true;
|
||||
} else if (arg.equals("--output") || arg.equals("-o")) {
|
||||
outFileName = args[++i];
|
||||
} else {
|
||||
fileName = arg;
|
||||
}
|
||||
}
|
||||
var file = new File(fileName);
|
||||
var bytes = Files.readAllBytes(file.toPath());
|
||||
var disassembler = new Disassembler(new OutputStreamWriter(System.out));
|
||||
var output = outFileName != null ? new FileOutputStream(outFileName) : System.out;
|
||||
var writer = new PrintWriter(output);
|
||||
var disassemblyWriter = htmlMode
|
||||
? new DisassemblyHTMLWriter(writer)
|
||||
: new DisassemblyTextWriter(writer);
|
||||
disassemblyWriter.setWithAddress(true);
|
||||
if (htmlMode) {
|
||||
disassemblyWriter.write("<html><body><pre>").eol();
|
||||
}
|
||||
var disassembler = new Disassembler(disassemblyWriter);
|
||||
disassembler.disassemble(bytes);
|
||||
if (htmlMode) {
|
||||
disassemblyWriter.write("</pre></body></html>").eol();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,10 @@ public class DisassemblyCodeListener extends BaseDisassemblyListener implements
|
|||
this.currentFunctionId = currentFunctionId;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
blockIdGen = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(int depth) {
|
||||
writer.address();
|
||||
|
@ -56,7 +60,9 @@ public class DisassemblyCodeListener extends BaseDisassemblyListener implements
|
|||
public int startBlock(boolean loop, WasmHollowType type) {
|
||||
writer.address();
|
||||
var label = blockIdGen++;
|
||||
writer.write(loop ? "loop" : "block").write(" $label_" + label);
|
||||
writer.startLinkTarget("start" + label).startLink("end" + label).write(loop ? "loop" : "block")
|
||||
.endLink().endLinkTarget();
|
||||
writer.write(" $label_" + label);
|
||||
writeBlockType(type);
|
||||
writer.indent().eol();
|
||||
return label;
|
||||
|
@ -66,7 +72,8 @@ public class DisassemblyCodeListener extends BaseDisassemblyListener implements
|
|||
public int startConditionalBlock(WasmHollowType type) {
|
||||
writer.address();
|
||||
var label = blockIdGen++;
|
||||
writer.write("if ").write(" $label_" + label);
|
||||
writer.startLinkTarget("start" + label).startLink("end" + label).write("if").endLink().endLinkTarget();
|
||||
writer.write(" $label_" + label);
|
||||
writeBlockType(type);
|
||||
writer.indent().eol();
|
||||
return label;
|
||||
|
@ -75,14 +82,16 @@ public class DisassemblyCodeListener extends BaseDisassemblyListener implements
|
|||
@Override
|
||||
public void startElseSection(int token) {
|
||||
writer.address();
|
||||
writer.outdent().write("else (; $label_" + token + " ;)").indent().eol();
|
||||
writer.outdent().startLink("start" + token).write("else").endLink();
|
||||
writer.write(" (; $label_" + token + " ;)").indent().eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int startTry(WasmHollowType type) {
|
||||
writer.address();
|
||||
var label = blockIdGen++;
|
||||
writer.write("try ").write(" $label_" + label);
|
||||
writer.startLinkTarget("start" + label).startLink("end" + label).write("try").endLink().endLinkTarget();
|
||||
writer.write(" $label_" + label);
|
||||
writeBlockType(type);
|
||||
writer.indent().eol();
|
||||
return label;
|
||||
|
@ -96,12 +105,14 @@ public class DisassemblyCodeListener extends BaseDisassemblyListener implements
|
|||
|
||||
@Override
|
||||
public void endBlock(int token, boolean loop) {
|
||||
writer.address().outdent().write("end (; $label_" + token + " ;)").eol();
|
||||
writer.address().outdent();
|
||||
writer.startLinkTarget("end" + token).startLink("start" + token).write("end").endLink().endLinkTarget();
|
||||
writer.write(" (; $label_" + token + " ;)").eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void branch(BranchOpcode opcode, int depth, int target) {
|
||||
writer.address();
|
||||
writer.address().startLink("start" + target);
|
||||
switch (opcode) {
|
||||
case BR:
|
||||
writer.write("br");
|
||||
|
@ -110,7 +121,7 @@ public class DisassemblyCodeListener extends BaseDisassemblyListener implements
|
|||
writer.write("br_if");
|
||||
break;
|
||||
}
|
||||
writer.write(" $label_" + target).eol();
|
||||
writer.endLink().write(" $label_" + target).eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -202,7 +213,9 @@ public class DisassemblyCodeListener extends BaseDisassemblyListener implements
|
|||
@Override
|
||||
public void callReference(int typeIndex) {
|
||||
writer.address();
|
||||
writer.write("call_ref " + typeIndex).eol();
|
||||
writer.write("call_ref ");
|
||||
writeTypeRef(typeIndex);
|
||||
writer.eol();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -31,12 +31,13 @@ public class DisassemblyCodeSectionListener extends BaseDisassemblyListener impl
|
|||
@Override
|
||||
public boolean functionStart(int index, int size) {
|
||||
currentFunctionId = index;
|
||||
writer.address().write("(func ").write("(; " + index + " ;)");
|
||||
writer.address().write("(func ");
|
||||
writer.startLinkTarget("f" + index).write("(; " + index + " ;)");
|
||||
var name = nameProvider.function(index);
|
||||
if (name != null) {
|
||||
writer.write(" $").write(name);
|
||||
}
|
||||
writer.indent().eol();
|
||||
writer.endLinkTarget().indent().eol();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -49,11 +50,14 @@ public class DisassemblyCodeSectionListener extends BaseDisassemblyListener impl
|
|||
public void local(int start, int count, WasmHollowType type) {
|
||||
writer.address();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
writer.write("(local (; " + (i + start) + " ;) ");
|
||||
var name = nameProvider.local(currentFunctionId, i + start);
|
||||
writer.write("(local ");
|
||||
var id = i + start;
|
||||
writer.startLinkTarget("l" + currentFunctionId + "." + id).write("(; " + id + " ;)");
|
||||
var name = nameProvider.local(currentFunctionId, id);
|
||||
if (name != null) {
|
||||
writer.write("$").write(name).write(" ");
|
||||
writer.write(" ").write("$").write(name);
|
||||
}
|
||||
writer.endLinkTarget().write(" ");
|
||||
writeType(type);
|
||||
writer.write(")").eol();
|
||||
}
|
||||
|
@ -62,6 +66,7 @@ public class DisassemblyCodeSectionListener extends BaseDisassemblyListener impl
|
|||
@Override
|
||||
public CodeListener code() {
|
||||
codeListener.setCurrentFunctionId(currentFunctionId);
|
||||
codeListener.reset();
|
||||
return codeListener;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,11 +29,13 @@ public class DisassemblyGlobalSectionListener extends BaseDisassemblyListener im
|
|||
|
||||
@Override
|
||||
public CodeListener startGlobal(int index, WasmHollowType type, boolean mutable) {
|
||||
writer.address().write("(global (; ").write(String.valueOf(index)).write(" ;) ");
|
||||
writer.address().write("(global ");
|
||||
writer.startLinkTarget("g" + index).write("(; ").write(String.valueOf(index)).write(" ;)");
|
||||
var name = nameProvider.global(index);
|
||||
if (name != null) {
|
||||
writer.write("$").write(name).write(" ");
|
||||
writer.write("$").write(name);
|
||||
}
|
||||
writer.endLinkTarget().write(" ");
|
||||
if (mutable) {
|
||||
writer.write("(mut ");
|
||||
writeType(type);
|
||||
|
@ -42,6 +44,7 @@ public class DisassemblyGlobalSectionListener extends BaseDisassemblyListener im
|
|||
writeType(type);
|
||||
}
|
||||
writer.indent().eol();
|
||||
codeListener.reset();
|
||||
return codeListener;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright 2024 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.disasm;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
public class DisassemblyHTMLWriter extends DisassemblyWriter {
|
||||
public DisassemblyHTMLWriter(PrintWriter out) {
|
||||
super(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisassemblyWriter prologue() {
|
||||
return writeExact("<html><body><pre>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisassemblyWriter epilogue() {
|
||||
return writeExact("</pre></body></html>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisassemblyWriter startLink(String s) {
|
||||
writeExact("<a href=\"#").writeExact(s).writeExact("\">");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisassemblyWriter endLink() {
|
||||
writeExact("</a>");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisassemblyWriter startLinkTarget(String s) {
|
||||
writeExact("<a name=\"").writeExact(s).writeExact("\">");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisassemblyWriter endLinkTarget() {
|
||||
writeExact("</a>");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisassemblyWriter write(String s) {
|
||||
StringBuilder sb = null;
|
||||
var i = 0;
|
||||
for (; i < s.length(); ++i) {
|
||||
var c = s.charAt(i);
|
||||
if (c == '<') {
|
||||
sb = new StringBuilder();
|
||||
sb.append(s, 0, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sb != null) {
|
||||
for (; i < s.length(); ++i) {
|
||||
var c = s.charAt(i);
|
||||
if (c == '<') {
|
||||
sb.append("<");
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
s = sb.toString();
|
||||
}
|
||||
writeExact(s);
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright 2024 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.disasm;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
public class DisassemblyTextWriter extends DisassemblyWriter {
|
||||
public DisassemblyTextWriter(PrintWriter out) {
|
||||
super(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisassemblyWriter startLink(String s) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisassemblyWriter endLink() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisassemblyWriter startLinkTarget(String s) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisassemblyWriter endLinkTarget() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisassemblyWriter prologue() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisassemblyWriter epilogue() {
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -43,11 +43,13 @@ public class DisassemblyTypeSectionListener extends BaseDisassemblyListener impl
|
|||
@Override
|
||||
public void startType(int index, boolean open, int[] supertypes) {
|
||||
currentTypeIndex = index;
|
||||
writer.address().write("(type (; ").write(String.valueOf(index)).write(" ;) ");
|
||||
writer.address().write("(type ");
|
||||
writer.startLinkTarget("t" + index).write("(; ").write(String.valueOf(index)).write(" ;) ");
|
||||
var name = nameProvider.type(index);
|
||||
if (name != null) {
|
||||
writer.write("$").write(name).write(" ");
|
||||
writer.write("$").write(name);
|
||||
}
|
||||
writer.endLinkTarget().write(" ");
|
||||
if (!open || supertypes.length > 0) {
|
||||
currentTypeNeedsClosing = true;
|
||||
writer.write("(sub ");
|
||||
|
@ -81,11 +83,13 @@ public class DisassemblyTypeSectionListener extends BaseDisassemblyListener impl
|
|||
public void field(WasmHollowStorageType hollowType, boolean mutable) {
|
||||
writer.address().write("(field ");
|
||||
if (needsFieldIndex) {
|
||||
writer.write("(; " + fieldIndex++ + " ;) ");
|
||||
var name = nameProvider.field(currentTypeIndex, fieldIndex);
|
||||
var index = fieldIndex++;
|
||||
writer.startLinkTarget("f" + currentTypeIndex + "." + index).write("(; " + index + " ;)");
|
||||
var name = nameProvider.field(currentTypeIndex, index);
|
||||
if (name != null) {
|
||||
writer.write("$").write(name);
|
||||
writer.write(" ").write("$").write(name);
|
||||
}
|
||||
writer.endLinkTarget().write(" ");
|
||||
}
|
||||
if (mutable) {
|
||||
writer.write("(mut ");
|
||||
|
|
|
@ -18,7 +18,7 @@ package org.teavm.backend.wasm.disasm;
|
|||
import java.io.PrintWriter;
|
||||
import org.teavm.backend.wasm.parser.AddressListener;
|
||||
|
||||
public class DisassemblyWriter {
|
||||
public abstract class DisassemblyWriter {
|
||||
private PrintWriter out;
|
||||
private boolean withAddress;
|
||||
private int indentLevel;
|
||||
|
@ -27,8 +27,11 @@ public class DisassemblyWriter {
|
|||
private boolean lineStarted;
|
||||
private int addressOffset;
|
||||
|
||||
public DisassemblyWriter(PrintWriter out, boolean withAddress) {
|
||||
public DisassemblyWriter(PrintWriter out) {
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
public void setWithAddress(boolean withAddress) {
|
||||
this.withAddress = withAddress;
|
||||
}
|
||||
|
||||
|
@ -84,11 +87,31 @@ public class DisassemblyWriter {
|
|||
}
|
||||
|
||||
public DisassemblyWriter write(String s) {
|
||||
return writeExact(s);
|
||||
}
|
||||
|
||||
protected DisassemblyWriter writeExact(String s) {
|
||||
startLine();
|
||||
out.print(s);
|
||||
return this;
|
||||
}
|
||||
|
||||
public abstract DisassemblyWriter startLink(String s);
|
||||
|
||||
public abstract DisassemblyWriter endLink();
|
||||
|
||||
public abstract DisassemblyWriter startLinkTarget(String s);
|
||||
|
||||
public abstract DisassemblyWriter endLinkTarget();
|
||||
|
||||
public abstract DisassemblyWriter prologue();
|
||||
|
||||
public abstract DisassemblyWriter epilogue();
|
||||
|
||||
public void flush() {
|
||||
out.flush();
|
||||
}
|
||||
|
||||
public final AddressListener addressListener = new AddressListener() {
|
||||
@Override
|
||||
public void address(int address) {
|
||||
|
|
|
@ -61,6 +61,8 @@ tasks.test {
|
|||
|
||||
systemProperty("teavm.junit.wasm-gc", providers.gradleProperty("teavm.tests.wasm-gc").orElse("false").get())
|
||||
systemProperty("teavm.junit.wasm-gc.runner", browser)
|
||||
systemProperty("teavm.junit.wasm-gc.disasm", providers.gradleProperty("teavm.tests.wasm-gc.disasm")
|
||||
.orElse("false").get())
|
||||
|
||||
systemProperty("teavm.junit.wasi", providers.gradleProperty("teavm.tests.wasi").orElse("true").get())
|
||||
systemProperty("teavm.junit.wasi.runner", providers.gradleProperty("teavm.tests.wasi.runner")
|
||||
|
|
|
@ -26,6 +26,7 @@ final class PropertyNames {
|
|||
static final String WASI_ENABLED = "teavm.junit.wasi";
|
||||
static final String WASI_RUNNER = "teavm.junit.wasi.runner";
|
||||
static final String WASM_GC_ENABLED = "teavm.junit.wasm-gc";
|
||||
static final String WASM_GC_DISASM = "teavm.junit.wasm-gc.disasm";
|
||||
static final String C_COMPILER = "teavm.junit.c.compiler";
|
||||
static final String C_LINE_NUMBERS = "teavm.junit.c.lineNumbers";
|
||||
static final String MINIFIED = "teavm.junit.minified";
|
||||
|
|
|
@ -106,7 +106,8 @@ public class TeaVMTestRunner extends Runner implements Filterable {
|
|||
|
||||
platforms.add(new JSPlatformSupport(classSource, referenceCache));
|
||||
platforms.add(new WebAssemblyPlatformSupport(classSource, referenceCache));
|
||||
platforms.add(new WebAssemblyGCPlatformSupport(classSource, referenceCache));
|
||||
platforms.add(new WebAssemblyGCPlatformSupport(classSource, referenceCache,
|
||||
Boolean.parseBoolean(System.getProperty(PropertyNames.WASM_GC_DISASM))));
|
||||
platforms.add(new WasiPlatformSupport(classSource, referenceCache));
|
||||
platforms.add(new CPlatformSupport(classSource, referenceCache));
|
||||
|
||||
|
|
|
@ -20,8 +20,12 @@ import static org.teavm.junit.PropertyNames.SOURCE_DIRS;
|
|||
import static org.teavm.junit.PropertyNames.WASM_GC_ENABLED;
|
||||
import static org.teavm.junit.PropertyNames.WASM_RUNNER;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -29,6 +33,8 @@ import java.util.StringTokenizer;
|
|||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import org.teavm.backend.wasm.WasmGCTarget;
|
||||
import org.teavm.backend.wasm.disasm.Disassembler;
|
||||
import org.teavm.backend.wasm.disasm.DisassemblyHTMLWriter;
|
||||
import org.teavm.browserrunner.BrowserRunner;
|
||||
import org.teavm.model.ClassHolderSource;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
@ -36,8 +42,11 @@ import org.teavm.model.ReferenceCache;
|
|||
import org.teavm.vm.TeaVM;
|
||||
|
||||
class WebAssemblyGCPlatformSupport extends TestPlatformSupport<WasmGCTarget> {
|
||||
WebAssemblyGCPlatformSupport(ClassHolderSource classSource, ReferenceCache referenceCache) {
|
||||
private boolean disassembly;
|
||||
|
||||
WebAssemblyGCPlatformSupport(ClassHolderSource classSource, ReferenceCache referenceCache, boolean disassembly) {
|
||||
super(classSource, referenceCache);
|
||||
this.disassembly = disassembly;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -117,6 +126,9 @@ class WebAssemblyGCPlatformSupport extends TestPlatformSupport<WasmGCTarget> {
|
|||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (disassembly) {
|
||||
writeDisassembly(outputPath, "classTest", configuration);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -130,5 +142,20 @@ class WebAssemblyGCPlatformSupport extends TestPlatformSupport<WasmGCTarget> {
|
|||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (disassembly) {
|
||||
writeDisassembly(outputPathForMethod, "test", configuration);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeDisassembly(File outputPath, String name, TeaVMTestConfiguration<?> configuration) {
|
||||
var binPath = getOutputFile(outputPath, name, configuration.getSuffix(), getExtension());
|
||||
var htmlPath = getOutputFile(outputPath, name, configuration.getSuffix(), ".wast.html");
|
||||
try (var writer = new OutputStreamWriter(new FileOutputStream(htmlPath))) {
|
||||
var disasmWriter = new DisassemblyHTMLWriter(new PrintWriter(writer));
|
||||
disasmWriter.setWithAddress(true);
|
||||
new Disassembler(disasmWriter).disassemble(Files.readAllBytes(binPath.toPath()));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user