Skip to content

Commit

Permalink
wasm gc: add support for imports from JS
Browse files Browse the repository at this point in the history
  • Loading branch information
konsoletyper committed Oct 17, 2024
1 parent 1fadc71 commit e4a2550
Show file tree
Hide file tree
Showing 21 changed files with 297 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public final class Disassembler {
private WasmHollowFunctionType[] functionTypes;
private int[] functionTypeRefs;
private int importFunctionCount;
private int importGlobalCount;
private Map<String, DebugSectionParser> debugSectionParsers = new HashMap<>();
private DebugLinesParser debugLines;
private LineInfo lineInfo;
Expand Down Expand Up @@ -143,6 +144,7 @@ public Consumer<byte[]> getSectionConsumer(int code, int pos, NameProvider nameP
var parser = new ImportSectionParser(importListener);
parser.parse(AddressListener.EMPTY, bytes);
importFunctionCount = importListener.functionCount();
importGlobalCount = importListener.globalCount();
};
} else if (code == 3) {
return bytes -> {
Expand All @@ -165,6 +167,7 @@ public void function(int index, int typeIndex) {
var globalWriter = new DisassemblyGlobalSectionListener(writer, nameProvider);
writer.setAddressOffset(pos);
var sectionParser = new GlobalSectionParser(globalWriter);
sectionParser.setGlobalIndexOffset(importGlobalCount);
sectionParser.parse(writer.addressListener, bytes);
writer.flush();
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@

import org.teavm.backend.wasm.parser.ImportSectionListener;
import org.teavm.backend.wasm.parser.WasmHollowFunctionType;
import org.teavm.backend.wasm.parser.WasmHollowType;

public class DisassemblyImportSectionListener extends BaseDisassemblyListener implements ImportSectionListener {
private WasmHollowFunctionType[] functionTypes;
private String currentModule;
private String currentName;
private int functionIndex;
private int globalIndex;

public DisassemblyImportSectionListener(DisassemblyWriter writer, NameProvider nameProvider,
WasmHollowFunctionType[] functionTypes) {
Expand All @@ -34,6 +36,10 @@ public int functionCount() {
return functionIndex;
}

public int globalCount() {
return globalIndex;
}

@Override
public void startEntry(String module, String name) {
currentModule = module;
Expand Down Expand Up @@ -81,4 +87,21 @@ public void function(int typeIndex) {

functionIndex++;
}

@Override
public void global(WasmHollowType type) {
writer.address().write("(import \"").write(currentModule).write("\" \"")
.write(currentName).write("\" ");
writer.write("(global ");
writer.startLinkTarget("g" + globalIndex).write("(; " + globalIndex + " ;)");
var name = nameProvider.global(globalIndex);
if (name != null) {
writer.write(" $").write(name);
}
writer.endLinkTarget();
writer.write(" (type ");
writeType(type);
writer.write("))").eol();
++globalIndex;
}
}
30 changes: 28 additions & 2 deletions core/src/main/java/org/teavm/backend/wasm/model/WasmGlobal.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ public class WasmGlobal extends WasmEntity {
private WasmExpression initialValue;
private boolean immutable;
private String exportName;
private String importName;
private String importModule;

public WasmGlobal(String name, WasmType type, WasmExpression initialValue) {
this.name = name;
this.type = Objects.requireNonNull(type);
this.initialValue = Objects.requireNonNull(initialValue);
this.initialValue = initialValue;
}

public String getName() {
Expand All @@ -48,7 +50,7 @@ public WasmExpression getInitialValue() {
}

public void setInitialValue(WasmExpression initialValue) {
this.initialValue = Objects.requireNonNull(initialValue);
this.initialValue = initialValue;
}

public boolean isImmutable() {
Expand All @@ -66,4 +68,28 @@ public String getExportName() {
public void setExportName(String exportName) {
this.exportName = exportName;
}

public String getImportName() {
return importName;
}

public void setImportName(String importName) {
this.importName = importName;
if (collection != null) {
collection.invalidateIndexes();
}
}

public String getImportModule() {
return importModule;
}

public void setImportModule(String importModule) {
this.importModule = importModule;
}

@Override
boolean isImported() {
return importName != null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,25 @@
public class GlobalSectionParser extends BaseSectionParser {
private final GlobalSectionListener listener;
private CodeParser codeParser;
private int globalIndexOffset;

public GlobalSectionParser(GlobalSectionListener listener) {
this.listener = listener;
codeParser = new CodeParser();
}

public void setGlobalIndexOffset(int globalIndexOffset) {
this.globalIndexOffset = globalIndexOffset;
}

@Override
protected void parseContent() {
var count = readLEB();
for (var i = 0; i < count; ++i) {
reportAddress();
var type = reader.readType();
var mutable = reader.data[reader.ptr++] != 0;
var codeListener = listener.startGlobal(i, type, mutable);
var codeListener = listener.startGlobal(i + globalIndexOffset, type, mutable);
if (codeListener == null) {
codeListener = CodeListener.EMPTY;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ default void startEntry(String module, String name) {
default void function(int typeIndex) {
}

default void global(WasmHollowType type) {
}

default void endEntry() {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,19 @@ private void readEntry() {
listener.startEntry(module, name);
reportAddress();
var type = reader.data[reader.ptr++];
if (type == 0) {
var typeIndex = readLEB();
listener.function(typeIndex);
} else {
throw new ParseException("Unsupported import type", reader.ptr);
switch (type) {
case 0: {
var typeIndex = readLEB();
listener.function(typeIndex);
break;
}
case 3: {
var valueType = reader.readType();
listener.global(valueType);
break;
}
default:
throw new ParseException("Unsupported import type", reader.ptr);
}
listener.endEntry();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.teavm.backend.wasm.generate.DwarfGenerator;
import org.teavm.backend.wasm.model.WasmCustomSection;
import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.backend.wasm.model.WasmGlobal;
import org.teavm.backend.wasm.model.WasmMemorySegment;
import org.teavm.backend.wasm.model.WasmModule;
import org.teavm.backend.wasm.model.WasmStructure;
Expand Down Expand Up @@ -138,33 +139,52 @@ private void renderTypes(WasmModule module) {
}

private void renderImports(WasmModule module) {
List<WasmFunction> functions = new ArrayList<>();
var functions = new ArrayList<WasmFunction>();
for (var function : module.functions) {
if (function.getImportName() == null) {
continue;
}
functions.add(function);
}
if (functions.isEmpty()) {

var globals = new ArrayList<WasmGlobal>();
for (var global : module.globals) {
if (global.getImportName() == null) {
continue;
}
globals.add(global);
}

if (functions.isEmpty() && globals.isEmpty()) {
return;
}

WasmBinaryWriter section = new WasmBinaryWriter();

section.writeLEB(functions.size());
section.writeLEB(functions.size() + globals.size());
for (WasmFunction function : functions) {
int signatureIndex = module.types.indexOf(function.getType());
String moduleName = function.getImportModule();
if (moduleName == null) {
moduleName = "";
}
section.writeAsciiString(moduleName);

section.writeAsciiString(function.getImportName());

section.writeByte(EXTERNAL_KIND_FUNCTION);
section.writeLEB(signatureIndex);
}
for (var global : globals) {
var moduleName = global.getImportModule();
if (moduleName == null) {
moduleName = "";
}
section.writeAsciiString(moduleName);
section.writeAsciiString(global.getImportName());
section.writeByte(EXTERNAL_KIND_GLOBAL);
section.writeType(global.getType(), module);
section.writeByte(global.isImmutable() ? 0 : 1);
}

writeSection(SECTION_IMPORT, "import", section.getData());
}
Expand Down Expand Up @@ -211,16 +231,19 @@ private void renderMemory(WasmModule module) {
}

private void renderGlobals(WasmModule module) {
if (module.globals.isEmpty()) {
var globals = module.globals.stream()
.filter(global -> global.getImportName() == null)
.collect(Collectors.toList());
if (globals.isEmpty()) {
return;
}

var section = new WasmBinaryWriter();
var visitor = new WasmBinaryRenderingVisitor(section, module, null, null, 0);
section.writeLEB(module.globals.size());
for (var global : module.globals) {
section.writeLEB(globals.size());
for (var global : globals) {
section.writeType(global.getType(), module);
section.writeByte(global.isImmutable() ? 0 : 1); // mutable
section.writeByte(global.isImmutable() ? 0 : 1);
global.getInitialValue().acceptVisitor(visitor);
section.writeByte(0x0b);
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/js/wasm-gc-runtime/module-wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
*/

include();
export { load, defaults };
export { load, defaults, wrapImport };
Loading

0 comments on commit e4a2550

Please sign in to comment.