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  }