VarBypassDetector.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. //===--- VarBypassDetector.cpp - Bypass jumps detector ------------*- C++ -*-=//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "VarBypassDetector.h"
  9. #include "clang/AST/Decl.h"
  10. #include "clang/AST/Expr.h"
  11. #include "clang/AST/Stmt.h"
  12. using namespace clang;
  13. using namespace CodeGen;
  14. /// Clear the object and pre-process for the given statement, usually function
  15. /// body statement.
  16. void VarBypassDetector::Init(const Stmt *Body) {
  17. FromScopes.clear();
  18. ToScopes.clear();
  19. Bypasses.clear();
  20. Scopes = {{~0U, nullptr}};
  21. unsigned ParentScope = 0;
  22. AlwaysBypassed = !BuildScopeInformation(Body, ParentScope);
  23. if (!AlwaysBypassed)
  24. Detect();
  25. }
  26. /// Build scope information for a declaration that is part of a DeclStmt.
  27. /// Returns false if we failed to build scope information and can't tell for
  28. /// which vars are being bypassed.
  29. bool VarBypassDetector::BuildScopeInformation(const Decl *D,
  30. unsigned &ParentScope) {
  31. const VarDecl *VD = dyn_cast<VarDecl>(D);
  32. if (VD && VD->hasLocalStorage()) {
  33. Scopes.push_back({ParentScope, VD});
  34. ParentScope = Scopes.size() - 1;
  35. }
  36. if (const VarDecl *VD = dyn_cast<VarDecl>(D))
  37. if (const Expr *Init = VD->getInit())
  38. return BuildScopeInformation(Init, ParentScope);
  39. return true;
  40. }
  41. /// Walk through the statements, adding any labels or gotos to
  42. /// LabelAndGotoScopes and recursively walking the AST as needed.
  43. /// Returns false if we failed to build scope information and can't tell for
  44. /// which vars are being bypassed.
  45. bool VarBypassDetector::BuildScopeInformation(const Stmt *S,
  46. unsigned &origParentScope) {
  47. // If this is a statement, rather than an expression, scopes within it don't
  48. // propagate out into the enclosing scope. Otherwise we have to worry about
  49. // block literals, which have the lifetime of their enclosing statement.
  50. unsigned independentParentScope = origParentScope;
  51. unsigned &ParentScope =
  52. ((isa<Expr>(S) && !isa<StmtExpr>(S)) ? origParentScope
  53. : independentParentScope);
  54. unsigned StmtsToSkip = 0u;
  55. switch (S->getStmtClass()) {
  56. case Stmt::IndirectGotoStmtClass:
  57. return false;
  58. case Stmt::SwitchStmtClass:
  59. if (const Stmt *Init = cast<SwitchStmt>(S)->getInit()) {
  60. if (!BuildScopeInformation(Init, ParentScope))
  61. return false;
  62. ++StmtsToSkip;
  63. }
  64. if (const VarDecl *Var = cast<SwitchStmt>(S)->getConditionVariable()) {
  65. if (!BuildScopeInformation(Var, ParentScope))
  66. return false;
  67. ++StmtsToSkip;
  68. }
  69. [[fallthrough]];
  70. case Stmt::GotoStmtClass:
  71. FromScopes.push_back({S, ParentScope});
  72. break;
  73. case Stmt::DeclStmtClass: {
  74. const DeclStmt *DS = cast<DeclStmt>(S);
  75. for (auto *I : DS->decls())
  76. if (!BuildScopeInformation(I, origParentScope))
  77. return false;
  78. return true;
  79. }
  80. case Stmt::CaseStmtClass:
  81. case Stmt::DefaultStmtClass:
  82. case Stmt::LabelStmtClass:
  83. llvm_unreachable("the loop below handles labels and cases");
  84. break;
  85. default:
  86. break;
  87. }
  88. for (const Stmt *SubStmt : S->children()) {
  89. if (!SubStmt)
  90. continue;
  91. if (StmtsToSkip) {
  92. --StmtsToSkip;
  93. continue;
  94. }
  95. // Cases, labels, and defaults aren't "scope parents". It's also
  96. // important to handle these iteratively instead of recursively in
  97. // order to avoid blowing out the stack.
  98. while (true) {
  99. const Stmt *Next;
  100. if (const SwitchCase *SC = dyn_cast<SwitchCase>(SubStmt))
  101. Next = SC->getSubStmt();
  102. else if (const LabelStmt *LS = dyn_cast<LabelStmt>(SubStmt))
  103. Next = LS->getSubStmt();
  104. else
  105. break;
  106. ToScopes[SubStmt] = ParentScope;
  107. SubStmt = Next;
  108. }
  109. // Recursively walk the AST.
  110. if (!BuildScopeInformation(SubStmt, ParentScope))
  111. return false;
  112. }
  113. return true;
  114. }
  115. /// Checks each jump and stores each variable declaration they bypass.
  116. void VarBypassDetector::Detect() {
  117. for (const auto &S : FromScopes) {
  118. const Stmt *St = S.first;
  119. unsigned from = S.second;
  120. if (const GotoStmt *GS = dyn_cast<GotoStmt>(St)) {
  121. if (const LabelStmt *LS = GS->getLabel()->getStmt())
  122. Detect(from, ToScopes[LS]);
  123. } else if (const SwitchStmt *SS = dyn_cast<SwitchStmt>(St)) {
  124. for (const SwitchCase *SC = SS->getSwitchCaseList(); SC;
  125. SC = SC->getNextSwitchCase()) {
  126. Detect(from, ToScopes[SC]);
  127. }
  128. } else {
  129. llvm_unreachable("goto or switch was expected");
  130. }
  131. }
  132. }
  133. /// Checks the jump and stores each variable declaration it bypasses.
  134. void VarBypassDetector::Detect(unsigned From, unsigned To) {
  135. while (From != To) {
  136. if (From < To) {
  137. assert(Scopes[To].first < To);
  138. const auto &ScopeTo = Scopes[To];
  139. To = ScopeTo.first;
  140. Bypasses.insert(ScopeTo.second);
  141. } else {
  142. assert(Scopes[From].first < From);
  143. From = Scopes[From].first;
  144. }
  145. }
  146. }