wa-lang.org/wazero@v1.0.2/internal/asm/impl.go (about) 1 package asm 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 ) 7 8 // BaseAssemblerImpl includes code common to all architectures. 9 // 10 // Note: When possible, add code here instead of in architecture-specific files to reduce drift: 11 // As this is internal, exporting symbols only to reduce duplication is ok. 12 type BaseAssemblerImpl struct { 13 // SetBranchTargetOnNextNodes holds branch kind instructions (BR, conditional BR, etc.) 14 // where we want to set the next coming instruction as the destination of these BR instructions. 15 SetBranchTargetOnNextNodes []Node 16 17 // OnGenerateCallbacks holds the callbacks which are called after generating native code. 18 OnGenerateCallbacks []func(code []byte) error 19 } 20 21 // SetJumpTargetOnNext implements AssemblerBase.SetJumpTargetOnNext 22 func (a *BaseAssemblerImpl) SetJumpTargetOnNext(nodes ...Node) { 23 a.SetBranchTargetOnNextNodes = append(a.SetBranchTargetOnNextNodes, nodes...) 24 } 25 26 // AddOnGenerateCallBack implements AssemblerBase.AddOnGenerateCallBack 27 func (a *BaseAssemblerImpl) AddOnGenerateCallBack(cb func([]byte) error) { 28 a.OnGenerateCallbacks = append(a.OnGenerateCallbacks, cb) 29 } 30 31 // BuildJumpTable implements AssemblerBase.BuildJumpTable 32 func (a *BaseAssemblerImpl) BuildJumpTable(table *StaticConst, labelInitialInstructions []Node) { 33 a.AddOnGenerateCallBack(func(code []byte) error { 34 // Compile the offset table for each target. 35 base := labelInitialInstructions[0].OffsetInBinary() 36 for i, nop := range labelInitialInstructions { 37 if nop.OffsetInBinary()-base >= JumpTableMaximumOffset { 38 return fmt.Errorf("too large br_table") 39 } 40 // We store the offset from the beginning of the L0's initial instruction. 41 binary.LittleEndian.PutUint32(code[table.offsetInBinary+uint64(i*4):table.offsetInBinary+uint64((i+1)*4)], 42 uint32(nop.OffsetInBinary())-uint32(base)) 43 } 44 return nil 45 }) 46 }