github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/internal/engine/wazevo/wazevoapi/offsetdata.go (about) 1 package wazevoapi 2 3 import ( 4 "github.com/tetratelabs/wazero/internal/wasm" 5 ) 6 7 const ( 8 // FunctionInstanceSize is the size of wazevo.functionInstance. 9 FunctionInstanceSize = 24 10 // FunctionInstanceExecutableOffset is an offset of `executable` field in wazevo.functionInstance 11 FunctionInstanceExecutableOffset = 0 12 // FunctionInstanceModuleContextOpaquePtrOffset is an offset of `moduleContextOpaquePtr` field in wazevo.functionInstance 13 FunctionInstanceModuleContextOpaquePtrOffset = 8 14 // FunctionInstanceTypeIDOffset is an offset of `typeID` field in wazevo.functionInstance 15 FunctionInstanceTypeIDOffset = 16 16 ) 17 18 const ( 19 // ExecutionContextOffsetExitCodeOffset is an offset of `exitCode` field in wazevo.executionContext 20 ExecutionContextOffsetExitCodeOffset Offset = 0 21 // ExecutionContextOffsetCallerModuleContextPtr is an offset of `callerModuleContextPtr` field in wazevo.executionContext 22 ExecutionContextOffsetCallerModuleContextPtr Offset = 8 23 // ExecutionContextOffsetOriginalFramePointer is an offset of `originalFramePointer` field in wazevo.executionContext 24 ExecutionContextOffsetOriginalFramePointer Offset = 16 25 // ExecutionContextOffsetOriginalStackPointer is an offset of `originalStackPointer` field in wazevo.executionContext 26 ExecutionContextOffsetOriginalStackPointer Offset = 24 27 // ExecutionContextOffsetGoReturnAddress is an offset of `goReturnAddress` field in wazevo.executionContext 28 ExecutionContextOffsetGoReturnAddress Offset = 32 29 // ExecutionContextOffsetStackBottomPtr is an offset of `stackBottomPtr` field in wazevo.executionContext 30 ExecutionContextOffsetStackBottomPtr Offset = 40 31 // ExecutionContextOffsetGoCallReturnAddress is an offset of `goCallReturnAddress` field in wazevo.executionContext 32 ExecutionContextOffsetGoCallReturnAddress Offset = 48 33 // ExecutionContextOffsetStackPointerBeforeGoCall is an offset of `StackPointerBeforeGoCall` field in wazevo.executionContext 34 ExecutionContextOffsetStackPointerBeforeGoCall Offset = 56 35 // ExecutionContextOffsetStackGrowRequiredSize is an offset of `stackGrowRequiredSize` field in wazevo.executionContext 36 ExecutionContextOffsetStackGrowRequiredSize Offset = 64 37 // ExecutionContextOffsetMemoryGrowTrampolineAddress is an offset of `memoryGrowTrampolineAddress` field in wazevo.executionContext 38 ExecutionContextOffsetMemoryGrowTrampolineAddress Offset = 72 39 // ExecutionContextOffsetStackGrowCallTrampolineAddress is an offset of `stackGrowCallTrampolineAddress` field in wazevo.executionContext. 40 ExecutionContextOffsetStackGrowCallTrampolineAddress Offset = 80 41 // ExecutionContextOffsetCheckModuleExitCodeTrampolineAddress is an offset of `checkModuleExitCodeTrampolineAddress` field in wazevo.executionContext. 42 ExecutionContextOffsetCheckModuleExitCodeTrampolineAddress Offset = 88 43 // ExecutionContextOffsetSavedRegistersBegin is an offset of the first element of `savedRegisters` field in wazevo.executionContext 44 ExecutionContextOffsetSavedRegistersBegin Offset = 96 45 // ExecutionContextOffsetGoFunctionCallCalleeModuleContextOpaque is an offset of `goFunctionCallCalleeModuleContextOpaque` field in wazevo.executionContext 46 ExecutionContextOffsetGoFunctionCallCalleeModuleContextOpaque Offset = 1120 47 // ExecutionContextOffsetTableGrowTrampolineAddress is an offset of `tableGrowTrampolineAddress` field in wazevo.executionContext 48 ExecutionContextOffsetTableGrowTrampolineAddress Offset = 1128 49 // ExecutionContextOffsetRefFuncTrampolineAddress is an offset of `refFuncTrampolineAddress` field in wazevo.executionContext 50 ExecutionContextOffsetRefFuncTrampolineAddress Offset = 1136 51 ExecutionContextOffsetMemmoveAddress Offset = 1144 52 ExecutionContextOffsetFramePointerBeforeGoCall Offset = 1152 53 ExecutionContextOffsetMemoryWait32TrampolineAddress Offset = 1160 54 ExecutionContextOffsetMemoryWait64TrampolineAddress Offset = 1168 55 ExecutionContextOffsetMemoryNotifyTrampolineAddress Offset = 1176 56 ) 57 58 // ModuleContextOffsetData allows the compilers to get the information about offsets to the fields of wazevo.moduleContextOpaque, 59 // This is unique per module. 60 type ModuleContextOffsetData struct { 61 TotalSize int 62 ModuleInstanceOffset, 63 LocalMemoryBegin, 64 ImportedMemoryBegin, 65 ImportedFunctionsBegin, 66 GlobalsBegin, 67 TypeIDs1stElement, 68 TablesBegin, 69 BeforeListenerTrampolines1stElement, 70 AfterListenerTrampolines1stElement, 71 DataInstances1stElement, 72 ElementInstances1stElement Offset 73 } 74 75 // ImportedFunctionOffset returns an offset of the i-th imported function. 76 // Each item is stored as wazevo.functionInstance whose size matches FunctionInstanceSize. 77 func (m *ModuleContextOffsetData) ImportedFunctionOffset(i wasm.Index) ( 78 executableOffset, moduleCtxOffset, typeIDOffset Offset, 79 ) { 80 base := m.ImportedFunctionsBegin + Offset(i)*FunctionInstanceSize 81 return base, base + 8, base + 16 82 } 83 84 // GlobalInstanceOffset returns an offset of the i-th global instance. 85 func (m *ModuleContextOffsetData) GlobalInstanceOffset(i wasm.Index) Offset { 86 return m.GlobalsBegin + Offset(i)*16 87 } 88 89 // Offset represents an offset of a field of a struct. 90 type Offset int32 91 92 // U32 encodes an Offset as uint32 for convenience. 93 func (o Offset) U32() uint32 { 94 return uint32(o) 95 } 96 97 // I64 encodes an Offset as int64 for convenience. 98 func (o Offset) I64() int64 { 99 return int64(o) 100 } 101 102 // U64 encodes an Offset as int64 for convenience. 103 func (o Offset) U64() uint64 { 104 return uint64(o) 105 } 106 107 // LocalMemoryBase returns an offset of the first byte of the local memory. 108 func (m *ModuleContextOffsetData) LocalMemoryBase() Offset { 109 return m.LocalMemoryBegin 110 } 111 112 // LocalMemoryLen returns an offset of the length of the local memory buffer. 113 func (m *ModuleContextOffsetData) LocalMemoryLen() Offset { 114 if l := m.LocalMemoryBegin; l >= 0 { 115 return l + 8 116 } 117 return -1 118 } 119 120 // TableOffset returns an offset of the i-th table instance. 121 func (m *ModuleContextOffsetData) TableOffset(tableIndex int) Offset { 122 return m.TablesBegin + Offset(tableIndex)*8 123 } 124 125 // NewModuleContextOffsetData creates a ModuleContextOffsetData determining the structure of moduleContextOpaque for the given Module. 126 // The structure is described in the comment of wazevo.moduleContextOpaque. 127 func NewModuleContextOffsetData(m *wasm.Module, withListener bool) ModuleContextOffsetData { 128 ret := ModuleContextOffsetData{} 129 var offset Offset 130 131 ret.ModuleInstanceOffset = 0 132 offset += 8 133 134 if m.MemorySection != nil { 135 ret.LocalMemoryBegin = offset 136 // buffer base + memory size. 137 const localMemorySizeInOpaqueModuleContext = 16 138 offset += localMemorySizeInOpaqueModuleContext 139 } else { 140 // Indicates that there's no local memory 141 ret.LocalMemoryBegin = -1 142 } 143 144 if m.ImportMemoryCount > 0 { 145 offset = align8(offset) 146 // *wasm.MemoryInstance + imported memory's owner (moduleContextOpaque) 147 const importedMemorySizeInOpaqueModuleContext = 16 148 ret.ImportedMemoryBegin = offset 149 offset += importedMemorySizeInOpaqueModuleContext 150 } else { 151 // Indicates that there's no imported memory 152 ret.ImportedMemoryBegin = -1 153 } 154 155 if m.ImportFunctionCount > 0 { 156 offset = align8(offset) 157 ret.ImportedFunctionsBegin = offset 158 // Each function is stored wazevo.functionInstance. 159 size := int(m.ImportFunctionCount) * FunctionInstanceSize 160 offset += Offset(size) 161 } else { 162 ret.ImportedFunctionsBegin = -1 163 } 164 165 if globals := int(m.ImportGlobalCount) + len(m.GlobalSection); globals > 0 { 166 // Align to 16 bytes for globals, as f32/f64/v128 might be loaded via SIMD instructions. 167 offset = align16(offset) 168 ret.GlobalsBegin = offset 169 // Pointers to *wasm.GlobalInstance. 170 offset += Offset(globals) * 16 171 } else { 172 ret.GlobalsBegin = -1 173 } 174 175 if tables := len(m.TableSection) + int(m.ImportTableCount); tables > 0 { 176 offset = align8(offset) 177 ret.TypeIDs1stElement = offset 178 offset += 8 // First element of TypeIDs. 179 180 ret.TablesBegin = offset 181 // Pointers to *wasm.TableInstance. 182 offset += Offset(tables) * 8 183 } else { 184 ret.TypeIDs1stElement = -1 185 ret.TablesBegin = -1 186 } 187 188 if withListener { 189 offset = align8(offset) 190 ret.BeforeListenerTrampolines1stElement = offset 191 offset += 8 // First element of BeforeListenerTrampolines. 192 193 ret.AfterListenerTrampolines1stElement = offset 194 offset += 8 // First element of AfterListenerTrampolines. 195 } else { 196 ret.BeforeListenerTrampolines1stElement = -1 197 ret.AfterListenerTrampolines1stElement = -1 198 } 199 200 ret.DataInstances1stElement = offset 201 offset += 8 // First element of DataInstances. 202 203 ret.ElementInstances1stElement = offset 204 offset += 8 // First element of ElementInstances. 205 206 ret.TotalSize = int(align16(offset)) 207 return ret 208 } 209 210 func align16(o Offset) Offset { 211 return (o + 15) &^ 15 212 } 213 214 func align8(o Offset) Offset { 215 return (o + 7) &^ 7 216 }