wasm gc: support imported functions in disassembler

This commit is contained in:
Alexey Andreev 2024-10-04 09:40:54 +02:00
parent 0057bbd00d
commit a5212fb9ca
4 changed files with 92 additions and 15 deletions

View File

@ -27,7 +27,6 @@ import org.teavm.backend.wasm.parser.CodeSectionParser;
import org.teavm.backend.wasm.parser.FunctionSectionListener; import org.teavm.backend.wasm.parser.FunctionSectionListener;
import org.teavm.backend.wasm.parser.FunctionSectionParser; import org.teavm.backend.wasm.parser.FunctionSectionParser;
import org.teavm.backend.wasm.parser.GlobalSectionParser; import org.teavm.backend.wasm.parser.GlobalSectionParser;
import org.teavm.backend.wasm.parser.ImportSectionListener;
import org.teavm.backend.wasm.parser.ImportSectionParser; import org.teavm.backend.wasm.parser.ImportSectionParser;
import org.teavm.backend.wasm.parser.ModuleParser; import org.teavm.backend.wasm.parser.ModuleParser;
import org.teavm.backend.wasm.parser.NameSectionListener; import org.teavm.backend.wasm.parser.NameSectionListener;
@ -41,6 +40,7 @@ public final class Disassembler {
private DisassemblyWriter writer; private DisassemblyWriter writer;
private WasmHollowFunctionType[] functionTypes; private WasmHollowFunctionType[] functionTypes;
private int[] functionTypeRefs; private int[] functionTypeRefs;
private int importFunctionCount;
public Disassembler(DisassemblyWriter writer) { public Disassembler(DisassemblyWriter writer) {
this.writer = writer; this.writer = writer;
@ -91,17 +91,6 @@ public final class Disassembler {
}; };
} }
ImportListenerImpl importListener = new ImportListenerImpl();
static class ImportListenerImpl implements ImportSectionListener {
int count;
@Override
public void function(int typeIndex) {
++count;
}
}
public Consumer<byte[]> getSectionConsumer(int code, int pos, NameProvider nameProvider) { public Consumer<byte[]> getSectionConsumer(int code, int pos, NameProvider nameProvider) {
if (code == 1) { if (code == 1) {
return bytes -> { return bytes -> {
@ -115,13 +104,15 @@ public final class Disassembler {
}; };
} else if (code == 2) { } else if (code == 2) {
return bytes -> { return bytes -> {
var importListener = new DisassemblyImportSectionListener(writer, nameProvider, functionTypes);
var parser = new ImportSectionParser(importListener); var parser = new ImportSectionParser(importListener);
parser.parse(AddressListener.EMPTY, bytes); parser.parse(AddressListener.EMPTY, bytes);
importFunctionCount = importListener.functionCount();
}; };
} else if (code == 3) { } else if (code == 3) {
return bytes -> { return bytes -> {
var signatures = new IntArrayList(); var signatures = new IntArrayList();
for (var i = 0; i < importListener.count; ++i) { for (var i = 0; i < importFunctionCount; ++i) {
signatures.add(0); signatures.add(0);
} }
var parser = new FunctionSectionParser(new FunctionSectionListener() { var parser = new FunctionSectionParser(new FunctionSectionListener() {
@ -150,7 +141,7 @@ public final class Disassembler {
writer.setAddressOffset(pos); writer.setAddressOffset(pos);
writer.write("(; code section size: " + bytes.length + " ;)").eol(); writer.write("(; code section size: " + bytes.length + " ;)").eol();
var sectionParser = new CodeSectionParser(disassembler); var sectionParser = new CodeSectionParser(disassembler);
sectionParser.setFunctionIndexOffset(importListener.count); sectionParser.setFunctionIndexOffset(importFunctionCount);
sectionParser.parse(writer.addressListener, bytes); sectionParser.parse(writer.addressListener, bytes);
writer.flush(); writer.flush();
}; };

View File

@ -0,0 +1,84 @@
/*
* 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 org.teavm.backend.wasm.parser.ImportSectionListener;
import org.teavm.backend.wasm.parser.WasmHollowFunctionType;
public class DisassemblyImportSectionListener extends BaseDisassemblyListener implements ImportSectionListener {
private WasmHollowFunctionType[] functionTypes;
private String currentModule;
private String currentName;
private int functionIndex;
public DisassemblyImportSectionListener(DisassemblyWriter writer, NameProvider nameProvider,
WasmHollowFunctionType[] functionTypes) {
super(writer, nameProvider);
this.functionTypes = functionTypes;
}
public int functionCount() {
return functionIndex;
}
@Override
public void startEntry(String module, String name) {
currentModule = module;
currentName = name;
}
@Override
public void function(int typeIndex) {
writer.address().write("(import \"").write(currentModule).write("\" \"")
.write(currentName).write("\" ");
writer.write("(func ");
writer.startLinkTarget("f" + functionIndex).write("(; " + functionIndex + " ;)");
var name = nameProvider.function(functionIndex);
if (name != null) {
writer.write(" $").write(name);
}
writer.endLinkTarget();
writer.write(" (type ");
writeTypeRef(typeIndex);
writer.write(")");
writer.indent().eol();
var type = typeIndex < functionTypes.length ? functionTypes[typeIndex] : null;
if (type != null) {
for (var i = 0; i < type.parameterTypes.length; ++i) {
writer.write("(param ");
writer.startLinkTarget("l" + functionIndex + "." + i).write(" (; " + i + " ;)");
var paramName = nameProvider.local(functionIndex, i);
if (paramName != null) {
writer.write(" $").write(paramName);
}
writer.endLinkTarget();
writer.write(" ");
writeType(type.parameterTypes[i]);
writer.write(")").eol();
}
for (var i = 0; i < type.returnTypes.length; ++i) {
writer.write("(result ");
writeType(type.returnTypes[i]);
writer.write(")").eol();
}
}
writer.outdent().write("))").eol();
functionIndex++;
}
}

View File

@ -112,6 +112,8 @@ public abstract class DisassemblyWriter {
out.flush(); out.flush();
} }
public final AddressListener addressListener = new AddressListener() { public final AddressListener addressListener = new AddressListener() {
@Override @Override
public void address(int address) { public void address(int address) {

View File

@ -462,7 +462,7 @@ public class WasmBinaryRenderer {
WasmBinaryWriter functionsSubsection = new WasmBinaryWriter(); WasmBinaryWriter functionsSubsection = new WasmBinaryWriter();
var functions = module.functions.stream() var functions = module.functions.stream()
.filter(f -> f.getName() != null && f.getImportName() == null) .filter(f -> f.getName() != null)
.collect(Collectors.toList()); .collect(Collectors.toList());
functionsSubsection.writeLEB(functions.size()); functionsSubsection.writeLEB(functions.size());