github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/internal/wasm/function_definition.go (about) 1 package wasm 2 3 import ( 4 "github.com/bananabytelabs/wazero/api" 5 "github.com/bananabytelabs/wazero/internal/internalapi" 6 "github.com/bananabytelabs/wazero/internal/wasmdebug" 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 i := uint32(0); i < m.ImportFunctionCount; i++ { 14 ret = append(ret, m.FunctionDefinition(i)) 15 } 16 return 17 } 18 19 // ExportedFunctions returns the definitions of each exported function. 20 func (m *Module) ExportedFunctions() map[string]api.FunctionDefinition { 21 ret := map[string]api.FunctionDefinition{} 22 for i := range m.ExportSection { 23 exp := &m.ExportSection[i] 24 if exp.Type == ExternTypeFunc { 25 d := m.FunctionDefinition(exp.Index) 26 ret[exp.Name] = d 27 } 28 } 29 return ret 30 } 31 32 // FunctionDefinition returns the FunctionDefinition for the given `index`. 33 func (m *Module) FunctionDefinition(index Index) *FunctionDefinition { 34 // TODO: function initialization is lazy, but bulk. Make it per function. 35 m.buildFunctionDefinitions() 36 return &m.FunctionDefinitionSection[index] 37 } 38 39 // buildFunctionDefinitions generates function metadata that can be parsed from 40 // the module. This must be called after all validation. 41 func (m *Module) buildFunctionDefinitions() { 42 m.functionDefinitionSectionInitOnce.Do(m.buildFunctionDefinitionsOnce) 43 } 44 45 func (m *Module) buildFunctionDefinitionsOnce() { 46 var moduleName string 47 var functionNames NameMap 48 var localNames, resultNames IndirectNameMap 49 if m.NameSection != nil { 50 moduleName = m.NameSection.ModuleName 51 functionNames = m.NameSection.FunctionNames 52 localNames = m.NameSection.LocalNames 53 resultNames = m.NameSection.ResultNames 54 } 55 56 importCount := m.ImportFunctionCount 57 m.FunctionDefinitionSection = make([]FunctionDefinition, importCount+uint32(len(m.FunctionSection))) 58 59 importFuncIdx := Index(0) 60 for i := range m.ImportSection { 61 imp := &m.ImportSection[i] 62 if imp.Type != ExternTypeFunc { 63 continue 64 } 65 66 def := &m.FunctionDefinitionSection[importFuncIdx] 67 def.importDesc = imp 68 def.index = importFuncIdx 69 def.Functype = &m.TypeSection[imp.DescFunc] 70 importFuncIdx++ 71 } 72 73 for codeIndex, typeIndex := range m.FunctionSection { 74 code := &m.CodeSection[codeIndex] 75 idx := importFuncIdx + Index(codeIndex) 76 def := &m.FunctionDefinitionSection[idx] 77 def.index = idx 78 def.Functype = &m.TypeSection[typeIndex] 79 def.goFunc = code.GoFunc 80 } 81 82 n, nLen := 0, len(functionNames) 83 for i := range m.FunctionDefinitionSection { 84 d := &m.FunctionDefinitionSection[i] 85 // The function name section begins with imports, but can be sparse. 86 // This keeps track of how far in the name section we've searched. 87 funcIdx := d.index 88 var funcName string 89 for ; n < nLen; n++ { 90 next := &functionNames[n] 91 if next.Index > funcIdx { 92 break // we have function names, but starting at a later index. 93 } else if next.Index == funcIdx { 94 funcName = next.Name 95 break 96 } 97 } 98 99 d.moduleName = moduleName 100 d.name = funcName 101 d.Debugname = wasmdebug.FuncName(moduleName, funcName, funcIdx) 102 d.paramNames = paramNames(localNames, funcIdx, len(d.Functype.Params)) 103 d.resultNames = paramNames(resultNames, funcIdx, len(d.Functype.Results)) 104 105 for i := range m.ExportSection { 106 e := &m.ExportSection[i] 107 if e.Type == ExternTypeFunc && e.Index == funcIdx { 108 d.exportNames = append(d.exportNames, e.Name) 109 } 110 } 111 } 112 } 113 114 // FunctionDefinition implements api.FunctionDefinition 115 type FunctionDefinition struct { 116 internalapi.WazeroOnlyType 117 moduleName string 118 index Index 119 name string 120 // Debugname is exported for testing purpose. 121 Debugname string 122 goFunc interface{} 123 // Functype is exported for testing purpose. 124 Functype *FunctionType 125 importDesc *Import 126 exportNames []string 127 paramNames []string 128 resultNames []string 129 } 130 131 // ModuleName implements the same method as documented on api.FunctionDefinition. 132 func (f *FunctionDefinition) ModuleName() string { 133 return f.moduleName 134 } 135 136 // Index implements the same method as documented on api.FunctionDefinition. 137 func (f *FunctionDefinition) Index() uint32 { 138 return f.index 139 } 140 141 // Name implements the same method as documented on api.FunctionDefinition. 142 func (f *FunctionDefinition) Name() string { 143 return f.name 144 } 145 146 // DebugName implements the same method as documented on api.FunctionDefinition. 147 func (f *FunctionDefinition) DebugName() string { 148 return f.Debugname 149 } 150 151 // Import implements the same method as documented on api.FunctionDefinition. 152 func (f *FunctionDefinition) Import() (moduleName, name string, isImport bool) { 153 if f.importDesc != nil { 154 importDesc := f.importDesc 155 moduleName, name, isImport = importDesc.Module, importDesc.Name, true 156 } 157 return 158 } 159 160 // ExportNames implements the same method as documented on api.FunctionDefinition. 161 func (f *FunctionDefinition) ExportNames() []string { 162 return f.exportNames 163 } 164 165 // GoFunction implements the same method as documented on api.FunctionDefinition. 166 func (f *FunctionDefinition) GoFunction() interface{} { 167 return f.goFunc 168 } 169 170 // ParamTypes implements api.FunctionDefinition ParamTypes. 171 func (f *FunctionDefinition) ParamTypes() []ValueType { 172 return f.Functype.Params 173 } 174 175 // ParamNames implements the same method as documented on api.FunctionDefinition. 176 func (f *FunctionDefinition) ParamNames() []string { 177 return f.paramNames 178 } 179 180 // ResultTypes implements api.FunctionDefinition ResultTypes. 181 func (f *FunctionDefinition) ResultTypes() []ValueType { 182 return f.Functype.Results 183 } 184 185 // ResultNames implements the same method as documented on api.FunctionDefinition. 186 func (f *FunctionDefinition) ResultNames() []string { 187 return f.resultNames 188 }