wa-lang.org/wazero@v1.0.2/internal/testing/proxy/proxy.go (about) 1 package proxy 2 3 import ( 4 "wa-lang.org/wazero" 5 "wa-lang.org/wazero/api" 6 "wa-lang.org/wazero/internal/leb128" 7 "wa-lang.org/wazero/internal/wasm" 8 binaryformat "wa-lang.org/wazero/internal/wasm/binary" 9 ) 10 11 // GetProxyModuleBinary creates the proxy module to proxy a function call against 12 // all the exported functions in `proxyTarget`, and returns its encoded binary. 13 // The resulting module exports the proxy functions whose names are exactly the same 14 // as the proxy destination. 15 // 16 // This is used to test host call implementations. 17 func GetProxyModuleBinary(moduleName string, proxyTarget wazero.CompiledModule) []byte { 18 funcDefs := proxyTarget.ExportedFunctions() 19 funcNum := uint32(len(funcDefs)) 20 proxyModule := &wasm.Module{ 21 MemorySection: &wasm.Memory{Min: 1}, 22 ExportSection: []*wasm.Export{{Name: "memory", Type: api.ExternTypeMemory}}, 23 NameSection: &wasm.NameSection{ModuleName: "proxy"}, 24 } 25 var cnt wasm.Index 26 for _, def := range funcDefs { 27 proxyModule.TypeSection = append(proxyModule.TypeSection, &wasm.FunctionType{ 28 Params: def.ParamTypes(), Results: def.ResultTypes(), 29 }) 30 31 // Imports the function. 32 name := def.ExportNames()[0] 33 proxyModule.ImportSection = append(proxyModule.ImportSection, &wasm.Import{ 34 Module: moduleName, 35 Name: name, 36 DescFunc: cnt, 37 }) 38 39 // Ensures that type of the proxy function matches the imported function. 40 proxyModule.FunctionSection = append(proxyModule.FunctionSection, cnt) 41 42 // Build the function body of the proxy function. 43 var body []byte 44 for i := range def.ParamTypes() { 45 body = append(body, wasm.OpcodeLocalGet) 46 body = append(body, leb128.EncodeUint32(uint32(i))...) 47 } 48 49 body = append(body, wasm.OpcodeCall) 50 body = append(body, leb128.EncodeUint32(cnt)...) 51 body = append(body, wasm.OpcodeEnd) 52 proxyModule.CodeSection = append(proxyModule.CodeSection, &wasm.Code{Body: body}) 53 54 proxyFuncIndex := cnt + funcNum 55 // Assigns the same params name as the imported one. 56 paramNames := &wasm.NameMapAssoc{Index: proxyFuncIndex} 57 for i, n := range def.ParamNames() { 58 paramNames.NameMap = append(paramNames.NameMap, &wasm.NameAssoc{Index: wasm.Index(i), Name: n}) 59 } 60 proxyModule.NameSection.LocalNames = append(proxyModule.NameSection.LocalNames, paramNames) 61 62 // Plus, assigns the same function name. 63 proxyModule.NameSection.FunctionNames = append(proxyModule.NameSection.FunctionNames, 64 &wasm.NameAssoc{Index: proxyFuncIndex, Name: name}) 65 66 // Finally, exports the proxy function with the same name as the imported one. 67 proxyModule.ExportSection = append(proxyModule.ExportSection, &wasm.Export{ 68 Type: wasm.ExternTypeFunc, 69 Name: name, 70 Index: proxyFuncIndex, 71 }) 72 cnt++ 73 } 74 return binaryformat.EncodeModule(proxyModule) 75 }