@@ -9,10 +9,7 @@ import java.io.ByteArrayOutputStream
9
9
import wasm .wasm4s ._
10
10
import wasm .wasm4s .Names ._
11
11
import 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 }
16
13
17
14
final class WasmBinaryWriter (module : WasmModule , emitDebugInfo : Boolean ) {
18
15
import WasmBinaryWriter ._
@@ -66,7 +63,7 @@ final class WasmBinaryWriter(module: WasmModule, emitDebugInfo: Boolean) {
66
63
}
67
64
68
65
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
70
67
71
68
private def withLocalIdxValues (values : Map [WasmLocalName , Int ])(f : => Unit ): Unit = {
72
69
val saved = localIdxValues
@@ -288,19 +285,23 @@ final class WasmBinaryWriter(module: WasmModule, emitDebugInfo: Boolean) {
288
285
}
289
286
290
287
private def writeType (buf : Buffer , typ : WasmStorageType ): Unit = {
291
- buf.byte(typ.code)
292
288
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)
296
298
}
297
299
}
298
300
299
301
private def writeHeapType (buf : Buffer , heapType : WasmHeapType ): Unit = {
300
302
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)
304
305
}
305
306
}
306
307
@@ -332,7 +333,7 @@ final class WasmBinaryWriter(module: WasmModule, emitDebugInfo: Boolean) {
332
333
}
333
334
}
334
335
335
- private def writeLabelIdx (buf : Buffer , labelIdx : WasmImmediate . LabelIdx ): Unit = {
336
+ private def writeLabelIdx (buf : Buffer , labelIdx : WasmLabelName ): Unit = {
336
337
val relativeNumber = labelsInScope.indexOf(Some (labelIdx))
337
338
if (relativeNumber < 0 )
338
339
throw new IllegalStateException (s " Cannot find $labelIdx in scope " )
@@ -358,8 +359,7 @@ final class WasmBinaryWriter(module: WasmModule, emitDebugInfo: Boolean) {
358
359
buf.byte(opcode.toByte)
359
360
}
360
361
361
- for (immediate <- instr.immediates)
362
- writeImmediate(buf, immediate)
362
+ writeInstrImmediates(buf, instr)
363
363
364
364
instr match {
365
365
case instr : WasmInstr .StructuredLabeledInstr =>
@@ -372,44 +372,87 @@ final class WasmBinaryWriter(module: WasmModule, emitDebugInfo: Boolean) {
372
372
}
373
373
}
374
374
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 ._
383
377
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
+ }
387
389
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
391
392
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)
405
430
buf.vec(clauses) { clause =>
406
431
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 )
409
434
}
410
435
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)
413
456
}
414
457
}
415
458
}
0 commit comments