MCPcopy Create free account
hub / github.com/KhronosGroup/SPIRV-Tools / FindCaseFallThrough

Function FindCaseFallThrough

source/val/validate_cfg.cpp:497–559  ·  view source on GitHub ↗

Finds the fall through case construct of |target_block| and records it in |case_fall_through|. Returns SPV_ERROR_INVALID_CFG if the case construct headed by |target_block| branches to multiple case constructs.

Source from the content-addressed store, hash-verified

495// |case_fall_through|. Returns SPV_ERROR_INVALID_CFG if the case construct
496// headed by |target_block| branches to multiple case constructs.
497spv_result_t FindCaseFallThrough(
498 ValidationState_t& _, BasicBlock* target_block, uint32_t* case_fall_through,
499 const Construct& switch_construct,
500 const std::unordered_set<uint32_t>& case_targets) {
501 const auto* merge = switch_construct.exit_block();
502 std::vector<BasicBlock*> stack;
503 stack.push_back(target_block);
504 std::unordered_set<const BasicBlock*> visited;
505 bool target_reachable = target_block->structurally_reachable();
506 while (!stack.empty()) {
507 auto block = stack.back();
508 stack.pop_back();
509
510 if (block == merge) continue;
511
512 if (!visited.insert(block).second) continue;
513
514 if (target_reachable && block->structurally_reachable() &&
515 target_block->structurally_dominates(*block)) {
516 // Still in the case construct.
517 for (auto successor : *block->successors()) {
518 stack.push_back(successor);
519 }
520 } else {
521 // Exiting the case construct to non-merge block.
522 if (!case_targets.count(block->id())) {
523 // We have already filtered out the following:
524 // * The switch's merge
525 // * Other case targets
526 // * Blocks in the same case construct
527 //
528 // So the only remaining valid branches are the structured exits from
529 // the overall selection construct of the switch.
530 if (switch_construct.IsStructuredExit(_, block)) {
531 continue;
532 }
533
534 return _.diag(SPV_ERROR_INVALID_CFG, target_block->label())
535 << "Case construct that targets "
536 << _.getIdName(target_block->id())
537 << " has invalid branch to block " << _.getIdName(block->id())
538 << " (not another case construct, corresponding merge, outer "
539 "loop merge or outer loop continue)";
540 }
541
542 if (*case_fall_through == 0u) {
543 if (target_block != block) {
544 *case_fall_through = block->id();
545 }
546 } else if (*case_fall_through != block->id()) {
547 // Case construct has at most one branch to another case construct.
548 return _.diag(SPV_ERROR_INVALID_CFG, target_block->label())
549 << "Case construct that targets "
550 << _.getIdName(target_block->id())
551 << " has branches to multiple other case construct targets "
552 << _.getIdName(*case_fall_through) << " and "
553 << _.getIdName(block->id());
554 }

Callers 1

StructuredSwitchChecksFunction · 0.85

Calls 15

exit_blockMethod · 0.80
backMethod · 0.80
pop_backMethod · 0.80
successorsMethod · 0.80
IsStructuredExitMethod · 0.80
diagMethod · 0.80
labelMethod · 0.80
getIdNameMethod · 0.80
push_backMethod · 0.45
emptyMethod · 0.45

Tested by

no test coverage detected