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

     1  package backend
     2  
     3  import (
     4  	"github.com/wasilibs/wazerox/internal/engine/wazevo/backend/regalloc"
     5  	"github.com/wasilibs/wazerox/internal/engine/wazevo/ssa"
     6  	"github.com/wasilibs/wazerox/internal/engine/wazevo/wazevoapi"
     7  )
     8  
     9  type (
    10  	// Machine is a backend for a specific ISA machine.
    11  	Machine interface {
    12  		// DisableStackCheck disables the stack check for the current compilation for debugging/testing.
    13  		DisableStackCheck()
    14  
    15  		// RegisterInfo returns the set of registers that can be used for register allocation.
    16  		// This is only called once, and the result is shared across all compilations.
    17  		RegisterInfo() *regalloc.RegisterInfo
    18  
    19  		// InitializeABI initializes the FunctionABI for the given signature.
    20  		InitializeABI(sig *ssa.Signature)
    21  
    22  		// ABI returns the FunctionABI used for the currently compiled function.
    23  		ABI() FunctionABI
    24  
    25  		// SetCompiler sets the compilation context used for the lifetime of Machine.
    26  		// This is only called once per Machine, i.e. before the first compilation.
    27  		SetCompiler(Compiler)
    28  
    29  		// StartLoweringFunction is called when the lowering of the given function is started.
    30  		// maximumBlockID is the maximum value of ssa.BasicBlockID existing in the function.
    31  		StartLoweringFunction(maximumBlockID ssa.BasicBlockID)
    32  
    33  		// StartBlock is called when the compilation of the given block is started.
    34  		// The order of this being called is the reverse post order of the ssa.BasicBlock(s) as we iterate with
    35  		// ssa.Builder BlockIteratorReversePostOrderBegin and BlockIteratorReversePostOrderEnd.
    36  		StartBlock(ssa.BasicBlock)
    37  
    38  		// LowerSingleBranch is called when the compilation of the given single branch is started.
    39  		LowerSingleBranch(b *ssa.Instruction)
    40  
    41  		// LowerConditionalBranch is called when the compilation of the given conditional branch is started.
    42  		LowerConditionalBranch(b *ssa.Instruction)
    43  
    44  		// LowerInstr is called for each instruction in the given block except for the ones marked as already lowered
    45  		// via Compiler.MarkLowered. The order is reverse, i.e. from the last instruction to the first one.
    46  		//
    47  		// Note: this can lower multiple instructions (which produce the inputs) at once whenever it's possible
    48  		// for optimization.
    49  		LowerInstr(*ssa.Instruction)
    50  
    51  		// EndBlock is called when the compilation of the current block is finished.
    52  		EndBlock()
    53  
    54  		// LinkAdjacentBlocks is called after finished lowering all blocks in order to create one single instruction list.
    55  		LinkAdjacentBlocks(prev, next ssa.BasicBlock)
    56  
    57  		// EndLoweringFunction is called when the lowering of the current function is finished.
    58  		EndLoweringFunction()
    59  
    60  		// Reset resets the machine state for the next compilation.
    61  		Reset()
    62  
    63  		// FlushPendingInstructions flushes the pending instructions to the buffer.
    64  		// This will be called after the lowering of each SSA Instruction.
    65  		FlushPendingInstructions()
    66  
    67  		// InsertMove inserts a move instruction from src to dst whose type is typ.
    68  		InsertMove(dst, src regalloc.VReg, typ ssa.Type)
    69  
    70  		// InsertReturn inserts the return instruction to return from the current function.
    71  		InsertReturn()
    72  
    73  		// InsertLoadConstant inserts the instruction(s) to load the constant value into the given regalloc.VReg.
    74  		InsertLoadConstant(instr *ssa.Instruction, vr regalloc.VReg)
    75  
    76  		// Format returns the string representation of the currently compiled machine code.
    77  		// This is only for testing purpose.
    78  		Format() string
    79  
    80  		// Function returns the currently compiled state as regalloc.Function so that we can perform register allocation.
    81  		Function() regalloc.Function
    82  
    83  		// SetupPrologue inserts the prologue after register allocations.
    84  		SetupPrologue()
    85  
    86  		// SetupEpilogue inserts the epilogue after register allocations.
    87  		// This sets up the instructions for the inverse of SetupPrologue right before
    88  		SetupEpilogue()
    89  
    90  		// ResolveRelativeAddresses resolves the relative addresses after register allocations and prologue/epilogue setup.
    91  		// After this, the compiler is finally ready to emit machine code.
    92  		ResolveRelativeAddresses()
    93  
    94  		// ResolveRelocations resolves the relocations after emitting machine code.
    95  		ResolveRelocations(refToBinaryOffset map[ssa.FuncRef]int, binary []byte, relocations []RelocationInfo)
    96  
    97  		// Encode encodes the machine instructions to the Compiler.
    98  		Encode()
    99  
   100  		// CompileGoFunctionTrampoline compiles the trampoline function  to call a Go function of the given exit code and signature.
   101  		CompileGoFunctionTrampoline(exitCode wazevoapi.ExitCode, sig *ssa.Signature, needModuleContextPtr bool) []byte
   102  
   103  		// CompileStackGrowCallSequence returns the sequence of instructions shared by all functions to
   104  		// call the stack grow builtin function.
   105  		CompileStackGrowCallSequence() []byte
   106  
   107  		// CompileEntryPreamble returns the sequence of instructions shared by multiple functions to
   108  		// enter the function from Go.
   109  		CompileEntryPreamble(signature *ssa.Signature) []byte
   110  	}
   111  )