package wazevoapi

import (
	
)

const (
	// FunctionInstanceSize is the size of wazevo.functionInstance.
	FunctionInstanceSize = 24
	// FunctionInstanceExecutableOffset is an offset of `executable` field in wazevo.functionInstance
	FunctionInstanceExecutableOffset = 0
	// FunctionInstanceModuleContextOpaquePtrOffset is an offset of `moduleContextOpaquePtr` field in wazevo.functionInstance
	FunctionInstanceModuleContextOpaquePtrOffset = 8
	// FunctionInstanceTypeIDOffset is an offset of `typeID` field in wazevo.functionInstance
	FunctionInstanceTypeIDOffset = 16
)

const (
	// ExecutionContextOffsetExitCodeOffset is an offset of `exitCode` field in wazevo.executionContext
	ExecutionContextOffsetExitCodeOffset Offset = 0
	// ExecutionContextOffsetCallerModuleContextPtr is an offset of `callerModuleContextPtr` field in wazevo.executionContext
	ExecutionContextOffsetCallerModuleContextPtr Offset = 8
	// ExecutionContextOffsetOriginalFramePointer is an offset of `originalFramePointer` field in wazevo.executionContext
	ExecutionContextOffsetOriginalFramePointer Offset = 16
	// ExecutionContextOffsetOriginalStackPointer is an offset of `originalStackPointer` field in wazevo.executionContext
	ExecutionContextOffsetOriginalStackPointer Offset = 24
	// ExecutionContextOffsetGoReturnAddress is an offset of `goReturnAddress` field in wazevo.executionContext
	ExecutionContextOffsetGoReturnAddress Offset = 32
	// ExecutionContextOffsetStackBottomPtr is an offset of `stackBottomPtr` field in wazevo.executionContext
	ExecutionContextOffsetStackBottomPtr Offset = 40
	// ExecutionContextOffsetGoCallReturnAddress is an offset of `goCallReturnAddress` field in wazevo.executionContext
	ExecutionContextOffsetGoCallReturnAddress Offset = 48
	// ExecutionContextOffsetStackPointerBeforeGoCall is an offset of `StackPointerBeforeGoCall` field in wazevo.executionContext
	ExecutionContextOffsetStackPointerBeforeGoCall Offset = 56
	// ExecutionContextOffsetStackGrowRequiredSize is an offset of `stackGrowRequiredSize` field in wazevo.executionContext
	ExecutionContextOffsetStackGrowRequiredSize Offset = 64
	// ExecutionContextOffsetMemoryGrowTrampolineAddress is an offset of `memoryGrowTrampolineAddress` field in wazevo.executionContext
	ExecutionContextOffsetMemoryGrowTrampolineAddress Offset = 72
	// ExecutionContextOffsetStackGrowCallTrampolineAddress is an offset of `stackGrowCallTrampolineAddress` field in wazevo.executionContext.
	ExecutionContextOffsetStackGrowCallTrampolineAddress Offset = 80
	// ExecutionContextOffsetCheckModuleExitCodeTrampolineAddress is an offset of `checkModuleExitCodeTrampolineAddress` field in wazevo.executionContext.
	ExecutionContextOffsetCheckModuleExitCodeTrampolineAddress Offset = 88
	// ExecutionContextOffsetSavedRegistersBegin is an offset of the first element of `savedRegisters` field in wazevo.executionContext
	ExecutionContextOffsetSavedRegistersBegin Offset = 96
	// ExecutionContextOffsetGoFunctionCallCalleeModuleContextOpaque is an offset of `goFunctionCallCalleeModuleContextOpaque` field in wazevo.executionContext
	ExecutionContextOffsetGoFunctionCallCalleeModuleContextOpaque Offset = 1120
	// ExecutionContextOffsetTableGrowTrampolineAddress is an offset of `tableGrowTrampolineAddress` field in wazevo.executionContext
	ExecutionContextOffsetTableGrowTrampolineAddress Offset = 1128
	// ExecutionContextOffsetRefFuncTrampolineAddress is an offset of `refFuncTrampolineAddress` field in wazevo.executionContext
	ExecutionContextOffsetRefFuncTrampolineAddress      Offset = 1136
	ExecutionContextOffsetMemmoveAddress                Offset = 1144
	ExecutionContextOffsetFramePointerBeforeGoCall      Offset = 1152
	ExecutionContextOffsetMemoryWait32TrampolineAddress Offset = 1160
	ExecutionContextOffsetMemoryWait64TrampolineAddress Offset = 1168
	ExecutionContextOffsetMemoryNotifyTrampolineAddress Offset = 1176
)

