| 299 | } |
| 300 | |
| 301 | int Function::GetBlockDepth(BasicBlock* bb) { |
| 302 | // Guard against nullptr. |
| 303 | if (!bb) { |
| 304 | return 0; |
| 305 | } |
| 306 | // Only calculate the depth if it's not already calculated. |
| 307 | // This function uses memoization to avoid duplicate CFG depth calculations. |
| 308 | if (block_depth_.find(bb) != block_depth_.end()) { |
| 309 | return block_depth_[bb]; |
| 310 | } |
| 311 | |
| 312 | BasicBlock* bb_dom = bb->immediate_dominator(); |
| 313 | if (!bb_dom || bb == bb_dom) { |
| 314 | // This block has no dominator, so it's at depth 0. |
| 315 | block_depth_[bb] = 0; |
| 316 | } else if (bb->is_type(kBlockTypeContinue)) { |
| 317 | // This rule must precede the rule for merge blocks in order to set up |
| 318 | // depths correctly. If a block is both a merge and continue then the merge |
| 319 | // is nested within the continue's loop (or the graph is incorrect). |
| 320 | // The depth of the continue block entry point is 1 + loop header depth. |
| 321 | Construct* continue_construct = |
| 322 | entry_block_to_construct_[std::make_pair(bb, ConstructType::kContinue)]; |
| 323 | assert(continue_construct); |
| 324 | // Continue construct has only 1 corresponding construct (loop header). |
| 325 | Construct* loop_construct = |
| 326 | continue_construct->corresponding_constructs()[0]; |
| 327 | assert(loop_construct); |
| 328 | BasicBlock* loop_header = loop_construct->entry_block(); |
| 329 | // The continue target may be the loop itself (while 1). |
| 330 | // In such cases, the depth of the continue block is: 1 + depth of the |
| 331 | // loop's dominator block. |
| 332 | if (loop_header == bb) { |
| 333 | block_depth_[bb] = 1 + GetBlockDepth(bb_dom); |
| 334 | } else { |
| 335 | block_depth_[bb] = 1 + GetBlockDepth(loop_header); |
| 336 | } |
| 337 | } else if (bb->is_type(kBlockTypeMerge)) { |
| 338 | // If this is a merge block, its depth is equal to the block before |
| 339 | // branching. |
| 340 | BasicBlock* header = merge_block_header_[bb]; |
| 341 | assert(header); |
| 342 | block_depth_[bb] = GetBlockDepth(header); |
| 343 | } else if (bb_dom->is_type(kBlockTypeSelection) || |
| 344 | bb_dom->is_type(kBlockTypeLoop)) { |
| 345 | // The dominator of the given block is a header block. So, the nesting |
| 346 | // depth of this block is: 1 + nesting depth of the header. |
| 347 | block_depth_[bb] = 1 + GetBlockDepth(bb_dom); |
| 348 | } else { |
| 349 | block_depth_[bb] = GetBlockDepth(bb_dom); |
| 350 | } |
| 351 | return block_depth_[bb]; |
| 352 | } |
| 353 | |
| 354 | void Function::RegisterExecutionModelLimitation(SpvExecutionModel model, |
| 355 | const std::string& message) { |
no test coverage detected