diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-06-29 23:43:30 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-06-29 23:43:30 +0100 |
| commit | a58b3ccb4d1b90dd5daeef04f5308ee06d3c64cb (patch) | |
| tree | 73cafee211d1b1f601279f893aab62f02b3c7f48 /src/main/java | |
| parent | 70e7de5d71eaf8703a0110a6a9e9a822c0c20430 (diff) | |
Check whether namespace is initialized when importing
Diffstat (limited to 'src/main/java')
13 files changed, 189 insertions, 13 deletions
diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenContext.java b/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenContext.java index b31ae005..5f80dbb9 100644 --- a/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenContext.java +++ b/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenContext.java @@ -25,6 +25,7 @@ public record WasmCodeGenContext( OrderedPSet<WasmFuncType> types, OrderedPSet<WasmImport> imports, PVector<WasmFunction> functions, + PVector<WasmGlobal> globals, PSet<String> symbolNames, WasmMemoryBuilder memory ) { @@ -33,6 +34,7 @@ public record WasmCodeGenContext( OrderedPSet.empty(), OrderedPSet.empty(), Empty.vector(), + Empty.vector(), Empty.set(), WasmMemoryBuilder.EMPTY ); @@ -43,6 +45,7 @@ public record WasmCodeGenContext( OrderedPSet.empty(), OrderedPSet.empty(), Empty.vector(), + Empty.vector(), Empty.set(), WasmMemoryBuilder.EMPTY ); @@ -54,6 +57,7 @@ public record WasmCodeGenContext( this.types.plus(funcType), this.imports, this.functions, + this.globals, this.symbolNames, this.memory ); @@ -65,6 +69,7 @@ public record WasmCodeGenContext( this.types, this.imports.plus(import_), this.functions, + this.globals, this.symbolNames, this.memory ); @@ -76,11 +81,24 @@ public record WasmCodeGenContext( this.types.plus(function.type()), this.imports, this.functions.plus(function), + this.globals, this.symbolNames.plus(function.name()), this.memory ); } + public ModuleContext addGlobal(WasmGlobal global) { + return new ModuleContext( + this.typeInfo, + this.types, + this.imports, + this.functions, + this.globals.plus(global), + this.symbolNames.plus(global.name()), + this.memory + ); + } + public String generateSymbolName(WasmCodeGenGlobalSpace space, Optional<String> name) { return NameAllocator.generateName( symbolNames::contains, @@ -101,6 +119,7 @@ public record WasmCodeGenContext( this.types, this.imports, this.functions, + this.globals, this.symbolNames.plus(name), result.memory() ).toResult(result.offset()); @@ -135,6 +154,10 @@ public record WasmCodeGenContext( module = module.addFunction(function); } + for (var global : globals) { + module = module.addGlobal(global); + } + return memory.toModule(module); } @@ -272,6 +295,13 @@ public record WasmCodeGenContext( ); } + public WasmCodeGenContext addGlobal(WasmGlobal global) { + return new WasmCodeGenContext( + this.moduleContext.addGlobal(global), + this.functionContext + ); + } + public WasmCodeGenResult<WasmMemoryAddress> addData( String name, byte[] data, diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenNamespaces.java b/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenNamespaces.java index f28ad61e..281c2f73 100644 --- a/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenNamespaces.java +++ b/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGenNamespaces.java @@ -4,6 +4,8 @@ import org.shedlang.compiler.backends.wasm.structure.ast.instructions.*; import org.shedlang.compiler.backends.wasm.structure.ast.linking.WasmMemoryAddress; import org.shedlang.compiler.backends.wasm.structure.ast.modules.*; import org.shedlang.compiler.backends.wasm.structure.ast.types.WasmFuncType; +import org.shedlang.compiler.backends.wasm.structure.ast.types.WasmGlobalType; +import org.shedlang.compiler.backends.wasm.structure.ast.types.WasmMutability; import org.shedlang.compiler.backends.wasm.structure.ast.types.WasmValueType; import org.shedlang.compiler.types.NamespaceName; @@ -45,7 +47,7 @@ public class WasmCodeGenNamespaces { WasmAlignment.ALIGN_32_BIT ).context(); - return context.createFunction( + context = context.createFunction( globalNameNamespaceInit(namespaceName), new WasmFuncType(List.of(), List.of()), initContext -> { @@ -69,16 +71,37 @@ public class WasmCodeGenNamespaces { return generateInitBody.apply(initContext); } - ).createFunction( + ); + + context = context.addGlobal(new WasmGlobal( + globalNameNamespaceIsInited(namespaceName), + new WasmGlobalType(WasmValueType.I32, WasmMutability.MUTABLE), + new WasmExpression(List.of(new WasmI32Const(0))) + )); + + context = context.createFunction( globalNameNamespaceImport(namespaceName), new WasmFuncType(List.of(), List.of(WasmCodeGenTypes.VALUE_TYPE)), bodyContext -> { // TODO: only init when necessary return bodyContext - .addInstruction(new WasmCall(new WasmFuncName(globalNameNamespaceInit(namespaceName)))) + .addInstruction(new WasmGlobalGet( + new WasmGlobalName(globalNameNamespaceIsInited(namespaceName)) + )) + .addInstruction(new WasmIf( + new WasmBlockType(List.of()), + List.of(), + List.of( + new WasmCall(new WasmFuncName(globalNameNamespaceInit(namespaceName))), + new WasmI32Const(1), + new WasmGlobalSet(new WasmGlobalName(globalNameNamespaceIsInited(namespaceName))) + ) + )) .addInstruction(new WasmMemoryAddressConst(namespaceMemoryAddress(namespaceName, bodyContext))); } ); + + return context; } public static WasmCodeGenContext fieldStore( @@ -141,6 +164,10 @@ public class WasmCodeGenNamespaces { return "shed__namespaceInit__" + namespaceNameToWasmIdentifier(namespaceName); } + private static String globalNameNamespaceIsInited(NamespaceName namespaceName) { + return "shed__namespaceIsInited__" + namespaceNameToWasmIdentifier(namespaceName); + } + private static String globalNameNamespaceImport(NamespaceName namespaceName) { return "shed__namespaceImport__" + namespaceNameToWasmIdentifier(namespaceName); } diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/instructions/WasmBlockType.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/instructions/WasmBlockType.java new file mode 100644 index 00000000..0740f58f --- /dev/null +++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/instructions/WasmBlockType.java @@ -0,0 +1,8 @@ +package org.shedlang.compiler.backends.wasm.structure.ast.instructions; + +import org.shedlang.compiler.backends.wasm.structure.ast.types.WasmValueType; + +import java.util.List; + +public record WasmBlockType(List<WasmValueType> resultTypes) { +} diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/instructions/WasmGlobalGet.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/instructions/WasmGlobalGet.java new file mode 100644 index 00000000..b8fe9efa --- /dev/null +++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/instructions/WasmGlobalGet.java @@ -0,0 +1,6 @@ +package org.shedlang.compiler.backends.wasm.structure.ast.instructions; + +import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmGlobalName; + +public record WasmGlobalGet(WasmGlobalName globalName) implements WasmInstruction { +} diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/instructions/WasmGlobalSet.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/instructions/WasmGlobalSet.java new file mode 100644 index 00000000..dea3328a --- /dev/null +++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/instructions/WasmGlobalSet.java @@ -0,0 +1,6 @@ +package org.shedlang.compiler.backends.wasm.structure.ast.instructions; + +import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmGlobalName; + +public record WasmGlobalSet(WasmGlobalName globalName) implements WasmInstruction { +} diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/instructions/WasmIf.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/instructions/WasmIf.java new file mode 100644 index 00000000..66751a74 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/instructions/WasmIf.java @@ -0,0 +1,10 @@ +package org.shedlang.compiler.backends.wasm.structure.ast.instructions; + +import java.util.List; + +public record WasmIf( + WasmBlockType blockType, + List<WasmInstruction> ifTrue, + List<WasmInstruction> ifFalse +) implements WasmInstruction { +} diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/instructions/WasmInstruction.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/instructions/WasmInstruction.java index ed1a1cf9..0e802d51 100644 --- a/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/instructions/WasmInstruction.java +++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/instructions/WasmInstruction.java @@ -1,4 +1,4 @@ package org.shedlang.compiler.backends.wasm.structure.ast.instructions; -public sealed interface WasmInstruction permits WasmCall, WasmCallIndirect, WasmDrop, WasmI32Const, WasmI32Load, WasmI32Store, WasmI64Const, WasmLocalGet, WasmLocalSet, WasmMemoryAddressConst, WasmMemoryGrow, WasmReturn, WasmTableElementIndexConst { +public sealed interface WasmInstruction permits WasmCall, WasmCallIndirect, WasmDrop, WasmGlobalGet, WasmGlobalSet, WasmI32Const, WasmI32Load, WasmI32Store, WasmI64Const, WasmIf, WasmLocalGet, WasmLocalSet, WasmMemoryAddressConst, WasmMemoryGrow, WasmReturn, WasmTableElementIndexConst { } diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/linking/WasmRelocatableIndex.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/linking/WasmRelocatableIndex.java index eec53af7..329d36d7 100644 --- a/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/linking/WasmRelocatableIndex.java +++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/linking/WasmRelocatableIndex.java @@ -1,10 +1,12 @@ package org.shedlang.compiler.backends.wasm.structure.ast.linking; import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmFuncName; +import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmGlobalName; import org.shedlang.compiler.backends.wasm.structure.ast.types.WasmFuncType; public sealed interface WasmRelocatableIndex { record FuncIndex(WasmFuncName funcName) implements WasmRelocatableIndex {} + record GlobalIndex(WasmGlobalName globalName) implements WasmRelocatableIndex {} record MemoryAddress(WasmMemoryAddress address) implements WasmRelocatableIndex {} record TableElementIndex(WasmFuncName funcName) implements WasmRelocatableIndex {} record TypeIndex(WasmFuncType funcType) implements WasmRelocatableIndex {} diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/modules/WasmGlobalName.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/modules/WasmGlobalName.java new file mode 100644 index 00000000..7c9d9c44 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/ast/modules/WasmGlobalName.java @@ -0,0 +1,4 @@ +package org.shedlang.compiler.backends.wasm.structure.ast.modules; + +public record WasmGlobalName(String value) { +} diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatInstructions.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatInstructions.java index 45403459..c9552a96 100644 --- a/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatInstructions.java +++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatInstructions.java @@ -21,6 +21,19 @@ public class WasmBinaryFormatInstructions { // == Control Instructions == + case WasmIf if_ -> { + writer.writeByte(0x04); + writeBlockType(if_.blockType(), writer); + for (var subInstruction : if_.ifTrue()) { + writeInstruction(subInstruction, writer); + } + writer.writeByte(0x05); + for (var subInstruction : if_.ifFalse()) { + writeInstruction(subInstruction, writer); + } + writer.writeByte(0x0b); + } + case WasmReturn ignored -> { writer.writeByte(0x0f); } @@ -54,6 +67,16 @@ public class WasmBinaryFormatInstructions { writeLocalIndex(localSet.localIndex(), writer); } + case WasmGlobalGet globalGet -> { + writer.writeByte(0x23); + writer.writeGlobalIndex(globalGet.globalName()); + } + + case WasmGlobalSet globalSet -> { + writer.writeByte(0x24); + writer.writeGlobalIndex(globalSet.globalName()); + } + // == Memory Instructions == case WasmI32Load i32Load -> { @@ -96,6 +119,17 @@ public class WasmBinaryFormatInstructions { } } + // == Control Instructions == + + private static void writeBlockType(WasmBlockType blockType, WasmBinaryWriter writer) { + if (blockType.resultTypes().isEmpty()) { + writer.writeByte(0x40); + } else { + // TODO: implement this + throw new RuntimeException("not implemented"); + } + } + // == Memory Instructions == private static void writeMemoryArg(WasmMemoryArg memoryArg, WasmBinaryWriter writer) { diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatLinking.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatLinking.java index 451229fc..f8813bb5 100644 --- a/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatLinking.java +++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryFormatLinking.java @@ -69,6 +69,9 @@ public class WasmBinaryFormatLinking { case WasmRelocatableIndex.FuncIndex funcIndex -> symbolTable.funcNameToSymbolIndex(funcIndex.funcName()).value(); + case WasmRelocatableIndex.GlobalIndex globalIndex -> + symbolTable.globalNameToSymbolIndex(globalIndex.globalName()).value(); + case WasmRelocatableIndex.MemoryAddress memoryAddress -> symbolTable.memoryAddressToSymbolIndex(memoryAddress.address()).value(); @@ -232,17 +235,20 @@ public class WasmBinaryFormatLinking { private final Map<WasmMemoryAddress, WasmSymbolIndex> memoryAddressToSymbolIndex; private final Map<WasmFuncType, WasmTypeIndex> funcTypeToTypeIndex; private final Map<String, WasmSymbolIndex> funcNameToSymbolIndex; + private final Map<String, WasmSymbolIndex> globalNameToSymbolIndex; public SymbolTable( List<SymbolInfo> symbolInfos, Map<WasmMemoryAddress, WasmSymbolIndex> memoryAddressToSymbolIndex, Map<WasmFuncType, WasmTypeIndex> funcTypeToTypeIndex, - Map<String, WasmSymbolIndex> funcNameToSymbolIndex + Map<String, WasmSymbolIndex> funcNameToSymbolIndex, + Map<String, WasmSymbolIndex> globalNameToSymbolIndex ) { this.symbolInfos = symbolInfos; this.memoryAddressToSymbolIndex = memoryAddressToSymbolIndex; this.funcTypeToTypeIndex = funcTypeToTypeIndex; this.funcNameToSymbolIndex = funcNameToSymbolIndex; + this.globalNameToSymbolIndex = globalNameToSymbolIndex; } public WasmSymbolIndex memoryAddressToSymbolIndex(WasmMemoryAddress memoryAddress) { @@ -274,11 +280,20 @@ public class WasmBinaryFormatLinking { return symbolIndex; } } + + public WasmSymbolIndex globalNameToSymbolIndex(WasmGlobalName name) { + var symbolIndex = globalNameToSymbolIndex.get(name.value()); + if (symbolIndex == null) { + // TODO: better error + throw new RuntimeException("could not find index for global: " + name); + } else { + return symbolIndex; + } + } } private static SymbolTable generateSymbolTable(WasmModule module) { var symbolInfos = new ArrayList<SymbolInfo>(); - var memoryAddressToSymbolIndex = new HashMap<WasmMemoryAddress, WasmSymbolIndex>(); var funcNameToSymbolIndex = new HashMap<String, WasmSymbolIndex>(); for (var function : module.indexedFunctions()) { @@ -299,6 +314,7 @@ public class WasmBinaryFormatLinking { funcNameToSymbolIndex.put(function.name(), symbolIndex); } + var memoryAddressToSymbolIndex = new HashMap<WasmMemoryAddress, WasmSymbolIndex>(); for (var dataSegment : module.dataSegments()) { for (var dataSymbol : dataSegment.symbols()) { var symbolInfo = new SymbolInfo.Data(List.of(), dataSymbol); @@ -311,6 +327,7 @@ public class WasmBinaryFormatLinking { } } + var globalNameToSymbolIndex = new HashMap<String, WasmSymbolIndex>(); for (var global : module.indexedGlobals()) { var flags = switch (global) { case WasmModule.IndexedGlobal.Definition definition -> @@ -319,12 +336,17 @@ public class WasmBinaryFormatLinking { case WasmModule.IndexedGlobal.Import import_ -> List.of(SymbolFlag.UNDEFINED, SymbolFlag.EXPLICIT_NAME); }; + var symbolInfo = new SymbolInfo.Global( flags, global.globalIndex(), global.name() ); + + var symbolIndex = new WasmSymbolIndex(symbolInfos.size()); symbolInfos.add(symbolInfo); + + globalNameToSymbolIndex.put(global.name(), symbolIndex); } var funcTypes = module.types().stream().toList(); @@ -339,7 +361,8 @@ public class WasmBinaryFormatLinking { symbolInfos, memoryAddressToSymbolIndex, funcTypeToTypeIndex, - funcNameToSymbolIndex + funcNameToSymbolIndex, + globalNameToSymbolIndex ); } diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryWriter.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryWriter.java index 0d4bc68f..3ac5d2bc 100644 --- a/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryWriter.java +++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmBinaryWriter.java @@ -4,6 +4,7 @@ import org.shedlang.compiler.backends.wasm.structure.BinaryWriter; import org.shedlang.compiler.backends.wasm.structure.ast.linking.WasmMemoryAddress; import org.shedlang.compiler.backends.wasm.structure.ast.linking.WasmRelocatableIndex; import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmFuncName; +import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmGlobalName; import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmTableIndex; import org.shedlang.compiler.backends.wasm.structure.ast.types.WasmFuncType; @@ -62,6 +63,15 @@ public class WasmBinaryWriter { ); } + public void writeGlobalIndex(WasmGlobalName globalName) throws IOException { + var globalIndex = indexTable.globalIndex(globalName); + writeRelocatableIndex( + WasmRelocationType.GLOBAL_INDEX_LEB, + () -> writePaddedUnsignedInt32(globalIndex.value()), + new WasmRelocatableIndex.GlobalIndex(globalName) + ); + } + public void writeMemoryAddressConst(WasmMemoryAddress index) throws IOException { writeRelocatableIndex( WasmRelocationType.MEMORY_ADDR_SLEB, diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmIndexTable.java b/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmIndexTable.java index e9b855f2..2aa8d63a 100644 --- a/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmIndexTable.java +++ b/src/main/java/org/shedlang/compiler/backends/wasm/structure/binary/WasmIndexTable.java @@ -1,9 +1,6 @@ package org.shedlang.compiler.backends.wasm.structure.binary; -import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmFuncIndex; -import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmFuncName; -import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmModule; -import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmTypeIndex; +import org.shedlang.compiler.backends.wasm.structure.ast.modules.*; import org.shedlang.compiler.backends.wasm.structure.ast.types.WasmFuncType; import java.util.HashMap; @@ -21,21 +18,30 @@ public class WasmIndexTable { functionNameToFuncIndex.put(indexedFunction.name(), indexedFunction.funcIndex()); } + var globalNameToGlobalIndex = new HashMap<String, WasmGlobalIndex>(); + for (var indexedGlobal : module.indexedGlobals()) { + globalNameToGlobalIndex.put(indexedGlobal.name(), indexedGlobal.globalIndex()); + } + return new WasmIndexTable( funcTypeToTypeIndex, - functionNameToFuncIndex + functionNameToFuncIndex, + globalNameToGlobalIndex ); } private final Map<WasmFuncType, WasmTypeIndex> funcTypeToTypeIndex; private final Map<String, WasmFuncIndex> functionNameToFuncIndex; + private final Map<String, WasmGlobalIndex> globalNameToGlobalIndex; private WasmIndexTable( Map<WasmFuncType, WasmTypeIndex> funcTypeToTypeIndex, - Map<String, WasmFuncIndex> functionNameToFuncIndex + Map<String, WasmFuncIndex> functionNameToFuncIndex, + Map<String, WasmGlobalIndex> globalNameToGlobalIndex ) { this.funcTypeToTypeIndex = funcTypeToTypeIndex; this.functionNameToFuncIndex = functionNameToFuncIndex; + this.globalNameToGlobalIndex = globalNameToGlobalIndex; } public WasmTypeIndex typeIndex(WasmFuncType type) { @@ -51,4 +57,14 @@ public class WasmIndexTable { return funcIndex; } } + + public WasmGlobalIndex globalIndex(WasmGlobalName globalName) { + var globalIndex = globalNameToGlobalIndex.get(globalName.value()); + if (globalIndex == null) { + // TODO: better error + throw new RuntimeException("missing global index for global: " + globalName.value()); + } else { + return globalIndex; + } + } } |
