github.com/taubyte/vm-wasm-utils@v1.0.2/function_definition.go (about) 1 package wasm 2 3 import ( 4 "reflect" 5 6 "github.com/tetratelabs/wazero/api" 7 ) 8 9 // ImportedFunctions returns the definitions of each imported function. 10 // 11 // Note: Unlike ExportedFunctions, there is no unique constraint on imports. 12 func (m *Module) ImportedFunctions() (ret []api.FunctionDefinition) { 13 for _, d := range m.FunctionDefinitionSection { 14 if d.importDesc != nil { 15 ret = append(ret, d) 16 } 17 } 18 return 19 } 20 21 // ExportedFunctions returns the definitions of each exported function. 22 func (m *Module) ExportedFunctions() map[string]api.FunctionDefinition { 23 ret := map[string]api.FunctionDefinition{} 24 for _, d := range m.FunctionDefinitionSection { 25 for _, e := range d.exportNames { 26 ret[e] = d 27 } 28 } 29 return ret 30 } 31 32 // BuildFunctionDefinitions generates function metadata that can be parsed from 33 // the module. This must be called after all validation. 34 // 35 // Note: This is exported for tests who don't use wazero.Runtime or 36 // NewHostModule to compile the module. 37 func (m *Module) BuildFunctionDefinitions() { 38 if len(m.FunctionSection) == 0 { 39 return 40 } 41 42 var moduleName string 43 var functionNames NameMap 44 var localNames IndirectNameMap 45 if m.NameSection != nil { 46 moduleName = m.NameSection.ModuleName 47 functionNames = m.NameSection.FunctionNames 48 localNames = m.NameSection.LocalNames 49 } 50 51 importCount := m.ImportFuncCount() 52 m.FunctionDefinitionSection = make([]*FunctionDefinition, 0, importCount+uint32(len(m.FunctionSection))) 53 54 importFuncIdx := Index(0) 55 for _, i := range m.ImportSection { 56 if i.Type != ExternTypeFunc { 57 continue 58 } 59 60 m.FunctionDefinitionSection = append(m.FunctionDefinitionSection, &FunctionDefinition{ 61 importDesc: &[2]string{i.Module, i.Name}, 62 index: importFuncIdx, 63 funcType: m.TypeSection[i.DescFunc], 64 }) 65 importFuncIdx++ 66 } 67 68 for codeIndex, typeIndex := range m.FunctionSection { 69 code := m.CodeSection[codeIndex] 70 m.FunctionDefinitionSection = append(m.FunctionDefinitionSection, &FunctionDefinition{ 71 index: Index(codeIndex) + importCount, 72 funcType: m.TypeSection[typeIndex], 73 goFunc: code.GoFunc, 74 }) 75 } 76 77 n, nLen := 0, len(functionNames) 78 for _, d := range m.FunctionDefinitionSection { 79 // The function name section begins with imports, but can be sparse. 80 // This keeps track of how far in the name section we've searched. 81 funcIdx := d.index 82 var funcName string 83 for ; n < nLen; n++ { 84 next := functionNames[n] 85 if next.Index > funcIdx { 86 break // we have function names, but starting at a later index. 87 } else if next.Index == funcIdx { 88 funcName = next.Name 89 break 90 } 91 } 92 93 d.moduleName = moduleName 94 d.name = funcName 95 //d.debugName = wasmdebug.FuncName(moduleName, funcName, funcIdx) 96 d.paramNames = paramNames(localNames, funcIdx, len(d.funcType.Params)) 97 98 for _, e := range m.ExportSection { 99 if e.Type == ExternTypeFunc && e.Index == funcIdx { 100 d.exportNames = append(d.exportNames, e.Name) 101 } 102 } 103 } 104 } 105 106 // FunctionDefinition implements api.FunctionDefinition 107 type FunctionDefinition struct { 108 moduleName string 109 index Index 110 name string 111 debugName string 112 goFunc *reflect.Value 113 funcType *FunctionType 114 importDesc *[2]string 115 exportNames []string 116 paramNames []string 117 } 118 119 // ModuleName implements the same method as documented on api.FunctionDefinition. 120 func (f *FunctionDefinition) ModuleName() string { 121 return f.moduleName 122 } 123 124 // Index implements the same method as documented on api.FunctionDefinition. 125 func (f *FunctionDefinition) Index() uint32 { 126 return f.index 127 } 128 129 // Name implements the same method as documented on api.FunctionDefinition. 130 func (f *FunctionDefinition) Name() string { 131 return f.name 132 } 133 134 // DebugName implements the same method as documented on api.FunctionDefinition. 135 func (f *FunctionDefinition) DebugName() string { 136 return f.debugName 137 } 138 139 // Import implements the same method as documented on api.FunctionDefinition. 140 func (f *FunctionDefinition) Import() (moduleName, name string, isImport bool) { 141 if importDesc := f.importDesc; importDesc != nil { 142 moduleName, name, isImport = importDesc[0], importDesc[1], true 143 } 144 return 145 } 146 147 // ExportNames implements the same method as documented on api.FunctionDefinition. 148 func (f *FunctionDefinition) ExportNames() []string { 149 return f.exportNames 150 } 151 152 // GoFunc implements the same method as documented on api.FunctionDefinition. 153 func (f *FunctionDefinition) GoFunction() interface{} { 154 return f.goFunc 155 } 156 157 // ParamNames implements the same method as documented on api.FunctionDefinition. 158 func (f *FunctionDefinition) ParamNames() []string { 159 return f.paramNames 160 } 161 162 // ParamTypes implements api.FunctionDefinition ParamTypes. 163 func (f *FunctionDefinition) ParamTypes() []ValueType { 164 return f.funcType.Params 165 } 166 167 // ResultTypes implements api.FunctionDefinition ResultTypes. 168 func (f *FunctionDefinition) ResultTypes() []ValueType { 169 return f.funcType.Results 170 } 171 172 func (f *FunctionDefinition) ResultNames() []string { 173 // TODO: Not necessary at the moment, but need to implement 174 return []string{} 175 }