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