Repository: tetratelabs/wazero
Pull request #140 (2022-01-17 13:55:32)

Flattens Export and Import and dodges Segment suffix
This flattens the type hierarchy of Export and Import a little as it
felt easier to reason with considering there are only 4 kinds.

This also dodges the Segment suffix because that only applies to
"element" and "data"


Patch:
diff --git a/wasm/module.go b/wasm/module.go
index eb490b7b..04932480 100644
--- a/wasm/module.go
+++ b/wasm/module.go
@@ -28,15 +28,21 @@ func (r *reader) Read(p []byte) (n int, err error) {
 
 // Module is a WebAssembly binary representation.
 // See https://www.w3.org/TR/wasm-core-1/#modules%E2%91%A8
+//
+// Differences from the specification:
+// * The NameSection is decoded, so not present as a key "name" in CustomSections.
 type Module struct {
 	// TypeSection contains the unique FunctionType of functions imported or defined in this module.
 	//
 	// See https://www.w3.org/TR/wasm-core-1/#type-section%E2%91%A0
 	TypeSection []*FunctionType
-	// ImportSection contains any types, tables, memories or globals imported into this module.
+	// ImportSection contains imported functions, tables, memories or globals required for instantiation
+	// (Store.Instantiate).
+	//
+	// Note: there are no unique constraints relating to the two-level namespace of Import.Module and Import.Name.
 	//
 	// See https://www.w3.org/TR/wasm-core-1/#import-section%E2%91%A0
-	ImportSection []*ImportSegment
+	ImportSection []*Import
 	// FunctionSection contains the index in TypeSection of each function defined in this module.
 	//
 	// Function indexes are offset by any imported functions because the function index space begins with imports,
@@ -77,11 +83,11 @@ type Module struct {
 	// global at index 3 is defined in this module at GlobalSection[0].
 	//
 	// See https://www.w3.org/TR/wasm-core-1/#global-section%E2%91%A0
-	GlobalSection []*GlobalSegment
-	ExportSection map[string]*ExportSegment
+	GlobalSection []*Global
+	ExportSection map[string]*Export
 	// StartSection is the index of a function to call before returning from Store.Instantiate.
 	//
-	// Note: The function index space begins with any ImportKindFunction in ImportSection, then the FunctionSection.
+	// Note: The function index space begins with any ImportKindFunc in ImportSection, then the FunctionSection.
 	// For example, if there are two imported functions and three defined in this module, the index space is five.
 	// Note: This is a pointer to avoid conflating no start section with the valid index zero.
 	//
@@ -91,7 +97,7 @@ type Module struct {
 	// CodeSection is index-correlated with FunctionSection and contains each function's locals and body.
 	//
 	// See https://www.w3.org/TR/wasm-core-1/#code-section%E2%91%A0
-	CodeSection []*CodeSegment
+	CodeSection []*Code
 	DataSection []*DataSegment
 	// NameSection is set when the custom section "name" was successfully decoded from the binary format.
 	//
diff --git a/wasm/section.go b/wasm/section.go
index 9c45ec84..f8afe6a3 100644
--- a/wasm/section.go
+++ b/wasm/section.go
@@ -230,9 +230,9 @@ func (m *Module) readSectionImports(r *reader) error {
 		return fmt.Errorf("get size of vector: %v", err)
 	}
 
-	m.ImportSection = make([]*ImportSegment, vs)
+	m.ImportSection = make([]*Import, vs)
 	for i := range m.ImportSection {
-		m.ImportSection[i], err = readImportSegment(r)
+		m.ImportSection[i], err = readImport(r)
 		if err != nil {
 			return fmt.Errorf("read import: %v", err)
 		}
@@ -294,9 +294,9 @@ func (m *Module) readSectionGlobals(r *reader) error {
 		return fmt.Errorf("get size of vector: %v", err)
 	}
 
-	m.GlobalSection = make([]*GlobalSegment, vs)
+	m.GlobalSection = make([]*Global, vs)
 	for i := range m.GlobalSection {
-		m.GlobalSection[i], err = readGlobalSegment(r)
+		m.GlobalSection[i], err = readGlobal(r)
 		if err != nil {
 			return fmt.Errorf("read global segment: %v ", err)
 		}
@@ -310,9 +310,9 @@ func (m *Module) readSectionExports(r *reader) error {
 		return fmt.Errorf("get size of vector: %v", err)
 	}
 
-	m.ExportSection = make(map[string]*ExportSegment, vs)
+	m.ExportSection = make(map[string]*Export, vs)
 	for i := uint32(0); i < vs; i++ {
-		expDesc, err := readExportSegment(r)
+		expDesc, err := readExport(r)
 		if err != nil {
 			return fmt.Errorf("read export: %v", err)
 		}
@@ -355,10 +355,10 @@ func (m *Module) readSectionCodes(r *reader) error {
 	if err != nil {
 		return fmt.Errorf("get size of vector: %v", err)
 	}
-	m.CodeSection = make([]*CodeSegment, vs)
+	m.CodeSection = make([]*Code, vs)
 
 	for i := range m.CodeSection {
-		m.CodeSection[i], err = readCodeSegment(r)
+		m.CodeSection[i], err = readCode(r)
 		if err != nil {
 			return fmt.Errorf("read %d-th code segment: %v", i, err)
 		}
diff --git a/wasm/segment.go b/wasm/segment.go
index cfcb9a45..40e78c9b 100644
--- a/wasm/segment.go
+++ b/wasm/segment.go
@@ -8,104 +8,80 @@ import (
 	"github.com/tetratelabs/wazero/wasm/leb128"
 )
 
+// ImportKind indicates which import description is present
+// See https://www.w3.org/TR/wasm-core-1/#import-section%E2%91%A0
 type ImportKind = byte
 
 const (
-	ImportKindFunction ImportKind = 0x00
-	ImportKindTable    ImportKind = 0x01
-	ImportKindMemory   ImportKind = 0x02
-	ImportKindGlobal   ImportKind = 0x03
+	ImportKindFunc   ImportKind = 0x00
+	ImportKindTable  ImportKind = 0x01
+	ImportKindMemory ImportKind = 0x02
+	ImportKindGlobal ImportKind = 0x03
 )
 
-type ImportDesc struct {
-	Kind byte
-
-	// FuncTypeIndex is the index in Module.TypeSection corresponding to this import's FunctionType.
-	// This is only valid when Kind equals ImportKindFunction
-	FuncTypeIndex uint32
-	TableTypePtr  *TableType
-	MemTypePtr    *MemoryType
-	GlobalTypePtr *GlobalType
+// Import is the binary representation of an import indicated by Kind
+// See https://www.w3.org/TR/wasm-core-1/#binary-import
+type Import struct {
+	Kind ImportKind
+	// Module is the possibly empty primary namespace of this import
+	Module string
+	// Module is the possibly empty secondary namespace of this import
+	Name string
+	// DescFunc is the index in Module.TypeSection when Kind equals ImportKindFunc
+	DescFunc uint32
+	// DescTable is the inlined TableType when Kind equals ImportKindTable
+	DescTable *TableType
+	// DescMem is the inlined MemoryType when Kind equals ImportKindMemory
+	DescMem *MemoryType
+	// DescGlobal is the inlined GlobalType when Kind equals ImportKindGlobal
+	DescGlobal *GlobalType
 }
 
-func readImportDesc(r io.Reader) (*ImportDesc, error) {
+func readImport(r io.Reader) (i *Import, err error) {
+	i = &Import{}
+	if i.Module, err = readNameValue(r); err != nil {
+		return nil, fmt.Errorf("error decoding import module: %w", err)
+	}
+
+	if i.Name, err = readNameValue(r); err != nil {
+		return nil, fmt.Errorf("error decoding import name: %w", err)
+	}
+
 	b := make([]byte, 1)
-	if _, err := io.ReadFull(r, b); err != nil {
-		return nil, fmt.Errorf("read value kind: %v", err)
+	if _, err = io.ReadFull(r, b); err != nil {
+		return nil, fmt.Errorf("error decoding import kind: %w", err)
 	}
 
-	switch b[0] {
-	case ImportKindFunction:
-		tID, _, err := leb128.DecodeUint32(r)
-		if err != nil {
-			return nil, fmt.Errorf("read typeindex: %v", err)
+	i.Kind = b[0]
+	switch i.Kind {
+	case ImportKindFunc:
+		if i.DescFunc, _, err = leb128.DecodeUint32(r); err != nil {
+			return nil, fmt.Errorf("error decoding import func typeindex: %w", err)
 		}
-		return &ImportDesc{
-			Kind:          ImportKindFunction,
-			FuncTypeIndex: tID,
-		}, nil
 	case ImportKindTable:
-		tt, err := readTableType(r)
-		if err != nil {
-			return nil, fmt.Errorf("read table type: %v", err)
+		if i.DescTable, err = readTableType(r); err != nil {
+			return nil, fmt.Errorf("error decoding import table desc: %w", err)
 		}
-		return &ImportDesc{
-			Kind:         ImportKindTable,
-			TableTypePtr: tt,
-		}, nil
 	case ImportKindMemory:
-		mt, err := readMemoryType(r)
-		if err != nil {
-			return nil, fmt.Errorf("read table type: %v", err)
+		if i.DescMem, err = readMemoryType(r); err != nil {
+			return nil, fmt.Errorf("error decoding import mem desc: %w", err)
 		}
-		return &ImportDesc{
-			Kind:       ImportKindMemory,
-			MemTypePtr: mt,
-		}, nil
 	case ImportKindGlobal:
-		gt, err := readGlobalType(r)
-		if err != nil {
-			return nil, fmt.Errorf("read global type: %v", err)
+		if i.DescGlobal, err = readGlobalType(r); err != nil {
+			return nil, fmt.Errorf("error decoding import global desc: %w", err)
 		}
-		return &ImportDesc{
-			Kind:          ImportKindGlobal,
-			GlobalTypePtr: gt,
-		}, nil
 	default:
 		return nil, fmt.Errorf("%w: invalid byte for importdesc: %#x", ErrInvalidByte, b[0])
 	}
+	return
 }
 
-type ImportSegment struct {
-	Module, Name string
-	Desc         *ImportDesc
-}
-
-func readImportSegment(r io.Reader) (*ImportSegment, error) {
-	mn, err := readNameValue(r)
-	if err != nil {
-		return nil, fmt.Errorf("read name of imported module: %v", err)
-	}
-
-	n, err := readNameValue(r)
-	if err != nil {
-		return nil, fmt.Errorf("read name of imported module component: %v", err)
-	}
-
-	d, err := readImportDesc(r)
-	if err != nil {
-		return nil, fmt.Errorf("read import description : %v", err)
-	}
-
-	return &ImportSegment{Module: mn, Name: n, Desc: d}, nil
-}
-
-type GlobalSegment struct {
+type Global struct {
 	Type *GlobalType
 	Init *ConstantExpression
 }
 
-func readGlobalSegment(r io.Reader) (*GlobalSegment, error) {
+func readGlobal(r io.Reader) (*Global, error) {
 	gt, err := readGlobalType(r)
 	if err != nil {
 		return nil, fmt.Errorf("read global type: %v", err)
@@ -116,66 +92,56 @@ func readGlobalSegment(r io.Reader) (*GlobalSegment, error) {
 		return nil, fmt.Errorf("get init expression: %v", err)
 	}
 
-	return &GlobalSegment{
+	return &Global{
 		Type: gt,
 		Init: init,
 	}, nil
 }
 
-type ExportDesc struct {
-	Kind  byte
-	Index uint32
-}
-
+// ExportKind indicates which index Export.Index points to
+// See https://www.w3.org/TR/wasm-core-1/#export-section%E2%91%A0
 type ExportKind = byte
 
 const (
-	ExportKindFunction ExportKind = 0x00
-	ExportKindTable    ExportKind = 0x01
-	ExportKindMemory   ExportKind = 0x02
-	ExportKindGlobal   ExportKind = 0x03
+	ExportKindFunc   ExportKind = 0x00
+	ExportKindTable  ExportKind = 0x01
+	ExportKindMemory ExportKind = 0x02
+	ExportKindGlobal ExportKind = 0x03
 )
 
-func readExportDesc(r io.Reader) (*ExportDesc, error) {
-	b := make([]byte, 1)
-	if _, err := io.ReadFull(r, b); err != nil {
-		return nil, fmt.Errorf("read value kind: %w", err)
-	}
-
-	kind := b[0]
-	if kind >= 0x04 {
-		return nil, fmt.Errorf("%w: invalid byte for exportdesc: %#x", ErrInvalidByte, kind)
-	}
-
-	id, _, err := leb128.DecodeUint32(r)
-	if err != nil {
-		return nil, fmt.Errorf("read funcidx: %w", err)
-	}
-
-	return &ExportDesc{
-		Kind:  kind,
-		Index: id,
-	}, nil
-
-}
-
-type ExportSegment struct {
+// Export is the binary representation of an export indicated by Kind
+// See https://www.w3.org/TR/wasm-core-1/#binary-export
+type Export struct {
+	Kind ExportKind
+	// Name is what the host refers to this definition as.
 	Name string
-	Desc *ExportDesc
+	// Index is the index of the definition to export, the index namespace is by Kind
+	// Ex. If ExportKindFunc, this is an index to ModuleInstance.Functions
+	Index uint32
 }
 
-func readExportSegment(r io.Reader) (*ExportSegment, error) {
-	name, err := readNameValue(r)
-	if err != nil {
-		return nil, fmt.Errorf("read name of export module: %w", err)
+func readExport(r io.Reader) (i *Export, err error) {
+	i = &Export{}
+
+	if i.Name, err = readNameValue(r); err != nil {
+		return nil, fmt.Errorf("error decoding export name: %w", err)
 	}
 
-	d, err := readExportDesc(r)
-	if err != nil {
-		return nil, fmt.Errorf("read export description: %w", err)
+	b := make([]byte, 1)
+	if _, err = io.ReadFull(r, b); err != nil {
+		return nil, fmt.Errorf("error decoding export kind: %w", err)
 	}
 
-	return &ExportSegment{Name: name, Desc: d}, nil
+	i.Kind = b[0]
+	switch i.Kind {
+	case ExportKindFunc, ExportKindTable, ExportKindMemory, ExportKindGlobal:
+		if i.Index, _, err = leb128.DecodeUint32(r); err != nil {
+			return nil, fmt.Errorf("error decoding export index: %w", err)
+		}
+	default:
+		return nil, fmt.Errorf("%w: invalid byte for exportdesc: %#x", ErrInvalidByte, b[0])
+	}
+	return
 }
 
 type ElementSegment struct {
@@ -216,13 +182,13 @@ func readElementSegment(r io.Reader) (*ElementSegment, error) {
 	}, nil
 }
 
-type CodeSegment struct {
+type Code struct {
 	NumLocals  uint32
 	LocalTypes []ValueType
 	Body       []byte
 }
 
-func readCodeSegment(r io.Reader) (*CodeSegment, error) {
+func readCode(r io.Reader) (*Code, error) {
 	ss, _, err := leb128.DecodeUint32(r)
 	if err != nil {
 		return nil, fmt.Errorf("get the size of code segment: %w", err)
@@ -281,7 +247,7 @@ func readCodeSegment(r io.Reader) (*CodeSegment, error) {
 		return nil, fmt.Errorf("expr not end with OpcodeEnd")
 	}
 
-	return &CodeSegment{
+	return &Code{
 		Body:       body,
 		NumLocals:  uint32(sum),
 		LocalTypes: localTypes,
diff --git a/wasm/store.go b/wasm/store.go
index dcf91e61..d883316c 100644
--- a/wasm/store.go
+++ b/wasm/store.go
@@ -272,7 +272,7 @@ func (s *Store) CallFunction(moduleName, funcName string, params ...uint64) (res
 		return nil, nil, fmt.Errorf("exported function '%s' not found in '%s'", funcName, moduleName)
 	}
 
-	if exp.Kind != ExportKindFunction {
+	if exp.Kind != ExportKindFunc {
 		return nil, nil, fmt.Errorf("'%s' is not functype", funcName)
 	}
 
@@ -299,7 +299,7 @@ func (s *Store) resolveImports(module *Module, target *ModuleInstance) error {
 	return nil
 }
 
-func (s *Store) resolveImport(target *ModuleInstance, is *ImportSegment) error {
+func (s *Store) resolveImport(target *ModuleInstance, is *Import) error {
 	em, ok := s.ModuleInstances[is.Module]
 	if !ok {
 		return fmt.Errorf("failed to resolve import of module name %s", is.Module)
@@ -310,28 +310,28 @@ func (s *Store) resolveImport(target *ModuleInstance, is *ImportSegment) error {
 		return fmt.Errorf("not exported in module %s", is.Module)
 	}
 
-	if is.Desc.Kind != e.Kind {
-		return fmt.Errorf("type mismatch on export: got %#x but want %#x", e.Kind, is.Desc.Kind)
+	if is.Kind != e.Kind {
+		return fmt.Errorf("type mismatch on export: got %#x but want %#x", e.Kind, is.Kind)
 	}
-	switch is.Desc.Kind {
-	case ImportKindFunction:
-		if err := s.applyFunctionImport(target, is.Desc.FuncTypeIndex, e); err != nil {
+	switch is.Kind {
+	case ImportKindFunc:
+		if err := s.applyFunctionImport(target, is.DescFunc, e); err != nil {
 			return fmt.Errorf("applyFunctionImport: %w", err)
 		}
 	case ImportKindTable:
-		if err := s.applyTableImport(target, is.Desc.TableTypePtr, e); err != nil {
+		if err := s.applyTableImport(target, is.DescTable, e); err != nil {
 			return fmt.Errorf("applyTableImport: %w", err)
 		}
 	case ImportKindMemory:
-		if err := s.applyMemoryImport(target, is.Desc.MemTypePtr, e); err != nil {
+		if err := s.applyMemoryImport(target, is.DescMem, e); err != nil {
 			return fmt.Errorf("applyMemoryImport: %w", err)
 		}
 	case ImportKindGlobal:
-		if err := s.applyGlobalImport(target, is.Desc.GlobalTypePtr, e); err != nil {
+		if err := s.applyGlobalImport(target, is.DescGlobal, e); err != nil {
 			return fmt.Errorf("applyGlobalImport: %w", err)
 		}
 	default:
-		return fmt.Errorf("invalid kind of import: %#x", is.Desc.Kind)
+		return fmt.Errorf("invalid kind of import: %#x", is.Kind)
 	}
 
 	return nil
@@ -509,15 +509,15 @@ func (s *Store) buildFunctionInstances(module *Module, target *ModuleInstance) (
 	var memoryDeclarations []*MemoryType
 	var tableDeclarations []*TableType
 	for _, imp := range module.ImportSection {
-		switch imp.Desc.Kind {
-		case ImportKindFunction:
-			functionDeclarations = append(functionDeclarations, imp.Desc.FuncTypeIndex)
+		switch imp.Kind {
+		case ImportKindFunc:
+			functionDeclarations = append(functionDeclarations, imp.DescFunc)
 		case ImportKindGlobal:
-			globalDeclarations = append(globalDeclarations, imp.Desc.GlobalTypePtr)
+			globalDeclarations = append(globalDeclarations, imp.DescGlobal)
 		case ImportKindMemory:
-			memoryDeclarations = append(memoryDeclarations, imp.Desc.MemTypePtr)
+			memoryDeclarations = append(memoryDeclarations, imp.DescMem)
 		case ImportKindTable:
-			tableDeclarations = append(tableDeclarations, imp.Desc.TableTypePtr)
+			tableDeclarations = append(tableDeclarations, imp.DescTable)
 		}
 	}
 	importedFunctionCount := len(functionDeclarations)
@@ -714,14 +714,14 @@ func (s *Store) buildTableInstances(module *Module, target *ModuleInstance) (rol
 func (s *Store) buildExportInstances(module *Module, target *ModuleInstance) (rollbackFuncs []func(), err error) {
 	target.Exports = make(map[string]*ExportInstance, len(module.ExportSection))
 	for name, exp := range module.ExportSection {
-		index := int(exp.Desc.Index)
-		switch exp.Desc.Kind {
-		case ExportKindFunction:
+		index := int(exp.Index)
+		switch exp.Kind {
+		case ExportKindFunc:
 			if index >= len(target.Functions) {
 				return nil, fmt.Errorf("unknown function for export")
 			}
 			target.Exports[name] = &ExportInstance{
-				Kind:     exp.Desc.Kind,
+				Kind:     exp.Kind,
 				Function: target.Functions[index],
 			}
 		case ExportKindGlobal:
@@ -729,15 +729,15 @@ func (s *Store) buildExportInstances(module *Module, target *ModuleInstance) (ro
 				return nil, fmt.Errorf("unknown global for export")
 			}
 			target.Exports[name] = &ExportInstance{
-				Kind:   exp.Desc.Kind,
-				Global: target.Globals[exp.Desc.Index],
+				Kind:   exp.Kind,
+				Global: target.Globals[index],
 			}
 		case ExportKindMemory:
 			if index != 0 || target.Memory == nil {
 				return nil, fmt.Errorf("unknown memory for export")
 			}
 			target.Exports[name] = &ExportInstance{
-				Kind:   exp.Desc.Kind,
+				Kind:   exp.Kind,
 				Memory: target.Memory,
 			}
 		case ExportKindTable:
@@ -745,8 +745,8 @@ func (s *Store) buildExportInstances(module *Module, target *ModuleInstance) (ro
 				return nil, fmt.Errorf("unknown memory for export")
 			}
 			target.Exports[name] = &ExportInstance{
-				Kind:  exp.Desc.Kind,
-				Table: target.Tables[exp.Desc.Index],
+				Kind:  exp.Kind,
+				Table: target.Tables[index],
 			}
 		}
 
@@ -1761,7 +1761,7 @@ func (s *Store) AddHostFunction(moduleName, funcName string, fn reflect.Value) e
 	if err := s.engine.Compile(f); err != nil {
 		return fmt.Errorf("failed to compile %s: %v", f.Name, err)
 	}
-	m.Exports[funcName] = &ExportInstance{Kind: ExportKindFunction, Function: f}
+	m.Exports[funcName] = &ExportInstance{Kind: ExportKindFunc, Function: f}
 	s.addFunctionInstance(f)
 	return nil
 }
diff --git a/wasm/wat/convert.go b/wasm/wat/convert.go
index da8ceb7f..eabbcb34 100644
--- a/wasm/wat/convert.go
+++ b/wasm/wat/convert.go
@@ -53,12 +53,10 @@ func TextToBinary(source []byte) (result *wasm.Module, err error) {
 				localNames[funcidx] = locals
 			}
 		}
-		result.ImportSection = append(result.ImportSection, &wasm.ImportSegment{
+		result.ImportSection = append(result.ImportSection, &wasm.Import{
 			Module: f.module, Name: f.name,
-			Desc: &wasm.ImportDesc{
-				Kind:          wasm.ImportKindFunction,
-				FuncTypeIndex: f.typeIndex.numeric,
-			},
+			Kind:     wasm.ImportKindFunc,
+			DescFunc: f.typeIndex.numeric,
 		})
 	}
 


Test patch:
diff --git a/wasm/wat/convert_test.go b/wasm/wat/convert_test.go
index 1b99c1ef..c4986ab6 100644
--- a/wasm/wat/convert_test.go
+++ b/wasm/wat/convert_test.go
@@ -29,12 +29,10 @@ func TestTextToBinary(t *testing.T) {
 			input: "(module (import \"foo\" \"bar\" (func)))", // ok empty sig
 			expected: &wasm.Module{
 				TypeSection: []*wasm.FunctionType{{}},
-				ImportSection: []*wasm.ImportSegment{{
+				ImportSection: []*wasm.Import{{
 					Module: "foo", Name: "bar",
-					Desc: &wasm.ImportDesc{
-						Kind:          wasm.ImportKindFunction,
-						FuncTypeIndex: 0,
-					},
+					Kind:     wasm.ImportKindFunc,
+					DescFunc: 0,
 				}},
 			},
 		},
@@ -51,19 +49,15 @@ func TestTextToBinary(t *testing.T) {
 					{Params: []wasm.ValueType{i32, i32, i32, i32, i32, i64, i64, i32, i32}, Results: []wasm.ValueType{i32}},
 					{Params: []wasm.ValueType{i32, i32, i32, i32}, Results: []wasm.ValueType{i32}},
 				},
-				ImportSection: []*wasm.ImportSegment{
+				ImportSection: []*wasm.Import{
 					{
 						Module: "wasi_snapshot_preview1", Name: "path_open",
-						Desc: &wasm.ImportDesc{
-							Kind:          wasm.ImportKindFunction,
-							FuncTypeIndex: 1,
-						},
+						Kind:     wasm.ImportKindFunc,
+						DescFunc: 1,
 					}, {
 						Module: "wasi_snapshot_preview1", Name: "fd_write",
-						Desc: &wasm.ImportDesc{
-							Kind:          wasm.ImportKindFunction,
-							FuncTypeIndex: 2,
-						},
+						Kind:     wasm.ImportKindFunc,
+						DescFunc: 2,
 					},
 				},
 				NameSection: &wasm.NameSection{
@@ -89,19 +83,15 @@ func TestTextToBinary(t *testing.T) {
 					{Params: []wasm.ValueType{i32, i32}, Results: []wasm.ValueType{i32}},
 					{Params: []wasm.ValueType{i32, i32, i32, i32}, Results: []wasm.ValueType{i32}},
 				},
-				ImportSection: []*wasm.ImportSegment{
+				ImportSection: []*wasm.Import{
 					{
 						Module: "wasi_snapshot_preview1", Name: "arg_sizes_get",
-						Desc: &wasm.ImportDesc{
-							Kind:          wasm.ImportKindFunction,
-							FuncTypeIndex: 1,
-						},
+						Kind:     wasm.ImportKindFunc,
+						DescFunc: 1,
 					}, {
 						Module: "wasi_snapshot_preview1", Name: "fd_write",
-						Desc: &wasm.ImportDesc{
-							Kind:          wasm.ImportKindFunction,
-							FuncTypeIndex: 2,
-						},
+						Kind:     wasm.ImportKindFunc,
+						DescFunc: 2,
 					},
 				},
 				NameSection: &wasm.NameSection{
@@ -120,12 +110,10 @@ func TestTextToBinary(t *testing.T) {
 )`,
 			expected: &wasm.Module{
 				TypeSection: []*wasm.FunctionType{{}},
-				ImportSection: []*wasm.ImportSegment{{
+				ImportSection: []*wasm.Import{{
 					Module: "", Name: "hello",
-					Desc: &wasm.ImportDesc{
-						Kind:          wasm.ImportKindFunction,
-						FuncTypeIndex: 0,
-					},
+					Kind:     wasm.ImportKindFunc,
+					DescFunc: 0,
 				}},
 				StartSection: &zero,
 				NameSection: &wasm.NameSection{
@@ -143,12 +131,10 @@ func TestTextToBinary(t *testing.T) {
 )`,
 			expected: &wasm.Module{
 				TypeSection: []*wasm.FunctionType{{}},
-				ImportSection: []*wasm.ImportSegment{{
+				ImportSection: []*wasm.Import{{
 					Module: "", Name: "hello",
-					Desc: &wasm.ImportDesc{
-						Kind:          wasm.ImportKindFunction,
-						FuncTypeIndex: 0,
-					},
+					Kind:     wasm.ImportKindFunc,
+					DescFunc: 0,
 				}},
 				StartSection: &zero,
 			},
@@ -163,37 +149,27 @@ func TestTextToBinary(t *testing.T) {
 					{Params: []wasm.ValueType{i32, i32, i32, i32}, Results: []wasm.ValueType{i32}},
 					{Params: []wasm.ValueType{f32, f32}, Results: []wasm.ValueType{f32}},
 				},
-				ImportSection: []*wasm.ImportSegment{
+				ImportSection: []*wasm.Import{
 					{
 						Module: "wasi_snapshot_preview1", Name: "arg_sizes_get",
-						Desc: &wasm.ImportDesc{
-							Kind:          wasm.ImportKindFunction,
-							FuncTypeIndex: 0,
-						},
+						Kind:     wasm.ImportKindFunc,
+						DescFunc: 0,
 					}, {
 						Module: "wasi_snapshot_preview1", Name: "fd_write",
-						Desc: &wasm.ImportDesc{
-							Kind:          wasm.ImportKindFunction,
-							FuncTypeIndex: 2,
-						},
+						Kind:     wasm.ImportKindFunc,
+						DescFunc: 2,
 					}, {
 						Module: "Math", Name: "Mul",
-						Desc: &wasm.ImportDesc{
-							Kind:          wasm.ImportKindFunction,
-							FuncTypeIndex: 3,
-						},
+						Kind:     wasm.ImportKindFunc,
+						DescFunc: 3,
 					}, {
 						Module: "Math", Name: "Add",
-						Desc: &wasm.ImportDesc{
-							Kind:          wasm.ImportKindFunction,
-							FuncTypeIndex: 0,
-						},
+						Kind:     wasm.ImportKindFunc,
+						DescFunc: 0,
 					}, {
 						Module: "", Name: "hello",
-						Desc: &wasm.ImportDesc{
-							Kind:          wasm.ImportKindFunction,
-							FuncTypeIndex: 1,
-						},
+						Kind:     wasm.ImportKindFunc,
+						DescFunc: 1,
 					},
 				},
 				StartSection: &four,