@@ -9,10 +9,7 @@ import java.io.ByteArrayOutputStream
99import wasm .wasm4s ._
1010import wasm .wasm4s .Names ._
1111import wasm .wasm4s .Types ._
12- import wasm .wasm4s .Types .WasmHeapType .Type
13- import wasm .wasm4s .Types .WasmHeapType .Func
14- import wasm .wasm4s .Types .WasmHeapType .Simple
15- import wasm .wasm4s .WasmInstr .END
12+ import wasm .wasm4s .WasmInstr .{BlockType , END }
1613
1714final class WasmBinaryWriter (module : WasmModule , emitDebugInfo : Boolean ) {
1815 import WasmBinaryWriter ._
@@ -66,7 +63,7 @@ final class WasmBinaryWriter(module: WasmModule, emitDebugInfo: Boolean) {
6663 }
6764
6865 private var localIdxValues : Option [Map [WasmLocalName , Int ]] = None
69- private var labelsInScope : List [Option [WasmImmediate . LabelIdx ]] = Nil
66+ private var labelsInScope : List [Option [WasmLabelName ]] = Nil
7067
7168 private def withLocalIdxValues (values : Map [WasmLocalName , Int ])(f : => Unit ): Unit = {
7269 val saved = localIdxValues
@@ -288,19 +285,23 @@ final class WasmBinaryWriter(module: WasmModule, emitDebugInfo: Boolean) {
288285 }
289286
290287 private def writeType (buf : Buffer , typ : WasmStorageType ): Unit = {
291- buf.byte(typ.code)
292288 typ match {
293- case WasmRefNullType (heapType) => writeHeapType(buf, heapType)
294- case WasmRefType (heapType) => writeHeapType(buf, heapType)
295- case _ => ()
289+ case typ : WasmSimpleType => buf.byte(typ.binaryCode)
290+ case typ : WasmPackedType => buf.byte(typ.binaryCode)
291+
292+ case WasmRefType (true , heapType : WasmHeapType .AbsHeapType ) =>
293+ buf.byte(heapType.binaryCode)
294+
295+ case WasmRefType (nullable, heapType) =>
296+ buf.byte(if (nullable) 0x63 else 0x64 )
297+ writeHeapType(buf, heapType)
296298 }
297299 }
298300
299301 private def writeHeapType (buf : Buffer , heapType : WasmHeapType ): Unit = {
300302 heapType match {
301- case Type (typeName) => writeTypeIdxs33(buf, typeName)
302- case Func (typeName) => writeTypeIdxs33(buf, typeName)
303- case heapType : Simple => buf.byte(heapType.code)
303+ case WasmHeapType .Type (typeName) => writeTypeIdxs33(buf, typeName)
304+ case heapType : WasmHeapType .AbsHeapType => buf.byte(heapType.binaryCode)
304305 }
305306 }
306307
@@ -332,7 +333,7 @@ final class WasmBinaryWriter(module: WasmModule, emitDebugInfo: Boolean) {
332333 }
333334 }
334335
335- private def writeLabelIdx (buf : Buffer , labelIdx : WasmImmediate . LabelIdx ): Unit = {
336+ private def writeLabelIdx (buf : Buffer , labelIdx : WasmLabelName ): Unit = {
336337 val relativeNumber = labelsInScope.indexOf(Some (labelIdx))
337338 if (relativeNumber < 0 )
338339 throw new IllegalStateException (s " Cannot find $labelIdx in scope " )
@@ -358,8 +359,7 @@ final class WasmBinaryWriter(module: WasmModule, emitDebugInfo: Boolean) {
358359 buf.byte(opcode.toByte)
359360 }
360361
361- for (immediate <- instr.immediates)
362- writeImmediate(buf, immediate)
362+ writeInstrImmediates(buf, instr)
363363
364364 instr match {
365365 case instr : WasmInstr .StructuredLabeledInstr =>
@@ -372,44 +372,87 @@ final class WasmBinaryWriter(module: WasmModule, emitDebugInfo: Boolean) {
372372 }
373373 }
374374
375- private def writeImmediate (buf : Buffer , immediate : WasmImmediate ): Unit = {
376- import WasmImmediate ._
377-
378- immediate match {
379- case I32 (value) => buf.i32(value)
380- case I64 (value) => buf.i64(value)
381- case F32 (value) => buf.f32(value)
382- case F64 (value) => buf.f64(value)
375+ private def writeInstrImmediates (buf : Buffer , instr : WasmInstr ): Unit = {
376+ import WasmInstr ._
383377
384- case MemArg (offset, align) =>
385- buf.u32(offset.toInt)
386- buf.u32(align.toInt)
378+ def writeBrOnCast (
379+ labelIdx : WasmLabelName ,
380+ from : WasmRefType ,
381+ to : WasmRefType
382+ ): Unit = {
383+ val castFlags = ((if (from.nullable) 1 else 0 ) | (if (to.nullable) 2 else 0 )).toByte
384+ buf.byte(castFlags)
385+ writeLabelIdx(buf, labelIdx)
386+ writeHeapType(buf, from.heapType)
387+ writeHeapType(buf, to.heapType)
388+ }
387389
388- case BlockType .ValueType (None ) => buf.byte(0x40 )
389- case BlockType .ValueType (Some (typ)) => writeType(buf, typ)
390- case BlockType .FunctionType (typeName) => writeTypeIdxs33(buf, typeName)
390+ instr match {
391+ // Convenience categories
391392
392- case FuncIdx (value) => writeFuncIdx(buf, value)
393- case labelIdx : LabelIdx => writeLabelIdx(buf, labelIdx)
394- case LabelIdxVector (value) => buf.vec(value)(writeLabelIdx(buf, _))
395- case TypeIdx (value) => writeTypeIdx(buf, value)
396- case DataIdx (value) => writeDataIdx(buf, value)
397- case TableIdx (value) => ???
398- case TagIdx (value) => writeTagIdx(buf, value)
399- case LocalIdx (value) => writeLocalIdx(buf, value)
400- case GlobalIdx (value) => writeGlobalIdx(buf, value)
401- case HeapType (value) => writeHeapType(buf, value)
402- case StructFieldIdx (value) => buf.u32(value)
403-
404- case CatchClauseVector (clauses) =>
393+ case instr : WasmSimpleInstr =>
394+ ()
395+ case instr : WasmBlockTypeLabeledInstr =>
396+ writeBlockType(buf, instr.blockTypeArgument)
397+ case instr : WasmLabelInstr =>
398+ writeLabelIdx(buf, instr.labelArgument)
399+ case instr : WasmFuncInstr =>
400+ writeFuncIdx(buf, instr.funcArgument)
401+ case instr : WasmTypeInstr =>
402+ writeTypeIdx(buf, instr.typeArgument)
403+ case instr : WasmTagInstr =>
404+ writeTagIdx(buf, instr.tagArgument)
405+ case instr : WasmLocalInstr =>
406+ writeLocalIdx(buf, instr.localArgument)
407+ case instr : WasmGlobalInstr =>
408+ writeGlobalIdx(buf, instr.globalArgument)
409+ case instr : WasmHeapTypeInstr =>
410+ writeHeapType(buf, instr.heapTypeArgument)
411+ case instr : WasmRefTypeInstr =>
412+ writeHeapType(buf, instr.refTypeArgument.heapType)
413+ case instr : WasmStructFieldInstr =>
414+ writeTypeIdx(buf, instr.structTypeName)
415+ buf.u32(instr.fieldIdx.value)
416+
417+ // Specific instructions with unique-ish shapes
418+
419+ case I32_CONST (v) => buf.i32(v)
420+ case I64_CONST (v) => buf.i64(v)
421+ case F32_CONST (v) => buf.f32(v)
422+ case F64_CONST (v) => buf.f64(v)
423+
424+ case BR_TABLE (labelIdxVector, defaultLabelIdx) =>
425+ buf.vec(labelIdxVector)(writeLabelIdx(buf, _))
426+ writeLabelIdx(buf, defaultLabelIdx)
427+
428+ case TRY_TABLE (blockType, clauses, _) =>
429+ writeBlockType(buf, blockType)
405430 buf.vec(clauses) { clause =>
406431 buf.byte(clause.opcode.toByte)
407- for (imm <- clause.immediates )
408- writeImmediate (buf, imm )
432+ clause.tag.foreach(tag => writeTagIdx(buf, tag) )
433+ writeLabelIdx (buf, clause.label )
409434 }
410435
411- case CastFlags (nullable1, nullable2) =>
412- buf.byte(((if (nullable1) 1 else 0 ) | (if (nullable2) 2 else 0 )).toByte)
436+ case ARRAY_NEW_DATA (typeIdx, dataIdx) =>
437+ writeTypeIdx(buf, typeIdx)
438+ writeDataIdx(buf, dataIdx)
439+
440+ case ARRAY_NEW_FIXED (typeIdx, length) =>
441+ writeTypeIdx(buf, typeIdx)
442+ buf.u32(length)
443+
444+ case BR_ON_CAST (labelIdx, from, to) =>
445+ writeBrOnCast(labelIdx, from, to)
446+ case BR_ON_CAST_FAIL (labelIdx, from, to) =>
447+ writeBrOnCast(labelIdx, from, to)
448+ }
449+ }
450+
451+ private def writeBlockType (buf : Buffer , blockType : BlockType ): Unit = {
452+ blockType match {
453+ case BlockType .ValueType (None ) => buf.byte(0x40 )
454+ case BlockType .ValueType (Some (typ)) => writeType(buf, typ)
455+ case BlockType .FunctionType (typeName) => writeTypeIdxs33(buf, typeName)
413456 }
414457 }
415458}
0 commit comments