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 )