Documentation
¶
Overview ¶
Package ssa is used to construct SSA function. By nature this is free of Wasm specific thing and ISA.
We use the "block argument" variant of SSA: https://en.wikipedia.org/wiki/Static_single-assignment_form#Block_arguments which is equivalent to the traditional PHI function based one, but more convenient during optimizations. However, in this package's source code comment, we might use PHI whenever it seems necessary in order to be aligned with existing literatures, e.g. SSA level optimization algorithms are often described using PHI nodes.
The rationale doc for the choice of "block argument" by MLIR of LLVM is worth a read: https://mlir.llvm.org/docs/Rationale/Rationale/#block-arguments-vs-phi-nodes
The algorithm to resolve variable definitions used here is based on the paper "Simple and Efficient Construction of Static Single Assignment Form": https://link.springer.com/content/pdf/10.1007/978-3-642-37051-9_6.pdf.
Index ¶
- type BasicBlock
- type BasicBlockID
- type Builder
- type FloatCmpCond
- type FuncRef
- type Instruction
- func (i *Instruction) Arg() Value
- func (i *Instruction) Arg2() (Value, Value)
- func (i *Instruction) Args() (v1, v2, v3 Value, vs []Value)
- func (i *Instruction) AsBrTable(index Value, targets []BasicBlock)
- func (i *Instruction) AsBrnz(v Value, args []Value, target BasicBlock)
- func (i *Instruction) AsBrz(v Value, args []Value, target BasicBlock)
- func (i *Instruction) AsCall(ref FuncRef, sig *Signature, args []Value)
- func (i *Instruction) AsCallIndirect(funcPtr Value, sig *Signature, args []Value)
- func (i *Instruction) AsClz(x Value)
- func (i *Instruction) AsCtz(x Value)
- func (i *Instruction) AsExitIfTrueWithCode(ctx, c Value, code wazevoapi.ExitCode)
- func (i *Instruction) AsExitWithCode(ctx Value, code wazevoapi.ExitCode)
- func (i *Instruction) AsExtLoad(op Opcode, ptr Value, offset uint32, dst64bit bool)
- func (i *Instruction) AsF32const(f float32) *Instruction
- func (i *Instruction) AsF64const(f float64) *Instruction
- func (i *Instruction) AsFadd(x, y Value)
- func (i *Instruction) AsFallthroughJump()
- func (i *Instruction) AsFcmp(x, y Value, c FloatCmpCond)
- func (i *Instruction) AsFcvtFromInt(x Value, signed bool, dst64bit bool)
- func (i *Instruction) AsFdiv(x, y Value)
- func (i *Instruction) AsFmax(x, y Value)
- func (i *Instruction) AsFmin(x, y Value)
- func (i *Instruction) AsFmul(x, y Value)
- func (i *Instruction) AsFneg(x Value)
- func (i *Instruction) AsFpromote(x Value)
- func (i *Instruction) AsFsub(x, y Value)
- func (i *Instruction) AsIadd(x, y Value) *Instruction
- func (i *Instruction) AsIcmp(x, y Value, c IntegerCmpCond) *Instruction
- func (i *Instruction) AsIconst32(v uint32) *Instruction
- func (i *Instruction) AsIconst64(v uint64) *Instruction
- func (i *Instruction) AsImul(x, y Value)
- func (i *Instruction) AsIreduce(v Value, dstType Type) *Instruction
- func (i *Instruction) AsIshl(x, amount Value)
- func (i *Instruction) AsIsub(x, y Value) *Instruction
- func (i *Instruction) AsJump(vs []Value, target BasicBlock)
- func (i *Instruction) AsLoad(ptr Value, offset uint32, typ Type)
- func (i *Instruction) AsPopcnt(x Value)
- func (i *Instruction) AsReturn(vs []Value) *Instruction
- func (i *Instruction) AsSExtend(v Value, from, to byte)
- func (i *Instruction) AsSelect(c, x, y Value)
- func (i *Instruction) AsSshr(x, amount Value)
- func (i *Instruction) AsStore(storeOp Opcode, value, ptr Value, offset uint32)
- func (i *Instruction) AsUExtend(v Value, from, to byte)
- func (i *Instruction) AsUshr(x, amount Value)
- func (i *Instruction) BinaryData() (x, y Value)
- func (i *Instruction) BrTableData() (index Value, targets []BasicBlock)
- func (i *Instruction) BranchData() (condVal Value, blockArgs []Value, target BasicBlock)
- func (i *Instruction) CallData() (ref FuncRef, sigID SignatureID, args []Value)
- func (i *Instruction) CallIndirectData() (funcPtr Value, sigID SignatureID, args []Value)
- func (i *Instruction) Constant() bool
- func (i *Instruction) ConstantVal() (ret uint64)
- func (i *Instruction) ExitIfTrueWithCodeData() (ctx, c Value, code wazevoapi.ExitCode)
- func (i *Instruction) ExitWithCodeData() (ctx Value, code wazevoapi.ExitCode)
- func (i *Instruction) ExtendData() (from, to byte, signed bool)
- func (i *Instruction) ExtendFromToBits() (from, to byte)
- func (i *Instruction) FcmpData() (x, y Value, c FloatCmpCond)
- func (i *Instruction) Format(b Builder) string
- func (i *Instruction) GroupID() InstructionGroupID
- func (i *Instruction) HasSideEffects() bool
- func (i *Instruction) IcmpData() (x, y Value, c IntegerCmpCond)
- func (i *Instruction) Insert(b Builder) *Instruction
- func (i *Instruction) InvertBrx()
- func (i *Instruction) IsBranching() bool
- func (i *Instruction) IsFallthroughJump() bool
- func (i *Instruction) LoadData() (ptr Value, offset uint32, typ Type)
- func (i *Instruction) Next() *Instruction
- func (i *Instruction) Opcode() Opcode
- func (i *Instruction) Prev() *Instruction
- func (i *Instruction) Return() (first Value)
- func (i *Instruction) ReturnVals() []Value
- func (i *Instruction) Returns() (first Value, rest []Value)
- func (i *Instruction) SelectData() (c, x, y Value)
- func (i *Instruction) StoreData() (value, ptr Value, offset uint32, storeSizeInBits byte)
- func (i *Instruction) UnaryData() Value
- type InstructionGroupID
- type IntegerCmpCond
- type Opcode
- type Signature
- type SignatureID
- type Type
- type Value
- type ValueID
- type Variable
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type BasicBlock ¶
type BasicBlock interface { // ID returns the unique ID of this block. ID() BasicBlockID // Name returns the unique string ID of this block. e.g. blk0, blk1, ... Name() string // AddParam adds the parameter to the block whose type specified by `t`. AddParam(b Builder, t Type) Value // Params returns the number of parameters to this block. Params() int // Param returns (Variable, Value) which corresponds to the i-th parameter of this block. // The returned Value is the definition of the param in this block. Param(i int) Value // InsertInstruction inserts an instruction that implements Value into the tail of this block. InsertInstruction(raw *Instruction) // Root returns the root instruction of this block. Root() *Instruction // Tail returns the tail instruction of this block. Tail() *Instruction // EntryBlock returns true if this block represents the function entry. EntryBlock() bool // ReturnBlock returns ture if this block represents the function return. ReturnBlock() bool // FormatHeader returns the debug string of this block, not including instruction. FormatHeader(b Builder) string // Valid is true if this block is still valid even after optimizations. Valid() bool // BeginPredIterator returns the first predecessor of this block. BeginPredIterator() BasicBlock // NextPredIterator returns the next predecessor of this block. NextPredIterator() BasicBlock // Preds returns the number of predecessors of this block. Preds() int }
BasicBlock represents the Basic Block of an SSA function. Each BasicBlock always ends with branching instructions (e.g. Branch, Return, etc.), and at most two branches are allowed. If there's two branches, these two are placed together at the end of the block. In other words, there's no branching instruction in the middle of the block.
Note: we use the "block argument" variant of SSA, instead of PHI functions. See the package level doc comments.
Note: we use "parameter/param" as a placeholder which represents a variant of PHI, and "argument/arg" as an actual Value passed to that "parameter/param".
type BasicBlockID ¶
type BasicBlockID uint32
BasicBlockID is the unique ID of a basicBlock.
func (BasicBlockID) String ¶
func (bid BasicBlockID) String() string
String implements fmt.Stringer for debugging.
type Builder ¶
type Builder interface { // Init must be called to reuse this builder for the next function. Init(typ *Signature) // Signature returns the Signature of the currently-compiled function. Signature() *Signature // Blocks returns the number of BasicBlocks(s) existing in the currently-compiled function. Blocks() int // AllocateBasicBlock creates a basic block in SSA function. AllocateBasicBlock() BasicBlock // CurrentBlock returns the currently handled BasicBlock which is set by the latest call to SetCurrentBlock. CurrentBlock() BasicBlock // SetCurrentBlock sets the instruction insertion target to the BasicBlock `b`. SetCurrentBlock(b BasicBlock) // DeclareVariable declares a Variable of the given Type. DeclareVariable(Type) Variable // DefineVariable defines a variable in the `block` with value. // The defining instruction will be inserted into the `block`. DefineVariable(variable Variable, value Value, block BasicBlock) // DefineVariableInCurrentBB is the same as DefineVariable except the definition is // inserted into the current BasicBlock. Alias to DefineVariable(x, y, CurrentBlock()). DefineVariableInCurrentBB(variable Variable, value Value) // AllocateInstruction returns a new Instruction. AllocateInstruction() *Instruction // InsertInstruction executes BasicBlock.InsertInstruction for the currently handled basic block. InsertInstruction(raw *Instruction) // MustFindValue searches the latest definition of the given Variable and returns the result. MustFindValue(variable Variable) Value // FindValue is the same as FindValue except that if the Value is not defined anywhere yet, // the given callback `create` is called to create a new Value. FindValue(variable Variable) Value // Seal declares that we've known all the predecessors to this block and were added via AddPred. // After calling this, AddPred will be forbidden. Seal(blk BasicBlock) // AnnotateValue is for debugging purpose. AnnotateValue(value Value, annotation string) // DeclareSignature appends the *Signature to be referenced by various instructions (e.g. OpcodeCall). DeclareSignature(signature *Signature) // UsedSignatures returns the slice of Signatures which are used/referenced by the currently-compiled function. UsedSignatures() []*Signature // ResolveSignature returns the Signature which corresponds to SignatureID. ResolveSignature(id SignatureID) *Signature // RunPasses runs various passes on the constructed SSA function. RunPasses() // Format returns the debugging string of the SSA function. Format() string // BlockIteratorBegin initializes the state to iterate over all the valid BasicBlock(s) compiled. // Combined with BlockIteratorNext, we can use this like: // // for blk := builder.BlockIteratorBegin(); blk != nil; blk = builder.BlockIteratorNext() { // // ... // } // // The returned blocks are ordered in the order of AllocateBasicBlock being called. BlockIteratorBegin() BasicBlock // BlockIteratorNext advances the state for iteration initialized by BlockIteratorBegin. // Returns nil if there's no unseen BasicBlock. BlockIteratorNext() BasicBlock // ValueRefCounts returns the map of ValueID to its reference count. // The returned slice must not be modified. ValueRefCounts() []int // LayoutBlocks layouts the BasicBlock(s) so that backend can easily generate the code. // During its process, it splits the critical edges in the function. // This must be called after RunPasses. Otherwise, it panics. // // The resulting order is available via BlockIteratorReversePostOrderBegin and BlockIteratorReversePostOrderNext. LayoutBlocks() // BlockIteratorReversePostOrderBegin is almost the same as BlockIteratorBegin except it returns the BasicBlock in the reverse post-order. // This is available after RunPasses is run. BlockIteratorReversePostOrderBegin() BasicBlock // BlockIteratorReversePostOrderNext is almost the same as BlockIteratorPostOrderNext except it returns the BasicBlock in the reverse post-order. // This is available after RunPasses is run. BlockIteratorReversePostOrderNext() BasicBlock // ReturnBlock returns the BasicBlock which is used to return from the function. ReturnBlock() BasicBlock // InsertUndefined inserts an undefined instruction at the current position. InsertUndefined() // contains filtered or unexported methods }
Builder is used to builds SSA consisting of Basic Blocks per function.
type FloatCmpCond ¶
type FloatCmpCond byte
const ( // FloatCmpCondInvalid represents an invalid condition. FloatCmpCondInvalid FloatCmpCond = iota // FloatCmpCondEqual represents "==". FloatCmpCondEqual // FloatCmpCondNotEqual represents "!=". FloatCmpCondNotEqual // FloatCmpCondLessThan represents "<". FloatCmpCondLessThan // FloatCmpCondLessThanOrEqual represents "<=". FloatCmpCondLessThanOrEqual // FloatCmpCondGreaterThan represents ">". FloatCmpCondGreaterThan // FloatCmpCondGreaterThanOrEqual represents ">=". FloatCmpCondGreaterThanOrEqual )
type FuncRef ¶
type FuncRef uint32
FuncRef is a unique identifier for a function of the frontend, and is used to reference the function in function call.
type Instruction ¶
type Instruction struct {
// contains filtered or unexported fields
}
Instruction represents an instruction whose opcode is specified by Opcode. Since Go doesn't have union type, we use this flattened type for all instructions, and therefore each field has different meaning depending on Opcode.
func (*Instruction) Arg ¶
func (i *Instruction) Arg() Value
Arg returns the first argument to this instruction.
func (*Instruction) Arg2 ¶
func (i *Instruction) Arg2() (Value, Value)
Arg2 returns the first two argument2 to this instruction.
func (*Instruction) Args ¶
func (i *Instruction) Args() (v1, v2, v3 Value, vs []Value)
Args returns the arguments to this instruction.
func (*Instruction) AsBrTable ¶
func (i *Instruction) AsBrTable(index Value, targets []BasicBlock)
AsBrTable initializes this instruction as a branch-table instruction with OpcodeBrTable.
func (*Instruction) AsBrnz ¶
func (i *Instruction) AsBrnz(v Value, args []Value, target BasicBlock)
AsBrnz initializes this instruction as a branch-if-not-zero instruction with OpcodeBrnz.
func (*Instruction) AsBrz ¶
func (i *Instruction) AsBrz(v Value, args []Value, target BasicBlock)
AsBrz initializes this instruction as a branch-if-zero instruction with OpcodeBrz.
func (*Instruction) AsCall ¶
func (i *Instruction) AsCall(ref FuncRef, sig *Signature, args []Value)
AsCall initializes this instruction as a call instruction with OpcodeCall.
func (*Instruction) AsCallIndirect ¶
func (i *Instruction) AsCallIndirect(funcPtr Value, sig *Signature, args []Value)
AsCallIndirect initializes this instruction as a call-indirect instruction with OpcodeCallIndirect.
func (*Instruction) AsClz ¶
func (i *Instruction) AsClz(x Value)
AsClz initializes this instruction as a Count Leading Zeroes instruction with OpcodeClz.
func (*Instruction) AsCtz ¶
func (i *Instruction) AsCtz(x Value)
AsCtz initializes this instruction as a Count Trailing Zeroes instruction with OpcodeCtz.
func (*Instruction) AsExitIfTrueWithCode ¶
func (i *Instruction) AsExitIfTrueWithCode(ctx, c Value, code wazevoapi.ExitCode)
AsExitIfTrueWithCode initializes this instruction as a trap instruction with OpcodeExitIfTrueWithCode.
func (*Instruction) AsExitWithCode ¶
func (i *Instruction) AsExitWithCode(ctx Value, code wazevoapi.ExitCode)
AsExitWithCode initializes this instruction as a trap instruction with OpcodeExitWithCode.
func (*Instruction) AsExtLoad ¶
func (i *Instruction) AsExtLoad(op Opcode, ptr Value, offset uint32, dst64bit bool)
AsExtLoad initializes this instruction as a store instruction with OpcodeLoad.
func (*Instruction) AsF32const ¶
func (i *Instruction) AsF32const(f float32) *Instruction
AsF32const initializes this instruction as a 32-bit floating-point constant instruction with OpcodeF32const.
func (*Instruction) AsF64const ¶
func (i *Instruction) AsF64const(f float64) *Instruction
AsF64const initializes this instruction as a 64-bit floating-point constant instruction with OpcodeF64const.
func (*Instruction) AsFadd ¶
func (i *Instruction) AsFadd(x, y Value)
AsFadd initializes this instruction as a floating-point addition instruction with OpcodeFadd.
func (*Instruction) AsFallthroughJump ¶
func (i *Instruction) AsFallthroughJump()
AsFallthroughJump marks this instruction as a fallthrough jump.
func (*Instruction) AsFcmp ¶
func (i *Instruction) AsFcmp(x, y Value, c FloatCmpCond)
AsFcmp initializes this instruction as an integer comparison instruction with OpcodeFcmp.
func (*Instruction) AsFcvtFromInt ¶
func (i *Instruction) AsFcvtFromInt(x Value, signed bool, dst64bit bool)
AsFcvtFromInt initializes this instruction as an instruction with either OpcodeFcvtFromUint or OpcodeFcvtFromSint
func (*Instruction) AsFdiv ¶
func (i *Instruction) AsFdiv(x, y Value)
AsFdiv initializes this instruction as a floating-point division instruction with OpcodeFdiv.
func (*Instruction) AsFmax ¶
func (i *Instruction) AsFmax(x, y Value)
AsFmax initializes this instruction to take the maximum of two floating-points with OpcodeFmax.
func (*Instruction) AsFmin ¶
func (i *Instruction) AsFmin(x, y Value)
AsFmin initializes this instruction to take the minimum of two floating-points with OpcodeFmin.
func (*Instruction) AsFmul ¶
func (i *Instruction) AsFmul(x, y Value)
AsFmul initializes this instruction as a floating-point multiplication instruction with OpcodeFmul.
func (*Instruction) AsFneg ¶
func (i *Instruction) AsFneg(x Value)
AsFneg initializes this instruction as an instruction with OpcodeFneg.
func (*Instruction) AsFpromote ¶
func (i *Instruction) AsFpromote(x Value)
AsFpromote initializes this instruction as an instruction with OpcodeFpromote.
func (*Instruction) AsFsub ¶
func (i *Instruction) AsFsub(x, y Value)
AsFsub initializes this instruction as a floating-point subtraction instruction with OpcodeFsub.
func (*Instruction) AsIadd ¶
func (i *Instruction) AsIadd(x, y Value) *Instruction
AsIadd initializes this instruction as an integer addition instruction with OpcodeIadd.
func (*Instruction) AsIcmp ¶
func (i *Instruction) AsIcmp(x, y Value, c IntegerCmpCond) *Instruction
AsIcmp initializes this instruction as an integer comparison instruction with OpcodeIcmp.
func (*Instruction) AsIconst32 ¶
func (i *Instruction) AsIconst32(v uint32) *Instruction
AsIconst32 initializes this instruction as a 32-bit integer constant instruction with OpcodeIconst.
func (*Instruction) AsIconst64 ¶
func (i *Instruction) AsIconst64(v uint64) *Instruction
AsIconst64 initializes this instruction as a 64-bit integer constant instruction with OpcodeIconst.
func (*Instruction) AsImul ¶
func (i *Instruction) AsImul(x, y Value)
AsImul initializes this instruction as an integer addition instruction with OpcodeImul.
func (*Instruction) AsIreduce ¶
func (i *Instruction) AsIreduce(v Value, dstType Type) *Instruction
AsIreduce initializes this instruction as a reduction instruction with OpcodeIreduce.
func (*Instruction) AsIshl ¶
func (i *Instruction) AsIshl(x, amount Value)
AsIshl initializes this instruction as an integer shift left instruction with OpcodeIshl.
func (*Instruction) AsIsub ¶
func (i *Instruction) AsIsub(x, y Value) *Instruction
AsIsub initializes this instruction as an integer subtraction instruction with OpcodeIsub.
func (*Instruction) AsJump ¶
func (i *Instruction) AsJump(vs []Value, target BasicBlock)
AsJump initializes this instruction as a jump instruction with OpcodeJump.
func (*Instruction) AsLoad ¶
func (i *Instruction) AsLoad(ptr Value, offset uint32, typ Type)
AsLoad initializes this instruction as a store instruction with OpcodeLoad.
func (*Instruction) AsPopcnt ¶
func (i *Instruction) AsPopcnt(x Value)
AsPopcnt initializes this instruction as a Population Count instruction with OpcodePopcnt.
func (*Instruction) AsReturn ¶
func (i *Instruction) AsReturn(vs []Value) *Instruction
AsReturn initializes this instruction as a return instruction with OpcodeReturn.
func (*Instruction) AsSExtend ¶
func (i *Instruction) AsSExtend(v Value, from, to byte)
AsSExtend initializes this instruction as a sign extension instruction with OpcodeSExtend.
func (*Instruction) AsSelect ¶
func (i *Instruction) AsSelect(c, x, y Value)
AsSelect initializes this instruction as an unsigned extension instruction with OpcodeSelect.
func (*Instruction) AsSshr ¶
func (i *Instruction) AsSshr(x, amount Value)
AsSshr initializes this instruction as an integer signed shift right (arithmetic shift right) instruction with OpcodeSshr.
func (*Instruction) AsStore ¶
func (i *Instruction) AsStore(storeOp Opcode, value, ptr Value, offset uint32)
AsStore initializes this instruction as a store instruction with OpcodeStore.
func (*Instruction) AsUExtend ¶
func (i *Instruction) AsUExtend(v Value, from, to byte)
AsUExtend initializes this instruction as an unsigned extension instruction with OpcodeUExtend.
func (*Instruction) AsUshr ¶
func (i *Instruction) AsUshr(x, amount Value)
AsUshr initializes this instruction as an integer unsigned shift right (logical shift right) instruction with OpcodeUshr.
func (*Instruction) BinaryData ¶
func (i *Instruction) BinaryData() (x, y Value)
BinaryData return the operands for a binary instruction.
func (*Instruction) BrTableData ¶
func (i *Instruction) BrTableData() (index Value, targets []BasicBlock)
BrTableData returns the branch table data for this instruction necessary for backends.
func (*Instruction) BranchData ¶
func (i *Instruction) BranchData() (condVal Value, blockArgs []Value, target BasicBlock)
BranchData returns the branch data for this instruction necessary for backends.
func (*Instruction) CallData ¶
func (i *Instruction) CallData() (ref FuncRef, sigID SignatureID, args []Value)
CallData returns the call data for this instruction necessary for backends.
func (*Instruction) CallIndirectData ¶
func (i *Instruction) CallIndirectData() (funcPtr Value, sigID SignatureID, args []Value)
CallIndirectData returns the call indirect data for this instruction necessary for backends.
func (*Instruction) Constant ¶
func (i *Instruction) Constant() bool
Constant returns true if this instruction is a constant instruction.
func (*Instruction) ConstantVal ¶
func (i *Instruction) ConstantVal() (ret uint64)
ConstantVal returns the constant value of this instruction. How to interpret the return value depends on the opcode.
func (*Instruction) ExitIfTrueWithCodeData ¶
func (i *Instruction) ExitIfTrueWithCodeData() (ctx, c Value, code wazevoapi.ExitCode)
ExitIfTrueWithCodeData returns the context and exit code of OpcodeExitWithCode.
func (*Instruction) ExitWithCodeData ¶
func (i *Instruction) ExitWithCodeData() (ctx Value, code wazevoapi.ExitCode)
ExitWithCodeData returns the context and exit code of OpcodeExitWithCode.
func (*Instruction) ExtendData ¶
func (i *Instruction) ExtendData() (from, to byte, signed bool)
func (*Instruction) ExtendFromToBits ¶
func (i *Instruction) ExtendFromToBits() (from, to byte)
ExtendFromToBits returns the from and to bit size for the extension instruction.
func (*Instruction) FcmpData ¶
func (i *Instruction) FcmpData() (x, y Value, c FloatCmpCond)
FcmpData returns the operands and comparison condition of this floating-point comparison instruction.
func (*Instruction) Format ¶
func (i *Instruction) Format(b Builder) string
Format returns a string representation of this instruction with the given builder. For debugging purposes only.
func (*Instruction) GroupID ¶
func (i *Instruction) GroupID() InstructionGroupID
GroupID returns the InstructionGroupID of this instruction.
func (*Instruction) HasSideEffects ¶
func (i *Instruction) HasSideEffects() bool
HasSideEffects returns true if this instruction has side effects.
func (*Instruction) IcmpData ¶
func (i *Instruction) IcmpData() (x, y Value, c IntegerCmpCond)
IcmpData returns the operands and comparison condition of this integer comparison instruction.
func (*Instruction) Insert ¶
func (i *Instruction) Insert(b Builder) *Instruction
func (*Instruction) InvertBrx ¶
func (i *Instruction) InvertBrx()
InvertBrx inverts either OpcodeBrz or OpcodeBrnz to the other.
func (*Instruction) IsBranching ¶
func (i *Instruction) IsBranching() bool
IsBranching returns true if this instruction is a branching instruction.
func (*Instruction) IsFallthroughJump ¶
func (i *Instruction) IsFallthroughJump() bool
IsFallthroughJump returns true if this instruction is a fallthrough jump.
func (*Instruction) LoadData ¶
func (i *Instruction) LoadData() (ptr Value, offset uint32, typ Type)
LoadData returns the operands for a load instruction.
func (*Instruction) Next ¶
func (i *Instruction) Next() *Instruction
Next returns the next instruction laid out next to itself.
func (*Instruction) Opcode ¶
func (i *Instruction) Opcode() Opcode
Opcode returns the opcode of this instruction.
func (*Instruction) Prev ¶
func (i *Instruction) Prev() *Instruction
Prev returns the previous instruction laid out prior to itself.
func (*Instruction) Return ¶
func (i *Instruction) Return() (first Value)
Return returns a Value(s) produced by this instruction if any. If there's multiple return values, only the first one is returned.
func (*Instruction) ReturnVals ¶
func (i *Instruction) ReturnVals() []Value
ReturnVals returns the return values of OpcodeReturn.
func (*Instruction) Returns ¶
func (i *Instruction) Returns() (first Value, rest []Value)
Returns Value(s) produced by this instruction if any. The `first` is the first return value, and `rest` is the rest of the values.
func (*Instruction) SelectData ¶
func (i *Instruction) SelectData() (c, x, y Value)
SelectData returns the select data for this instruction necessary for backends.
func (*Instruction) StoreData ¶
func (i *Instruction) StoreData() (value, ptr Value, offset uint32, storeSizeInBits byte)
StoreData returns the operands for a store instruction.
func (*Instruction) UnaryData ¶
func (i *Instruction) UnaryData() Value
UnaryData return the operand for a unary instruction.
type InstructionGroupID ¶
type InstructionGroupID uint32
InstructionGroupID is assigned to each instruction and represents a group of instructions where each instruction is interchangeable with others except for the last instruction in the group which has side effects. In short, InstructionGroupID is determined by the side effects of instructions. That means, if there's an instruction with side effect between two instructions, then these two instructions will have different instructionGroupID. Note that each block always ends with branching, which is with side effects, therefore, instructions in different blocks always have different InstructionGroupID(s).
The notable application of this is used in lowering SSA-level instruction to a ISA specific instruction, where we eagerly try to merge multiple instructions into single operation etc. Such merging cannot be done if these instruction have different InstructionGroupID since it will change the semantics of a program.
See passDeadCodeElimination.
type IntegerCmpCond ¶
type IntegerCmpCond byte
IntegerCmpCond represents a condition for integer comparison.
const ( // IntegerCmpCondInvalid represents an invalid condition. IntegerCmpCondInvalid IntegerCmpCond = iota // IntegerCmpCondEqual represents "==". IntegerCmpCondEqual // IntegerCmpCondNotEqual represents "!=". IntegerCmpCondNotEqual // IntegerCmpCondSignedLessThan represents Signed "<". IntegerCmpCondSignedLessThan // IntegerCmpCondSignedGreaterThanOrEqual represents Signed ">=". IntegerCmpCondSignedGreaterThanOrEqual // IntegerCmpCondSignedGreaterThan represents Signed ">". IntegerCmpCondSignedGreaterThan // IntegerCmpCondSignedLessThanOrEqual represents Signed "<=". IntegerCmpCondSignedLessThanOrEqual // IntegerCmpCondUnsignedLessThan represents Unsigned "<". IntegerCmpCondUnsignedLessThan // IntegerCmpCondUnsignedGreaterThanOrEqual represents Unsigned ">=". IntegerCmpCondUnsignedGreaterThanOrEqual // IntegerCmpCondUnsignedGreaterThan represents Unsigned ">". IntegerCmpCondUnsignedGreaterThan // IntegerCmpCondUnsignedLessThanOrEqual represents Unsigned "<=". IntegerCmpCondUnsignedLessThanOrEqual )
func (IntegerCmpCond) Signed ¶
func (i IntegerCmpCond) Signed() bool
Signed returns true if the condition is signed integer comparison.
func (IntegerCmpCond) String ¶
func (i IntegerCmpCond) String() string
String implements fmt.Stringer.
type Opcode ¶
type Opcode uint32
Opcode represents a SSA instruction.
const ( OpcodeInvalid Opcode = iota // OpcodeUndefined is a placeholder for undefined opcode. This can be used for debugging to intentionally // cause a crash at certain point. OpcodeUndefined // OpcodeJump takes the list of args to the `block` and unconditionally jumps to it. OpcodeJump // OpcodeBrz branches into `blk` with `args` if the value `c` equals zero: `Brz c, blk, args`. OpcodeBrz // OpcodeBrnz branches into `blk` with `args` if the value `c` is not zero: `Brnz c, blk, args`. OpcodeBrnz // OpcodeBrTable takes the index value `index`, and branches into `labelX`. If the `index` is out of range, // it branches into the last labelN: `BrTable index, [label1, label2, ... labelN]`. OpcodeBrTable // OpcodeExitWithCode exit the execution immediately. OpcodeExitWithCode // OpcodeExitIfTrueWithCode exits the execution immediately if the value `c` is not zero. OpcodeExitIfTrueWithCode // OpcodeReturn returns from the function: `return rvalues`. OpcodeReturn // OpcodeCall calls a function specified by the symbol FN with arguments `args`: `returnvals = Call FN, args...` // This is a "near" call, which means the call target is known at compile time, and the target is relatively close // to this function. If the target cannot be reached by near call, the backend fails to compile. OpcodeCall // OpcodeCallIndirect calls a function specified by `callee` which is a function address: `returnvals = call_indirect SIG, callee, args`. // Note that this is different from call_indirect in Wasm, which also does type checking, etc. OpcodeCallIndirect // OpcodeFuncAddr ... // `addr = func_addr FN`. OpcodeFuncAddr // OpcodeSplat ... // `v = splat x`. OpcodeSplat // OpcodeSwizzle ... // `v = swizzle x, y`. OpcodeSwizzle // OpcodeInsertlane ... // `v = insertlane x, y, Idx`. (TernaryImm8) OpcodeInsertlane // OpcodeExtractlane ... // `v = extractlane x, Idx`. (BinaryImm8) OpcodeExtractlane // OpcodeSmin ... // `v = smin x, y`. OpcodeSmin // OpcodeUmin ... // `v = umin x, y`. OpcodeUmin // OpcodeSmax ... // `v = smax x, y`. OpcodeSmax // OpcodeUmax ... // `v = umax x, y`. OpcodeUmax // OpcodeAvgRound ... // `v = avg_round x, y`. OpcodeAvgRound // OpcodeUaddSat ... // `v = uadd_sat x, y`. OpcodeUaddSat // OpcodeSaddSat ... // `v = sadd_sat x, y`. OpcodeSaddSat // OpcodeUsubSat ... // `v = usub_sat x, y`. OpcodeUsubSat // OpcodeSsubSat ... // `v = ssub_sat x, y`. OpcodeSsubSat // OpcodeLoad loads a Type value from the [base + offset] address: `v = Load base, offset`. OpcodeLoad // OpcodeStore stores a Type value to the [base + offset] address: `Store v, base, offset`. OpcodeStore // OpcodeUload8 loads the 8-bit value from the [base + offset] address, zero-extended to 64 bits: `v = Uload8 base, offset`. OpcodeUload8 // OpcodeSload8 loads the 8-bit value from the [base + offset] address, sign-extended to 64 bits: `v = Sload8 base, offset`. OpcodeSload8 // OpcodeIstore8 stores the 8-bit value to the [base + offset] address, sign-extended to 64 bits: `Istore8 v, base, offset`. OpcodeIstore8 // OpcodeUload16 loads the 16-bit value from the [base + offset] address, zero-extended to 64 bits: `v = Uload16 base, offset`. OpcodeUload16 // OpcodeSload16 loads the 16-bit value from the [base + offset] address, sign-extended to 64 bits: `v = Sload16 base, offset`. OpcodeSload16 // OpcodeIstore16 stores the 16-bit value to the [base + offset] address, zero-extended to 64 bits: `Istore16 v, base, offset`. OpcodeIstore16 // OpcodeUload32 loads the 32-bit value from the [base + offset] address, zero-extended to 64 bits: `v = Uload32 base, offset`. OpcodeUload32 // OpcodeSload32 loads the 32-bit value from the [base + offset] address, sign-extended to 64 bits: `v = Sload32 base, offset`. OpcodeSload32 // OpcodeIstore32 stores the 32-bit value to the [base + offset] address, zero-extended to 64 bits: `Istore16 v, base, offset`. OpcodeIstore32 // OpcodeUload8x8 ... // `v = uload8x8 MemFlags, p, Offset`. OpcodeUload8x8 // OpcodeSload8x8 ... // `v = sload8x8 MemFlags, p, Offset`. OpcodeSload8x8 // OpcodeUload16x4 ... // `v = uload16x4 MemFlags, p, Offset`. OpcodeUload16x4 // OpcodeSload16x4 ... // `v = sload16x4 MemFlags, p, Offset`. OpcodeSload16x4 // OpcodeUload32x2 ... // `v = uload32x2 MemFlags, p, Offset`. OpcodeUload32x2 // OpcodeSload32x2 ... // `v = sload32x2 MemFlags, p, Offset`. OpcodeSload32x2 // OpcodeGlobalValue ... // `v = global_value GV`. OpcodeGlobalValue // OpcodeSymbolValue ... // `v = symbol_value GV`. OpcodeSymbolValue // OpcodeHeapAddr ... // `addr = heap_addr H, index, Offset, Size`. OpcodeHeapAddr // OpcodeHeapLoad ... // `v = heap_load heap_imm, index`. OpcodeHeapLoad // OpcodeHeapStore ... // `heap_store heap_imm, index, a`. OpcodeHeapStore // OpcodeGetReturnAddress ... // `addr = get_return_address`. OpcodeGetReturnAddress // OpcodeTableAddr ... // `addr = table_addr T, p, Offset`. OpcodeTableAddr // OpcodeIconst represents the integer const. OpcodeIconst // OpcodeF32const ... // `v = f32const N`. (UnaryIeee32) OpcodeF32const // OpcodeF64const ... // `v = f64const N`. (UnaryIeee64) OpcodeF64const // OpcodeVconst ... // `v = vconst N`. OpcodeVconst // OpcodeShuffle ... // `v = shuffle a, b, mask`. OpcodeShuffle // OpcodeNull ... // `v = null`. OpcodeNull // OpcodeNop ... // `nop`. OpcodeNop // OpcodeSelect chooses between two values based on a condition `c`: `v = Select c, x, y`. OpcodeSelect // OpcodeBitselect ... // `v = bitselect c, x, y`. OpcodeBitselect // OpcodeVsplit ... // `lo, hi = vsplit x`. OpcodeVsplit // OpcodeVconcat ... // `v = vconcat x, y`. OpcodeVconcat // OpcodeVselect ... // `v = vselect c, x, y`. OpcodeVselect // OpcodeVanyTrue ... // `s = vany_true a`. OpcodeVanyTrue // OpcodeVallTrue ... // `s = vall_true a`. OpcodeVallTrue // OpcodeVhighBits ... // `x = vhigh_bits a`. OpcodeVhighBits // OpcodeIcmp compares two integer values with the given condition: `v = icmp Cond, x, y`. OpcodeIcmp // OpcodeIcmpImm compares an integer value with the immediate value on the given condition: `v = icmp_imm Cond, x, Y`. OpcodeIcmpImm // OpcodeIadd performs an integer addition: `v = Iadd x, y`. OpcodeIadd // OpcodeIsub performs an integer subtraction: `v = Isub x, y`. OpcodeIsub // OpcodeIneg ... // `v = ineg x`. OpcodeIneg // OpcodeIabs ... // `v = iabs x`. OpcodeIabs // OpcodeImul performs an integer multiplication: `v = Imul x, y`. OpcodeImul // OpcodeUmulhi ... // `v = umulhi x, y`. OpcodeUmulhi // OpcodeSmulhi ... // `v = smulhi x, y`. OpcodeSmulhi // OpcodeSqmulRoundSat ... // `v = sqmul_round_sat x, y`. OpcodeSqmulRoundSat // OpcodeUdiv ... // `v = udiv x, y`. OpcodeUdiv // OpcodeSdiv ... // `v = sdiv x, y`. OpcodeSdiv // OpcodeUrem ... // `v = urem x, y`. OpcodeUrem // OpcodeSrem ... // `v = srem x, y`. OpcodeSrem // OpcodeIaddImm ... // `v = iadd_imm x, Y`. (BinaryImm64) OpcodeIaddImm // OpcodeImulImm ... // `v = imul_imm x, Y`. (BinaryImm64) OpcodeImulImm // OpcodeUdivImm ... // `v = udiv_imm x, Y`. (BinaryImm64) OpcodeUdivImm // OpcodeSdivImm ... // `v = sdiv_imm x, Y`. (BinaryImm64) OpcodeSdivImm // OpcodeUremImm ... // `v = urem_imm x, Y`. (BinaryImm64) OpcodeUremImm // OpcodeSremImm ... // `v = srem_imm x, Y`. (BinaryImm64) OpcodeSremImm // OpcodeIrsubImm ... // `v = irsub_imm x, Y`. (BinaryImm64) OpcodeIrsubImm // OpcodeIaddCin ... // `v = iadd_cin x, y, c_in`. OpcodeIaddCin // OpcodeIaddIfcin ... // `v = iadd_ifcin x, y, c_in`. OpcodeIaddIfcin // OpcodeIaddCout ... // `a, c_out = iadd_cout x, y`. OpcodeIaddCout // OpcodeIaddIfcout ... // `a, c_out = iadd_ifcout x, y`. OpcodeIaddIfcout // OpcodeIaddCarry ... // `a, c_out = iadd_carry x, y, c_in`. OpcodeIaddCarry // OpcodeIaddIfcarry ... // `a, c_out = iadd_ifcarry x, y, c_in`. OpcodeIaddIfcarry // OpcodeUaddOverflowTrap ... // `v = uadd_overflow_trap x, y, code`. OpcodeUaddOverflowTrap // OpcodeIsubBin ... // `v = isub_bin x, y, b_in`. OpcodeIsubBin // OpcodeIsubIfbin ... // `v = isub_ifbin x, y, b_in`. OpcodeIsubIfbin // OpcodeIsubBout ... // `a, b_out = isub_bout x, y`. OpcodeIsubBout // OpcodeIsubIfbout ... // `a, b_out = isub_ifbout x, y`. OpcodeIsubIfbout // OpcodeIsubBorrow ... // `a, b_out = isub_borrow x, y, b_in`. OpcodeIsubBorrow // OpcodeIsubIfborrow ... // `a, b_out = isub_ifborrow x, y, b_in`. OpcodeIsubIfborrow // OpcodeBand ... // `v = band x, y`. OpcodeBand // OpcodeBor ... // `v = bor x, y`. OpcodeBor // OpcodeBxor ... // `v = bxor x, y`. OpcodeBxor // OpcodeBnot ... // `v = bnot x`. OpcodeBnot // OpcodeBandNot ... // `v = band_not x, y`. OpcodeBandNot // OpcodeBorNot ... // `v = bor_not x, y`. OpcodeBorNot // OpcodeBxorNot ... // `v = bxor_not x, y`. OpcodeBxorNot // OpcodeBandImm ... // `v = band_imm x, Y`. (BinaryImm64) OpcodeBandImm // OpcodeBorImm ... // `v = bor_imm x, Y`. (BinaryImm64) OpcodeBorImm // OpcodeBxorImm ... // `v = bxor_imm x, Y`. (BinaryImm64) OpcodeBxorImm // OpcodeRotl ... // `v = rotl x, y`. OpcodeRotl // OpcodeRotr ... // `v = rotr x, y`. OpcodeRotr // OpcodeRotlImm ... // `v = rotl_imm x, Y`. (BinaryImm64) OpcodeRotlImm // OpcodeRotrImm ... // `v = rotr_imm x, Y`. (BinaryImm64) OpcodeRotrImm // OpcodeIshl ... // `v = ishl x, y`. OpcodeIshl // OpcodeUshr ... // `v = ushr x, y`. OpcodeUshr // OpcodeSshr ... // `v = sshr x, y`. OpcodeSshr // OpcodeIshlImm ... // `v = ishl_imm x, Y`. (BinaryImm64) OpcodeIshlImm // OpcodeUshrImm ... // `v = ushr_imm x, Y`. (BinaryImm64) OpcodeUshrImm // OpcodeSshrImm ... // `v = sshr_imm x, Y`. (BinaryImm64) OpcodeSshrImm // OpcodeBitrev ... // `v = bitrev x`. OpcodeBitrev // OpcodeClz ... // `v = clz x`. OpcodeClz // OpcodeCls ... // `v = cls x`. OpcodeCls // OpcodeCtz ... // `v = ctz x`. OpcodeCtz // OpcodeBswap ... // `v = bswap x`. OpcodeBswap // OpcodePopcnt ... // `v = popcnt x`. OpcodePopcnt // OpcodeFcmp compares two floating point values: `v = fcmp Cond, x, y`. OpcodeFcmp // OpcodeFadd performs an floating point addition. // `v = Fadd x, y`. OpcodeFadd // OpcodeFsub performs an floating point subtraction. // `v = Fsub x, y`. OpcodeFsub // OpcodeFmul ... // `v = fmul x, y`. OpcodeFmul // OpcodeFdiv ... // `v = fdiv x, y`. OpcodeFdiv // OpcodeSqrt ... // `v = sqrt x`. OpcodeSqrt // OpcodeFma ... // `v = fma x, y, z`. OpcodeFma // OpcodeFneg negates the given floating point value: `v = Fneg x`. OpcodeFneg // OpcodeFabs ... // `v = fabs x`. OpcodeFabs // OpcodeFcopysign ... // `v = fcopysign x, y`. OpcodeFcopysign // OpcodeFmin ... // `v = fmin x, y`. OpcodeFmin // OpcodeFminPseudo ... // `v = fmin_pseudo x, y`. OpcodeFminPseudo // OpcodeFmax ... // `v = fmax x, y`. OpcodeFmax // OpcodeFmaxPseudo ... // `v = fmax_pseudo x, y`. OpcodeFmaxPseudo // OpcodeCeil ... // `v = ceil x`. OpcodeCeil // OpcodeFloor ... // `v = floor x`. OpcodeFloor // OpcodeTrunc ... // `v = trunc x`. OpcodeTrunc // OpcodeNearest ... // `v = nearest x`. OpcodeNearest // OpcodeIsNull ... // `v = is_null x`. OpcodeIsNull // OpcodeIsInvalid ... // `v = is_invalid x`. OpcodeIsInvalid // OpcodeBitcast ... // `v = bitcast MemFlags, x`. OpcodeBitcast // OpcodeScalarToVector ... // `v = scalar_to_vector s`. OpcodeScalarToVector // OpcodeBmask ... // `v = bmask x`. OpcodeBmask // OpcodeIreduce ... // `v = ireduce x`. OpcodeIreduce // OpcodeSnarrow ... OpcodeSnarrow // OpcodeUnarrow ... OpcodeUnarrow // OpcodeUunarrow ... OpcodeUunarrow // OpcodeSwidenLow ... OpcodeSwidenLow // OpcodeSwidenHigh ... OpcodeSwidenHigh // OpcodeUwidenLow ... OpcodeUwidenLow // OpcodeUwidenHigh ... OpcodeUwidenHigh // OpcodeIaddPairwise ... OpcodeIaddPairwise // OpcodeWideningPairwiseDotProductS ... // `v = widening_pairwise_dot_product_s x, y`. OpcodeWideningPairwiseDotProductS // OpcodeUExtend zero-extends the given integer: `v = UExtend x, from->to`. OpcodeUExtend // OpcodeSExtend sign-extends the given integer: `v = SExtend x, from->to`. OpcodeSExtend // OpcodeFpromote promotes the given floating point value: `v = Fpromote x`. OpcodeFpromote // OpcodeFdemote ... // `v = fdemote x`. OpcodeFdemote // OpcodeFvdemote ... // `v = fvdemote x`. OpcodeFvdemote // OpcodeFcvtToUint ... // `v = fcvt_to_uint x`. OpcodeFcvtToUint // OpcodeFcvtToSint ... // `v = fcvt_to_sint x`. OpcodeFcvtToSint // OpcodeFcvtToUintSat ... // `v = fcvt_to_uint_sat x`. OpcodeFcvtToUintSat // OpcodeFcvtToSintSat ... // `v = fcvt_to_sint_sat x`. OpcodeFcvtToSintSat // OpcodeFcvtFromUint converts an unsigned integer to a floating point value: `v = FcvtFromUint x`. OpcodeFcvtFromUint // OpcodeFcvtFromSint converts a signed integer to a floating point value: `v = FcvtFromSint x`. OpcodeFcvtFromSint // OpcodeIsplit ... // `lo, hi = isplit x`. OpcodeIsplit // OpcodeIconcat ... // `v = iconcat lo, hi`. OpcodeIconcat // OpcodeAtomicRmw ... // `v = atomic_rmw MemFlags, AtomicRmwOp, p, x`. OpcodeAtomicRmw // OpcodeAtomicCas ... // `v = atomic_cas MemFlags, p, e, x`. OpcodeAtomicCas // OpcodeAtomicLoad ... // `v = atomic_load MemFlags, p`. OpcodeAtomicLoad // OpcodeAtomicStore ... // `atomic_store MemFlags, x, p`. OpcodeAtomicStore // OpcodeFence ... // `fence`. OpcodeFence // OpcodeExtractVector ... // `v = extract_vector x, y`. (BinaryImm8) OpcodeExtractVector )
TODO: complete opcode comments. TODO: there should be unnecessary opcodes.
type Signature ¶
type Signature struct { // ID is a unique identifier for this signature used to lookup. ID SignatureID // Params and Results are the types of the parameters and results of the function. Params, Results []Type // contains filtered or unexported fields }
Signature is a function prototype.
type Type ¶
type Type byte
const ( // TypeI32 represents an integer type with 32 bits. TypeI32 Type // TypeI64 represents an integer type with 64 bits. TypeI64 // TypeF32 represents 32-bit floats in the IEEE 754. TypeF32 // TypeF64 represents 64-bit floats in the IEEE 754. TypeF64 )
type Value ¶
type Value uint64
Value represents an SSA value with a type information. The relationship with Variable is 1: N (including 0), that means there might be multiple Variable(s) for a Value.
Higher 32-bit is used to store Type for this value.
type ValueID ¶
type ValueID uint32
ValueID is the lower 32bit of Value, which is the pure identifier of Value without type info.
type Variable ¶
type Variable uint32
Variable is a unique identifier for a source program's variable and will correspond to multiple ssa Value(s).
For example, `Local 1` is a Variable in WebAssembly, and Value(s) will be created for it whenever it executes `local.set 1`.
Variable is useful to track the SSA Values of a variable in the source program, and can be used to find the corresponding latest SSA Value via Builder.FindValue.