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  }