1 package wasm
2
3 import (
4 "bytes"
5 "crypto/sha256"
6 "encoding/binary"
7 "errors"
8 "fmt"
9 "io"
10 "sort"
11 "strings"
12 "sync"
13
14 "github.com/tetratelabs/wazero/api"
15 "github.com/tetratelabs/wazero/experimental"
16 "github.com/tetratelabs/wazero/internal/ieee754"
17 "github.com/tetratelabs/wazero/internal/leb128"
18 "github.com/tetratelabs/wazero/internal/wasmdebug"
19 )
20
21
22
23
24
25
26
27
28 type Module struct {
29
30
31
32
33
34
35
36
37 TypeSection []FunctionType
38
39
40
41
42
43
44
45
46
47 ImportSection []Import
48
49
50 ImportFunctionCount,
51 ImportGlobalCount,
52 ImportMemoryCount,
53 ImportTableCount Index
54
55
56 ImportPerModule map[string][]*Import
57
58
59
60
61
62
63
64
65
66
67
68
69
70 FunctionSection []Index
71
72
73
74
75
76
77
78
79
80
81
82
83
84 TableSection []Table
85
86
87
88
89
90
91
92
93
94
95
96
97
98 MemorySection *Memory
99
100
101
102
103
104
105
106
107
108
109 GlobalSection []Global
110
111
112
113
114
115
116 ExportSection []Export
117
118
119 Exports map[string]*Export
120
121
122
123
124
125
126
127
128
129 StartSection *Index
130
131
132 ElementSection []ElementSegment
133
134
135
136
137
138
139
140
141
142 CodeSection []Code
143
144
145 DataSection []DataSegment
146
147
148
149
150
151
152
153
154 NameSection *NameSection
155
156
157
158
159 CustomSections []*CustomSection
160
161
162
163
164
165
166 DataCountSection *uint32
167
168
169
170 ID ModuleID
171
172
173 IsHostModule bool
174
175
176 functionDefinitionSectionInitOnce sync.Once
177
178
179 FunctionDefinitionSection []FunctionDefinition
180
181
182 MemoryDefinitionSection []MemoryDefinition
183
184
185
186
187 DWARFLines *wasmdebug.DWARFLines
188 }
189
190
191 type ModuleID = [sha256.Size]byte
192
193
194
195 const (
196 MaximumGlobals = uint32(1 << 27)
197 MaximumFunctionIndex = uint32(1 << 27)
198 MaximumTableIndex = uint32(1 << 27)
199 )
200
201
202
203 func (m *Module) AssignModuleID(wasm []byte, listeners []experimental.FunctionListener, withEnsureTermination bool) {
204 h := sha256.New()
205 h.Write(wasm)
206
207
208
209 for i, l := range listeners {
210 binary.LittleEndian.PutUint32(m.ID[:], uint32(i))
211 m.ID[4] = boolToByte(l != nil)
212 h.Write(m.ID[:5])
213 }
214
215 m.ID[0] = boolToByte(withEnsureTermination)
216 h.Write(m.ID[:1])
217
218 h.Sum(m.ID[:0])
219 }
220
221 func boolToByte(b bool) (ret byte) {
222 if b {
223 ret = 1
224 }
225 return
226 }
227
228
229 func (m *Module) typeOfFunction(funcIdx Index) *FunctionType {
230 typeSectionLength, importedFunctionCount := uint32(len(m.TypeSection)), m.ImportFunctionCount
231 if funcIdx < importedFunctionCount {
232
233 cur := Index(0)
234 for i := range m.ImportSection {
235 imp := &m.ImportSection[i]
236 if imp.Type != ExternTypeFunc {
237 continue
238 }
239 if funcIdx == cur {
240 if imp.DescFunc >= typeSectionLength {
241 return nil
242 }
243 return &m.TypeSection[imp.DescFunc]
244 }
245 cur++
246 }
247 }
248
249 funcSectionIdx := funcIdx - m.ImportFunctionCount
250 if funcSectionIdx >= uint32(len(m.FunctionSection)) {
251 return nil
252 }
253 typeIdx := m.FunctionSection[funcSectionIdx]
254 if typeIdx >= typeSectionLength {
255 return nil
256 }
257 return &m.TypeSection[typeIdx]
258 }
259
260 func (m *Module) Validate(enabledFeatures api.CoreFeatures) error {
261 for i := range m.TypeSection {
262 tp := &m.TypeSection[i]
263 tp.CacheNumInUint64()
264 }
265
266 if err := m.validateStartSection(); err != nil {
267 return err
268 }
269
270 functions, globals, memory, tables, err := m.AllDeclarations()
271 if err != nil {
272 return err
273 }
274
275 if err = m.validateImports(enabledFeatures); err != nil {
276 return err
277 }
278
279 if err = m.validateGlobals(globals, uint32(len(functions)), MaximumGlobals); err != nil {
280 return err
281 }
282
283 if err = m.validateMemory(memory, globals, enabledFeatures); err != nil {
284 return err
285 }
286
287 if err = m.validateExports(enabledFeatures, functions, globals, memory, tables); err != nil {
288 return err
289 }
290
291 if m.CodeSection != nil {
292 if err = m.validateFunctions(enabledFeatures, functions, globals, memory, tables, MaximumFunctionIndex); err != nil {
293 return err
294 }
295 }
296
297 if err = m.validateTable(enabledFeatures, tables, MaximumTableIndex); err != nil {
298 return err
299 }
300
301 if err = m.validateDataCountSection(); err != nil {
302 return err
303 }
304 return nil
305 }
306
307 func (m *Module) validateStartSection() error {
308
309
310 if m.StartSection != nil {
311 startIndex := *m.StartSection
312 ft := m.typeOfFunction(startIndex)
313 if ft == nil {
314 return fmt.Errorf("invalid start function: func[%d] has an invalid type", startIndex)
315 }
316 if len(ft.Params) > 0 || len(ft.Results) > 0 {
317 return fmt.Errorf("invalid start function: func[%d] must have an empty (nullary) signature: %s", startIndex, ft)
318 }
319 }
320 return nil
321 }
322
323 func (m *Module) validateGlobals(globals []GlobalType, numFuncts, maxGlobals uint32) error {
324 if uint32(len(globals)) > maxGlobals {
325 return fmt.Errorf("too many globals in a module")
326 }
327
328
329
330 importedGlobals := globals[:m.ImportGlobalCount]
331 for i := range m.GlobalSection {
332 g := &m.GlobalSection[i]
333 if err := validateConstExpression(importedGlobals, numFuncts, &g.Init, g.Type.ValType); err != nil {
334 return err
335 }
336 }
337 return nil
338 }
339
340 func (m *Module) validateFunctions(enabledFeatures api.CoreFeatures, functions []Index, globals []GlobalType, memory *Memory, tables []Table, maximumFunctionIndex uint32) error {
341 if uint32(len(functions)) > maximumFunctionIndex {
342 return fmt.Errorf("too many functions (%d) in a module", len(functions))
343 }
344
345 functionCount := m.SectionElementCount(SectionIDFunction)
346 codeCount := m.SectionElementCount(SectionIDCode)
347 if functionCount == 0 && codeCount == 0 {
348 return nil
349 }
350
351 typeCount := m.SectionElementCount(SectionIDType)
352 if codeCount != functionCount {
353 return fmt.Errorf("code count (%d) != function count (%d)", codeCount, functionCount)
354 }
355
356 declaredFuncIndexes, err := m.declaredFunctionIndexes()
357 if err != nil {
358 return err
359 }
360
361
362
363 br := bytes.NewReader(nil)
364
365 vs := &stacks{}
366 for idx, typeIndex := range m.FunctionSection {
367 if typeIndex >= typeCount {
368 return fmt.Errorf("invalid %s: type section index %d out of range", m.funcDesc(SectionIDFunction, Index(idx)), typeIndex)
369 }
370 c := &m.CodeSection[idx]
371 if c.GoFunc != nil {
372 continue
373 }
374 if err = m.validateFunction(vs, enabledFeatures, Index(idx), functions, globals, memory, tables, declaredFuncIndexes, br); err != nil {
375 return fmt.Errorf("invalid %s: %w", m.funcDesc(SectionIDFunction, Index(idx)), err)
376 }
377 }
378 return nil
379 }
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400 func (m *Module) declaredFunctionIndexes() (ret map[Index]struct{}, err error) {
401 ret = map[uint32]struct{}{}
402
403 for i := range m.ExportSection {
404 exp := &m.ExportSection[i]
405 if exp.Type == ExternTypeFunc {
406 ret[exp.Index] = struct{}{}
407 }
408 }
409
410 for i := range m.GlobalSection {
411 g := &m.GlobalSection[i]
412 if g.Init.Opcode == OpcodeRefFunc {
413 var index uint32
414 index, _, err = leb128.LoadUint32(g.Init.Data)
415 if err != nil {
416 err = fmt.Errorf("%s[%d] failed to initialize: %w", SectionIDName(SectionIDGlobal), i, err)
417 return
418 }
419 ret[index] = struct{}{}
420 }
421 }
422
423 for i := range m.ElementSection {
424 elem := &m.ElementSection[i]
425 for _, index := range elem.Init {
426 if index != ElementInitNullReference {
427 ret[index] = struct{}{}
428 }
429 }
430 }
431 return
432 }
433
434 func (m *Module) funcDesc(sectionID SectionID, sectionIndex Index) string {
435
436 var exportNames []string
437 funcIdx := sectionIndex + m.ImportFunctionCount
438 for i := range m.ExportSection {
439 exp := &m.ExportSection[i]
440 if exp.Index == funcIdx && exp.Type == ExternTypeFunc {
441 exportNames = append(exportNames, fmt.Sprintf("%q", exp.Name))
442 }
443 }
444 sectionIDName := SectionIDName(sectionID)
445 if exportNames == nil {
446 return fmt.Sprintf("%s[%d]", sectionIDName, sectionIndex)
447 }
448 sort.Strings(exportNames)
449 return fmt.Sprintf("%s[%d] export[%s]", sectionIDName, sectionIndex, strings.Join(exportNames, ","))
450 }
451
452 func (m *Module) validateMemory(memory *Memory, globals []GlobalType, _ api.CoreFeatures) error {
453 var activeElementCount int
454 for i := range m.DataSection {
455 d := &m.DataSection[i]
456 if !d.IsPassive() {
457 activeElementCount++
458 }
459 }
460 if activeElementCount > 0 && memory == nil {
461 return fmt.Errorf("unknown memory")
462 }
463
464
465
466 importedGlobals := globals[:m.ImportGlobalCount]
467 for i := range m.DataSection {
468 d := &m.DataSection[i]
469 if !d.IsPassive() {
470 if err := validateConstExpression(importedGlobals, 0, &d.OffsetExpression, ValueTypeI32); err != nil {
471 return fmt.Errorf("calculate offset: %w", err)
472 }
473 }
474 }
475 return nil
476 }
477
478 func (m *Module) validateImports(enabledFeatures api.CoreFeatures) error {
479 for i := range m.ImportSection {
480 imp := &m.ImportSection[i]
481 if imp.Module == "" {
482 return fmt.Errorf("import[%d] has an empty module name", i)
483 }
484 switch imp.Type {
485 case ExternTypeFunc:
486 if int(imp.DescFunc) >= len(m.TypeSection) {
487 return fmt.Errorf("invalid import[%q.%q] function: type index out of range", imp.Module, imp.Name)
488 }
489 case ExternTypeGlobal:
490 if !imp.DescGlobal.Mutable {
491 continue
492 }
493 if err := enabledFeatures.RequireEnabled(api.CoreFeatureMutableGlobal); err != nil {
494 return fmt.Errorf("invalid import[%q.%q] global: %w", imp.Module, imp.Name, err)
495 }
496 }
497 }
498 return nil
499 }
500
501 func (m *Module) validateExports(enabledFeatures api.CoreFeatures, functions []Index, globals []GlobalType, memory *Memory, tables []Table) error {
502 for i := range m.ExportSection {
503 exp := &m.ExportSection[i]
504 index := exp.Index
505 switch exp.Type {
506 case ExternTypeFunc:
507 if index >= uint32(len(functions)) {
508 return fmt.Errorf("unknown function for export[%q]", exp.Name)
509 }
510 case ExternTypeGlobal:
511 if index >= uint32(len(globals)) {
512 return fmt.Errorf("unknown global for export[%q]", exp.Name)
513 }
514 if !globals[index].Mutable {
515 continue
516 }
517 if err := enabledFeatures.RequireEnabled(api.CoreFeatureMutableGlobal); err != nil {
518 return fmt.Errorf("invalid export[%q] global[%d]: %w", exp.Name, index, err)
519 }
520 case ExternTypeMemory:
521 if index > 0 || memory == nil {
522 return fmt.Errorf("memory for export[%q] out of range", exp.Name)
523 }
524 case ExternTypeTable:
525 if index >= uint32(len(tables)) {
526 return fmt.Errorf("table for export[%q] out of range", exp.Name)
527 }
528 }
529 }
530 return nil
531 }
532
533 func validateConstExpression(globals []GlobalType, numFuncs uint32, expr *ConstantExpression, expectedType ValueType) (err error) {
534 var actualType ValueType
535 switch expr.Opcode {
536 case OpcodeI32Const:
537
538 _, _, err = leb128.LoadInt32(expr.Data)
539 if err != nil {
540 return fmt.Errorf("read i32: %w", err)
541 }
542 actualType = ValueTypeI32
543 case OpcodeI64Const:
544
545 _, _, err = leb128.LoadInt64(expr.Data)
546 if err != nil {
547 return fmt.Errorf("read i64: %w", err)
548 }
549 actualType = ValueTypeI64
550 case OpcodeF32Const:
551 _, err = ieee754.DecodeFloat32(expr.Data)
552 if err != nil {
553 return fmt.Errorf("read f32: %w", err)
554 }
555 actualType = ValueTypeF32
556 case OpcodeF64Const:
557 _, err = ieee754.DecodeFloat64(expr.Data)
558 if err != nil {
559 return fmt.Errorf("read f64: %w", err)
560 }
561 actualType = ValueTypeF64
562 case OpcodeGlobalGet:
563 id, _, err := leb128.LoadUint32(expr.Data)
564 if err != nil {
565 return fmt.Errorf("read index of global: %w", err)
566 }
567 if uint32(len(globals)) <= id {
568 return fmt.Errorf("global index out of range")
569 }
570 actualType = globals[id].ValType
571 case OpcodeRefNull:
572 if len(expr.Data) == 0 {
573 return fmt.Errorf("read reference type for ref.null: %w", io.ErrShortBuffer)
574 }
575 reftype := expr.Data[0]
576 if reftype != RefTypeFuncref && reftype != RefTypeExternref {
577 return fmt.Errorf("invalid type for ref.null: 0x%x", reftype)
578 }
579 actualType = reftype
580 case OpcodeRefFunc:
581 index, _, err := leb128.LoadUint32(expr.Data)
582 if err != nil {
583 return fmt.Errorf("read i32: %w", err)
584 } else if index >= numFuncs {
585 return fmt.Errorf("ref.func index out of range [%d] with length %d", index, numFuncs-1)
586 }
587 actualType = ValueTypeFuncref
588 case OpcodeVecV128Const:
589 if len(expr.Data) != 16 {
590 return fmt.Errorf("%s needs 16 bytes but was %d bytes", OpcodeVecV128ConstName, len(expr.Data))
591 }
592 actualType = ValueTypeV128
593 default:
594 return fmt.Errorf("invalid opcode for const expression: 0x%x", expr.Opcode)
595 }
596
597 if actualType != expectedType {
598 return fmt.Errorf("const expression type mismatch expected %s but got %s",
599 ValueTypeName(expectedType), ValueTypeName(actualType))
600 }
601 return nil
602 }
603
604 func (m *Module) validateDataCountSection() (err error) {
605 if m.DataCountSection != nil && int(*m.DataCountSection) != len(m.DataSection) {
606 err = fmt.Errorf("data count section (%d) doesn't match the length of data section (%d)",
607 *m.DataCountSection, len(m.DataSection))
608 }
609 return
610 }
611
612 func (m *ModuleInstance) buildGlobals(module *Module, funcRefResolver func(funcIndex Index) Reference) {
613 importedGlobals := m.Globals[:module.ImportGlobalCount]
614
615 me := m.Engine
616 engineOwnGlobal := me.OwnsGlobals()
617 for i := Index(0); i < Index(len(module.GlobalSection)); i++ {
618 gs := &module.GlobalSection[i]
619 g := &GlobalInstance{}
620 if engineOwnGlobal {
621 g.Me = me
622 g.Index = i + module.ImportGlobalCount
623 }
624 m.Globals[i+module.ImportGlobalCount] = g
625 g.Type = gs.Type
626 g.initialize(importedGlobals, &gs.Init, funcRefResolver)
627 }
628 }
629
630 func paramNames(localNames IndirectNameMap, funcIdx uint32, paramLen int) []string {
631 for i := range localNames {
632 nm := &localNames[i]
633
634 if nm.Index != funcIdx || len(nm.NameMap) < paramLen {
635 continue
636 }
637
638 ret := make([]string, paramLen)
639 for j := range nm.NameMap {
640 p := &nm.NameMap[j]
641 if int(p.Index) < paramLen {
642 ret[p.Index] = p.Name
643 }
644 }
645 return ret
646 }
647 return nil
648 }
649
650 func (m *ModuleInstance) buildMemory(module *Module) {
651 memSec := module.MemorySection
652 if memSec != nil {
653 m.MemoryInstance = NewMemoryInstance(memSec)
654 m.MemoryInstance.definition = &module.MemoryDefinitionSection[0]
655 }
656 }
657
658
659
660
661
662
663
664
665 type Index = uint32
666
667
668
669
670 type FunctionType struct {
671
672 Params []ValueType
673
674
675
676
677
678 Results []ValueType
679
680
681 string string
682
683
684 ParamNumInUint64 int
685
686
687 ResultNumInUint64 int
688 }
689
690 func (f *FunctionType) CacheNumInUint64() {
691 if f.ParamNumInUint64 == 0 {
692 for _, tp := range f.Params {
693 f.ParamNumInUint64++
694 if tp == ValueTypeV128 {
695 f.ParamNumInUint64++
696 }
697 }
698 }
699
700 if f.ResultNumInUint64 == 0 {
701 for _, tp := range f.Results {
702 f.ResultNumInUint64++
703 if tp == ValueTypeV128 {
704 f.ResultNumInUint64++
705 }
706 }
707 }
708 }
709
710
711 func (f *FunctionType) EqualsSignature(params []ValueType, results []ValueType) bool {
712 return bytes.Equal(f.Params, params) && bytes.Equal(f.Results, results)
713 }
714
715
716 func (f *FunctionType) key() string {
717 if f.string != "" {
718 return f.string
719 }
720 var ret string
721 for _, b := range f.Params {
722 ret += ValueTypeName(b)
723 }
724 if len(f.Params) == 0 {
725 ret += "v_"
726 } else {
727 ret += "_"
728 }
729 for _, b := range f.Results {
730 ret += ValueTypeName(b)
731 }
732 if len(f.Results) == 0 {
733 ret += "v"
734 }
735 f.string = ret
736 return ret
737 }
738
739
740 func (f *FunctionType) String() string {
741 return f.key()
742 }
743
744
745
746 type Import struct {
747 Type ExternType
748
749 Module string
750
751 Name string
752
753 DescFunc Index
754
755 DescTable Table
756
757 DescMem *Memory
758
759 DescGlobal GlobalType
760
761 IndexPerType Index
762 }
763
764
765 type Memory struct {
766 Min, Cap, Max uint32
767
768 IsMaxEncoded bool
769 }
770
771
772 func (m *Memory) Validate(memoryLimitPages uint32) error {
773 min, capacity, max := m.Min, m.Cap, m.Max
774
775 if max > memoryLimitPages {
776 return fmt.Errorf("max %d pages (%s) over limit of %d pages (%s)",
777 max, PagesToUnitOfBytes(max), memoryLimitPages, PagesToUnitOfBytes(memoryLimitPages))
778 } else if min > memoryLimitPages {
779 return fmt.Errorf("min %d pages (%s) over limit of %d pages (%s)",
780 min, PagesToUnitOfBytes(min), memoryLimitPages, PagesToUnitOfBytes(memoryLimitPages))
781 } else if min > max {
782 return fmt.Errorf("min %d pages (%s) > max %d pages (%s)",
783 min, PagesToUnitOfBytes(min), max, PagesToUnitOfBytes(max))
784 } else if capacity < min {
785 return fmt.Errorf("capacity %d pages (%s) less than minimum %d pages (%s)",
786 capacity, PagesToUnitOfBytes(capacity), min, PagesToUnitOfBytes(min))
787 } else if capacity > memoryLimitPages {
788 return fmt.Errorf("capacity %d pages (%s) over limit of %d pages (%s)",
789 capacity, PagesToUnitOfBytes(capacity), memoryLimitPages, PagesToUnitOfBytes(memoryLimitPages))
790 }
791 return nil
792 }
793
794 type GlobalType struct {
795 ValType ValueType
796 Mutable bool
797 }
798
799 type Global struct {
800 Type GlobalType
801 Init ConstantExpression
802 }
803
804 type ConstantExpression struct {
805 Opcode Opcode
806 Data []byte
807 }
808
809
810
811 type Export struct {
812 Type ExternType
813
814
815 Name string
816
817
818
819 Index Index
820 }
821
822
823
824 type Code struct {
825
826
827 LocalTypes []ValueType
828
829
830
831 Body []byte
832
833
834
835
836
837
838
839 GoFunc interface{}
840
841
842
843 BodyOffsetInCodeSection uint64
844 }
845
846 type DataSegment struct {
847 OffsetExpression ConstantExpression
848 Init []byte
849 Passive bool
850 }
851
852
853
854
855
856
857 func (d *DataSegment) IsPassive() bool {
858 return d.Passive
859 }
860
861
862
863
864
865 type NameSection struct {
866
867
868
869 ModuleName string
870
871
872
873
874
875
876
877
878
879
880
881 FunctionNames NameMap
882
883
884
885
886
887
888
889
890
891
892
893 LocalNames IndirectNameMap
894
895
896 ResultNames IndirectNameMap
897 }
898
899
900 type CustomSection struct {
901 Name string
902 Data []byte
903 }
904
905
906
907
908
909
910
911
912
913 type NameMap []NameAssoc
914
915 type NameAssoc struct {
916 Index Index
917 Name string
918 }
919
920
921
922
923
924
925 type IndirectNameMap []NameMapAssoc
926
927 type NameMapAssoc struct {
928 Index Index
929 NameMap NameMap
930 }
931
932
933 func (m *Module) AllDeclarations() (functions []Index, globals []GlobalType, memory *Memory, tables []Table, err error) {
934 for i := range m.ImportSection {
935 imp := &m.ImportSection[i]
936 switch imp.Type {
937 case ExternTypeFunc:
938 functions = append(functions, imp.DescFunc)
939 case ExternTypeGlobal:
940 globals = append(globals, imp.DescGlobal)
941 case ExternTypeMemory:
942 memory = imp.DescMem
943 case ExternTypeTable:
944 tables = append(tables, imp.DescTable)
945 }
946 }
947
948 functions = append(functions, m.FunctionSection...)
949 for i := range m.GlobalSection {
950 g := &m.GlobalSection[i]
951 globals = append(globals, g.Type)
952 }
953 if m.MemorySection != nil {
954 if memory != nil {
955 err = errors.New("at most one table allowed in module")
956 return
957 }
958 memory = m.MemorySection
959 }
960 if m.TableSection != nil {
961 tables = append(tables, m.TableSection...)
962 }
963 return
964 }
965
966
967
968
969
970
971
972 type SectionID = byte
973
974 const (
975
976 SectionIDCustom SectionID = iota
977 SectionIDType
978 SectionIDImport
979 SectionIDFunction
980 SectionIDTable
981 SectionIDMemory
982 SectionIDGlobal
983 SectionIDExport
984 SectionIDStart
985 SectionIDElement
986 SectionIDCode
987 SectionIDData
988
989
990
991
992
993 SectionIDDataCount
994 )
995
996
997
998 func SectionIDName(sectionID SectionID) string {
999 switch sectionID {
1000 case SectionIDCustom:
1001 return "custom"
1002 case SectionIDType:
1003 return "type"
1004 case SectionIDImport:
1005 return "import"
1006 case SectionIDFunction:
1007 return "function"
1008 case SectionIDTable:
1009 return "table"
1010 case SectionIDMemory:
1011 return "memory"
1012 case SectionIDGlobal:
1013 return "global"
1014 case SectionIDExport:
1015 return "export"
1016 case SectionIDStart:
1017 return "start"
1018 case SectionIDElement:
1019 return "element"
1020 case SectionIDCode:
1021 return "code"
1022 case SectionIDData:
1023 return "data"
1024 case SectionIDDataCount:
1025 return "data_count"
1026 }
1027 return "unknown"
1028 }
1029
1030
1031 type ValueType = api.ValueType
1032
1033 const (
1034 ValueTypeI32 = api.ValueTypeI32
1035 ValueTypeI64 = api.ValueTypeI64
1036 ValueTypeF32 = api.ValueTypeF32
1037 ValueTypeF64 = api.ValueTypeF64
1038
1039 ValueTypeV128 ValueType = 0x7b
1040
1041 ValueTypeFuncref ValueType = 0x70
1042 ValueTypeExternref = api.ValueTypeExternref
1043 )
1044
1045
1046 func ValueTypeName(t ValueType) string {
1047 if t == ValueTypeFuncref {
1048 return "funcref"
1049 } else if t == ValueTypeV128 {
1050 return "v128"
1051 }
1052 return api.ValueTypeName(t)
1053 }
1054
1055 func isReferenceValueType(vt ValueType) bool {
1056 return vt == ValueTypeExternref || vt == ValueTypeFuncref
1057 }
1058
1059
1060 type ExternType = api.ExternType
1061
1062 const (
1063 ExternTypeFunc = api.ExternTypeFunc
1064 ExternTypeFuncName = api.ExternTypeFuncName
1065 ExternTypeTable = api.ExternTypeTable
1066 ExternTypeTableName = api.ExternTypeTableName
1067 ExternTypeMemory = api.ExternTypeMemory
1068 ExternTypeMemoryName = api.ExternTypeMemoryName
1069 ExternTypeGlobal = api.ExternTypeGlobal
1070 ExternTypeGlobalName = api.ExternTypeGlobalName
1071 )
1072
1073
1074 func ExternTypeName(t ValueType) string {
1075 return api.ExternTypeName(t)
1076 }
1077
View as plain text