SplitBasicBlock splits a LLVM basic block into two parts. All instructions after afterInst are moved into a new basic block (created right after the current one) with the given name.
(builder llvm.Builder, afterInst llvm.Value, insertAfter llvm.BasicBlock, name string)
| 109 | // after afterInst are moved into a new basic block (created right after the |
| 110 | // current one) with the given name. |
| 111 | func SplitBasicBlock(builder llvm.Builder, afterInst llvm.Value, insertAfter llvm.BasicBlock, name string) llvm.BasicBlock { |
| 112 | oldBlock := afterInst.InstructionParent() |
| 113 | newBlock := afterInst.Type().Context().InsertBasicBlock(insertAfter, name) |
| 114 | var nextInstructions []llvm.Value // values to move |
| 115 | |
| 116 | // Collect to-be-moved instructions. |
| 117 | inst := afterInst |
| 118 | for { |
| 119 | inst = llvm.NextInstruction(inst) |
| 120 | if inst.IsNil() { |
| 121 | break |
| 122 | } |
| 123 | nextInstructions = append(nextInstructions, inst) |
| 124 | } |
| 125 | |
| 126 | // Move instructions. |
| 127 | builder.SetInsertPointAtEnd(newBlock) |
| 128 | for _, inst := range nextInstructions { |
| 129 | inst.RemoveFromParentAsInstruction() |
| 130 | builder.Insert(inst) |
| 131 | } |
| 132 | |
| 133 | // Find PHI nodes to update. |
| 134 | var phiNodes []llvm.Value // PHI nodes to update |
| 135 | for bb := insertAfter.Parent().FirstBasicBlock(); !bb.IsNil(); bb = llvm.NextBasicBlock(bb) { |
| 136 | for inst := bb.FirstInstruction(); !inst.IsNil(); inst = llvm.NextInstruction(inst) { |
| 137 | if inst.IsAPHINode().IsNil() { |
| 138 | continue |
| 139 | } |
| 140 | needsUpdate := false |
| 141 | incomingCount := inst.IncomingCount() |
| 142 | for i := 0; i < incomingCount; i++ { |
| 143 | if inst.IncomingBlock(i) == oldBlock { |
| 144 | needsUpdate = true |
| 145 | break |
| 146 | } |
| 147 | } |
| 148 | if !needsUpdate { |
| 149 | // PHI node has no incoming edge from the old block. |
| 150 | continue |
| 151 | } |
| 152 | phiNodes = append(phiNodes, inst) |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | // Update PHI nodes. |
| 157 | for _, phi := range phiNodes { |
| 158 | builder.SetInsertPointBefore(phi) |
| 159 | newPhi := builder.CreatePHI(phi.Type(), "") |
| 160 | incomingCount := phi.IncomingCount() |
| 161 | incomingVals := make([]llvm.Value, incomingCount) |
| 162 | incomingBlocks := make([]llvm.BasicBlock, incomingCount) |
| 163 | for i := 0; i < incomingCount; i++ { |
| 164 | value := phi.IncomingValue(i) |
| 165 | block := phi.IncomingBlock(i) |
| 166 | if block == oldBlock { |
| 167 | block = newBlock |
| 168 | } |