Target-neutral semantic machine IR
///|
test "build and verify a virtual-register copy" {
let func = AbstractFunction::new("copy")
let entry = func.new_block()
let src = func.add_param(Int)
let dst = func.new_vreg(Int)
let mov = func.new_inst(Move)
mov.add_operand(Operand::use_reg(Virtual(src)))
mov.add_operand(Operand::def(Virtual(dst)))
entry.append(mov)
entry.set_terminator(TermReturn([Virtual(dst)]))
inspect(func.verify(), content="()")
inspect(func.blocks.length(), content="1")
inspect(entry.instructions.length(), content="1")
}///|
test "represent a call clobber and outgoing stack frame" {
let func = AbstractFunction::new("call_host")
let entry = func.new_block()
let call = func.new_inst(Call("host.print"))
call.add_clobber({ index: 0, class: Int })
call.set_stack_effect(CallFrame(16))
entry.append(call)
inspect(call.clobbers.length(), content="1")
debug_inspect(call.stack_effect, content="CallFrame(16)")
}impl Show for VerifyErrorpub(all) struct AbstractFunction {
name : String
params : Array[VReg]
results : Array[RegClass]
blocks : Array[Block]
stack_slots : Array[StackSlot]
num_spill_slots : Int
param_pregs : Array[PReg?]
param_locations : Array[AbiValueLocation]
result_locations : Array[AbiValueLocation]
return_area : AbiReturnArea?
int_stack_params : Int
max_outgoing_args_size : Int
next_block_id : Int
next_inst_id : Int
next_vreg_id : Int
next_stack_slot_id : Int
} derive(Debug)fn AbstractFunction::add_param_location(self : AbstractFunction, location : AbiValueLocation) -> Unitfn AbstractFunction::add_result_location(self : AbstractFunction, location : AbiValueLocation) -> Unitpub(all) struct Block {
id : Int
params : Array[VReg]
instructions : Array[Instruction]
successors : Array[Int]
terminator : Terminator?
} derive(Debug)pub(all) struct Function {
name : String
params : Array[VReg]
results : Array[RegClass]
result_kinds : Array[ValueKind]
blocks : Array[MachVBlock]
next_vreg_id : Int
num_spill_slots : Int
param_pregs : Array[PReg?]
int_stack_params : Int
max_outgoing_args_size : Int
uses_context_cache_0_source : Bool
}pub(all) struct Instruction {
id : Int
opcode : Opcode
operands : Array[Operand]
clobbers : Array[PReg]
constraints : Array[Constraint]
abi_arg_locations : Array[AbiValueLocation]
abi_result_locations : Array[AbiValueLocation]
stack_effect : StackEffect
} derive(Eq, Debug)pub(all) enum Opcode {
Target(String)
Move
IntConst(Int64)
FloatConst(Double)
IntAdd
IntSub
IntMul
IntMulHigh(Bool)
IntDiv(Bool)
IntRem(Bool)
IntAnd
IntOr
IntXor
IntNot
IntShl
IntShr(Bool)
IntRotl
IntRotr
IntClz
IntCtz
IntPopcnt
IntCmp(Cond)
FloatAdd
FloatSub
FloatMul
FloatDiv
FloatMin
FloatMax
FloatCmp(Cond)
FloatNeg
FloatAbs
FloatSqrt
FloatCeil
FloatFloor
FloatTrunc
FloatNearest
Ireduce
Sextend
Uextend
Fpromote
Fdemote
FcvtToSint
FcvtToUint
FcvtToSintSat
FcvtToUintSat
SintToFcvt
UintToFcvt
Bitcast
Sextend8
Sextend16
Sextend32
Select
LoadMemory(MemType, Int)
StoreMemory(MemType, Int)
LoadPtr(MemType, Int)
LoadPtrNarrow(Int, Bool, Int)
StorePtr(MemType, Int)
StorePtrNarrow(Int, Int)
StackAddr(Int)
CallIndirect
CallPtr(Int, Int)
Custom(String)
Load(StackSlot)
Store(StackSlot)
Call(String)
Trap(Int)
Jump(Int)
Branch(Int, Int)
Return
} derive(Eq, Debug)impl Show for OperandConstraintpub(all) enum Terminator {
TermJump(Int, Array[Reg])
TermBranch(Reg, Int, Array[Reg], Int, Array[Reg])
TermBranchCmp(Reg, Reg, Cond, Bool, Int, Array[Reg], Int, Array[Reg])
TermBranchZero(Reg, Bool, Bool, Int, Array[Reg], Int, Array[Reg])
TermBranchCmpImm(Reg, Int, Cond, Bool, Int, Array[Reg], Int, Array[Reg])
TermReturn(Array[Reg])
TermTrap(Int)
TermBrTable(Reg, Array[Int], Int)
} derive(Eq, Debug)Target-neutral semantic machine IR