From 2e6142277f9c28a8327e99b21c3d5680bf8d196a Mon Sep 17 00:00:00 2001 From: Robin Eklind Date: Thu, 20 Jan 2022 01:35:03 +0100 Subject: [PATCH 1/5] ir/value: add User interface with Operands method for use tracking Updates #19. --- ir/value/value.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ir/value/value.go b/ir/value/value.go index 9dbd78cf..2866cf1d 100644 --- a/ir/value/value.go +++ b/ir/value/value.go @@ -44,3 +44,10 @@ type Named interface { // SetName sets the name of the value. SetName(name string) } + +// User is an instruction or terminator which uses values as operands. +type User interface { + // Operands returns a mutable list of operands of the given value user + // (instruction or terminator). + Operands() []*Value +} From 6c16ca385a8f9f17fe27a4446773330ca698e762 Mon Sep 17 00:00:00 2001 From: Robin Eklind Date: Thu, 20 Jan 2022 01:35:48 +0100 Subject: [PATCH 2/5] ir: add Operands method for instructions and terminators Note, the Operands method returns a mutable list of values used as operands by the user (instruction or terminator). --- ir/inst_aggregate.go | 10 ++++ ir/inst_binary.go | 60 ++++++++++++++++++++++++ ir/inst_bitwise.go | 30 ++++++++++++ ir/inst_conversion.go | 65 ++++++++++++++++++++++++++ ir/inst_memory.go | 43 +++++++++++++++++ ir/inst_other.go | 74 +++++++++++++++++++++++++++++ ir/inst_unary.go | 5 ++ ir/inst_vector.go | 15 ++++++ ir/instruction.go | 4 ++ ir/terminator.go | 105 ++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 411 insertions(+) diff --git a/ir/inst_aggregate.go b/ir/inst_aggregate.go index 6ed4e493..638329f4 100644 --- a/ir/inst_aggregate.go +++ b/ir/inst_aggregate.go @@ -69,6 +69,11 @@ func (inst *InstExtractValue) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstExtractValue) Operands() []*value.Value { + return []*value.Value{&inst.X} +} + // ~~~ [ insertvalue ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstInsertValue is an LLVM IR insertvalue instruction. @@ -134,6 +139,11 @@ func (inst *InstInsertValue) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstInsertValue) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Elem} +} + // ### [ Helper functions ] #################################################### // aggregateElemType returns the element type at the position in the aggregate diff --git a/ir/inst_binary.go b/ir/inst_binary.go index 23b405d8..2ee9f93e 100644 --- a/ir/inst_binary.go +++ b/ir/inst_binary.go @@ -70,6 +70,11 @@ func (inst *InstAdd) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstAdd) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} + // ~~~ [ fadd ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstFAdd is an LLVM IR fadd instruction. @@ -129,6 +134,11 @@ func (inst *InstFAdd) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstFAdd) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} + // ~~~ [ sub ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstSub is an LLVM IR sub instruction. @@ -188,6 +198,11 @@ func (inst *InstSub) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstSub) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} + // ~~~ [ fsub ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstFSub is an LLVM IR fsub instruction. @@ -247,6 +262,11 @@ func (inst *InstFSub) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstFSub) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} + // ~~~ [ mul ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstMul is an LLVM IR mul instruction. @@ -306,6 +326,11 @@ func (inst *InstMul) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstMul) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} + // ~~~ [ fmul ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstFMul is an LLVM IR fmul instruction. @@ -365,6 +390,11 @@ func (inst *InstFMul) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstFMul) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} + // ~~~ [ udiv ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstUDiv is an LLVM IR udiv instruction. @@ -424,6 +454,11 @@ func (inst *InstUDiv) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstUDiv) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} + // ~~~ [ sdiv ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstSDiv is an LLVM IR sdiv instruction. @@ -483,6 +518,11 @@ func (inst *InstSDiv) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstSDiv) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} + // ~~~ [ fdiv ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstFDiv is an LLVM IR fdiv instruction. @@ -542,6 +582,11 @@ func (inst *InstFDiv) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstFDiv) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} + // ~~~ [ urem ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstURem is an LLVM IR urem instruction. @@ -595,6 +640,11 @@ func (inst *InstURem) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstURem) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} + // ~~~ [ srem ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstSRem is an LLVM IR srem instruction. @@ -648,6 +698,11 @@ func (inst *InstSRem) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstSRem) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} + // ~~~ [ frem ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstFRem is an LLVM IR frem instruction. @@ -706,3 +761,8 @@ func (inst *InstFRem) LLString() string { } return buf.String() } + +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstFRem) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} diff --git a/ir/inst_bitwise.go b/ir/inst_bitwise.go index 5fee28fc..fcde071c 100644 --- a/ir/inst_bitwise.go +++ b/ir/inst_bitwise.go @@ -70,6 +70,11 @@ func (inst *InstShl) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstShl) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} + // ~~~ [ lshr ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstLShr is an LLVM IR lshr instruction. @@ -129,6 +134,11 @@ func (inst *InstLShr) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstLShr) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} + // ~~~ [ ashr ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstAShr is an LLVM IR ashr instruction. @@ -188,6 +198,11 @@ func (inst *InstAShr) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstAShr) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} + // ~~~ [ and ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstAnd is an LLVM IR and instruction. @@ -241,6 +256,11 @@ func (inst *InstAnd) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstAnd) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} + // ~~~ [ or ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstOr is an LLVM IR or instruction. @@ -294,6 +314,11 @@ func (inst *InstOr) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstOr) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} + // ~~~ [ xor ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstXor is an LLVM IR xor instruction. @@ -346,3 +371,8 @@ func (inst *InstXor) LLString() string { } return buf.String() } + +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstXor) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} diff --git a/ir/inst_conversion.go b/ir/inst_conversion.go index e60954ac..9c7de158 100644 --- a/ir/inst_conversion.go +++ b/ir/inst_conversion.go @@ -84,6 +84,11 @@ func (inst *InstTrunc) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstTrunc) Operands() []*value.Value { + return []*value.Value{&inst.From} +} + // ~~~ [ zext ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstZExt is an LLVM IR zext instruction. @@ -131,6 +136,11 @@ func (inst *InstZExt) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstZExt) Operands() []*value.Value { + return []*value.Value{&inst.From} +} + // ~~~ [ sext ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstSExt is an LLVM IR sext instruction. @@ -178,6 +188,11 @@ func (inst *InstSExt) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstSExt) Operands() []*value.Value { + return []*value.Value{&inst.From} +} + // ~~~ [ fptrunc ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstFPTrunc is an LLVM IR fptrunc instruction. @@ -225,6 +240,11 @@ func (inst *InstFPTrunc) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstFPTrunc) Operands() []*value.Value { + return []*value.Value{&inst.From} +} + // ~~~ [ fpext ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstFPExt is an LLVM IR fpext instruction. @@ -272,6 +292,11 @@ func (inst *InstFPExt) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstFPExt) Operands() []*value.Value { + return []*value.Value{&inst.From} +} + // ~~~ [ fptoui ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstFPToUI is an LLVM IR fptoui instruction. @@ -319,6 +344,11 @@ func (inst *InstFPToUI) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstFPToUI) Operands() []*value.Value { + return []*value.Value{&inst.From} +} + // ~~~ [ fptosi ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstFPToSI is an LLVM IR fptosi instruction. @@ -366,6 +396,11 @@ func (inst *InstFPToSI) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstFPToSI) Operands() []*value.Value { + return []*value.Value{&inst.From} +} + // ~~~ [ uitofp ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstUIToFP is an LLVM IR uitofp instruction. @@ -413,6 +448,11 @@ func (inst *InstUIToFP) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstUIToFP) Operands() []*value.Value { + return []*value.Value{&inst.From} +} + // ~~~ [ sitofp ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstSIToFP is an LLVM IR sitofp instruction. @@ -460,6 +500,11 @@ func (inst *InstSIToFP) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstSIToFP) Operands() []*value.Value { + return []*value.Value{&inst.From} +} + // ~~~ [ ptrtoint ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstPtrToInt is an LLVM IR ptrtoint instruction. @@ -507,6 +552,11 @@ func (inst *InstPtrToInt) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstPtrToInt) Operands() []*value.Value { + return []*value.Value{&inst.From} +} + // ~~~ [ inttoptr ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstIntToPtr is an LLVM IR inttoptr instruction. @@ -554,6 +604,11 @@ func (inst *InstIntToPtr) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstIntToPtr) Operands() []*value.Value { + return []*value.Value{&inst.From} +} + // ~~~ [ bitcast ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstBitCast is an LLVM IR bitcast instruction. @@ -601,6 +656,11 @@ func (inst *InstBitCast) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstBitCast) Operands() []*value.Value { + return []*value.Value{&inst.From} +} + // ~~~ [ addrspacecast ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstAddrSpaceCast is an LLVM IR addrspacecast instruction. @@ -647,3 +707,8 @@ func (inst *InstAddrSpaceCast) LLString() string { } return buf.String() } + +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstAddrSpaceCast) Operands() []*value.Value { + return []*value.Value{&inst.From} +} diff --git a/ir/inst_memory.go b/ir/inst_memory.go index 99648f75..e24c4811 100644 --- a/ir/inst_memory.go +++ b/ir/inst_memory.go @@ -94,6 +94,14 @@ func (inst *InstAlloca) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstAlloca) Operands() []*value.Value { + if inst.NElems != nil { + return []*value.Value{&inst.NElems} + } + return nil +} + // ~~~ [ load ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstLoad is an LLVM IR load instruction. @@ -174,6 +182,11 @@ func (inst *InstLoad) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstLoad) Operands() []*value.Value { + return []*value.Value{&inst.Src} +} + // ~~~ [ store ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstStore is an LLVM IR store instruction. @@ -247,6 +260,11 @@ func (inst *InstStore) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstStore) Operands() []*value.Value { + return []*value.Value{&inst.Src, &inst.Dst} +} + // ~~~ [ fence ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstFence is an LLVM IR fence instruction. @@ -283,6 +301,11 @@ func (inst *InstFence) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstFence) Operands() []*value.Value { + return nil +} + // ~~~ [ cmpxchg ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstCmpXchg is an LLVM IR cmpxchg instruction. @@ -368,6 +391,11 @@ func (inst *InstCmpXchg) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstCmpXchg) Operands() []*value.Value { + return []*value.Value{&inst.Ptr, &inst.Cmp, &inst.New} +} + // ~~~ [ atomicrmw ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstAtomicRMW is an LLVM IR atomicrmw instruction. @@ -444,6 +472,11 @@ func (inst *InstAtomicRMW) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstAtomicRMW) Operands() []*value.Value { + return []*value.Value{&inst.Dst, &inst.X} +} + // ~~~ [ getelementptr ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstGetElementPtr is an LLVM IR getelementptr instruction. @@ -511,6 +544,16 @@ func (inst *InstGetElementPtr) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstGetElementPtr) Operands() []*value.Value { + ops := make([]*value.Value, 0, 1+len(inst.Indices)) + ops = append(ops, &inst.Src) + for i := range inst.Indices { + ops = append(ops, &inst.Indices[i]) + } + return ops +} + // ### [ Helper functions ] #################################################### // gepInstType computes the result type of a getelementptr instruction. diff --git a/ir/inst_other.go b/ir/inst_other.go index 4d27c325..831bbb36 100644 --- a/ir/inst_other.go +++ b/ir/inst_other.go @@ -75,6 +75,11 @@ func (inst *InstICmp) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstICmp) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} + // ~~~ [ fcmp ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstFCmp is an LLVM IR fcmp instruction. @@ -145,6 +150,11 @@ func (inst *InstFCmp) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstFCmp) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y} +} + // ~~~ [ phi ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstPhi is an LLVM IR phi instruction. @@ -213,6 +223,16 @@ func (inst *InstPhi) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstPhi) Operands() []*value.Value { + ops := make([]*value.Value, 0, 2*len(inst.Incs)) + for i := range inst.Incs { + ops = append(ops, &inst.Incs[i].X) + ops = append(ops, &inst.Incs[i].Pred) + } + return ops +} + // ___ [ Incoming value ] ______________________________________________________ // Incoming is an incoming value of a phi instruction. @@ -299,6 +319,11 @@ func (inst *InstSelect) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstSelect) Operands() []*value.Value { + return []*value.Value{&inst.Cond, &inst.ValueTrue, &inst.ValueFalse} +} + // ~~~ [ freeze ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstFreeze is an LLVM IR freeze instruction. @@ -352,6 +377,11 @@ func (inst *InstFreeze) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstFreeze) Operands() []*value.Value { + return []*value.Value{&inst.X} +} + // ~~~ [ call ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstCall is an LLVM IR call instruction. @@ -475,6 +505,16 @@ func (inst *InstCall) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstCall) Operands() []*value.Value { + ops := make([]*value.Value, 0, 1+len(inst.Args)) + ops = append(ops, &inst.Callee) + for i := range inst.Args { + ops = append(ops, &inst.Args[i]) + } + return ops +} + // Sig returns the function signature of the callee. func (inst *InstCall) Sig() *types.FuncType { t, ok := inst.Callee.Type().(*types.PointerType) @@ -535,6 +575,11 @@ func (inst *InstVAArg) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstVAArg) Operands() []*value.Value { + return []*value.Value{&inst.ArgList} +} + // ~~~ [ landingpad ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstLandingPad is an LLVM IR landingpad instruction. @@ -591,6 +636,15 @@ func (inst *InstLandingPad) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstLandingPad) Operands() []*value.Value { + ops := make([]*value.Value, 0, len(inst.Clauses)) + for i := range inst.Clauses { + ops = append(ops, &inst.Clauses[i].X) + } + return ops +} + // ___ [ Landingpad clause ] ___________________________________________________ // Clause is a landingpad catch or filter clause. @@ -670,6 +724,16 @@ func (inst *InstCatchPad) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstCatchPad) Operands() []*value.Value { + ops := make([]*value.Value, 0, 1+len(inst.Args)) + ops = append(ops, &inst.CatchSwitch) + for i := range inst.Args { + ops = append(ops, &inst.Args[i]) + } + return ops +} + // ~~~ [ cleanuppad ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstCleanupPad is an LLVM IR cleanuppad instruction. @@ -727,3 +791,13 @@ func (inst *InstCleanupPad) LLString() string { } return buf.String() } + +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstCleanupPad) Operands() []*value.Value { + ops := make([]*value.Value, 0, 1+len(inst.Args)) + ops = append(ops, &inst.ParentPad) + for i := range inst.Args { + ops = append(ops, &inst.Args[i]) + } + return ops +} diff --git a/ir/inst_unary.go b/ir/inst_unary.go index 2ff4707e..e3130f84 100644 --- a/ir/inst_unary.go +++ b/ir/inst_unary.go @@ -69,3 +69,8 @@ func (inst *InstFNeg) LLString() string { } return buf.String() } + +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstFNeg) Operands() []*value.Value { + return []*value.Value{&inst.X} +} diff --git a/ir/inst_vector.go b/ir/inst_vector.go index 75f9c88b..746922f7 100644 --- a/ir/inst_vector.go +++ b/ir/inst_vector.go @@ -70,6 +70,11 @@ func (inst *InstExtractElement) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstExtractElement) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Index} +} + // ~~~ [ insertelement ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstInsertElement is an LLVM IR insertelement instruction. @@ -133,6 +138,11 @@ func (inst *InstInsertElement) LLString() string { return buf.String() } +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstInsertElement) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Elem, &inst.Index} +} + // ~~~ [ shufflevector ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // InstShuffleVector is an LLVM IR shufflevector instruction. @@ -197,3 +207,8 @@ func (inst *InstShuffleVector) LLString() string { } return buf.String() } + +// Operands returns a mutable list of operands of the given instruction. +func (inst *InstShuffleVector) Operands() []*value.Value { + return []*value.Value{&inst.X, &inst.Y, &inst.Mask} +} diff --git a/ir/instruction.go b/ir/instruction.go index d14df24f..063c8aae 100644 --- a/ir/instruction.go +++ b/ir/instruction.go @@ -1,5 +1,7 @@ package ir +import "github.com/llir/llvm/ir/value" + // === [ Instructions ] ======================================================== // Instruction is an LLVM IR instruction. All instructions (except store and @@ -106,4 +108,6 @@ type Instruction interface { // isInstruction ensures that only instructions can be assigned to the // instruction.Instruction interface. isInstruction() + // Instruction implements the value.User interface. + value.User } diff --git a/ir/terminator.go b/ir/terminator.go index df12e5bc..3b1cc290 100644 --- a/ir/terminator.go +++ b/ir/terminator.go @@ -36,6 +36,8 @@ type Terminator interface { LLStringer // Succs returns the successor basic blocks of the terminator. Succs() []*Block + // Terminator implements the value.User interface. + value.User } // --- [ ret ] ----------------------------------------------------------------- @@ -63,6 +65,14 @@ func (*TermRet) Succs() []*Block { return nil } +// Operands returns a mutable list of operands of the given terminator. +func (term *TermRet) Operands() []*value.Value { + if term.X != nil { + return []*value.Value{&term.X} + } + return nil +} + // LLString returns the LLVM syntax representation of the terminator. // // Void return instruction. @@ -115,6 +125,11 @@ func (term *TermBr) Succs() []*Block { return term.Successors } +// Operands returns a mutable list of operands of the given terminator. +func (term *TermBr) Operands() []*value.Value { + return []*value.Value{&term.Target} +} + // LLString returns the LLVM syntax representation of the terminator. // // 'br' Target=Label Metadata=(',' MetadataAttachment)+? @@ -161,6 +176,11 @@ func (term *TermCondBr) Succs() []*Block { return term.Successors } +// Operands returns a mutable list of operands of the given terminator. +func (term *TermCondBr) Operands() []*value.Value { + return []*value.Value{&term.Cond, &term.TargetTrue, &term.TargetFalse} +} + // LLString returns the LLVM syntax representation of the terminator. // // 'br' CondTyp=IntType Cond=Value ',' TargetTrue=Label ',' TargetFalse=Label Metadata=(',' MetadataAttachment)+? @@ -212,6 +232,18 @@ func (term *TermSwitch) Succs() []*Block { return term.Successors } +// Operands returns a mutable list of operands of the given terminator. +func (term *TermSwitch) Operands() []*value.Value { + ops := make([]*value.Value, 0, 1+1+2*len(term.Cases)) + ops = append(ops, &term.X) + ops = append(ops, &term.TargetDefault) + for i := range term.Cases { + ops = append(ops, &term.Cases[i].X) + ops = append(ops, &term.Cases[i].Target) + } + return ops +} + // LLString returns the LLVM syntax representation of the terminator. // // 'switch' X=TypeValue ',' Default=Label '[' Cases=Case* ']' Metadata=(',' MetadataAttachment)+? @@ -291,6 +323,16 @@ func (term *TermIndirectBr) Succs() []*Block { return term.Successors } +// Operands returns a mutable list of operands of the given terminator. +func (term *TermIndirectBr) Operands() []*value.Value { + ops := make([]*value.Value, 0, 1+len(term.ValidTargets)) + ops = append(ops, &term.Addr) + for i := range term.ValidTargets { + ops = append(ops, &term.ValidTargets[i]) + } + return ops +} + // LLString returns the LLVM syntax representation of the terminator. // // 'indirectbr' Addr=TypeValue ',' '[' ValidTargets=(Label separator ',')* ']' Metadata=(',' MetadataAttachment)+? @@ -387,6 +429,18 @@ func (term *TermInvoke) Succs() []*Block { return term.Successors } +// Operands returns a mutable list of operands of the given terminator. +func (term *TermInvoke) Operands() []*value.Value { + ops := make([]*value.Value, 0, 1+len(term.Args)+1+1) + ops = append(ops, &term.Invokee) + for i := range term.Args { + ops = append(ops, &term.Args[i]) + } + ops = append(ops, &term.NormalRetTarget) + ops = append(ops, &term.ExceptionRetTarget) + return ops +} + // LLString returns the LLVM syntax representation of the terminator. // // 'invoke' CallingConvopt ReturnAttrs=ReturnAttribute* AddrSpaceopt Typ=Type Invokee=Value '(' Args ')' FuncAttrs=FuncAttribute* OperandBundles=('[' (OperandBundle separator ',')+ ']')? 'to' NormalRetTarget=Label 'unwind' ExceptionRetTarget=Label Metadata=(',' MetadataAttachment)+? @@ -538,6 +592,20 @@ func (term *TermCallBr) Succs() []*Block { return term.Successors } +// Operands returns a mutable list of operands of the given terminator. +func (term *TermCallBr) Operands() []*value.Value { + ops := make([]*value.Value, 0, 1+len(term.Args)+1+len(term.OtherRetTargets)) + ops = append(ops, &term.Callee) + for i := range term.Args { + ops = append(ops, &term.Args[i]) + } + ops = append(ops, &term.NormalRetTarget) + for i := range term.OtherRetTargets { + ops = append(ops, &term.OtherRetTargets[i]) + } + return ops +} + // LLString returns the LLVM syntax representation of the terminator. // // 'callbr' CallingConvopt ReturnAttrs=ReturnAttribute* AddrSpaceopt Typ=Type Callee=Value '(' Args ')' FuncAttrs=FuncAttribute* OperandBundles=('[' (OperandBundle separator ',')+ ']')? 'to' NormalRetTarget=Label '[' OtherRetTargets=(Label separator ',')* ']' Metadata=(',' MetadataAttachment)+? @@ -635,6 +703,11 @@ func (term *TermResume) Succs() []*Block { return nil } +// Operands returns a mutable list of operands of the given terminator. +func (term *TermResume) Operands() []*value.Value { + return []*value.Value{&term.X} +} + // LLString returns the LLVM syntax representation of the terminator. // // 'resume' X=TypeValue Metadata=(',' MetadataAttachment)+? @@ -716,6 +789,19 @@ func (term *TermCatchSwitch) Succs() []*Block { return term.Successors } +// Operands returns a mutable list of operands of the given terminator. +func (term *TermCatchSwitch) Operands() []*value.Value { + ops := make([]*value.Value, 0, 1+len(term.Handlers)+1) + ops = append(ops, &term.ParentPad) + for i := range term.Handlers { + ops = append(ops, &term.Handlers[i]) + } + if term.DefaultUnwindTarget != nil { + ops = append(ops, &term.DefaultUnwindTarget) + } + return ops +} + // LLString returns the LLVM syntax representation of the terminator. // // 'catchswitch' 'within' ParentPad=ExceptionPad '[' Handlers=Handlers ']' 'unwind' DefaultUnwindTarget=UnwindTarget Metadata=(',' MetadataAttachment)+? @@ -774,6 +860,11 @@ func (term *TermCatchRet) Succs() []*Block { return term.Successors } +// Operands returns a mutable list of operands of the given terminator. +func (term *TermCatchRet) Operands() []*value.Value { + return []*value.Value{&term.CatchPad, &term.Target} +} + // LLString returns the LLVM syntax representation of the terminator. // // 'catchret' 'from' CatchPad=Value 'to' Target=Label Metadata=(',' MetadataAttachment)+? @@ -835,6 +926,15 @@ func (term *TermCleanupRet) Succs() []*Block { return term.Successors } +// Operands returns a mutable list of operands of the given terminator. +func (term *TermCleanupRet) Operands() []*value.Value { + ops := []*value.Value{&term.CleanupPad} + if term.UnwindTarget != nil { + ops = append(ops, &term.UnwindTarget) + } + return ops +} + // LLString returns the LLVM syntax representation of the terminator. // // 'cleanupret' 'from' CleanupPad=Value 'unwind' UnwindTarget Metadata=(',' MetadataAttachment)+? @@ -873,6 +973,11 @@ func (term *TermUnreachable) Succs() []*Block { return nil } +// Operands returns a mutable list of operands of the given terminator. +func (term *TermUnreachable) Operands() []*value.Value { + return nil +} + // LLString returns the LLVM syntax representation of the terminator. // // 'unreachable' Metadata=(',' MetadataAttachment)+? From 53e3f588803e524c8b682c17f723a550c311b5fa Mon Sep 17 00:00:00 2001 From: Robin Eklind Date: Thu, 20 Jan 2022 01:43:31 +0100 Subject: [PATCH 3/5] ir: add TermCallBr test case for implementing the Terminator interface ref: https://github.com/llir/llvm/commit/2a7b338c3839767f6efea10234c3ef565d5bb0b7#diff-0bff324d3c7f097ff5979f8db0d689bfa690c80eeb774d741a50987773c0b4c8 --- ir/ir_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ir/ir_test.go b/ir/ir_test.go index 3e7c24a0..7f4bf0fe 100644 --- a/ir/ir_test.go +++ b/ir/ir_test.go @@ -120,6 +120,7 @@ var ( _ Terminator = (*TermSwitch)(nil) _ Terminator = (*TermIndirectBr)(nil) _ Terminator = (*TermInvoke)(nil) + _ Terminator = (*TermCallBr)(nil) _ Terminator = (*TermResume)(nil) _ Terminator = (*TermCatchSwitch)(nil) _ Terminator = (*TermCatchRet)(nil) @@ -210,5 +211,6 @@ var ( // Terminators. _ value.Named = (*TermInvoke)(nil) + _ value.Named = (*TermCallBr)(nil) _ value.Named = (*TermCatchSwitch)(nil) // token result used by catchpad ) From 79a5aaa100908553a7882877cf74d5a533040f8d Mon Sep 17 00:00:00 2001 From: Robin Eklind Date: Thu, 20 Jan 2022 01:45:55 +0100 Subject: [PATCH 4/5] ir: add InstFNeg test case for implementing the Instruction interface ref: https://github.com/llir/llvm/commit/bf083a795600de0d09779a666dc51555c0f9bf8d#diff-0bff324d3c7f097ff5979f8db0d689bfa690c80eeb774d741a50987773c0b4c8 --- ir/ir_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ir/ir_test.go b/ir/ir_test.go index 7f4bf0fe..48ffd0a2 100644 --- a/ir/ir_test.go +++ b/ir/ir_test.go @@ -50,6 +50,8 @@ var ( // Assert that each instruction implements the ir.Instruction interface. var ( + // Unary instructions. + _ Instruction = (*InstFNeg)(nil) // Binary instructions. _ Instruction = (*InstAdd)(nil) _ Instruction = (*InstFAdd)(nil) @@ -151,6 +153,8 @@ var ( _ value.Named = (*Block)(nil) // Instructions. + // Unary instructions. + _ value.Named = (*InstFNeg)(nil) // Binary instructions. _ value.Named = (*InstAdd)(nil) _ value.Named = (*InstFAdd)(nil) From f38394a0c5be314779b8f902a59c1ec7199b4ca9 Mon Sep 17 00:00:00 2001 From: Robin Eklind Date: Thu, 20 Jan 2022 01:47:27 +0100 Subject: [PATCH 5/5] ir: add InstFreeze test case for implementing the Instruction interface ref: https://github.com/llir/llvm/commit/5444acf5b3cd1c86b5c3e0533ebeed24e02354af#diff-0bff324d3c7f097ff5979f8db0d689bfa690c80eeb774d741a50987773c0b4c8 --- ir/ir_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ir/ir_test.go b/ir/ir_test.go index 48ffd0a2..a2933d5c 100644 --- a/ir/ir_test.go +++ b/ir/ir_test.go @@ -106,6 +106,7 @@ var ( _ Instruction = (*InstFCmp)(nil) _ Instruction = (*InstPhi)(nil) _ Instruction = (*InstSelect)(nil) + _ Instruction = (*InstFreeze)(nil) _ Instruction = (*InstCall)(nil) _ Instruction = (*InstVAArg)(nil) _ Instruction = (*InstLandingPad)(nil) @@ -207,6 +208,7 @@ var ( _ value.Named = (*InstFCmp)(nil) _ value.Named = (*InstPhi)(nil) _ value.Named = (*InstSelect)(nil) + _ value.Named = (*InstFreeze)(nil) _ value.Named = (*InstCall)(nil) _ value.Named = (*InstVAArg)(nil) _ value.Named = (*InstLandingPad)(nil)