Skip to content
This repository was archived by the owner on Jul 12, 2024. It is now read-only.

Commit d379e39

Browse files
authored
Merge pull request #86 from sjrd/simpler-wasm-model
Refactoring: Simplify our model of WebAssembly.
2 parents 9f8295d + 5d326c6 commit d379e39

13 files changed

+1305
-1275
lines changed

Diff for: wasm/src/main/scala/converters/WasmBinaryWriter.scala

+89-46
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@ import java.io.ByteArrayOutputStream
99
import wasm.wasm4s._
1010
import wasm.wasm4s.Names._
1111
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}
1613

1714
final 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

Comments
 (0)