1506 lines
36 KiB
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
|
|
}
|