diff options
author | Hans-Kristian Arntzen <post@arntzen-software.no> | 2022-04-28 13:44:44 +0300 |
---|---|---|
committer | Hans-Kristian Arntzen <post@arntzen-software.no> | 2022-04-28 13:49:34 +0300 |
commit | c54fb6b208aab6de30ded82b6f1a0cb7dd8f52c7 (patch) | |
tree | ee7aaf25c199e27df3b70532b685be235ad784db | |
parent | 4b15e8564ff0d9c9da81edde4bf6e5dbcd49ae69 (diff) |
Handle infinite loops when emitting SPIR-V.
-rw-r--r-- | spirv_module.cpp | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/spirv_module.cpp b/spirv_module.cpp index c7d56db..4f5b957 100644 --- a/spirv_module.cpp +++ b/spirv_module.cpp @@ -784,12 +784,15 @@ void SPIRVModule::Impl::emit_basic_block(CFGNode *node) builder.setBuildPoint(bb); - spv::Block *fake_incoming_block = nullptr; + spv::Block *fake_loop_block = nullptr; + + // Break-like loops might not have a continue block. + // Infinite loops won't have merge blocks. if (node->ir.merge_info.merge_type == MergeType::Loop && - node->ir.merge_info.merge_block && - !node->ir.merge_info.continue_block) + (int(node->ir.merge_info.merge_block != nullptr) + + int(node->ir.merge_info.continue_block != nullptr) == 1)) { - fake_incoming_block = new spv::Block(builder.getUniqueId(), *active_function); + fake_loop_block = new spv::Block(builder.getUniqueId(), *active_function); } // Emit phi nodes. @@ -805,12 +808,12 @@ void SPIRVModule::Impl::emit_basic_block(CFGNode *node) phi_op->addIdOperand(incoming.block->id); } - if (fake_incoming_block) + if (fake_loop_block && !node->ir.merge_info.continue_block) { - builder.setBuildPoint(fake_incoming_block); + builder.setBuildPoint(fake_loop_block); phi_op->addIdOperand(builder.createUndefined(phi.type_id)); builder.setBuildPoint(bb); - phi_op->addIdOperand(fake_incoming_block->getId()); + phi_op->addIdOperand(fake_loop_block->getId()); } bb->addInstruction(std::move(phi_op)); @@ -947,13 +950,21 @@ void SPIRVModule::Impl::emit_basic_block(CFGNode *node) } else if (ir.merge_info.merge_block) { - auto *continue_bb = fake_incoming_block; + auto *continue_bb = fake_loop_block; active_function->addBlock(continue_bb); builder.setBuildPoint(continue_bb); builder.createBranch(get_spv_block(node)); builder.setBuildPoint(bb); builder.createLoopMerge(get_spv_block(ir.merge_info.merge_block), continue_bb, 0); - break; + } + else if (ir.merge_info.continue_block) + { + auto *merge_bb = fake_loop_block; + active_function->addBlock(merge_bb); + builder.setBuildPoint(merge_bb); + builder.createUnreachable(); + builder.setBuildPoint(bb); + builder.createLoopMerge(merge_bb, get_spv_block(ir.merge_info.continue_block), 0); } break; |