Files
wazero/wasm/section.go
2020-05-09 18:06:17 +09:00

263 lines
5.9 KiB
Go

package wasm
import (
"errors"
"fmt"
"io"
"github.com/mathetake/gasm/wasm/leb128"
)
type SectionID byte
const (
SectionIDCustom SectionID = 0
SectionIDType SectionID = 1
SectionIDImport SectionID = 2
SectionIDFunction SectionID = 3
SectionIDTable SectionID = 4
SectionIDMemory SectionID = 5
SectionIDGlobal SectionID = 6
SectionIDExport SectionID = 7
SectionIDStart SectionID = 8
SectionIDElement SectionID = 9
SectionIDCode SectionID = 10
SectionIDData SectionID = 11
)
func (m *Module) readSections(r io.Reader) error {
for {
if err := m.readSection(r); errors.Is(err, io.EOF) {
return nil
} else if err != nil {
return err
}
}
}
func (m *Module) readSection(r io.Reader) error {
b := make([]byte, 1)
if _, err := io.ReadFull(r, b); err != nil {
return fmt.Errorf("read section id: %w", err)
}
ss, _, err := leb128.DecodeUint32(r)
if err != nil {
return fmt.Errorf("get size of section for id=%d: %w", SectionID(b[0]), err)
}
switch SectionID(b[0]) {
case SectionIDCustom:
// TODO: should support custom section
bb := make([]byte, ss)
_, err = io.ReadFull(r, bb)
case SectionIDType:
err = m.readSectionTypes(r)
case SectionIDImport:
err = m.readSectionImports(r)
case SectionIDFunction:
err = m.readSectionFunctions(r)
case SectionIDTable:
err = m.readSectionTables(r)
case SectionIDMemory:
err = m.readSectionMemories(r)
case SectionIDGlobal:
err = m.readSectionGlobals(r)
case SectionIDExport:
err = m.readSectionExports(r)
case SectionIDStart:
err = m.readSectionStart(r)
case SectionIDElement:
err = m.readSectionElement(r)
case SectionIDCode:
err = m.readSectionCodes(r)
case SectionIDData:
err = m.readSectionData(r)
default:
err = errors.New("invalid section id")
}
if err != nil {
return fmt.Errorf("read section for %d: %w", SectionID(b[0]), err)
}
return nil
}
func (m *Module) readSectionTypes(r io.Reader) error {
vs, _, err := leb128.DecodeUint32(r)
if err != nil {
return fmt.Errorf("get size of vector: %w", err)
}
m.SecTypes = make([]*FunctionType, vs)
for i := range m.SecTypes {
m.SecTypes[i], err = readFunctionType(r)
if err != nil {
return fmt.Errorf("read %d-th function type: %w", i, err)
}
}
return nil
}
func (m *Module) readSectionImports(r io.Reader) error {
vs, _, err := leb128.DecodeUint32(r)
if err != nil {
return fmt.Errorf("get size of vector: %w", err)
}
m.SecImports = make([]*ImportSegment, vs)
for i := range m.SecImports {
m.SecImports[i], err = readImportSegment(r)
if err != nil {
return fmt.Errorf("read import: %w", err)
}
}
return nil
}
func (m *Module) readSectionFunctions(r io.Reader) error {
vs, _, err := leb128.DecodeUint32(r)
if err != nil {
return fmt.Errorf("get size of vector: %w", err)
}
m.SecFunctions = make([]uint32, vs)
for i := range m.SecFunctions {
m.SecFunctions[i], _, err = leb128.DecodeUint32(r)
if err != nil {
return fmt.Errorf("get typeidx: %w", err)
}
}
return nil
}
func (m *Module) readSectionTables(r io.Reader) error {
vs, _, err := leb128.DecodeUint32(r)
if err != nil {
return fmt.Errorf("get size of vector: %w", err)
}
m.SecTables = make([]*TableType, vs)
for i := range m.SecTables {
m.SecTables[i], err = readTableType(r)
if err != nil {
return fmt.Errorf("read table type: %w", err)
}
}
return nil
}
func (m *Module) readSectionMemories(r io.Reader) error {
vs, _, err := leb128.DecodeUint32(r)
if err != nil {
return fmt.Errorf("get size of vector: %w", err)
}
m.SecMemory = make([]*MemoryType, vs)
for i := range m.SecMemory {
m.SecMemory[i], err = readMemoryType(r)
if err != nil {
return fmt.Errorf("read memory type: %w", err)
}
}
return nil
}
func (m *Module) readSectionGlobals(r io.Reader) error {
vs, _, err := leb128.DecodeUint32(r)
if err != nil {
return fmt.Errorf("get size of vector: %w", err)
}
m.SecGlobals = make([]*GlobalSegment, vs)
for i := range m.SecGlobals {
m.SecGlobals[i], err = readGlobalSegment(r)
if err != nil {
return fmt.Errorf("read global segment: %w ", err)
}
}
return nil
}
func (m *Module) readSectionExports(r io.Reader) error {
vs, _, err := leb128.DecodeUint32(r)
if err != nil {
return fmt.Errorf("get size of vector: %w", err)
}
m.SecExports = make(map[string]*ExportSegment, vs)
for i := uint32(0); i < vs; i++ {
expDesc, err := readExportSegment(r)
if err != nil {
return fmt.Errorf("read export: %w", err)
}
m.SecExports[expDesc.Name] = expDesc
}
return nil
}
func (m *Module) readSectionStart(r io.Reader) error {
vs, _, err := leb128.DecodeUint32(r)
if err != nil {
return fmt.Errorf("get size of vector: %w", err)
}
m.SecStart = make([]uint32, vs)
for i := range m.SecStart {
m.SecStart[i], _, err = leb128.DecodeUint32(r)
if err != nil {
return fmt.Errorf("read function index: %w", err)
}
}
return nil
}
func (m *Module) readSectionElement(r io.Reader) error {
vs, _, err := leb128.DecodeUint32(r)
if err != nil {
return fmt.Errorf("get size of vector: %w", err)
}
m.SecElements = make([]*ElementSegment, vs)
for i := range m.SecElements {
m.SecElements[i], err = readElementSegment(r)
if err != nil {
return fmt.Errorf("read element: %w", err)
}
}
return nil
}
func (m *Module) readSectionCodes(r io.Reader) error {
vs, _, err := leb128.DecodeUint32(r)
if err != nil {
return fmt.Errorf("get size of vector: %w", err)
}
m.SecCodes = make([]*CodeSegment, vs)
for i := range m.SecCodes {
m.SecCodes[i], err = readCodeSegment(r)
if err != nil {
return fmt.Errorf("read code segment: %w", err)
}
}
return nil
}
func (m *Module) readSectionData(r io.Reader) error {
vs, _, err := leb128.DecodeUint32(r)
if err != nil {
return fmt.Errorf("get size of vector: %w", err)
}
m.SecData = make([]*DataSegment, vs)
for i := range m.SecData {
m.SecData[i], err = readDataSegment(r)
if err != nil {
return fmt.Errorf("read data segment: %w", err)
}
}
return nil
}