github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/internal/engine/wazevo/backend/regalloc/api_test.go (about)

     1  package regalloc
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  )
     7  
     8  // Following mock types are used for testing.
     9  type (
    10  	// mockFunction implements Function.
    11  	mockFunction struct {
    12  		iter            int
    13  		blocks          []*mockBlock
    14  		befores, afters []storeOrReloadInfo
    15  		lnfRoots        []*mockBlock
    16  	}
    17  
    18  	storeOrReloadInfo struct {
    19  		reload bool
    20  		v      VReg
    21  		instr  Instr
    22  	}
    23  
    24  	// mockBlock implements Block.
    25  	mockBlock struct {
    26  		id             int
    27  		instructions   []*mockInstr
    28  		preds, succs   []*mockBlock
    29  		_preds, _succs []Block
    30  		iter           int
    31  		_entry         bool
    32  		_loop          bool
    33  		lnfChildren    []*mockBlock
    34  		blockParams    []VReg
    35  	}
    36  
    37  	// mockInstr implements Instr.
    38  	mockInstr struct {
    39  		defs, uses                 []VReg
    40  		isCopy, isCall, isIndirect bool
    41  	}
    42  )
    43  
    44  func (m *mockFunction) LowestCommonAncestor(blk1, blk2 Block) Block { panic("TODO") }
    45  
    46  func (m *mockFunction) Idom(blk Block) Block { panic("TODO") }
    47  
    48  func (m *mockFunction) SwapAtEndOfBlock(x1, x2, tmp VReg, block Block) { panic("TODO") }
    49  
    50  func (m *mockFunction) InsertMoveBefore(dst, src VReg, instr Instr) { panic("TODO") }
    51  
    52  func newMockFunction(blocks ...*mockBlock) *mockFunction {
    53  	return &mockFunction{blocks: blocks}
    54  }
    55  
    56  func (m *mockFunction) loopNestingForestRoots(blocks ...*mockBlock) {
    57  	m.lnfRoots = blocks
    58  }
    59  
    60  func newMockBlock(id int, instructions ...*mockInstr) *mockBlock {
    61  	return &mockBlock{id: id, instructions: instructions}
    62  }
    63  
    64  func newMockInstr() *mockInstr {
    65  	return &mockInstr{}
    66  }
    67  
    68  // String implements fmt.Stringer for debugging.
    69  func (m *mockFunction) String() string {
    70  	var block []string
    71  	for _, b := range m.blocks {
    72  		block = append(block, "\t"+b.String())
    73  	}
    74  	return fmt.Sprintf("mockFunction:\n%s", strings.Join(block, ",\n"))
    75  }
    76  
    77  // String implements fmt.Stringer for debugging.
    78  func (m *mockInstr) String() string {
    79  	return fmt.Sprintf("mockInstr{defs=%v, uses=%v}", m.defs, m.uses)
    80  }
    81  
    82  // String implements fmt.Stringer for debugging.
    83  func (m *mockBlock) String() string {
    84  	var preds []int
    85  	for _, p := range m.preds {
    86  		preds = append(preds, p.id)
    87  	}
    88  	return fmt.Sprintf("mockBlock{\n\tid=%v,\n\tinstructions=%v,\n\tpreds=%v,\n}", m.id, preds, m.instructions)
    89  }
    90  
    91  func (m *mockBlock) addPred(b *mockBlock) {
    92  	m.preds = append(m.preds, b)
    93  	m._preds = append(m._preds, b)
    94  	b._succs = append(b._succs, m)
    95  	b.succs = append(b.succs, m)
    96  }
    97  
    98  func (m *mockInstr) use(uses ...VReg) *mockInstr {
    99  	m.uses = uses
   100  	return m
   101  }
   102  
   103  func (m *mockInstr) def(defs ...VReg) *mockInstr {
   104  	m.defs = defs
   105  	return m
   106  }
   107  
   108  func (m *mockBlock) loop(children ...*mockBlock) *mockBlock {
   109  	m._loop = true
   110  	m.lnfChildren = children
   111  	return m
   112  }
   113  
   114  func (m *mockBlock) entry() *mockBlock {
   115  	m._entry = true
   116  	return m
   117  }
   118  
   119  func (m *mockInstr) asCopy() *mockInstr {
   120  	m.isCopy = true
   121  	return m
   122  }
   123  
   124  func (m *mockInstr) asCall() *mockInstr { //nolint:unused
   125  	m.isCall = true
   126  	return m
   127  }
   128  
   129  func (m *mockInstr) asIndirectCall() *mockInstr { //nolint:unused
   130  	m.isIndirect = true
   131  	return m
   132  }
   133  
   134  // StoreRegisterAfter implements Function.StoreRegisterAfter.
   135  func (m *mockFunction) StoreRegisterAfter(v VReg, instr Instr) {
   136  	m.afters = append(m.afters, storeOrReloadInfo{false, v, instr})
   137  }
   138  
   139  // ReloadRegisterBefore implements Function.ReloadRegisterBefore.
   140  func (m *mockFunction) ReloadRegisterBefore(v VReg, instr Instr) {
   141  	m.befores = append(m.befores, storeOrReloadInfo{true, v, instr})
   142  }
   143  
   144  // StoreRegisterBefore implements Function.StoreRegisterBefore.
   145  func (m *mockFunction) StoreRegisterBefore(v VReg, instr Instr) {
   146  	m.befores = append(m.befores, storeOrReloadInfo{false, v, instr})
   147  }
   148  
   149  // ReloadRegisterAfter implements Function.ReloadRegisterAfter.
   150  func (m *mockFunction) ReloadRegisterAfter(v VReg, instr Instr) {
   151  	m.afters = append(m.afters, storeOrReloadInfo{true, v, instr})
   152  }
   153  
   154  // ClobberedRegisters implements Function.ClobberedRegisters.
   155  func (m *mockFunction) ClobberedRegisters(regs []VReg) {
   156  	// TODO implement me
   157  	panic("implement me")
   158  }
   159  
   160  // Done implements Function.Done.
   161  func (m *mockFunction) Done() {}
   162  
   163  // PostOrderBlockIteratorBegin implements Block.
   164  func (m *mockFunction) PostOrderBlockIteratorBegin() Block {
   165  	m.iter = 1
   166  	l := len(m.blocks)
   167  	return m.blocks[l-1]
   168  }
   169  
   170  // PostOrderBlockIteratorNext implements Block.
   171  func (m *mockFunction) PostOrderBlockIteratorNext() Block {
   172  	if m.iter == len(m.blocks) {
   173  		return nil
   174  	}
   175  	l := len(m.blocks)
   176  	ret := m.blocks[l-m.iter-1]
   177  	m.iter++
   178  	return ret
   179  }
   180  
   181  // ReversePostOrderBlockIteratorBegin implements Block.
   182  func (m *mockFunction) ReversePostOrderBlockIteratorBegin() Block {
   183  	m.iter = 1
   184  	return m.blocks[0]
   185  }
   186  
   187  // ReversePostOrderBlockIteratorNext implements Block.
   188  func (m *mockFunction) ReversePostOrderBlockIteratorNext() Block {
   189  	if m.iter == len(m.blocks) {
   190  		return nil
   191  	}
   192  	ret := m.blocks[m.iter]
   193  	m.iter++
   194  	return ret
   195  }
   196  
   197  // ID implements Block.
   198  func (m *mockBlock) ID() int {
   199  	return m.id
   200  }
   201  
   202  // InstrIteratorBegin implements Block.
   203  func (m *mockBlock) InstrIteratorBegin() Instr {
   204  	if len(m.instructions) == 0 {
   205  		return nil
   206  	}
   207  	m.iter = 1
   208  	return m.instructions[0]
   209  }
   210  
   211  // InstrIteratorNext implements Block.
   212  func (m *mockBlock) InstrIteratorNext() Instr {
   213  	if m.iter == len(m.instructions) {
   214  		return nil
   215  	}
   216  	ret := m.instructions[m.iter]
   217  	m.iter++
   218  	return ret
   219  }
   220  
   221  // InstrRevIteratorBegin implements Block.
   222  func (m *mockBlock) InstrRevIteratorBegin() Instr {
   223  	if len(m.instructions) == 0 {
   224  		return nil
   225  	}
   226  	m.iter = len(m.instructions)
   227  	return m.InstrRevIteratorNext()
   228  }
   229  
   230  // InstrRevIteratorNext implements Block.
   231  func (m *mockBlock) InstrRevIteratorNext() Instr {
   232  	m.iter--
   233  	if m.iter < 0 {
   234  		return nil
   235  	}
   236  	return m.instructions[m.iter]
   237  }
   238  
   239  // Preds implements Block.
   240  func (m *mockBlock) Preds() int {
   241  	return len(m._preds)
   242  }
   243  
   244  // BlockParams implements Block.
   245  func (m *mockBlock) BlockParams(ret *[]VReg) []VReg {
   246  	*ret = append((*ret)[:0], m.blockParams...)
   247  	return *ret
   248  }
   249  
   250  func (m *mockBlock) blockParam(v VReg) {
   251  	m.blockParams = append(m.blockParams, v)
   252  }
   253  
   254  // Pred implements Instr.
   255  func (m *mockBlock) Pred(i int) Block { return m._preds[i] }
   256  
   257  // Defs implements Instr.
   258  func (m *mockInstr) Defs(ret *[]VReg) []VReg {
   259  	*ret = append((*ret)[:0], m.defs...)
   260  	return *ret
   261  }
   262  
   263  // Uses implements Instr.
   264  func (m *mockInstr) Uses(ret *[]VReg) []VReg {
   265  	*ret = append((*ret)[:0], m.uses...)
   266  	return *ret
   267  }
   268  
   269  // IsCopy implements Instr.
   270  func (m *mockInstr) IsCopy() bool { return m.isCopy }
   271  
   272  // IsCall implements Instr.
   273  func (m *mockInstr) IsCall() bool { return m.isCall }
   274  
   275  // IsIndirectCall implements Instr.
   276  func (m *mockInstr) IsIndirectCall() bool { return m.isIndirect }
   277  
   278  // IsReturn implements Instr.
   279  func (m *mockInstr) IsReturn() bool { return false }
   280  
   281  // Entry implements Entry.
   282  func (m *mockBlock) Entry() bool { return m._entry }
   283  
   284  // AssignUses implements Instr.
   285  func (m *mockInstr) AssignUse(index int, reg VReg) {
   286  	if index >= len(m.uses) {
   287  		m.uses = append(m.uses, make([]VReg, 5)...)
   288  	}
   289  	m.uses[index] = reg
   290  }
   291  
   292  // AssignDef implements Instr.
   293  func (m *mockInstr) AssignDef(reg VReg) {
   294  	m.defs = []VReg{reg}
   295  }
   296  
   297  var (
   298  	_ Function = (*mockFunction)(nil)
   299  	_ Block    = (*mockBlock)(nil)
   300  	_ Instr    = (*mockInstr)(nil)
   301  )
   302  
   303  func (m *mockFunction) LoopNestingForestRoots() int {
   304  	return len(m.lnfRoots)
   305  }
   306  
   307  func (m *mockFunction) LoopNestingForestRoot(i int) Block {
   308  	return m.lnfRoots[i]
   309  }
   310  
   311  func (m *mockBlock) LoopHeader() bool {
   312  	return m._loop
   313  }
   314  
   315  func (m *mockBlock) Succs() int {
   316  	return len(m.succs)
   317  }
   318  
   319  func (m *mockBlock) Succ(i int) Block {
   320  	return m.succs[i]
   321  }
   322  
   323  func (m *mockBlock) LoopNestingForestChildren() int {
   324  	return len(m.lnfChildren)
   325  }
   326  
   327  func (m *mockBlock) LoopNestingForestChild(i int) Block {
   328  	return m.lnfChildren[i]
   329  }
   330  
   331  func (m *mockBlock) LastInstr() Instr {
   332  	return m.instructions[len(m.instructions)-1]
   333  }
   334  
   335  func (m *mockBlock) FirstInstr() Instr {
   336  	return m.instructions[0]
   337  }