github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/internal/engine/wazevo/backend/isa/arm64/util_test.go (about) 1 package arm64 2 3 import ( 4 "context" 5 "strings" 6 7 "github.com/tetratelabs/wazero/internal/engine/wazevo/backend" 8 "github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc" 9 "github.com/tetratelabs/wazero/internal/engine/wazevo/ssa" 10 ) 11 12 func getPendingInstr(m *machine) *instruction { 13 return m.executableContext.PendingInstructions[0] 14 } 15 16 func formatEmittedInstructionsInCurrentBlock(m *machine) string { 17 m.executableContext.FlushPendingInstructions() 18 var strs []string 19 for cur := m.executableContext.PerBlockHead; cur != nil; cur = cur.next { 20 strs = append(strs, cur.String()) 21 } 22 return strings.Join(strs, "\n") 23 } 24 25 func newSetup() (ssa.Builder, *machine) { 26 m := NewBackend().(*machine) 27 ssaB := ssa.NewBuilder() 28 backend.NewCompiler(context.Background(), m, ssaB) 29 blk := ssaB.AllocateBasicBlock() 30 ssaB.SetCurrentBlock(blk) 31 return ssaB, m 32 } 33 34 func newSetupWithMockContext() (*mockCompiler, ssa.Builder, *machine) { 35 ctx := newMockCompilationContext() 36 m := NewBackend().(*machine) 37 m.SetCompiler(ctx) 38 ssaB := ssa.NewBuilder() 39 blk := ssaB.AllocateBasicBlock() 40 ssaB.SetCurrentBlock(blk) 41 return ctx, ssaB, m 42 } 43 44 func regToVReg(reg regalloc.RealReg) regalloc.VReg { 45 return regalloc.VReg(0).SetRealReg(reg).SetRegType(regalloc.RegTypeInt) 46 } 47 48 func intToVReg(i int) regalloc.VReg { 49 return regalloc.VReg(i).SetRegType(regalloc.RegTypeInt) 50 } 51 52 // mockCompiler implements backend.Compiler for testing. 53 type mockCompiler struct { 54 currentGID ssa.InstructionGroupID 55 vRegCounter int 56 vRegMap map[ssa.Value]regalloc.VReg 57 definitions map[ssa.Value]*backend.SSAValueDefinition 58 sigs map[ssa.SignatureID]*ssa.Signature 59 typeOf map[regalloc.VRegID]ssa.Type 60 relocs []backend.RelocationInfo 61 buf []byte 62 } 63 64 func (m *mockCompiler) BufPtr() *[]byte { return &m.buf } 65 66 func (m *mockCompiler) GetFunctionABI(sig *ssa.Signature) *backend.FunctionABI { 67 // TODO implement me 68 panic("implement me") 69 } 70 71 func (m *mockCompiler) SSABuilder() ssa.Builder { return nil } 72 73 func (m *mockCompiler) LoopNestingForestRoots() []ssa.BasicBlock { panic("TODO") } 74 75 func (m *mockCompiler) SourceOffsetInfo() []backend.SourceOffsetInfo { return nil } 76 77 func (m *mockCompiler) AddSourceOffsetInfo(int64, ssa.SourceOffset) {} 78 79 func (m *mockCompiler) AddRelocationInfo(funcRef ssa.FuncRef) { 80 m.relocs = append(m.relocs, backend.RelocationInfo{FuncRef: funcRef, Offset: int64(len(m.buf))}) 81 } 82 83 func (m *mockCompiler) Emit4Bytes(b uint32) { 84 m.buf = append(m.buf, byte(b), byte(b>>8), byte(b>>16), byte(b>>24)) 85 } 86 87 func (m *mockCompiler) EmitByte(b byte) { 88 m.buf = append(m.buf, b) 89 } 90 91 func (m *mockCompiler) Emit8Bytes(b uint64) { 92 m.buf = append(m.buf, byte(b), byte(b>>8), byte(b>>16), byte(b>>24), byte(b>>32), byte(b>>40), byte(b>>48), byte(b>>56)) 93 } 94 95 func (m *mockCompiler) Encode() {} 96 func (m *mockCompiler) Buf() []byte { return m.buf } 97 func (m *mockCompiler) TypeOf(v regalloc.VReg) (ret ssa.Type) { 98 return m.typeOf[v.ID()] 99 } 100 func (m *mockCompiler) Finalize(context.Context) (err error) { return } 101 func (m *mockCompiler) RegAlloc() {} 102 func (m *mockCompiler) Lower() {} 103 func (m *mockCompiler) Format() string { return "" } 104 func (m *mockCompiler) Init() {} 105 106 func newMockCompilationContext() *mockCompiler { 107 return &mockCompiler{ 108 vRegMap: make(map[ssa.Value]regalloc.VReg), 109 definitions: make(map[ssa.Value]*backend.SSAValueDefinition), 110 typeOf: map[regalloc.VRegID]ssa.Type{}, 111 } 112 } 113 114 // ResolveSignature implements backend.Compiler. 115 func (m *mockCompiler) ResolveSignature(id ssa.SignatureID) *ssa.Signature { 116 return m.sigs[id] 117 } 118 119 // AllocateVReg implements backend.Compiler. 120 func (m *mockCompiler) AllocateVReg(typ ssa.Type) regalloc.VReg { 121 m.vRegCounter++ 122 regType := regalloc.RegTypeOf(typ) 123 ret := regalloc.VReg(m.vRegCounter).SetRegType(regType) 124 m.typeOf[ret.ID()] = typ 125 return ret 126 } 127 128 // ValueDefinition implements backend.Compiler. 129 func (m *mockCompiler) ValueDefinition(value ssa.Value) *backend.SSAValueDefinition { 130 definition, exists := m.definitions[value] 131 if !exists { 132 return nil 133 } 134 return definition 135 } 136 137 // VRegOf implements backend.Compiler. 138 func (m *mockCompiler) VRegOf(value ssa.Value) regalloc.VReg { 139 vReg, exists := m.vRegMap[value] 140 if !exists { 141 panic("Value does not exist") 142 } 143 return vReg 144 } 145 146 // MatchInstr implements backend.Compiler. 147 func (m *mockCompiler) MatchInstr(def *backend.SSAValueDefinition, opcode ssa.Opcode) bool { 148 instr := def.Instr 149 return def.IsFromInstr() && 150 instr.Opcode() == opcode && 151 instr.GroupID() == m.currentGID && 152 def.RefCount < 2 153 } 154 155 // MatchInstrOneOf implements backend.Compiler. 156 func (m *mockCompiler) MatchInstrOneOf(def *backend.SSAValueDefinition, opcodes []ssa.Opcode) ssa.Opcode { 157 for _, opcode := range opcodes { 158 if m.MatchInstr(def, opcode) { 159 return opcode 160 } 161 } 162 return ssa.OpcodeInvalid 163 } 164 165 // Compile implements backend.Compiler. 166 func (m *mockCompiler) Compile(context.Context) (_ []byte, _ []backend.RelocationInfo, _ error) { 167 return 168 }