github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/testing/binaryencoding/code.go (about) 1 package binaryencoding 2 3 import ( 4 "github.com/wasilibs/wazerox/internal/leb128" 5 "github.com/wasilibs/wazerox/internal/wasm" 6 ) 7 8 // encodeCode returns the wasm.Code encoded in WebAssembly 1.0 (20191205) Binary Format. 9 // 10 // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-code 11 func encodeCode(c *wasm.Code) []byte { 12 if c.GoFunc != nil { 13 panic("BUG: GoFunction is not encodable") 14 } 15 16 // local blocks compress locals while preserving index order by grouping locals of the same type. 17 // https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#code-section%E2%91%A0 18 localBlockCount := uint32(0) // how many blocks of locals with the same type (types can repeat!) 19 var localBlocks []byte 20 localTypeLen := len(c.LocalTypes) 21 if localTypeLen > 0 { 22 i := localTypeLen - 1 23 var runCount uint32 // count of the same type 24 var lastValueType wasm.ValueType // initialize to an invalid type 0 25 26 // iterate backwards so it is easier to size prefix 27 for ; i >= 0; i-- { 28 vt := c.LocalTypes[i] 29 if lastValueType != vt { 30 if runCount != 0 { // Only on the first iteration, this is zero when vt is compared against invalid 31 localBlocks = append(leb128.EncodeUint32(runCount), localBlocks...) 32 } 33 lastValueType = vt 34 localBlocks = append(leb128.EncodeUint32(uint32(vt)), localBlocks...) // reuse the EncodeUint32 cache 35 localBlockCount++ 36 runCount = 1 37 } else { 38 runCount++ 39 } 40 } 41 localBlocks = append(leb128.EncodeUint32(runCount), localBlocks...) 42 localBlocks = append(leb128.EncodeUint32(localBlockCount), localBlocks...) 43 } else { 44 localBlocks = leb128.EncodeUint32(0) 45 } 46 code := append(localBlocks, c.Body...) 47 return append(leb128.EncodeUint32(uint32(len(code))), code...) 48 }