ForN builds a logic block with the following psuedocode: for it := 0; it < n; it++ { cont := cb() if cont == false { break; } } If cb returns nil then the loop will never exit early.
(n *Value, cb func(iterator *Value) (cont *Value))
| 223 | // |
| 224 | // If cb returns nil then the loop will never exit early. |
| 225 | func (b *Builder) ForN(n *Value, cb func(iterator *Value) (cont *Value)) { |
| 226 | one := llvm.ConstInt(n.Type().llvmTy(), 1, false) |
| 227 | zero := b.Zero(n.Type()) |
| 228 | iterator := b.LocalInit("loop_iterator", zero) |
| 229 | |
| 230 | test := b.m.ctx.AddBasicBlock(b.function.llvm, "for_n_test") |
| 231 | loop := b.m.ctx.AddBasicBlock(b.function.llvm, "for_n_loop") |
| 232 | exit := b.m.ctx.AddBasicBlock(b.function.llvm, "for_n_exit") |
| 233 | |
| 234 | b.llvm.CreateBr(test) |
| 235 | |
| 236 | b.block(test, llvm.BasicBlock{}, func() { |
| 237 | done := b.llvm.CreateICmp(llvm.IntSLT, iterator.Load().llvm, n.llvm, "for_n_condition") |
| 238 | b.llvm.CreateCondBr(done, loop, exit) |
| 239 | }) |
| 240 | |
| 241 | b.block(loop, llvm.BasicBlock{}, func() { |
| 242 | it := iterator.Load() |
| 243 | cont := cb(it) |
| 244 | if b.IsBlockTerminated() { |
| 245 | return |
| 246 | } |
| 247 | b.llvm.CreateStore(b.llvm.CreateAdd(it.llvm, one, "for_n_iterator_inc"), iterator.llvm) |
| 248 | if cont == nil { |
| 249 | b.llvm.CreateBr(test) |
| 250 | } else { |
| 251 | assertTypesEqual(cont.ty, b.m.Types.Bool) |
| 252 | b.llvm.CreateCondBr(cont.llvm, test, exit) |
| 253 | } |
| 254 | }) |
| 255 | |
| 256 | b.setInsertPointAtEnd(exit) |
| 257 | } |
| 258 | |
| 259 | // SwitchCase is a single condition and block used as a case statement in a |
| 260 | // switch. |
nothing calls this directly
no test coverage detected