backend

package
v1.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 28, 2023 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package backend must be free of Wasm-specific concept. In other words, this package must not import internal/wasm package.

Index

Constants

View Source
const (
	// ABIArgKindReg represents an argument passed in a register.
	ABIArgKindReg = iota
	// ABIArgKindStack represents an argument passed in the stack.
	ABIArgKindStack
)

Variables

This section is empty.

Functions

This section is empty.

Types

type ABIArg

type ABIArg struct {
	// Index is the index of the argument.
	Index int
	// Kind is the kind of the argument.
	Kind ABIArgKind
	// Reg is valid if Kind == ABIArgKindReg.
	// This VReg must be based on RealReg.
	Reg regalloc.VReg
	// Offset is valid if Kind == ABIArgKindStack.
	// This is the offset from the beginning of either arg or ret stack slot.
	Offset int64
	// Type is the type of the argument.
	Type ssa.Type
}

ABIArg represents either argument or return value's location.

func (*ABIArg) String

func (a *ABIArg) String() string

String implements fmt.Stringer.

type ABIArgKind

type ABIArgKind byte

ABIArgKind is the kind of ABI argument.

func (ABIArgKind) String

func (a ABIArgKind) String() string

String implements fmt.Stringer.

type Compiler

type Compiler interface {
	// SSABuilder returns the ssa.Builder used by this compiler.
	SSABuilder() ssa.Builder

	// Compile executes the following steps:
	// 	1. Lower()
	// 	2. RegAlloc()
	// 	3. Finalize()
	// 	4. Encode()
	//
	// Each step can be called individually for testing purpose, therefore they are exposed in this interface too.
	//
	// The returned byte slices are the machine code and the relocation information for the machine code.
	// The caller is responsible for copying them immediately since the compiler may reuse the buffer.
	Compile(ctx context.Context) (_ []byte, _ []RelocationInfo, _ error)

	// Lower lowers the given ssa.Instruction to the machine-specific instructions.
	Lower()

	// RegAlloc performs the register allocation after Lower is called.
	RegAlloc()

	// Finalize performs the finalization of the compilation. This must be called after RegAlloc.
	Finalize(ctx context.Context)

	// Encode encodes the machine code to the buffer.
	Encode()

	// Buf returns the buffer of the encoded machine code. This is only used for testing purpose.
	Buf() []byte

	// Format returns the debug string of the current state of the compiler.
	Format() string

	// Init initializes the internal state of the compiler for the next compilation.
	Init()

	// AllocateVReg allocates a new virtual register of the given type.
	AllocateVReg(typ ssa.Type) regalloc.VReg

	// ValueDefinition returns the definition of the given value.
	ValueDefinition(ssa.Value) *SSAValueDefinition

	// VRegOf returns the virtual register of the given ssa.Value.
	VRegOf(value ssa.Value) regalloc.VReg

	// TypeOf returns the ssa.Type of the given virtual register.
	TypeOf(regalloc.VReg) ssa.Type

	// MatchInstr returns true if the given definition is from an instruction with the given opcode, the current group ID,
	// and a refcount of 1. That means, the instruction can be merged/swapped within the current instruction group.
	MatchInstr(def *SSAValueDefinition, opcode ssa.Opcode) bool

	// MatchInstrOneOf is the same as MatchInstr but for multiple opcodes. If it matches one of ssa.Opcode,
	// this returns the opcode. Otherwise, this returns ssa.OpcodeInvalid.
	//
	// Note: caller should be careful to avoid excessive allocation on opcodes slice.
	MatchInstrOneOf(def *SSAValueDefinition, opcodes []ssa.Opcode) ssa.Opcode

	// AddRelocationInfo appends the relocation information for the function reference at the current buffer offset.
	AddRelocationInfo(funcRef ssa.FuncRef)

	// AddSourceOffsetInfo appends the source offset information for the given offset.
	AddSourceOffsetInfo(executableOffset int64, sourceOffset ssa.SourceOffset)

	// SourceOffsetInfo returns the source offset information for the current buffer offset.
	SourceOffsetInfo() []SourceOffsetInfo

	// Emit4Bytes appends 4 bytes to the buffer. Used during the code emission.
	Emit4Bytes(b uint32)
}

Compiler is the backend of wazevo which takes ssa.Builder and Machine, use the information there to emit the final machine code.

func NewCompiler

func NewCompiler(ctx context.Context, mach Machine, builder ssa.Builder) Compiler

NewCompiler returns a new Compiler that can generate a machine code.

type FunctionABI

type FunctionABI interface {
	// CalleeGenFunctionArgsToVRegs generates instructions to move arguments to virtual registers.
	CalleeGenFunctionArgsToVRegs(regs []ssa.Value)
	// CalleeGenVRegsToFunctionReturns generates instructions to move virtual registers to a return value locations.
	CalleeGenVRegsToFunctionReturns(regs []ssa.Value)
}

FunctionABI represents an ABI for the specific target combined with the function signature.

type Machine

