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  }