| 315 | } |
| 316 | |
| 317 | int Function::GetBlockDepth(BasicBlock* bb) { |
| 318 | // Guard against nullptr. |
| 319 | if (!bb) { |
| 320 | return 0; |
| 321 | } |
| 322 | // Only calculate the depth if it's not already calculated. |
| 323 | // This function uses memoization to avoid duplicate CFG depth calculations. |
| 324 | if (block_depth_.find(bb) != block_depth_.end()) { |
| 325 | return block_depth_[bb]; |
| 326 | } |
| 327 | // Avoid recursion. Something is wrong if the same block is encountered |
| 328 | // multiple times. |
| 329 | block_depth_[bb] = 0; |
| 330 | |
| 331 | BasicBlock* bb_dom = bb->immediate_dominator(); |
| 332 | if (!bb_dom || bb == bb_dom) { |
| 333 | // This block has no dominator, so it's at depth 0. |
| 334 | block_depth_[bb] = 0; |
| 335 | } else if (bb->is_type(kBlockTypeContinue)) { |
| 336 | // This rule must precede the rule for merge blocks in order to set up |
| 337 | // depths correctly. If a block is both a merge and continue then the merge |
| 338 | // is nested within the continue's loop (or the graph is incorrect). |
| 339 | // The depth of the continue block entry point is 1 + loop header depth. |
| 340 | Construct* continue_construct = |
| 341 | entry_block_to_construct_[std::make_pair(bb, ConstructType::kContinue)]; |
| 342 | assert(continue_construct); |
| 343 | // Continue construct has only 1 corresponding construct (loop header). |
| 344 | Construct* loop_construct = |
| 345 | continue_construct->corresponding_constructs()[0]; |
| 346 | assert(loop_construct); |
| 347 | BasicBlock* loop_header = loop_construct->entry_block(); |
| 348 | // The continue target may be the loop itself (while 1). |
| 349 | // In such cases, the depth of the continue block is: 1 + depth of the |
| 350 | // loop's dominator block. |
| 351 | if (loop_header == bb) { |
| 352 | block_depth_[bb] = 1 + GetBlockDepth(bb_dom); |
| 353 | } else { |
| 354 | block_depth_[bb] = 1 + GetBlockDepth(loop_header); |
| 355 | } |
| 356 | } else if (bb->is_type(kBlockTypeMerge)) { |
| 357 | // If this is a merge block, its depth is equal to the block before |
| 358 | // branching. |
| 359 | BasicBlock* header = merge_block_header_[bb]; |
| 360 | assert(header); |
| 361 | block_depth_[bb] = GetBlockDepth(header); |
| 362 | } else if (bb_dom->is_type(kBlockTypeSelection) || |
| 363 | bb_dom->is_type(kBlockTypeLoop)) { |
| 364 | // The dominator of the given block is a header block. So, the nesting |
| 365 | // depth of this block is: 1 + nesting depth of the header. |
| 366 | block_depth_[bb] = 1 + GetBlockDepth(bb_dom); |
| 367 | } else { |
| 368 | block_depth_[bb] = GetBlockDepth(bb_dom); |
| 369 | } |
| 370 | return block_depth_[bb]; |
| 371 | } |
| 372 | |
| 373 | void Function::RegisterExecutionModelLimitation(spv::ExecutionModel model, |
| 374 | const std::string& message) { |
no test coverage detected