// ModuleContextOffsetData allows the compilers to get the information about offsets to the fields of wazevo.moduleContextOpaque,
// This is unique per module.
type ModuleContextOffsetData struct {
	TotalSize int
	ModuleInstanceOffset,
	LocalMemoryBegin,
	ImportedMemoryBegin,
	ImportedFunctionsBegin,
	GlobalsBegin,
	TypeIDs1stElement,
	TablesBegin,
	BeforeListenerTrampolines1stElement,
	AfterListenerTrampolines1stElement,
	DataInstances1stElement,
	ElementInstances1stElement Offset
}

// ImportedFunctionOffset returns an offset of the i-th imported function.
// Each item is stored as wazevo.functionInstance whose size matches FunctionInstanceSize.
func ( *ModuleContextOffsetData) ( wasm.Index) (
	, ,  Offset,
) {
	 := .ImportedFunctionsBegin + Offset()*FunctionInstanceSize
	return ,  + 8,  + 16
}

// GlobalInstanceOffset returns an offset of the i-th global instance.
func ( *ModuleContextOffsetData) ( wasm.Index) Offset {
	return .GlobalsBegin + Offset()*16
}

// Offset represents an offset of a field of a struct.
type Offset int32

// U32 encodes an Offset as uint32 for convenience.
func ( Offset) () uint32 {
	return uint32()
}

// I64 encodes an Offset as int64 for convenience.
func ( Offset) () int64 {
	return int64()
}

// U64 encodes an Offset as int64 for convenience.
func ( Offset) () uint64 {
	return uint64()
}

// LocalMemoryBase returns an offset of the first byte of the local memory.
func ( *ModuleContextOffsetData) () Offset {
	return .LocalMemoryBegin
}

// LocalMemoryLen returns an offset of the length of the local memory buffer.
func ( *ModuleContextOffsetData) () Offset {
	if  := .LocalMemoryBegin;  >= 0 {
		return  + 8
	}
	return -1
}

// TableOffset returns an offset of the i-th table instance.
func ( *ModuleContextOffsetData) ( int) Offset {
	return .TablesBegin + Offset()*8
}

// NewModuleContextOffsetData creates a ModuleContextOffsetData determining the structure of moduleContextOpaque for the given Module.
// The structure is described in the comment of wazevo.moduleContextOpaque.
func ( *wasm.Module,  bool) ModuleContextOffsetData {
	 := ModuleContextOffsetData{}
	var  Offset

	.ModuleInstanceOffset = 0
	 += 8

	if .MemorySection != nil {
		.LocalMemoryBegin = 
		// buffer base + memory size.
		const  = 16
		 += 
	} else {
		// Indicates that there's no local memory
		.LocalMemoryBegin = -1
	}

	if .ImportMemoryCount > 0 {
		 = align8()
		// *wasm.MemoryInstance + imported memory's owner (moduleContextOpaque)
		const  = 16
		.ImportedMemoryBegin = 
		 += 
	} else {
		// Indicates that there's no imported memory
		.ImportedMemoryBegin = -1
	}

	if .ImportFunctionCount > 0 {
		 = align8()
		.ImportedFunctionsBegin = 
		// Each function is stored wazevo.functionInstance.
		 := int(.ImportFunctionCount) * FunctionInstanceSize
		 += Offset()
	} else {
		.ImportedFunctionsBegin = -1
	}

	if  := int(.ImportGlobalCount) + len(.GlobalSection);  > 0 {
		// Align to 16 bytes for globals, as f32/f64/v128 might be loaded via SIMD instructions.
		 = align16()
		.GlobalsBegin = 
		// Pointers to *wasm.GlobalInstance.
		 += Offset() * 16
	} else {
		.GlobalsBegin = -1
	}

	if  := len(.TableSection) + int(.ImportTableCount);  > 0 {
		 = align8()
		.TypeIDs1stElement = 
		 += 8 // First element of TypeIDs.

		.TablesBegin = 
		// Pointers to *wasm.TableInstance.
		 += Offset() * 8
	} else {
		.TypeIDs1stElement = -1
		.TablesBegin = -1
	}

	if  {
		 = align8()
		.BeforeListenerTrampolines1stElement = 
		 += 8 // First element of BeforeListenerTrampolines.

		.AfterListenerTrampolines1stElement = 
		 += 8 // First element of AfterListenerTrampolines.
	} else {
		.BeforeListenerTrampolines1stElement = -1
		.AfterListenerTrampolines1stElement = -1
	}

	.DataInstances1stElement = 
	 += 8 // First element of DataInstances.

	.ElementInstances1stElement = 
	 += 8 // First element of ElementInstances.

	.TotalSize = int(align16())
	return 
}

func align16( Offset) Offset {
	return ( + 15) &^ 15
}

func align8( Offset) Offset {
	return ( + 7) &^ 7
}