offsetdata.go

  1package wazevoapi
  2
  3import (
  4	"github.com/tetratelabs/wazero/internal/wasm"
  5)
  6
  7const (
  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
 18const (
 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.
 60type 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.
 77func (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.
 85func (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.
 90type Offset int32
 91
 92// U32 encodes an Offset as uint32 for convenience.
 93func (o Offset) U32() uint32 {
 94	return uint32(o)
 95}
 96
 97// I64 encodes an Offset as int64 for convenience.
 98func (o Offset) I64() int64 {
 99	return int64(o)
100}
101
102// U64 encodes an Offset as int64 for convenience.
103func (o Offset) U64() uint64 {
104	return uint64(o)
105}
106
107// LocalMemoryBase returns an offset of the first byte of the local memory.
108func (m *ModuleContextOffsetData) LocalMemoryBase() Offset {
109	return m.LocalMemoryBegin
110}
111
112// LocalMemoryLen returns an offset of the length of the local memory buffer.
113func (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.
121func (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.
127func 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
210func align16(o Offset) Offset {
211	return (o + 15) &^ 15
212}
213
214func align8(o Offset) Offset {
215	return (o + 7) &^ 7
216}