ScopeNestIterator.h 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // ScopeNestIterator.h //
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. // This file is distributed under the University of Illinois Open Source //
  6. // License. See LICENSE.TXT for details. //
  7. // //
  8. // Implementation of ScopeNestIterator class. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. // The ScopeNestIterator class iterates over a cfg that has been annoated with
  12. // scope markers by the scopenestedcfg pass.
  13. //
  14. // The iterator produces a sequence of ScopeNestEvent tokens as it iterates
  15. // over the cfg. The tokens describe the nesting structure of the cfg and
  16. // the blocks that correspond to the nesting events. Each block will only be
  17. // returned once by the iterator.
  18. //
  19. // Because each block is only returned once some events do not have an
  20. // associated block (i.e. it will be nullptr). This is necessary to handle
  21. // cases where a block has two logical events assocaited with it. For example,
  22. // when a block is the start of an else branch but also starts a new nested if
  23. // scope.
  24. //
  25. // For example, for a nested if-else like this:
  26. // A
  27. // / \
  28. // B C
  29. // | / \
  30. // | D E
  31. // | \ /
  32. // | F
  33. // \ /
  34. // \ /
  35. // X
  36. // We would get an event sequence like this:
  37. //
  38. // @TopLevel_Begin (null)
  39. // @If_Begin (A)
  40. // @Body (B)
  41. // @If_Else (null)
  42. // @IF_Begin (C)
  43. // @Body (D)
  44. // @If_Else (null)
  45. // @Body (E)
  46. // @If_End (F)
  47. // @If_End (X)
  48. // @TopLevel_End (null)
  49. //
  50. // See @ScopeNest.h for details on the scope events.
  51. //
  52. // Note:
  53. // This iterator is implemented in a header file with the intention that
  54. // it will be made into a templated version to support both const and non-const
  55. // iterators.
  56. //
  57. ///////////////////////////////////////////////////////////////////////////////
  58. #pragma once
  59. #include "DxilConvPasses/ScopeNestedCFG.h"
  60. #include "DxilConvPasses/ScopeNest.h"
  61. #include "dxc/Support/Global.h"
  62. #include "llvm/IR/Function.h"
  63. #include "llvm/IR/BasicBlock.h"
  64. #include "llvm/IR/Instruction.h"
  65. #include "llvm/IR/Instructions.h"
  66. #include "llvm/IR/Constant.h"
  67. #include "llvm/IR/Constants.h"
  68. #include "llvm/IR/Metadata.h"
  69. #include "llvm/IR/CFG.h"
  70. #include <stack>
  71. namespace llvm {
  72. class Function;
  73. class BasicBlock;
  74. // The ScopeNestIterator class is a heavy-weight iterator that walks the cfg
  75. // in scope nest order. The iterator keeps a large amount of state while
  76. // iterating and so it is expensive to copy and compare iterators for equality.
  77. // The end() iterator has no state so comparing and copying the end is
  78. // relatively cheap.
  79. //
  80. // The iterator provides a standard c++ iterator interface. All the logic is
  81. // handled by the IteratorState class.
  82. //
  83. class ScopeNestIterator
  84. {
  85. public:
  86. typedef ScopeNestEvent::BlockTy Block; // TODO: make this a template.
  87. static ScopeNestIterator begin(const Function &F) {
  88. return ScopeNestIterator(F.getEntryBlock());
  89. }
  90. static ScopeNestIterator end() {
  91. return ScopeNestIterator();
  92. }
  93. ScopeNestEvent& operator*() {
  94. DXASSERT_NOMSG(!m_state.IsDone());
  95. return m_currentElement;
  96. }
  97. ScopeNestIterator& operator++() {
  98. (void)GetNextElement();
  99. return *this;
  100. }
  101. bool operator==(const ScopeNestIterator &other) const {
  102. return m_state == other.m_state;
  103. }
  104. bool operator!=(const ScopeNestIterator &other) const {
  105. return !(*this == other);
  106. }
  107. private: // Interface
  108. ScopeNestIterator(Block &entry)
  109. : m_state(&entry)
  110. , m_currentElement(ScopeNestEvent::Invalid())
  111. {
  112. // Must advance iterator to first element. Should always succeed.
  113. bool ok = GetNextElement();
  114. DXASSERT_LOCALVAR_NOMSG(ok, ok);
  115. }
  116. ScopeNestIterator()
  117. : m_state(nullptr)
  118. , m_currentElement(ScopeNestEvent::Invalid())
  119. {
  120. }
  121. bool GetNextElement() {
  122. bool ok = m_state.MoveNext();
  123. if (ok) {
  124. m_currentElement = m_state.GetCurrent();
  125. }
  126. return ok;
  127. }
  128. private: // ScopeNestIterator Implementation
  129. // BranchAnnotation
  130. //
  131. // Provides safe access to the scope annotation on the block. Use
  132. // the operator bool() to check if there is an annotation.
  133. // e.g. if (BranchAnnotation a = BranchAnnotation::Read(B)) { ... }
  134. class BranchAnnotation
  135. {
  136. public:
  137. static BranchAnnotation Read(Block *B) {
  138. if (!B) { return BranchAnnotation(); }
  139. const TerminatorInst *end = B->getTerminator();
  140. if (!end) { DXASSERT_NOMSG(false); return BranchAnnotation(); }
  141. MDNode *md = end->getMetadata("dx.BranchKind");
  142. if (!md) { return BranchAnnotation(); }
  143. BranchKind kind = static_cast<BranchKind>(cast<ConstantInt>(cast<ConstantAsMetadata>(md->getOperand(0))->getValue())->getZExtValue());
  144. return BranchAnnotation(kind);
  145. }
  146. BranchAnnotation(BranchKind kind) : Kind(kind) {}
  147. operator bool() const { return IsSome(); }
  148. BranchKind Get() const { DXASSERT_NOMSG(IsSome()); return Kind; }
  149. bool IsEndIf() const { return Kind == BranchKind::IfEnd; }
  150. bool IsEndScope() {
  151. switch (Kind) {
  152. case BranchKind::IfEnd:
  153. case BranchKind::LoopBreak:
  154. case BranchKind::LoopContinue:
  155. case BranchKind::LoopBackEdge:
  156. case BranchKind::LoopExit:
  157. case BranchKind::SwitchBreak:
  158. case BranchKind::SwitchEnd:
  159. return true;
  160. default:
  161. return false;
  162. }
  163. }
  164. bool IsBeginScope() {
  165. switch (Kind) {
  166. case BranchKind::IfBegin:
  167. case BranchKind::IfNoEnd:
  168. case BranchKind::LoopBegin:
  169. case BranchKind::LoopNoEnd:
  170. case BranchKind::SwitchBegin:
  171. case BranchKind::SwitchNoEnd:
  172. return true;
  173. default:
  174. return false;
  175. }
  176. }
  177. // Translate a branch annoatation to the corresponding event type.
  178. ScopeNestEvent::Type TranslateToNestType() {
  179. switch (Kind) {
  180. case BranchKind::Invalid: return ScopeNestEvent::Type::Invalid;
  181. case BranchKind::IfBegin: return ScopeNestEvent::Type::If_Begin;
  182. case BranchKind::IfEnd: return ScopeNestEvent::Type::If_End;
  183. case BranchKind::IfNoEnd: return ScopeNestEvent::Type::If_Begin;
  184. case BranchKind::SwitchBegin: return ScopeNestEvent::Type::Switch_Begin;
  185. case BranchKind::SwitchEnd: return ScopeNestEvent::Type::Switch_End;
  186. case BranchKind::SwitchNoEnd: return ScopeNestEvent::Type::Switch_Begin;
  187. case BranchKind::SwitchBreak: return ScopeNestEvent::Type::Switch_Break;
  188. case BranchKind::LoopBegin: return ScopeNestEvent::Type::Loop_Begin;
  189. case BranchKind::LoopExit: return ScopeNestEvent::Type::Loop_End;
  190. case BranchKind::LoopNoEnd: return ScopeNestEvent::Type::Loop_Begin;
  191. case BranchKind::LoopBreak: return ScopeNestEvent::Type::Loop_Break;
  192. case BranchKind::LoopContinue: return ScopeNestEvent::Type::Loop_Continue;
  193. case BranchKind::LoopBackEdge: return ScopeNestEvent::Type::Body; // End of loop is marked at loop exit.
  194. }
  195. DXASSERT(false, "unreachable");
  196. return ScopeNestEvent::Type::Invalid;
  197. }
  198. private:
  199. bool IsSome() const { return Kind != BranchKind::Invalid; }
  200. BranchAnnotation() : Kind(BranchKind::Invalid) {}
  201. BranchKind Kind;
  202. };
  203. // Scope
  204. //
  205. // A nested scope. Used as part of the stack state to keep track of what
  206. // kind of scopes we have entered but not yet exited.
  207. //
  208. // Instead of using a class heirarchy we provide scope-specific methods
  209. // and validate the scope type to ensure that we only operate on the kind
  210. // of scope we expect to see.
  211. struct Scope {
  212. enum class Type { TopLevel, If, Loop, Switch };
  213. public:
  214. Scope(Type scopeType, Block *startBlock, BranchKind annotation)
  215. : m_type(scopeType)
  216. , m_startBlock(startBlock)
  217. , m_startAnnotation(annotation)
  218. , m_endBlock(nullptr)
  219. , m_backedge(nullptr)
  220. {
  221. if (m_type == Type::If) { DXASSERT_NOMSG(startBlock && startBlock->getTerminator()->getNumSuccessors() == 2); }
  222. }
  223. Type GetType() const { return m_type; }
  224. Block *GetStartBlock() { return m_startBlock; }
  225. Block *GetIfEndBlock() { return GetEndBlock(Type::If); }
  226. Block *GetLoopBackedgeBlock() { AssertType(Type::Loop); return m_backedge; }
  227. Block *GetLoopEndBlock() { return GetEndBlock(Type::Loop); }
  228. Block *GetSwitchEndBlock() { return GetEndBlock(Type::Switch); }
  229. void SetIfEndBlock(Block *B) {
  230. SetEndBlock(Type::If, B);
  231. }
  232. void SetLoopBackedgeBlock(Block *B) {
  233. SetBackedgeBlock(Type::Loop, B);
  234. }
  235. void SetLoopEndBlock(Block *B) {
  236. SetEndBlock(Type::Loop, B);
  237. }
  238. void SetSwitchEndBlock(Block *B) {
  239. SetEndBlock(Type::Switch, B);
  240. }
  241. bool operator==(const Scope &other) const {
  242. return m_type == other.m_type &&
  243. m_startAnnotation == other.m_startAnnotation &&
  244. m_startBlock == other.m_startBlock &&
  245. m_endBlock == other.m_endBlock &&
  246. m_backedge == other.m_backedge;
  247. }
  248. private:
  249. Type m_type;
  250. BranchKind m_startAnnotation;
  251. Block *m_startBlock;
  252. Block *m_endBlock;
  253. Block *m_backedge; // only for loop.
  254. void SetEndBlock(Type expectedType, Block *endBlock) {
  255. AssertType(expectedType);
  256. AssertUnchanged(m_endBlock, endBlock);
  257. m_endBlock = endBlock;
  258. }
  259. void SetBackedgeBlock(Type expectedType, Block *backedge) {
  260. AssertType(expectedType);
  261. AssertUnchanged(m_backedge, backedge);
  262. m_backedge = backedge;
  263. }
  264. void AssertUnchanged(Block *oldBlock, Block *newBlock) {
  265. DXASSERT((oldBlock == nullptr || oldBlock == newBlock), "block should not change");
  266. }
  267. void AssertType(Type t) {
  268. DXASSERT_NOMSG(t == m_type);
  269. }
  270. Block *GetEndBlock(Type t) {
  271. AssertType(t);
  272. return m_endBlock;
  273. }
  274. };
  275. // StackState
  276. //
  277. // Keeps track of the state of exploration for an open scope. Uses a small
  278. // state machine to move through the exploration stages. When moving to a
  279. // new state it notifies the caller of the new state and any block associated
  280. // with the state.
  281. //
  282. // Transitions:
  283. //
  284. // Top Level
  285. // -------------------------------
  286. // Start -> Top_begin
  287. // Top_begin -> Top_body
  288. // Top_body -> Top_end
  289. // Top_end -> Done
  290. //
  291. // If
  292. // -------------------------------
  293. // If_thenbody -> If_else | If_end
  294. // If_else -> If_elsebody
  295. // If_elsebody -> If_end
  296. //
  297. // Loop
  298. // -------------------------------
  299. // Loop_body -> Loop_backedge
  300. // Loop_backedge -> Loop_end
  301. //
  302. // Switch
  303. // -------------------------------
  304. // Switch_begin -> Switch_case
  305. // Switch_case -> Switch_body
  306. // Switch_body -> Switch_break
  307. // Switch_break -> Switch_case | Switch_end
  308. //
  309. //
  310. // Terminal States:
  311. // Done, Switch_end, Loop_end, If_end
  312. //
  313. class StackState {
  314. public:
  315. enum State {
  316. // Initial top level state before emitting the Top_begin token.
  317. Start,
  318. // If
  319. If_thenbody, // Exploring the true branch of the if.
  320. If_else, // Transitioning from true to false branch.
  321. If_elsebody, // Exploring the false branch of the if.
  322. If_end, // Finished exploring the if.
  323. // Loop
  324. Loop_body, // Exploring the loop body.
  325. Loop_backedge, // On the loop latch block (branch to loop header).
  326. Loop_end, // Finshed exploring the loop.
  327. // Switch
  328. Switch_begin, // Start of switch before entering any case.
  329. Switch_case, // Starting a new case.
  330. Switch_body, // Exploring a case body.
  331. Switch_break, // Break from a case.
  332. Switch_end, // Finished exploring the switch.
  333. // Top level
  334. Top_begin, // Before exploring the first block.
  335. Top_body, // Exploring the body of the function.
  336. Top_end, // After exploring all blocks.
  337. // Final state after top level is popped.
  338. Done
  339. };
  340. StackState(Scope scope, unsigned edge)
  341. : m_scope(scope)
  342. , m_edgeNumber(edge)
  343. {
  344. switch (scope.GetType()) {
  345. case Scope::Type::If: m_state = If_thenbody; break;
  346. case Scope::Type::Loop: m_state = Loop_body; break;
  347. case Scope::Type::Switch: m_state = Switch_begin; break;
  348. case Scope::Type::TopLevel: m_state = Start; break;
  349. default:
  350. DXASSERT_NOMSG(false);
  351. }
  352. }
  353. Scope &GetScope() { return m_scope; }
  354. const Scope &GetScope() const { return m_scope; }
  355. struct StateTransition { State state; Block *block; };
  356. // Transition this stack element to the next state and return associated block.
  357. StateTransition MoveToNextState() {
  358. Block *block = nullptr;
  359. switch (m_state) {
  360. // IF
  361. case If_thenbody: {
  362. // See if we have an else body or not.
  363. // The else body is missing when:
  364. // Case 1: Successor block is the found endif block.
  365. // Case 2: Endif block was not found and successor is marked as an endif block.
  366. Block *succ = GetNextSuccessor();
  367. BranchAnnotation annotation = BranchAnnotation::Read(succ);
  368. const bool succMatchesFoundEndIf = (succ == m_scope.GetIfEndBlock());
  369. const bool succIsMarkedAsEndIf = (m_scope.GetIfEndBlock() == nullptr && annotation && annotation.Get() == BranchKind::IfEnd);
  370. const bool succIsEndif = succMatchesFoundEndIf || succIsMarkedAsEndIf;
  371. if (succIsEndif) {
  372. m_state = If_end;
  373. block = succ;
  374. }
  375. else {
  376. m_state = If_else;
  377. block = nullptr;
  378. }
  379. break;
  380. }
  381. case If_else:
  382. m_state = If_elsebody;
  383. block = MoveToNextSuccessor();
  384. break;
  385. case If_elsebody:
  386. m_state = If_end;
  387. block = m_scope.GetIfEndBlock();
  388. break;
  389. // LOOP
  390. case Loop_body:
  391. m_state = Loop_backedge;
  392. block = m_scope.GetLoopBackedgeBlock();
  393. break;
  394. case Loop_backedge:
  395. m_state = Loop_end;
  396. block = m_scope.GetLoopEndBlock();
  397. break;
  398. // SWITCH
  399. case Switch_begin:
  400. m_state = Switch_case;
  401. block = nullptr;
  402. break;
  403. case Switch_case:
  404. block = GetCurrentSuccessor();
  405. m_state = Switch_body;
  406. break;
  407. case Switch_body:
  408. m_state = Switch_break;
  409. block = nullptr;
  410. break;
  411. case Switch_break:
  412. block = MoveToNextUniqueSuccessor();
  413. if (block) {
  414. m_state = Switch_case;
  415. block = nullptr; // will resume after emitting case marker.
  416. }
  417. else {
  418. m_state = Switch_end;
  419. block = m_scope.GetSwitchEndBlock();
  420. }
  421. break;
  422. // TOP LEVEL
  423. case Start:
  424. m_state = Top_begin;
  425. block = nullptr;
  426. break;
  427. case Top_begin:
  428. m_state = Top_body;
  429. block = m_scope.GetStartBlock();
  430. break;
  431. case Top_body:
  432. m_state = Top_end;
  433. block = nullptr;
  434. break;
  435. case Top_end:
  436. m_state = Done;
  437. block = nullptr;
  438. break;
  439. // INVALID
  440. // The stack state should already be popped because there is no next state.
  441. case If_end:
  442. case Switch_end:
  443. case Loop_end:
  444. case Done:
  445. default:
  446. DXASSERT_NOMSG(false);
  447. }
  448. return { m_state, block };
  449. }
  450. bool operator==(const StackState& other) const {
  451. return m_scope == other.m_scope &&
  452. m_edgeNumber == other.m_edgeNumber &&
  453. m_state == other.m_state;
  454. }
  455. private:
  456. Scope m_scope;
  457. unsigned m_edgeNumber;
  458. State m_state;
  459. private:
  460. // Return next successor or nullptr if no more successors need to be explored.
  461. // Does not modify current edge number.
  462. Block *GetNextSuccessor() {
  463. return GetSuccessor(m_edgeNumber+1);
  464. }
  465. // Increment edge number and return next successor.
  466. Block *MoveToNextSuccessor() {
  467. Block *succ = GetNextSuccessor();
  468. if (succ) {
  469. ++m_edgeNumber;
  470. }
  471. return succ;
  472. }
  473. // Get the successor we are currently set to explore.
  474. Block *GetCurrentSuccessor() {
  475. return GetSuccessor(m_edgeNumber);
  476. }
  477. // Get successor block or nullptr if there is no such succssor.
  478. Block *GetSuccessor(unsigned succNumber) {
  479. Block *const scopeStartBlock = m_scope.GetStartBlock();
  480. Block *succ = nullptr;
  481. if (scopeStartBlock && scopeStartBlock->getTerminator()) {
  482. if (succNumber < scopeStartBlock->getTerminator()->getNumSuccessors()) {
  483. succ_const_iterator succs = succ_begin(scopeStartBlock);
  484. std::advance(succs, succNumber);
  485. succ = *succs;
  486. }
  487. }
  488. return succ;
  489. }
  490. // Move to the next succssor that does not match a previous successor.
  491. // Needed to avoid visiting blocks multiple times blocks in a switch
  492. // when multiple cases point to the same block.
  493. Block *MoveToNextUniqueSuccessor() {
  494. Block *succ = nullptr;
  495. SmallPtrSet<Block *, 8> visited;
  496. Block *const scopeStartBlock = m_scope.GetStartBlock();
  497. if (scopeStartBlock && scopeStartBlock->getTerminator()) {
  498. succ_const_iterator succs = succ_begin(scopeStartBlock);
  499. succ_const_iterator succsEnd = succ_end(scopeStartBlock);
  500. const unsigned nextEdgeNumber = m_edgeNumber + 1;
  501. unsigned edge = 0;
  502. // Mark all successors less than the current edge number as visited.
  503. for (; succs != succsEnd && edge < nextEdgeNumber; ++succs, ++edge) {
  504. visited.insert(*succs);
  505. }
  506. DXASSERT_NOMSG(succs == succsEnd || edge == nextEdgeNumber);
  507. // Look for next unvisited edge.
  508. for (; succs != succsEnd; ++succs, ++edge) {
  509. if (!visited.count(*succs)) {
  510. break;
  511. }
  512. }
  513. // If we found an edge before the end then move to it.
  514. if (succs != succsEnd) {
  515. DXASSERT_NOMSG(edge < scopeStartBlock->getTerminator()->getNumSuccessors());
  516. succ = *succs;
  517. m_edgeNumber = edge;
  518. }
  519. }
  520. return succ;
  521. }
  522. };
  523. // ScopeStack
  524. //
  525. // A stack to hold state information about scopes that are under exploration.
  526. //
  527. class ScopeStack {
  528. public:
  529. bool Empty() const {
  530. return m_stack.empty();
  531. }
  532. void Clear() {
  533. m_stack.clear();
  534. }
  535. void PushScope(const Scope &scope) {
  536. m_stack.push_back(StackState(scope, 0));
  537. }
  538. void PopScope() {
  539. DXASSERT_NOMSG(!Empty());
  540. m_stack.pop_back();
  541. }
  542. Scope &Top() {
  543. DXASSERT_NOMSG(!Empty());
  544. return m_stack.back().GetScope();
  545. }
  546. const Scope &Top() const {
  547. DXASSERT_NOMSG(!Empty());
  548. return m_stack.back().GetScope();
  549. }
  550. // Transition state on the top of the stack to the next state.
  551. StackState::StateTransition AdvanceTopOfStack() {
  552. DXASSERT_NOMSG(!Empty());
  553. return m_stack.back().MoveToNextState();
  554. }
  555. Scope &FindInnermostLoop() {
  556. return FindInnermost(Scope::Type::Loop);
  557. }
  558. Scope &FindInnermostIf() {
  559. return FindInnermost(Scope::Type::If);
  560. }
  561. Scope &FindInnermostSwitch() {
  562. return FindInnermost(Scope::Type::Switch);
  563. }
  564. // Define equality to be fast for comparing to the "end" state
  565. // so that the iterator test in a loop is fase.
  566. bool operator==(const ScopeStack& other) const {
  567. // Quick check on size to make non-equality fast.
  568. return m_stack.size() == other.m_stack.size() &&
  569. m_stack == other.m_stack;
  570. }
  571. private:
  572. typedef std::vector<StackState> Stack;
  573. Stack m_stack;
  574. Scope &FindInnermost(Scope::Type type) {
  575. Stack::reverse_iterator scope =
  576. std::find_if(m_stack.rbegin(), m_stack.rend(), [type](const StackState &s) {return s.GetScope().GetType() == type; });
  577. DXASSERT_NOMSG(scope != m_stack.rend());
  578. return scope->GetScope();
  579. }
  580. };
  581. // IteratorState
  582. //
  583. // Keeps track of all the current state of the iteration. The iterator state
  584. // works as follows.
  585. //
  586. // We keep a current event that describes the most recent event returned by
  587. // the iterator. To advance the iterator we look at whether we have a valid
  588. // block associated with the event. If we do then we keep exploring from
  589. // that block. If there is no block (i.e. it is nullptr) then we explore from
  590. // the top element of the scope stack.
  591. //
  592. // The scope stack is used to keep track of the nested scopes. The stack elements
  593. // are a little state machine that keep track of what the next action should be
  594. // when exploring from the stack. The last action is the "end scope" action which
  595. // tells us we should pop the scope from the stack.
  596. class IteratorState {
  597. public:
  598. IteratorState(Block *entry)
  599. : m_current(ScopeNestEvent::Invalid())
  600. , m_stack()
  601. {
  602. if (entry) {
  603. m_stack.PushScope(Scope(Scope::Type::TopLevel, entry, BranchKind::Invalid));
  604. }
  605. else {
  606. SetDone();
  607. }
  608. }
  609. ScopeNestEvent GetCurrent()
  610. {
  611. return m_current;
  612. }
  613. // Move to the next event.
  614. // Return true if there is a new valid event or false if there is no more events.
  615. bool MoveNext()
  616. {
  617. if (IsDone())
  618. {
  619. return false;
  620. }
  621. if (m_current.Block == nullptr)
  622. {
  623. MoveFromTopOfStack();
  624. }
  625. else
  626. {
  627. MoveFromCurrentBlock();
  628. }
  629. return !IsDone();
  630. }
  631. bool IsDone() {
  632. return m_stack.Empty() && m_current.Block == nullptr;
  633. }
  634. bool operator==(const IteratorState &other) const {
  635. return m_current == other.m_current &&
  636. m_stack == other.m_stack;
  637. }
  638. private:
  639. ScopeNestEvent m_current;
  640. ScopeStack m_stack;
  641. private:
  642. void SetDone() {
  643. m_stack.Clear();
  644. m_current = ScopeNestEvent::Invalid();
  645. DXASSERT_NOMSG(IsDone());
  646. }
  647. void SetCurrent(ScopeNestEvent::Type T, Block *B) {
  648. m_current.ElementType = T;
  649. m_current.Block = B;
  650. if (B) {
  651. BranchAnnotation annotation = BranchAnnotation::Read(B);
  652. if (annotation) {
  653. DXASSERT_NOMSG(annotation.TranslateToNestType() == T);
  654. }
  655. }
  656. }
  657. void MoveFromTopOfStack() {
  658. DXASSERT_NOMSG(!m_stack.Empty());
  659. StackState::StateTransition next = m_stack.AdvanceTopOfStack();
  660. switch (next.state) {
  661. case StackState::If_else:
  662. DXASSERT_NOMSG(next.block == nullptr);
  663. SetCurrent(ScopeNestEvent::Type::If_Else, next.block);
  664. break;
  665. case StackState::If_elsebody:
  666. EnterScopeBodyFromStack(next.block);
  667. break;
  668. case StackState::If_end:
  669. m_stack.PopScope();
  670. SetCurrent(ScopeNestEvent::Type::If_End, next.block);
  671. break;
  672. case StackState::Loop_backedge:
  673. SetCurrent(BranchAnnotation(BranchKind::LoopBackEdge).TranslateToNestType(), next.block);
  674. break;
  675. case StackState::Loop_end:
  676. m_stack.PopScope();
  677. SetCurrent(ScopeNestEvent::Type::Loop_End, next.block);
  678. break;
  679. case StackState::Switch_case:
  680. DXASSERT_NOMSG(next.block == nullptr);
  681. SetCurrent(ScopeNestEvent::Type::Switch_Case, next.block);
  682. break;
  683. case StackState::Switch_body:
  684. EnterScopeBodyFromStack(next.block);
  685. break;
  686. case StackState::Switch_break:
  687. DXASSERT_NOMSG(next.block == nullptr);
  688. SetCurrent(ScopeNestEvent::Type::Switch_Break, next.block);
  689. break;
  690. case StackState::Switch_end:
  691. m_stack.PopScope();
  692. SetCurrent(ScopeNestEvent::Type::Switch_End, next.block);
  693. break;
  694. case StackState::Top_begin:
  695. DXASSERT_NOMSG(next.block == nullptr);
  696. SetCurrent(ScopeNestEvent::Type::TopLevel_Begin, next.block);
  697. break;
  698. case StackState::Top_body:
  699. EnterScopeBodyFromStack(next.block);
  700. break;
  701. case StackState::Top_end:
  702. DXASSERT_NOMSG(next.block == nullptr);
  703. SetCurrent(ScopeNestEvent::Type::TopLevel_End, next.block);
  704. break;
  705. case StackState::Done:
  706. m_stack.PopScope();
  707. SetDone();
  708. break;
  709. default:
  710. DXASSERT_NOMSG(false);
  711. }
  712. }
  713. void EnterScopeBodyFromStack(Block *B)
  714. {
  715. DXASSERT_NOMSG(B);
  716. BranchAnnotation annotation = BranchAnnotation::Read(B);
  717. if (annotation) {
  718. // Make sure we are not ending a scope end because that will cause
  719. // us to move from the stack again. Indicates some problem with the
  720. // state transition.
  721. BranchKind Kind = annotation.Get();
  722. DXASSERT_LOCALVAR_NOMSG(Kind, Kind != BranchKind::IfEnd &&
  723. Kind != BranchKind::LoopBackEdge &&
  724. Kind != BranchKind::LoopExit &&
  725. Kind != BranchKind::SwitchEnd);
  726. }
  727. MoveToBlock(B);
  728. }
  729. void MoveFromCurrentBlock() {
  730. DXASSERT_NOMSG(m_current.Block && m_current.Block->getTerminator());
  731. BranchAnnotation annotation = BranchAnnotation::Read(m_current.Block);
  732. if (annotation) {
  733. MoveFromAnnotatedBlock(annotation.Get());
  734. }
  735. else {
  736. MoveFromNonAnnotatedBlock();
  737. }
  738. }
  739. void MoveFromAnnotatedBlock(BranchKind annotation) {
  740. switch (annotation) {
  741. // Already entered a new scope.
  742. case BranchKind::IfBegin:
  743. case BranchKind::IfNoEnd:
  744. case BranchKind::LoopBegin:
  745. case BranchKind::LoopNoEnd:
  746. DXASSERT(m_current.Block->getTerminator()->getNumSuccessors() >= 1, "scope entry should have a successor");
  747. MoveToFirstSuccessor();
  748. break;
  749. // Start switch. Need to emit first case element from stack.
  750. case BranchKind::SwitchBegin:
  751. case BranchKind::SwitchNoEnd:
  752. MoveFromTopOfStack();
  753. break;
  754. // Already exited an old scope.
  755. case BranchKind::IfEnd:
  756. case BranchKind::SwitchEnd:
  757. case BranchKind::LoopExit:
  758. DXASSERT(m_current.Block->getTerminator()->getNumSuccessors() <= 1, "scope exit should not have multiple successors");
  759. MoveToFirstSuccessor();
  760. break;
  761. // Keep exploring in same scope.
  762. case BranchKind::SwitchBreak:
  763. case BranchKind::LoopBreak:
  764. case BranchKind::LoopContinue:
  765. case BranchKind::LoopBackEdge:
  766. MoveFromTopOfStack();
  767. break;
  768. default: DXASSERT_NOMSG(false);
  769. }
  770. }
  771. void MoveFromNonAnnotatedBlock() {
  772. DXASSERT(m_current.Block->getTerminator()->getNumSuccessors() <= 1, "multi-way branch should be annotated");
  773. MoveToFirstSuccessor();
  774. }
  775. void MoveToFirstSuccessor() {
  776. // No successors to explore. Continue from current scope.
  777. if (!m_current.Block->getTerminator()->getNumSuccessors()) {
  778. DXASSERT_NOMSG(isa<ReturnInst>(m_current.Block->getTerminator()));
  779. MoveFromTopOfStack();
  780. return;
  781. }
  782. // Get first successor block.
  783. Block *succ = *succ_const_iterator(m_current.Block->getTerminator());
  784. MoveToBlock(succ);
  785. }
  786. void MoveToBlock(Block *B) {
  787. // Annotated successor.
  788. if (BranchAnnotation annotation = BranchAnnotation::Read(B))
  789. {
  790. if (annotation.IsEndScope()) {
  791. EnterEndOfScope(B, annotation.Get());
  792. }
  793. else {
  794. DXASSERT_NOMSG(annotation.IsBeginScope());
  795. StartNewScope(B, annotation.Get());
  796. }
  797. }
  798. // Non-Annotated successor.
  799. else {
  800. SetCurrent(ScopeNestEvent::Type::Body, B);
  801. }
  802. }
  803. // Visit the end of scope node from a predecssor we have already explored.
  804. void EnterEndOfScope(Block *endOfScopeBlock, BranchKind endofScopeKind) {
  805. switch (endofScopeKind) {
  806. case BranchKind::IfEnd: {
  807. Scope &ifScope = m_stack.FindInnermostIf();
  808. ifScope.SetIfEndBlock(endOfScopeBlock);
  809. MoveFromTopOfStack();
  810. break;
  811. }
  812. case BranchKind::LoopBackEdge: {
  813. Scope &loopScope = m_stack.FindInnermostLoop();
  814. loopScope.SetLoopBackedgeBlock(endOfScopeBlock);
  815. MoveFromTopOfStack();
  816. break;
  817. }
  818. case BranchKind::LoopExit: {
  819. Scope &loopScope = m_stack.FindInnermostLoop();
  820. loopScope.SetLoopEndBlock(endOfScopeBlock);
  821. MoveFromTopOfStack();
  822. break;
  823. }
  824. case BranchKind::SwitchEnd: {
  825. Scope &switchScope = m_stack.FindInnermostSwitch();
  826. switchScope.SetSwitchEndBlock(endOfScopeBlock);
  827. MoveFromTopOfStack();
  828. break;
  829. }
  830. case BranchKind::LoopBreak: {
  831. Scope &loopScope = m_stack.FindInnermostLoop();
  832. loopScope.SetLoopEndBlock(endOfScopeBlock->getUniqueSuccessor());
  833. SetCurrent(ScopeNestEvent::Type::Loop_Break, endOfScopeBlock);
  834. break;
  835. }
  836. case BranchKind::LoopContinue: {
  837. Scope &loopScope = m_stack.FindInnermostLoop();
  838. loopScope.SetLoopBackedgeBlock(endOfScopeBlock->getUniqueSuccessor());
  839. SetCurrent(ScopeNestEvent::Type::Loop_Continue, endOfScopeBlock);
  840. break;
  841. }
  842. case BranchKind::SwitchBreak: {
  843. Scope &switchScope = m_stack.FindInnermostSwitch();
  844. switchScope.SetSwitchEndBlock(endOfScopeBlock->getUniqueSuccessor());
  845. SetCurrent(ScopeNestEvent::Type::Switch_Break, endOfScopeBlock);
  846. break;
  847. }
  848. default:
  849. DXASSERT_NOMSG(false);
  850. }
  851. }
  852. void StartNewScope(Block *startOfScopeBlock, BranchKind startOfScopeKind) {
  853. Scope::Type scopeType;
  854. ScopeNestEvent::Type nestType;
  855. switch (startOfScopeKind) {
  856. case BranchKind::IfBegin:
  857. case BranchKind::IfNoEnd:
  858. scopeType = Scope::Type::If;
  859. nestType = ScopeNestEvent::Type::If_Begin;
  860. break;
  861. case BranchKind::LoopBegin:
  862. case BranchKind::LoopNoEnd:
  863. scopeType = Scope::Type::Loop;
  864. nestType = ScopeNestEvent::Type::Loop_Begin;
  865. break;
  866. case BranchKind::SwitchBegin:
  867. case BranchKind::SwitchNoEnd:
  868. scopeType = Scope::Type::Switch;
  869. nestType = ScopeNestEvent::Type::Switch_Begin;
  870. break;
  871. default:
  872. DXASSERT_NOMSG(false);
  873. }
  874. SetCurrent(nestType, startOfScopeBlock);
  875. m_stack.PushScope(Scope(scopeType, startOfScopeBlock, startOfScopeKind));
  876. }
  877. };
  878. private: // Members
  879. IteratorState m_state;
  880. ScopeNestEvent m_currentElement;
  881. };
  882. }