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