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  }