github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/engine/wazevo/backend/isa/arm64/util_test.go (about)

     1  package arm64
     2  
     3  import (
     4  	"context"
     5  	"strings"
     6  
     7  	"github.com/wasilibs/wazerox/internal/engine/wazevo/backend"
     8  	"github.com/wasilibs/wazerox/internal/engine/wazevo/backend/regalloc"
     9  	"github.com/wasilibs/wazerox/internal/engine/wazevo/ssa"
    10  )
    11  
    12  func getPendingInstr(m *machine) *instruction {
    13  	return m.pendingInstructions[0]
    14  }
    15  
    16  func formatEmittedInstructionsInCurrentBlock(m *machine) string {
    17  	m.FlushPendingInstructions()
    18  	var strs []string
    19  	for cur := m.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) SSABuilder() ssa.Builder { panic("TODO") }
    65  
    66  func (m *mockCompiler) LoopNestingForestRoots() []ssa.BasicBlock { panic("TODO") }
    67  
    68  func (m *mockCompiler) SourceOffsetInfo() []backend.SourceOffsetInfo { return nil }
    69  
    70  func (m *mockCompiler) AddSourceOffsetInfo(int64, ssa.SourceOffset) {}
    71  
    72  func (m *mockCompiler) AddRelocationInfo(funcRef ssa.FuncRef) {
    73  	m.relocs = append(m.relocs, backend.RelocationInfo{FuncRef: funcRef, Offset: int64(len(m.buf))})
    74  }
    75  
    76  func (m *mockCompiler) Emit4Bytes(b uint32) {
    77  	m.buf = append(m.buf, byte(b), byte(b>>8), byte(b>>16), byte(b>>24))
    78  }
    79  
    80  func (m *mockCompiler) Encode()     {}
    81  func (m *mockCompiler) Buf() []byte { return m.buf }
    82  func (m *mockCompiler) TypeOf(v regalloc.VReg) (ret ssa.Type) {
    83  	return m.typeOf[v.ID()]
    84  }
    85  func (m *mockCompiler) Finalize()      {}
    86  func (m *mockCompiler) RegAlloc()      {}
    87  func (m *mockCompiler) Lower()         {}
    88  func (m *mockCompiler) Format() string { return "" }
    89  func (m *mockCompiler) Init()          {}
    90  
    91  func newMockCompilationContext() *mockCompiler {
    92  	return &mockCompiler{
    93  		vRegMap:     make(map[ssa.Value]regalloc.VReg),
    94  		definitions: make(map[ssa.Value]*backend.SSAValueDefinition),
    95  		typeOf:      map[regalloc.VRegID]ssa.Type{},
    96  	}
    97  }
    98  
    99  // ResolveSignature implements backend.Compiler.
   100  func (m *mockCompiler) ResolveSignature(id ssa.SignatureID) *ssa.Signature {
   101  	return m.sigs[id]
   102  }
   103  
   104  // AllocateVReg implements backend.Compiler.
   105  func (m *mockCompiler) AllocateVReg(typ ssa.Type) regalloc.VReg {
   106  	m.vRegCounter++
   107  	regType := regalloc.RegTypeOf(typ)
   108  	ret := regalloc.VReg(m.vRegCounter).SetRegType(regType)
   109  	m.typeOf[ret.ID()] = typ
   110  	return ret
   111  }
   112  
   113  // ValueDefinition implements backend.Compiler.
   114  func (m *mockCompiler) ValueDefinition(value ssa.Value) *backend.SSAValueDefinition {
   115  	definition, exists := m.definitions[value]
   116  	if !exists {
   117  		return nil
   118  	}
   119  	return definition
   120  }
   121  
   122  // VRegOf implements backend.Compiler.
   123  func (m *mockCompiler) VRegOf(value ssa.Value) regalloc.VReg {
   124  	vReg, exists := m.vRegMap[value]
   125  	if !exists {
   126  		panic("Value does not exist")
   127  	}
   128  	return vReg
   129  }
   130  
   131  // MatchInstr implements backend.Compiler.
   132  func (m *mockCompiler) MatchInstr(def *backend.SSAValueDefinition, opcode ssa.Opcode) bool {
   133  	instr := def.Instr
   134  	return def.IsFromInstr() &&
   135  		instr.Opcode() == opcode &&
   136  		instr.GroupID() == m.currentGID &&
   137  		def.RefCount < 2
   138  }
   139  
   140  // MatchInstrOneOf implements backend.Compiler.
   141  func (m *mockCompiler) MatchInstrOneOf(def *backend.SSAValueDefinition, opcodes []ssa.Opcode) ssa.Opcode {
   142  	for _, opcode := range opcodes {
   143  		if m.MatchInstr(def, opcode) {
   144  			return opcode
   145  		}
   146  	}
   147  	return ssa.OpcodeInvalid
   148  }
   149  
   150  // Compile implements backend.Compiler.
   151  func (m *mockCompiler) Compile(context.Context) (_ []byte, _ []backend.RelocationInfo, _ error) {
   152  	return
   153  }