1 //===- LexicalScopes.cpp - Collecting lexical scope info --------*- 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 // This file implements LexicalScopes analysis. 10 // 11 // This pass collects lexical scope information and maps machine instructions 12 // to respective lexical scopes. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLVM_CODEGEN_LEXICALSCOPES_H 17 #define LLVM_CODEGEN_LEXICALSCOPES_H 18 19 #include "llvm/ADT/ArrayRef.h" 20 #include "llvm/ADT/DenseMap.h" 21 #include "llvm/ADT/SmallPtrSet.h" 22 #include "llvm/ADT/SmallVector.h" 23 #include "llvm/IR/DebugInfoMetadata.h" 24 #include "llvm/Support/Compiler.h" 25 #include <cassert> 26 #include <unordered_map> 27 #include <utility> 28 29 namespace llvm { 30 31 class MachineBasicBlock; 32 class MachineFunction; 33 class MachineInstr; 34 class MDNode; 35 36 //===----------------------------------------------------------------------===// 37 /// InsnRange - This is used to track range of instructions with identical 38 /// lexical scope. 39 /// 40 using InsnRange = std::pair<const MachineInstr *, const MachineInstr *>; 41 42 //===----------------------------------------------------------------------===// 43 /// LexicalScope - This class is used to track scope information. 44 /// 45 class LexicalScope { 46 public: LexicalScope(LexicalScope * P,const DILocalScope * D,const DILocation * I,bool A)47 LexicalScope(LexicalScope *P, const DILocalScope *D, const DILocation *I, 48 bool A) 49 : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A) { 50 assert(D); 51 assert(D->getSubprogram()->getUnit()->getEmissionKind() != 52 DICompileUnit::NoDebug && 53 "Don't build lexical scopes for non-debug locations"); 54 assert(D->isResolved() && "Expected resolved node"); 55 assert((!I || I->isResolved()) && "Expected resolved node"); 56 if (Parent) 57 Parent->addChild(this); 58 } 59 60 // Accessors. getParent()61 LexicalScope *getParent() const { return Parent; } getDesc()62 const MDNode *getDesc() const { return Desc; } getInlinedAt()63 const DILocation *getInlinedAt() const { return InlinedAtLocation; } getScopeNode()64 const DILocalScope *getScopeNode() const { return Desc; } isAbstractScope()65 bool isAbstractScope() const { return AbstractScope; } getChildren()66 SmallVectorImpl<LexicalScope *> &getChildren() { return Children; } getRanges()67 SmallVectorImpl<InsnRange> &getRanges() { return Ranges; } 68 69 /// addChild - Add a child scope. addChild(LexicalScope * S)70 void addChild(LexicalScope *S) { Children.push_back(S); } 71 72 /// openInsnRange - This scope covers instruction range starting from MI. openInsnRange(const MachineInstr * MI)73 void openInsnRange(const MachineInstr *MI) { 74 if (!FirstInsn) 75 FirstInsn = MI; 76 77 if (Parent) 78 Parent->openInsnRange(MI); 79 } 80 81 /// extendInsnRange - Extend the current instruction range covered by 82 /// this scope. extendInsnRange(const MachineInstr * MI)83 void extendInsnRange(const MachineInstr *MI) { 84 assert(FirstInsn && "MI Range is not open!"); 85 LastInsn = MI; 86 if (Parent) 87 Parent->extendInsnRange(MI); 88 } 89 90 /// closeInsnRange - Create a range based on FirstInsn and LastInsn collected 91 /// until now. This is used when a new scope is encountered while walking 92 /// machine instructions. 93 void closeInsnRange(LexicalScope *NewScope = nullptr) { 94 assert(LastInsn && "Last insn missing!"); 95 Ranges.push_back(InsnRange(FirstInsn, LastInsn)); 96 FirstInsn = nullptr; 97 LastInsn = nullptr; 98 // If Parent dominates NewScope then do not close Parent's instruction 99 // range. 100 if (Parent && (!NewScope || !Parent->dominates(NewScope))) 101 Parent->closeInsnRange(NewScope); 102 } 103 104 /// dominates - Return true if current scope dominates given lexical scope. dominates(const LexicalScope * S)105 bool dominates(const LexicalScope *S) const { 106 if (S == this) 107 return true; 108 if (DFSIn < S->getDFSIn() && DFSOut > S->getDFSOut()) 109 return true; 110 return false; 111 } 112 113 // Depth First Search support to walk and manipulate LexicalScope hierarchy. getDFSOut()114 unsigned getDFSOut() const { return DFSOut; } setDFSOut(unsigned O)115 void setDFSOut(unsigned O) { DFSOut = O; } getDFSIn()116 unsigned getDFSIn() const { return DFSIn; } setDFSIn(unsigned I)117 void setDFSIn(unsigned I) { DFSIn = I; } 118 119 /// dump - print lexical scope. 120 LLVM_ABI void dump(unsigned Indent = 0) const; 121 122 private: 123 LexicalScope *Parent; // Parent to this scope. 124 const DILocalScope *Desc; // Debug info descriptor. 125 const DILocation *InlinedAtLocation; // Location at which this 126 // scope is inlined. 127 bool AbstractScope; // Abstract Scope 128 SmallVector<LexicalScope *, 4> Children; // Scopes defined in scope. 129 // Contents not owned. 130 SmallVector<InsnRange, 4> Ranges; 131 132 const MachineInstr *LastInsn = nullptr; // Last instruction of this scope. 133 const MachineInstr *FirstInsn = nullptr; // First instruction of this scope. 134 unsigned DFSIn = 0; // In & Out Depth use to determine scope nesting. 135 unsigned DFSOut = 0; 136 }; 137 138 //===----------------------------------------------------------------------===// 139 /// LexicalScopes - This class provides interface to collect and use lexical 140 /// scoping information from machine instruction. 141 /// 142 class LexicalScopes { 143 public: 144 LexicalScopes() = default; 145 146 /// initialize - Scan machine function and constuct lexical scope nest, resets 147 /// the instance if necessary. 148 LLVM_ABI void initialize(const MachineFunction &); 149 150 /// releaseMemory - release memory. 151 LLVM_ABI void reset(); 152 153 /// empty - Return true if there is any lexical scope information available. empty()154 bool empty() { return CurrentFnLexicalScope == nullptr; } 155 156 /// getCurrentFunctionScope - Return lexical scope for the current function. getCurrentFunctionScope()157 LexicalScope *getCurrentFunctionScope() const { 158 return CurrentFnLexicalScope; 159 } 160 161 /// getMachineBasicBlocks - Populate given set using machine basic blocks 162 /// which have machine instructions that belong to lexical scope identified by 163 /// DebugLoc. 164 LLVM_ABI void 165 getMachineBasicBlocks(const DILocation *DL, 166 SmallPtrSetImpl<const MachineBasicBlock *> &MBBs); 167 168 /// Return true if DebugLoc's lexical scope dominates at least one machine 169 /// instruction's lexical scope in a given machine basic block. 170 LLVM_ABI bool dominates(const DILocation *DL, MachineBasicBlock *MBB); 171 172 /// findLexicalScope - Find lexical scope, either regular or inlined, for the 173 /// given DebugLoc. Return NULL if not found. 174 LLVM_ABI LexicalScope *findLexicalScope(const DILocation *DL); 175 176 /// getAbstractScopesList - Return a reference to list of abstract scopes. getAbstractScopesList()177 ArrayRef<LexicalScope *> getAbstractScopesList() const { 178 return AbstractScopesList; 179 } 180 181 /// findAbstractScope - Find an abstract scope or return null. findAbstractScope(const DILocalScope * N)182 LexicalScope *findAbstractScope(const DILocalScope *N) { 183 auto I = AbstractScopeMap.find(N); 184 return I != AbstractScopeMap.end() ? &I->second : nullptr; 185 } 186 187 /// findInlinedScope - Find an inlined scope for the given scope/inlined-at. findInlinedScope(const DILocalScope * N,const DILocation * IA)188 LexicalScope *findInlinedScope(const DILocalScope *N, const DILocation *IA) { 189 auto I = InlinedLexicalScopeMap.find(std::make_pair(N, IA)); 190 return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr; 191 } 192 193 /// findLexicalScope - Find regular lexical scope or return null. findLexicalScope(const DILocalScope * N)194 LexicalScope *findLexicalScope(const DILocalScope *N) { 195 auto I = LexicalScopeMap.find(N); 196 return I != LexicalScopeMap.end() ? &I->second : nullptr; 197 } 198 199 /// getOrCreateAbstractScope - Find or create an abstract lexical scope. 200 LLVM_ABI LexicalScope *getOrCreateAbstractScope(const DILocalScope *Scope); 201 202 private: 203 /// getOrCreateLexicalScope - Find lexical scope for the given Scope/IA. If 204 /// not available then create new lexical scope. 205 LLVM_ABI LexicalScope * 206 getOrCreateLexicalScope(const DILocalScope *Scope, 207 const DILocation *IA = nullptr); getOrCreateLexicalScope(const DILocation * DL)208 LexicalScope *getOrCreateLexicalScope(const DILocation *DL) { 209 return DL ? getOrCreateLexicalScope(DL->getScope(), DL->getInlinedAt()) 210 : nullptr; 211 } 212 213 /// getOrCreateRegularScope - Find or create a regular lexical scope. 214 LexicalScope *getOrCreateRegularScope(const DILocalScope *Scope); 215 216 /// getOrCreateInlinedScope - Find or create an inlined lexical scope. 217 LexicalScope *getOrCreateInlinedScope(const DILocalScope *Scope, 218 const DILocation *InlinedAt); 219 220 /// extractLexicalScopes - Extract instruction ranges for each lexical scopes 221 /// for the given machine function. 222 void extractLexicalScopes(SmallVectorImpl<InsnRange> &MIRanges, 223 DenseMap<const MachineInstr *, LexicalScope *> &M); 224 void constructScopeNest(LexicalScope *Scope); 225 void 226 assignInstructionRanges(SmallVectorImpl<InsnRange> &MIRanges, 227 DenseMap<const MachineInstr *, LexicalScope *> &M); 228 229 const MachineFunction *MF = nullptr; 230 231 /// LexicalScopeMap - Tracks the scopes in the current function. 232 // Use an unordered_map to ensure value pointer validity over insertion. 233 std::unordered_map<const DILocalScope *, LexicalScope> LexicalScopeMap; 234 235 /// InlinedLexicalScopeMap - Tracks inlined function scopes in current 236 /// function. 237 std::unordered_map<std::pair<const DILocalScope *, const DILocation *>, 238 LexicalScope, 239 pair_hash<const DILocalScope *, const DILocation *>> 240 InlinedLexicalScopeMap; 241 242 /// AbstractScopeMap - These scopes are not included LexicalScopeMap. 243 // Use an unordered_map to ensure value pointer validity over insertion. 244 std::unordered_map<const DILocalScope *, LexicalScope> AbstractScopeMap; 245 246 /// AbstractScopesList - Tracks abstract scopes constructed while processing 247 /// a function. 248 SmallVector<LexicalScope *, 4> AbstractScopesList; 249 250 /// CurrentFnLexicalScope - Top level scope for the current function. 251 /// 252 LexicalScope *CurrentFnLexicalScope = nullptr; 253 254 /// Map a location to the set of basic blocks it dominates. This is a cache 255 /// for \ref LexicalScopes::getMachineBasicBlocks results. 256 using BlockSetT = SmallPtrSet<const MachineBasicBlock *, 4>; 257 DenseMap<const DILocation *, std::unique_ptr<BlockSetT>> DominatedBlocks; 258 }; 259 260 } // end namespace llvm 261 262 #endif // LLVM_CODEGEN_LEXICALSCOPES_H 263