ScopeNest.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // ScopeNest.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. ///////////////////////////////////////////////////////////////////////////////
  9. //
  10. // This file holds the type used to represent a scope nest. The
  11. // ScopeNestEvent is the type used by the iterator to represent the nesting
  12. // structure in the cfg.
  13. //
  14. // The iterator returns tokens of type ScopeNestEvent that describe the
  15. // structure. A ScopeNestEvent is a pair of a basic block and a scope type.
  16. // The block may be null depending on the scope type so it should always be
  17. // checked for null before using.
  18. //
  19. // See @ScopeNestIterator.h for more details on the iteration.
  20. //
  21. // The element types represent the major "events" that occur when walking a
  22. // scope nest. The block field corresponds to the basic block where the
  23. // event occurs. There may not always be a block associated with the event
  24. // because some events are used just to indicate transitions. For example,
  25. // with the If_Else and Switch_Case events, the actual else and case blocks
  26. // will be returned with the next event, which will have its own type indicating
  27. // the event caused by that block.
  28. //
  29. // The event location in the block depends on the scope type. For scope-opening
  30. // events, the location is at the end of the block. For example, the @If_Begin
  31. // event occurs an the end of the A block. For scope closing events the event
  32. // occurs at the top of the block. For example, the @If_End event occurs at
  33. // the entry to the X block. For events that do not open or close scopes
  34. // the events generally occur at the bottom of the block. For example, the
  35. // @Loop_Continue event occurs with the branch at the end of the block.
  36. //
  37. ///////////////////////////////////////////////////////////////////////////////
  38. #pragma once
  39. namespace llvm {
  40. struct ScopeNestEvent {
  41. enum class Type {
  42. Invalid, // Not a valid event.
  43. TopLevel_Begin, // Before the first block. Block will be null.
  44. Body, // In the body of a scope. No interesting event.
  45. Switch_Begin, // Begin a switch scope. Block has multi-way branch.
  46. Switch_Break, // Break out of a switch scope. Block may be null.
  47. Switch_Case, // A case will start at the next event. Block will be null.
  48. Switch_End, // End a switch scope. Block is after all switch exits.
  49. Loop_Begin, // Begin a loop scope. Block has one branch leading to loop header.
  50. Loop_Continue, // A "continue" inside a loop. Block has one branch leading to loop latch.
  51. Loop_Break, // A "break" inside a loop. Block has one branch leading to Loop_End block.
  52. Loop_End, // End of loop marker. Block is after the loop (the post loop footer).
  53. If_Begin, // Start of if. Block has branch leading to the two sides of the if.
  54. If_Else, // The else body starts at the next event. Block will be null.
  55. If_End, // The end if marker. Block may be null.
  56. TopLevel_End, // After the last block. Block will be null.
  57. };
  58. typedef const BasicBlock BlockTy; // TODO: make this a template so we can have const and non-const iterators.
  59. Type ElementType;
  60. BlockTy *Block;
  61. ScopeNestEvent(BlockTy *B, Type T) : Block(B), ElementType(T) {}
  62. static ScopeNestEvent Invalid() { return ScopeNestEvent(nullptr, Type::Invalid); }
  63. const bool IsBeginScope() const {
  64. switch (ElementType) {
  65. case Type::TopLevel_Begin: return "TopLevel_Begin";
  66. case Type::Switch_Begin: return "Switch_Begin";
  67. case Type::Loop_Begin: return "Loop_Begin";
  68. case Type::If_Begin: return "If_Begin";
  69. return true;
  70. }
  71. return false;
  72. }
  73. const bool IsEndScope() const {
  74. switch (ElementType) {
  75. case Type::If_End:
  76. case Type::Switch_End:
  77. case Type::Loop_End:
  78. case Type::TopLevel_End:
  79. return true;
  80. }
  81. return false;
  82. }
  83. const char *GetElementTypeName() const {
  84. switch (ElementType) {
  85. case Type::Invalid: return "Invalid";
  86. case Type::TopLevel_Begin: return "TopLevel_Begin";
  87. case Type::Body: return "Body";
  88. case Type::Switch_Begin: return "Switch_Begin";
  89. case Type::Switch_Case: return "Switch_Case";
  90. case Type::Switch_Break: return "Switch_Break";
  91. case Type::Switch_End: return "Switch_End";
  92. case Type::Loop_Begin: return "Loop_Begin";
  93. case Type::Loop_Continue: return "Loop_Continue";
  94. case Type::Loop_Break: return "Loop_Break";
  95. case Type::Loop_End: return "Loop_End";
  96. case Type::If_Begin: return "If_Begin";
  97. case Type::If_Else: return "If_Else";
  98. case Type::If_End: return "If_End";
  99. case Type::TopLevel_End: return "TopLevel_End";
  100. }
  101. assert(false && "unreachable");
  102. return "Unknown";
  103. }
  104. bool operator==(const ScopeNestEvent &other) const {
  105. return Block == other.Block && ElementType == other.ElementType;
  106. }
  107. };
  108. }