move binary encoder to its own package Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>
49 lines
1.7 KiB
Go
49 lines
1.7 KiB
Go
package binaryencoding
|
|
|
|
import (
|
|
"github.com/tetratelabs/wazero/internal/leb128"
|
|
"github.com/tetratelabs/wazero/internal/wasm"
|
|
)
|
|
|
|
// encodeCode returns the wasm.Code encoded in WebAssembly 1.0 (20191205) Binary Format.
|
|
//
|
|
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-code
|
|
func encodeCode(c *wasm.Code) []byte {
|
|
if c.GoFunc != nil {
|
|
panic("BUG: GoFunction is not encodable")
|
|
}
|
|
|
|
// local blocks compress locals while preserving index order by grouping locals of the same type.
|
|
// https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#code-section%E2%91%A0
|
|
localBlockCount := uint32(0) // how many blocks of locals with the same type (types can repeat!)
|
|
var localBlocks []byte
|
|
localTypeLen := len(c.LocalTypes)
|
|
if localTypeLen > 0 {
|
|
i := localTypeLen - 1
|
|
var runCount uint32 // count of the same type
|
|
var lastValueType wasm.ValueType // initialize to an invalid type 0
|
|
|
|
// iterate backwards so it is easier to size prefix
|
|
for ; i >= 0; i-- {
|
|
vt := c.LocalTypes[i]
|
|
if lastValueType != vt {
|
|
if runCount != 0 { // Only on the first iteration, this is zero when vt is compared against invalid
|
|
localBlocks = append(leb128.EncodeUint32(runCount), localBlocks...)
|
|
}
|
|
lastValueType = vt
|
|
localBlocks = append(leb128.EncodeUint32(uint32(vt)), localBlocks...) // reuse the EncodeUint32 cache
|
|
localBlockCount++
|
|
runCount = 1
|
|
} else {
|
|
runCount++
|
|
}
|
|
}
|
|
localBlocks = append(leb128.EncodeUint32(runCount), localBlocks...)
|
|
localBlocks = append(leb128.EncodeUint32(localBlockCount), localBlocks...)
|
|
} else {
|
|
localBlocks = leb128.EncodeUint32(0)
|
|
}
|
|
code := append(localBlocks, c.Body...)
|
|
return append(leb128.EncodeUint32(uint32(len(code))), code...)
|
|
}
|