type Machine interface {
	// DisableStackCheck disables the stack check for the current compilation for debugging/testing.
	DisableStackCheck()

	// RegisterInfo returns the set of registers that can be used for register allocation.
	// This is only called once, and the result is shared across all compilations.
	RegisterInfo() *regalloc.RegisterInfo

	// InitializeABI initializes the FunctionABI for the given signature.
	InitializeABI(sig *ssa.Signature)

	// ABI returns the FunctionABI used for the currently compiled function.
	ABI() FunctionABI

	// SetCompiler sets the compilation context used for the lifetime of Machine.
	// This is only called once per Machine, i.e. before the first compilation.
	SetCompiler(Compiler)

	// StartLoweringFunction is called when the lowering of the given function is started.
	// maximumBlockID is the maximum value of ssa.BasicBlockID existing in the function.
	StartLoweringFunction(maximumBlockID ssa.BasicBlockID)

	// StartBlock is called when the compilation of the given block is started.
	// The order of this being called is the reverse post order of the ssa.BasicBlock(s) as we iterate with
	// ssa.Builder BlockIteratorReversePostOrderBegin and BlockIteratorReversePostOrderEnd.
	StartBlock(ssa.BasicBlock)

	// LowerSingleBranch is called when the compilation of the given single branch is started.
	LowerSingleBranch(b *ssa.Instruction)

	// LowerConditionalBranch is called when the compilation of the given conditional branch is started.
	LowerConditionalBranch(b *ssa.Instruction)

	// LowerInstr is called for each instruction in the given block except for the ones marked as already lowered
	// via Compiler.MarkLowered. The order is reverse, i.e. from the last instruction to the first one.
	//
	// Note: this can lower multiple instructions (which produce the inputs) at once whenever it's possible
	// for optimization.
	LowerInstr(*ssa.Instruction)

	// EndBlock is called when the compilation of the current block is finished.
	EndBlock()

	// LinkAdjacentBlocks is called after finished lowering all blocks in order to create one single instruction list.
	LinkAdjacentBlocks(prev, next ssa.BasicBlock)

	// EndLoweringFunction is called when the lowering of the current function is finished.
	EndLoweringFunction()

	// Reset resets the machine state for the next compilation.
	Reset()

	// FlushPendingInstructions flushes the pending instructions to the buffer.
	// This will be called after the lowering of each SSA Instruction.
	FlushPendingInstructions()

	// InsertMove inserts a move instruction from src to dst whose type is typ.
	InsertMove(dst, src regalloc.VReg, typ ssa.Type)

	// InsertReturn inserts the return instruction to return from the current function.
	InsertReturn()

	// InsertLoadConstant inserts the instruction(s) to load the constant value into the given regalloc.VReg.
	InsertLoadConstant(instr *ssa.Instruction, vr regalloc.VReg)

	// Format returns the string representation of the currently compiled machine code.
	// This is only for testing purpose.
	Format() string

	// Function returns the currently compiled state as regalloc.Function so that we can perform register allocation.
	Function() regalloc.Function

	// SetupPrologue inserts the prologue after register allocations.
	SetupPrologue()

	// SetupEpilogue inserts the epilogue after register allocations.
	// This sets up the instructions for the inverse of SetupPrologue right before
	SetupEpilogue()

	// ResolveRelativeAddresses resolves the relative addresses after register allocations and prologue/epilogue setup.
	// After this, the compiler is finally ready to emit machine code.
	ResolveRelativeAddresses(ctx context.Context)

	// ResolveRelocations resolves the relocations after emitting machine code.
	ResolveRelocations(refToBinaryOffset map[ssa.FuncRef]int, binary []byte, relocations []RelocationInfo)

	// Encode encodes the machine instructions to the Compiler.
	Encode()

	// CompileGoFunctionTrampoline compiles the trampoline function  to call a Go function of the given exit code and signature.
	CompileGoFunctionTrampoline(exitCode wazevoapi.ExitCode, sig *ssa.Signature, needModuleContextPtr bool) []byte

	// CompileStackGrowCallSequence returns the sequence of instructions shared by all functions to
	// call the stack grow builtin function.
	CompileStackGrowCallSequence() []byte

	// CompileEntryPreamble returns the sequence of instructions shared by multiple functions to
	// enter the function from Go.
	CompileEntryPreamble(signature *ssa.Signature) []byte
}

Machine is a backend for a specific ISA machine.

type RelocationInfo

type RelocationInfo struct {
	// Offset represents the offset from the beginning of the machine code of either a function or the entire module.
	Offset int64
	// Target is the target function of the call instruction.
	FuncRef ssa.FuncRef
}

RelocationInfo represents the relocation information for a call instruction.

type SSAValueDefinition

type SSAValueDefinition struct {
	// BlockParamValue is valid if Instr == nil
	BlockParamValue ssa.Value

	// BlkParamVReg is valid if Instr == nil
	BlkParamVReg regalloc.VReg

	// Instr is not nil if this is a definition from an instruction.
	Instr *ssa.Instruction
	// N is the index of the return value in the instr's return values list.
	N int
	// RefCount is the number of references to the result.
	RefCount int
}

SSAValueDefinition represents a definition of an SSA value.

func (*SSAValueDefinition) IsFromBlockParam

func (d *SSAValueDefinition) IsFromBlockParam() bool

func (*SSAValueDefinition) IsFromInstr

func (d *SSAValueDefinition) IsFromInstr() bool

func (*SSAValueDefinition) SSAValue

func (d *SSAValueDefinition) SSAValue() ssa.Value

type SourceOffsetInfo

type SourceOffsetInfo struct {
	// SourceOffset is the source offset in the original source code.
	SourceOffset ssa.SourceOffset
	// ExecutableOffset is the offset in the compiled executable.
	ExecutableOffset int64
}

SourceOffsetInfo is a data to associate the source offset with the executable offset.

Directories

Path Synopsis
isa
Package regalloc performs register allocation.
Package regalloc performs register allocation.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL