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