fspl/llvm/instruction.go

1506 lines
36 KiB
Go

package llvm
import "fmt"
import "strings"
// TODO add metadata
type Instruction interface {
LLString () string
}
type ValueInstruction interface {
fmt.Stringer
Instruction
Value
SetName (name string)
}
type AbstractInstructionBinary struct {
Register
Token string
X, Y Value
}
func (this *AbstractInstructionBinary) LLString () string {
buf := &strings.Builder { }
if this.Named () {
fmt.Fprintf(buf, "%s = ", this.Identifier())
}
buf.WriteString(this.Token)
fmt.Fprintf(buf, " %s, %s", this.X, this.Y.Identifier())
return buf.String()
}
type AbstractInstructionBinaryFP struct {
AbstractInstructionBinary
FastMathFlags []FastMathFlag
}
func (this *AbstractInstructionBinaryFP) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
buf.WriteString(this.Token)
for _, flag := range this.FastMathFlags {
fmt.Fprintf(buf, " %s", flag)
}
fmt.Fprintf(buf, " %s, %s", this.X, this.Y.Identifier())
return buf.String()
}
type AbstractInstructionCast struct {
Register
Token string
From Value
To Type
}
func (this *AbstractInstructionCast) LLString () string {
buf := &strings.Builder { }
if this.Named () {
fmt.Fprintf(buf, "%s = ", this.Identifier())
}
buf.WriteString(this.Token)
fmt.Fprintf(buf, " %s to %s", this.From, this.To)
return buf.String()
}
type AbstractInstructionBinaryExact struct {
AbstractInstructionBinary
Exact bool
}
func (this *AbstractInstructionBinaryExact) LLString () string {
buf := &strings.Builder { }
if this.Named () {
fmt.Fprintf(buf, "%s = ", this.Identifier())
}
buf.WriteString(this.Token)
if this.Exact { buf.WriteString(" exact") }
fmt.Fprintf(buf, " %s, %s", this.X, this.Y.Identifier())
return buf.String()
}
type InstructionAShr struct {
AbstractInstructionBinaryExact
}
func (this *Block) NewAShr (x, y Value) *InstructionAShr {
instruction := &InstructionAShr { }
instruction.Token = "ashr"
instruction.X = x
instruction.Y = y
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type InstructionAdd struct {
AbstractInstructionBinary
}
func (this *Block) NewAdd (x, y Value) *InstructionAdd {
instruction := &InstructionAdd { }
instruction.Token = "add"
instruction.X = x
instruction.Y = y
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type InstructionAddrSpaceCast struct {
AbstractInstructionCast
}
func (this *Block) NewAddrSpaceCast (from Value, to Type) *InstructionAddrSpaceCast {
instruction := &InstructionAddrSpaceCast { }
instruction.Token = "addrspacecast"
instruction.From = from
instruction.To = to
instruction.Ty = to
this.AddInstruction(instruction)
return instruction
}
type InstructionAlloca struct {
Register
Element Type
Count Value
InAlloca bool
Align Align
AddressSpace AddressSpace
}
func (this *Block) NewAlloca (element Type) *InstructionAlloca {
instruction := NewAlloca(element)
this.AddInstruction(instruction)
return instruction
}
func NewAlloca (element Type) *InstructionAlloca {
instruction := &InstructionAlloca {
Element: element,
}
ty := &TypePointer { }
ty.AddressSpace = instruction.AddressSpace
instruction.Ty = ty
return instruction
}
func (this *InstructionAlloca) LLString () string {
buf := &strings.Builder { }
fmt.Fprintf(buf, "%s = ", this.Identifier())
buf.WriteString("alloca")
if this.InAlloca {
buf.WriteString(" inalloca")
}
fmt.Fprintf(buf, " %s", this.Element)
if this.Count != nil {
fmt.Fprintf(buf, ", %s", this.Count)
}
if this.Align != 0 {
fmt.Fprintf(buf, ", %s", this.Align)
}
if this.AddressSpace != 0 {
fmt.Fprintf(buf, ", %s", this.AddressSpace)
}
return buf.String()
}
type InstructionAnd struct {
AbstractInstructionBinary
}
func (this *Block) NewAnd (x, y Value) *InstructionAnd {
instruction := &InstructionAnd { }
instruction.Token = "and"
instruction.X = x
instruction.Y = y
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type AtomicOp uint8; const (
AtomicOpAdd AtomicOp = iota + 1 // add
AtomicOpAnd // and
AtomicOpFAdd // fadd
AtomicOpFSub // fsub
AtomicOpMax // max
AtomicOpMin // min
AtomicOpNAnd // nand
AtomicOpOr // or
AtomicOpSub // sub
AtomicOpUMax // umax
AtomicOpUMin // umin
AtomicOpXChg // xchg
AtomicOpXor // xor
)
func (op AtomicOp) String () string {
switch op {
case AtomicOpAdd: return "add"
case AtomicOpAnd: return "and"
case AtomicOpFAdd: return "fadd"
case AtomicOpFSub: return "fsub"
case AtomicOpMax: return "max"
case AtomicOpMin: return "min"
case AtomicOpNAnd: return "nand"
case AtomicOpOr: return "or"
case AtomicOpSub: return "sub"
case AtomicOpUMax: return "umax"
case AtomicOpUMin: return "umin"
case AtomicOpXChg: return "xchg"
case AtomicOpXor: return "xor"
default: return fmt.Sprintf("AtomicOp(%d)", op)
}
}
type AtomicOrdering uint8; const (
// not_atomic
AtomicOrderingNone AtomicOrdering = 0 // none
AtomicOrderingUnordered AtomicOrdering = 1 // unordered
AtomicOrderingMonotonic AtomicOrdering = 2 // monotonic
//AtomicOrderingConsume AtomicOrdering = 3 // consume
AtomicOrderingAcquire AtomicOrdering = 4 // acquire
AtomicOrderingRelease AtomicOrdering = 5 // release
AtomicOrderingAcquireRelease AtomicOrdering = 6 // acq_rel
AtomicOrderingSequentiallyConsistent AtomicOrdering = 7 // seq_cst
)
func (ordering AtomicOrdering) String () string {
switch ordering {
case AtomicOrderingNone: return "none"
case AtomicOrderingUnordered: return "unordered"
case AtomicOrderingMonotonic: return "monotonic"
case AtomicOrderingAcquire: return "acquire"
case AtomicOrderingRelease: return "release"
case AtomicOrderingAcquireRelease: return "acq_rel"
case AtomicOrderingSequentiallyConsistent: return "seq_cst"
default: return fmt.Sprintf("AtomicOrdering(%d)", ordering)
}
}
type InstructionAtomicRMW struct {
Register
Op AtomicOp
Destination Value
X Value
Ordering AtomicOrdering
Volatile bool
SyncScope string
}
func (this *Block) NewAtomicRMW (op AtomicOp, destination, x Value, ordering AtomicOrdering) *InstructionAtomicRMW {
instruction := &InstructionAtomicRMW {
Op: op,
Destination: destination,
X: x,
Ordering: ordering,
}
instruction.Ty = destination.Type()
this.AddInstruction(instruction)
return instruction
}
func (this *InstructionAtomicRMW) LLString () string {
buf := &strings.Builder { }
fmt.Fprintf(buf, "%s = ", this.Identifier())
buf.WriteString("atomicrmw")
if this.Volatile {
buf.WriteString(" volatile")
}
fmt.Fprintf(buf, " %s %s, %s", this.Op, this.Destination, this.X)
if len(this.SyncScope) > 0 {
fmt.Fprintf(buf, " syncscope(%s)", EscapeQuoteString([]byte(this.SyncScope)))
}
fmt.Fprintf(buf, " %s", this.Ordering)
return buf.String()
}
type InstructionBitCast struct {
Register
From Value
To Type
}
func (this *InstructionBitCast) LLString () string {
buf := &strings.Builder { }
if this.Named () {
fmt.Fprintf(buf, "%s = ", this.Identifier())
}
buf.WriteString("bitcast")
fmt.Fprintf(buf, " %s to %s", this.From, this.To)
return buf.String()
}
func (this *Block) NewBitCast (from Value, to Type) *InstructionBitCast {
instruction := &InstructionBitCast { From: from, To: to }
instruction.Ty = to
this.AddInstruction(instruction)
return instruction
}
type InstructionCall struct {
Register
Callee Value
Signature *TypeFunction
Arguments []Value
AddressSpace AddressSpace
// TODO complete this
}
func (this *InstructionCall) LLString () string {
buf := &strings.Builder{}
if _, ok := this.Type().(*TypeVoid); !ok {
fmt.Fprintf(buf, "%s = ", this.Identifier())
}
buf.WriteString("call")
// (optional) Address space.
if this.AddressSpace != 0 {
fmt.Fprintf(buf, " %s", this.AddressSpace)
}
// Use function signature instead of return type for variadic functions.
calleeType := this.Type()
if sig := this.Signature; sig.Variadic {
calleeType = sig
}
fmt.Fprintf(buf, " %s %s(", calleeType, this.Callee.Identifier())
for index, arg := range this.Arguments {
if index > 0 {
buf.WriteString(", ")
}
buf.WriteString(arg.String())
}
buf.WriteString(")")
return buf.String()
}
func (this *InstructionCall) Type () Type {
return this.Signature.Return
}
func (this *Block) NewCall (callee Value, signature *TypeFunction, args ...Value) *InstructionCall {
instruction := &InstructionCall {
Callee: callee,
Signature: signature,
Arguments: args,
}
instruction.Ty = signature.Return
this.AddInstruction(instruction)
return instruction
}
type InstructionCatchPad struct {
Register
CatchSwitch Value
Arguments []Value
}
func (this *InstructionCatchPad) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
fmt.Fprintf(buf, "catchpad within %s [", this.CatchSwitch)
for index, arg := range this.Arguments {
if index > 0 {
buf.WriteString(", ")
}
buf.WriteString(arg.String())
}
buf.WriteString("]")
return buf.String()
}
func (this *Block) NewCatchPad (catchSwitch Value, args ...Value) *InstructionCatchPad {
instruction := &InstructionCatchPad {
CatchSwitch: catchSwitch,
Arguments: args,
}
instruction.Ty = &TypeToken { }
this.AddInstruction(instruction)
return instruction
}
type InstructionCleanupPad struct {
Register
ParentPad Value
Arguments []Value
}
func (this *InstructionCleanupPad) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
fmt.Fprintf(buf, "cleanuppad within %s [", this.ParentPad)
for index, arg := range this.Arguments {
if index > 0 {
buf.WriteString(", ")
}
buf.WriteString(arg.String())
}
buf.WriteString("]")
return buf.String()
}
func (this *Block) NewCleanupPad (parentPad Value, args ...Value) *InstructionCleanupPad {
instruction := &InstructionCleanupPad {
ParentPad: parentPad,
Arguments: args,
}
instruction.Ty = &TypeToken { }
this.AddInstruction(instruction)
return instruction
}
type InstructionCmpXchg struct {
Register
Source Value
Against Value
New Value
SuccessOrdering AtomicOrdering
FailureOrdering AtomicOrdering
Weak bool
Volatile bool
SyncScope string
}
func (this *InstructionCmpXchg) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
buf.WriteString("cmpxchg")
if this.Weak {
buf.WriteString(" weak")
}
if this.Volatile {
buf.WriteString(" volatile")
}
fmt.Fprintf(buf, " %s, %s, %s", this.Source, this.Against, this.New)
if len(this.SyncScope) > 0 {
fmt.Fprintf(buf, " syncscope(%s)", EscapeQuoteString([]byte(this.SyncScope)))
}
fmt.Fprintf(buf, " %s", this.SuccessOrdering)
fmt.Fprintf(buf, " %s", this.FailureOrdering)
return buf.String()
}
func (this *Block) NewCmpXchg (source, against, neww Value, success, failure AtomicOrdering) *InstructionCmpXchg {
instruction := &InstructionCmpXchg {
Source: source,
Against: against,
New: neww,
SuccessOrdering: success,
FailureOrdering: failure,
}
instruction.Ty = &TypeStruct { Fields: []Type {
neww.Type(),
&TypeInt { BitSize: 1 },
}}
this.AddInstruction(instruction)
return instruction
}
type InstructionExtractElement struct {
Register
X Value
Index Value
}
func (this *InstructionExtractElement) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
fmt.Fprintf(buf, "extractelement %s, %s", this.X, this.Index)
return buf.String()
}
func (this *Block) NewExtractElement (x, index Value) *InstructionExtractElement {
instruction := &InstructionExtractElement { X: x, Index: index }
instruction.Ty = x.Type().(*TypeVector).Element
this.AddInstruction(instruction)
return instruction
}
type InstructionExtractValue struct {
Register
X Value
Indices []uint64
}
func (this *InstructionExtractValue) LLString () string {
buf := &strings.Builder { }
fmt.Fprintf(buf, "%s = ", this.Identifier())
fmt.Fprintf(buf, "extractvalue %s", this.X)
for _, index := range this.Indices {
fmt.Fprintf(buf, ", %d", index)
}
return buf.String()
}
func (this *Block) NewExtractValue (x Value, indices ...uint64) *InstructionExtractValue {
instruction := &InstructionExtractValue {
X: x,
Indices: indices,
}
instruction.Ty = aggregateElemType(x.Type(), indices)
this.AddInstruction(instruction)
return instruction
}
type FastMathFlag uint8; const (
FastMathFlagAFn FastMathFlag = iota // afn
FastMathFlagARcp // arcp
FastMathFlagContract // contract
FastMathFlagFast // fast
FastMathFlagNInf // ninf
FastMathFlagNNaN // nnan
FastMathFlagNSZ // nsz
FastMathFlagReassoc // reassoc
)
func (flag FastMathFlag) String () string {
switch flag {
case FastMathFlagAFn: return "afn"
case FastMathFlagARcp: return "arcp"
case FastMathFlagContract: return "contract"
case FastMathFlagFast: return "fast"
case FastMathFlagNInf: return "ninf"
case FastMathFlagNNaN: return "nnan"
case FastMathFlagNSZ: return "nsz"
case FastMathFlagReassoc: return "reassoc"
default: return fmt.Sprintf("FastMathFlag(%d)", flag)
}
}
type InstructionFAdd struct {
AbstractInstructionBinaryFP
}
func (this *Block) NewFAdd (x, y Value) *InstructionFAdd {
instruction := &InstructionFAdd { }
instruction.Token = "fadd"
instruction.X = x
instruction.Y = y
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type FPredicate uint8; const (
FPredicateFalse FPredicate = iota // false
FPredicateOEQ // oeq
FPredicateOGE // oge
FPredicateOGT // ogt
FPredicateOLE // ole
FPredicateOLT // olt
FPredicateONE // one
FPredicateORD // ord
FPredicateTrue // true
FPredicateUEQ // ueq
FPredicateUGE // uge
FPredicateUGT // ugt
FPredicateULE // ule
FPredicateULT // ult
FPredicateUNE // une
FPredicateUNO // uno
)
func (predicate FPredicate) String () string {
switch predicate {
case FPredicateFalse: return "false"
case FPredicateOEQ: return "oeq"
case FPredicateOGE: return "oge"
case FPredicateOGT: return "ogt"
case FPredicateOLE: return "ole"
case FPredicateOLT: return "olt"
case FPredicateONE: return "one"
case FPredicateORD: return "ord"
case FPredicateTrue: return "true"
case FPredicateUEQ: return "ueq"
case FPredicateUGE: return "uge"
case FPredicateUGT: return "ugt"
case FPredicateULE: return "ule"
case FPredicateULT: return "ult"
case FPredicateUNE: return "une"
case FPredicateUNO: return "uno"
default: return fmt.Sprintf("FPredicate(%d)", predicate)
}
}
type InstructionFCmp struct {
AbstractInstructionBinaryFP
Predicate FPredicate
}
func (this *InstructionFCmp) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
buf.WriteString("fcmp")
for _, flag := range this.FastMathFlags {
fmt.Fprintf(buf, " %s", flag)
}
fmt.Fprintf(buf, " %s %s, %s", this.Predicate, this.X, this.Y.Identifier())
return buf.String()
}
func (this *Block) NewFCmp (predicate FPredicate, x, y Value) *InstructionFCmp {
instruction := &InstructionFCmp { }
instruction.Token = "fcmp"
instruction.X = x
instruction.Y = y
instruction.Predicate = predicate
switch xType := ReduceToBase(x.Type()).(type) {
case *TypeFloat:
instruction.Ty = &TypeInt { BitSize: 1 }
case *TypeVector:
instruction.Ty = &TypeVector {
Length: xType.Length,
Element: &TypeInt { BitSize: 1 },
}
default:
panic(fmt.Errorf("invalid fcmp operand type %T", xType))
}
this.AddInstruction(instruction)
return instruction
}
type InstructionFDiv struct {
AbstractInstructionBinaryFP
}
func (this *Block) NewFDiv (x, y Value) *InstructionFDiv {
instruction := &InstructionFDiv { }
instruction.Token = "fdiv"
instruction.X = x
instruction.Y = y
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type InstructionFMul struct {
AbstractInstructionBinaryFP
}
func (this *Block) NewFMul (x, y Value) *InstructionFMul {
instruction := &InstructionFMul { }
instruction.Token = "fmul"
instruction.X = x
instruction.Y = y
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type InstructionFNeg struct {
Register
X Value
FastMathFlags []FastMathFlag
}
func (this *InstructionFNeg) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
buf.WriteString("fneg")
for _, flag := range this.FastMathFlags {
fmt.Fprintf(buf, " %s", flag)
}
fmt.Fprintf(buf, " %s", this.X)
return buf.String()
}
func (this *Block) NewFNeg (x Value) *InstructionFNeg {
instruction := &InstructionFNeg { }
instruction.X = x
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type InstructionFPExt struct {
AbstractInstructionCast
}
func (this *Block) NewFPExt (from Value, to Type) *InstructionFPExt {
instruction := &InstructionFPExt { }
instruction.Token = "fpext"
instruction.From = from
instruction.To = to
instruction.Ty = to
this.AddInstruction(instruction)
return instruction
}
type InstructionFPToSI struct {
AbstractInstructionCast
}
func (this *Block) NewFPToSI (from Value, to Type) *InstructionFPToSI {
instruction := &InstructionFPToSI { }
instruction.Token = "fptosi"
instruction.From = from
instruction.To = to
instruction.Ty = to
this.AddInstruction(instruction)
return instruction
}
type InstructionFPToUI struct {
AbstractInstructionCast
}
func (this *Block) NewFPToUI (from Value, to Type) *InstructionFPToUI {
instruction := &InstructionFPToUI { }
instruction.Token = "fptoui"
instruction.From = from
instruction.To = to
instruction.Ty = to
this.AddInstruction(instruction)
return instruction
}
type InstructionFPTrunc struct {
AbstractInstructionCast
}
func (this *Block) NewFPTrunc (from Value, to Type) *InstructionFPTrunc {
instruction := &InstructionFPTrunc { }
instruction.Token = "fptrunc"
instruction.From = from
instruction.To = to
instruction.Ty = to
this.AddInstruction(instruction)
return instruction
}
type InstructionFRem struct {
AbstractInstructionBinaryFP
}
func (this *Block) NewFRem (x, y Value) *InstructionFRem {
instruction := &InstructionFRem { }
instruction.Token = "frem"
instruction.X = x
instruction.Y = y
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type InstructionFSub struct {
AbstractInstructionBinaryFP
}
func (this *Block) NewFSub (x, y Value) *InstructionFSub {
instruction := &InstructionFSub { }
instruction.Token = "fsub"
instruction.X = x
instruction.Y = y
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type InstructionFence struct {
Ordering AtomicOrdering
SyncScope string
}
func (this *InstructionFence) LLString () string {
buf := &strings.Builder{}
buf.WriteString("fence")
if len(this.SyncScope) > 0 {
fmt.Fprintf(buf, " syncscope(%s)", EscapeQuoteString([]byte(this.SyncScope)))
}
fmt.Fprintf(buf, " %s", this.Ordering)
return buf.String()
}
func (this *Block) NewFence (ordering AtomicOrdering) *InstructionFence {
instruction := &InstructionFence { Ordering: ordering }
this.AddInstruction(instruction)
return instruction
}
type InstructionFreeze struct {
Register
X Value
}
func (this *InstructionFreeze) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
fmt.Fprintf(buf, "freeze %s", this.X)
return buf.String()
}
func (this *Block) NewFreeze (x Value) *InstructionFreeze {
instruction := &InstructionFreeze { X: x }
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type InstructionGetElementPtr struct {
Register
Element Type
Source Value
Indices []Value
InBounds bool
}
func (this *InstructionGetElementPtr) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
buf.WriteString("getelementptr")
if this.InBounds {
buf.WriteString(" inbounds")
}
fmt.Fprintf(buf, " %s, %s", this.Element, this.Source)
for _, index := range this.Indices {
fmt.Fprintf(buf, ", %s", index)
}
return buf.String()
}
func (this *Block) NewGetElementPtr (element Type, source Value, indices ...Value) *InstructionGetElementPtr {
instruction := &InstructionGetElementPtr {
Element: element,
Source: source,
Indices: indices,
}
instruction.Ty = gepInstType(element, source.Type(), indices)
this.AddInstruction(instruction)
return instruction
}
type IPredicate uint8; const (
IPredicateEQ IPredicate = iota // eq
IPredicateNE // ne
IPredicateSGE // sge
IPredicateSGT // sgt
IPredicateSLE // sle
IPredicateSLT // slt
IPredicateUGE // uge
IPredicateUGT // ugt
IPredicateULE // ule
IPredicateULT // ult
)
func (predicate IPredicate) String () string {
switch predicate {
case IPredicateEQ: return "eq"
case IPredicateNE: return "ne"
case IPredicateSGE: return "sge"
case IPredicateSGT: return "sgt"
case IPredicateSLE: return "sle"
case IPredicateSLT: return "slt"
case IPredicateUGE: return "uge"
case IPredicateUGT: return "ugt"
case IPredicateULE: return "ule"
case IPredicateULT: return "ult"
default: return fmt.Sprintf("IPredicate(%d)", predicate)
}
}
type InstructionICmp struct {
AbstractInstructionBinary
Predicate IPredicate
}
func (this *InstructionICmp) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
buf.WriteString("icmp")
fmt.Fprintf(buf, " %s %s, %s", this.Predicate, this.X, this.Y.Identifier())
return buf.String()
}
func (this *Block) NewICmp (predicate IPredicate, x, y Value) *InstructionICmp {
instruction := &InstructionICmp { }
instruction.Token = "icmp"
instruction.X = x
instruction.Y = y
instruction.Predicate = predicate
switch xType := ReduceToBase(x.Type()).(type) {
case *TypeInt, *TypePointer:
instruction.Ty = &TypeInt { BitSize: 1 }
case *TypeVector:
instruction.Ty = &TypeVector {
Length: xType.Length,
Element: &TypeInt { BitSize: 1 },
}
default:
panic(fmt.Errorf("invalid icmp operand type %T", xType))
}
this.AddInstruction(instruction)
return instruction
}
type InstructionInsertElement struct {
Register
X Value
Element Value
Index Value
}
func (this *InstructionInsertElement) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
fmt.Fprintf(buf, "insertelement %s, %s, %s", this.X, this.Element, this.Index)
return buf.String()
}
func (this *Block) NewInsertElement (x, element, index Value) *InstructionInsertElement {
instruction := &InstructionInsertElement {
X: x,
Element: element,
Index: index,
}
t, ok := x.Type().(*TypeVector)
if !ok {
panic(fmt.Errorf("invalid vector type %T", x.Type()))
}
instruction.Ty = t
return instruction
}
type InstructionInsertValue struct {
Register
X Value
Element Value
Indices []uint64
}
func (this *InstructionInsertValue) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
fmt.Fprintf(buf, "insertvalue %s, %s", this.X, this.Element)
for _, index := range this.Indices {
fmt.Fprintf(buf, ", %d", index)
}
return buf.String()
}
func (this *Block) NewInsertValue (x, element Value, indices ...uint64) *InstructionInsertValue {
instruction := &InstructionInsertValue {
X: x,
Element: element,
Indices: indices,
}
instruction.Ty = x.Type()
return instruction
}
type InstructionIntToPtr struct {
AbstractInstructionCast
}
func (this *Block) NewIntToPtr (from Value, to Type) *InstructionIntToPtr {
if to == nil { to = &TypePointer { } }
instruction := &InstructionIntToPtr { }
instruction.Token = "inttoptr"
instruction.From = from
instruction.To = to
instruction.Ty = to
this.AddInstruction(instruction)
return instruction
}
type InstructionLShr struct {
AbstractInstructionBinaryExact
}
func (this *Block) NewLShr (x, y Value) *InstructionLShr {
instruction := &InstructionLShr { }
instruction.Token = "lshr"
instruction.X = x
instruction.Y = y
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type ClauseType uint8; const (
ClauseTypeCatch ClauseType = iota + 1 // catch
ClauseTypeFilter // filter
)
func (ty ClauseType) String () string {
switch ty {
case ClauseTypeCatch: return "catch"
case ClauseTypeFilter: return "filter"
default: return fmt.Sprintf("ClauseType(%d)", ty)
}
}
type Clause struct {
Type ClauseType
X Value
}
func (this *Clause) String () string {
return fmt.Sprintf("%s %s", this.Type, this.X)
}
type InstructionLandingPad struct {
Register
Cleanup bool
Clauses []*Clause
}
func (this *InstructionLandingPad) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
fmt.Fprintf(buf, "landingpad %s", this.Type())
if this.Cleanup {
buf.WriteString("\n\t\tcleanup")
}
for _, clause := range this.Clauses {
fmt.Fprintf(buf, "\n\t\t%s", clause)
}
return buf.String()
}
func (this *Block) NewLandingPad (result Type, clauses ...*Clause) *InstructionLandingPad {
instruction := &InstructionLandingPad { Clauses: clauses }
instruction.Ty = result
this.AddInstruction(instruction)
return instruction
}
type InstructionLoad struct {
Register
Source Value
Atomic bool
Volatile bool
SyncScope string
Ordering AtomicOrdering
Align Align
}
func (this *InstructionLoad) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
buf.WriteString("load")
if this.Atomic {
buf.WriteString(" atomic")
}
if this.Volatile {
buf.WriteString(" volatile")
}
fmt.Fprintf(buf, " %s, %s", this.Type(), this.Source)
if len(this.SyncScope) > 0 {
fmt.Fprintf(buf, " syncscope(%s)", EscapeQuoteString([]byte(this.SyncScope)))
}
if this.Ordering != AtomicOrderingNone {
fmt.Fprintf(buf, " %s", this.Ordering)
}
if this.Align != 0 {
fmt.Fprintf(buf, ", %s", this.Align)
}
return buf.String()
}
func (this *Block) NewLoad (element Type, source Value) *InstructionLoad {
instruction := &InstructionLoad { Source: source }
instruction.Ty = element
this.AddInstruction(instruction)
return instruction
}
type OverflowFlag uint8; const (
OverflowFlagNSW OverflowFlag = iota // nsw
OverflowFlagNUW // nuw
)
func (flag OverflowFlag) String () string {
switch flag {
case OverflowFlagNSW: return "nsw"
case OverflowFlagNUW: return "nuw"
default: return fmt.Sprintf("OverflowFlag(%d)", flag)
}
}
type InstructionMul struct {
AbstractInstructionBinary
OverflowFlags []OverflowFlag
}
func (this *InstructionMul) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
buf.WriteString("mul")
for _, flag := range this.OverflowFlags {
fmt.Fprintf(buf, " %s", flag)
}
fmt.Fprintf(buf, " %s, %s", this.X, this.Y.Identifier())
return buf.String()
}
func (this *Block) NewMul (x, y Value) *InstructionMul {
instruction := &InstructionMul { }
instruction.Token = "mul"
instruction.X = x
instruction.Y = y
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type InstructionOr struct {
AbstractInstructionBinary
}
func (this *Block) NewOr (x, y Value) *InstructionOr {
instruction := &InstructionOr { }
instruction.Token = "or"
instruction.X = x
instruction.Y = y
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type Incoming struct {
X Value
Predecessor Value
}
func (this *Incoming) String () string {
return fmt.Sprintf("[ %s, %s ]", this.X.Identifier(), this.Predecessor.Identifier())
}
type InstructionPhi struct {
Register
Incoming []*Incoming
FastMathFlags []FastMathFlag
}
func (this *InstructionPhi) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
buf.WriteString("phi ")
for _, flag := range this.FastMathFlags {
buf.WriteString(flag.String())
buf.WriteString(" ")
}
buf.WriteString(this.Type().String())
buf.WriteString(" ")
for i, inc := range this.Incoming {
if i != 0 {
buf.WriteString(", ")
}
buf.WriteString(inc.String())
}
return buf.String()
}
func (this *Block) NewPhi (incoming ...*Incoming) *InstructionPhi {
instruction := &InstructionPhi {
Incoming: incoming,
}
instruction.Ty = incoming[0].X.Type()
this.AddInstruction(instruction)
return instruction
}
type InstructionPtrToInt struct {
AbstractInstructionCast
}
func (this *Block) NewPtrToInt (from Value, to Type) *InstructionPtrToInt {
instruction := &InstructionPtrToInt { }
instruction.Token = "ptrtoint"
instruction.From = from
instruction.To = to
instruction.Ty = to
this.AddInstruction(instruction)
return instruction
}
type InstructionSDiv struct {
AbstractInstructionBinary
Exact bool
}
func (this *InstructionSDiv) LLString () string {
buf := &strings.Builder { }
if this.Named () {
fmt.Fprintf(buf, "%s = ", this.Identifier())
}
buf.WriteString("sdiv")
if this.Exact { buf.WriteString(" exact") }
fmt.Fprintf(buf, " %s, %s", this.X, this.Y.Identifier())
return buf.String()
}
func (this *Block) NewSDiv (x, y Value) *InstructionSDiv {
instruction := &InstructionSDiv { }
instruction.Token = "sdiv"
instruction.X = x
instruction.Y = y
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type InstructionSExt struct {
AbstractInstructionCast
}
func (this *Block) NewSExt (from Value, to Type) *InstructionSExt {
instruction := &InstructionSExt { }
instruction.Token = "sext"
instruction.From = from
instruction.To = to
instruction.Ty = to
this.AddInstruction(instruction)
return instruction
}
type InstructionSIToFP struct {
AbstractInstructionCast
}
func (this *Block) NewSIToFP (from Value, to Type) *InstructionSExt {
instruction := &InstructionSExt { }
instruction.Token = "sitofp"
instruction.From = from
instruction.To = to
instruction.Ty = to
this.AddInstruction(instruction)
return instruction
}
type InstructionSRem struct {
AbstractInstructionBinary
}
func (this *Block) NewSRem (x, y Value) *InstructionSRem {
instruction := &InstructionSRem { }
instruction.Token = "srem"
instruction.X = x
instruction.Y = y
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type InstructionSelect struct {
Register
Condition Value
True Value
False Value
FastMathFlags []FastMathFlag
}
func (this *InstructionSelect) LLString() string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
buf.WriteString("select")
for _, flag := range this.FastMathFlags {
fmt.Fprintf(buf, " %s", flag)
}
fmt.Fprintf(buf, " %s, %s, %s", this.Condition, this.True, this.False)
return buf.String()
}
func (this *Block) NewSelect (condition, tru, fals Value) *InstructionSelect {
instruction := &InstructionSelect {
Condition: condition,
True: tru,
False: fals,
}
instruction.Ty = tru.Type()
return instruction
}
type InstructionShl struct {
AbstractInstructionBinary
OverflowFlags []OverflowFlag
}
func (this *InstructionShl) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
buf.WriteString("shl")
for _, flag := range this.OverflowFlags {
fmt.Fprintf(buf, " %s", flag)
}
fmt.Fprintf(buf, " %s, %s", this.X, this.Y.Identifier())
return buf.String()
}
func (this *Block) NewShl (x, y Value) *InstructionShl {
instruction := &InstructionShl { }
instruction.Token = "shl"
instruction.X = x
instruction.Y = y
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type InstructionShuffleVector struct {
Register
X, Y Value
Mask Value
}
func (this *InstructionShuffleVector) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
fmt.Fprintf(buf, "shufflevector %s, %s, %s", this.X, this.Y, this.Mask)
return buf.String()
}
func (this *Block) NewShuffleVector (x, y, mask Value) *InstructionShuffleVector {
instruction := &InstructionShuffleVector {
X: x, Y: y,
Mask: mask,
}
xType, ok := x.Type().(*TypeVector)
if !ok {
panic(fmt.Errorf("invalid vector type %T", x.Type()))
}
maskType, ok := mask.Type().(*TypeVector)
if !ok {
panic(fmt.Errorf("invalid vector type %T", mask.Type()))
}
instruction.Ty = &TypeVector {
Length: maskType.Length,
Element: xType.Element,
}
this.AddInstruction(instruction)
return instruction
}
type InstructionStore struct {
Source, Destination Value
Atomic bool
Volatile bool
SyncScope string
Ordering AtomicOrdering
Align Align
}
func (this *InstructionStore) LLString () string {
buf := &strings.Builder{}
buf.WriteString("store")
if this.Atomic {
buf.WriteString(" atomic")
}
if this.Volatile {
buf.WriteString(" volatile")
}
fmt.Fprintf(buf, " %s, %s", this.Source, this.Destination)
if len(this.SyncScope) > 0 {
fmt.Fprintf(buf, " syncscope(%s)", EscapeQuoteString([]byte(this.SyncScope)))
}
if this.Ordering != AtomicOrderingNone {
fmt.Fprintf(buf, " %s", this.Ordering)
}
if this.Align != 0 {
fmt.Fprintf(buf, ", %s", this.Align)
}
return buf.String()
}
func (this *Block) NewStore (source, destination Value) *InstructionStore {
instruction := &InstructionStore {
Source: source,
Destination: destination,
}
this.AddInstruction(instruction)
return instruction
}
type InstructionSub struct {
AbstractInstructionBinary
OverflowFlags []OverflowFlag
}
func (this *InstructionSub) LLString () string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
buf.WriteString("sub")
for _, flag := range this.OverflowFlags {
fmt.Fprintf(buf, " %s", flag)
}
fmt.Fprintf(buf, " %s, %s", this.X, this.Y.Identifier())
return buf.String()
}
func (this *Block) NewSub (x, y Value) *InstructionSub {
instruction := &InstructionSub { }
instruction.Token = "sub"
instruction.X = x
instruction.Y = y
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type InstructionTrunc struct {
AbstractInstructionCast
}
func (this *Block) NewTrunc (from Value, to Type) *InstructionTrunc {
instruction := &InstructionTrunc { }
instruction.Token = "trunc"
instruction.From = from
instruction.To = to
instruction.Ty = to
this.AddInstruction(instruction)
return instruction
}
type InstructionUDiv struct {
AbstractInstructionBinaryExact
}
func (this *Block) NewUDiv (x, y Value) *InstructionUDiv {
instruction := &InstructionUDiv { }
instruction.Token = "udiv"
instruction.X = x
instruction.Y = y
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type InstructionUIToFP struct {
AbstractInstructionCast
}
func (this *Block) NewUIToFP (from Value, to Type) *InstructionUIToFP {
instruction := &InstructionUIToFP { }
instruction.Token = "uitofp"
instruction.From = from
instruction.To = to
instruction.Ty = to
this.AddInstruction(instruction)
return instruction
}
type InstructionURem struct {
AbstractInstructionBinary
}
func (this *Block) NewURem (x, y Value) *InstructionURem {
instruction := &InstructionURem { }
instruction.Token = "urem"
instruction.X = x
instruction.Y = y
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type InstructionVAArg struct {
Register
List Value
}
func (this *InstructionVAArg) LLString() string {
buf := &strings.Builder{}
fmt.Fprintf(buf, "%s = ", this.Identifier())
fmt.Fprintf(buf, "va_arg %s, %s", this.List, this.Type())
return buf.String()
}
func (this *Block) NewVAArg (list Value, ty Type) *InstructionVAArg {
instruction := &InstructionVAArg { List: list }
instruction.Ty = ty
this.AddInstruction(instruction)
return instruction
}
type InstructionXor struct {
AbstractInstructionBinary
}
func (this *Block) NewXor (x, y Value) *InstructionXor {
instruction := &InstructionXor { }
instruction.Token = "xor"
instruction.X = x
instruction.Y = y
instruction.Ty = x.Type()
this.AddInstruction(instruction)
return instruction
}
type InstructionZext struct {
AbstractInstructionCast
}
func (this *Block) NewZext (from Value, to Type) *InstructionZext {
instruction := &InstructionZext { }
instruction.Token = "zext"
instruction.From = from
instruction.To = to
instruction.Ty = to
this.AddInstruction(instruction)
return instruction
}