mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +00:00 
			
		
		
		
	git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146960 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			338 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			338 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===- LexicalScopes.cpp - Collecting lexical scope info ------------------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file implements LexicalScopes analysis.
 | |
| //
 | |
| // This pass collects lexical scope information and maps machine instructions
 | |
| // to respective lexical scopes.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #define DEBUG_TYPE "lexicalscopes"
 | |
| #include "llvm/CodeGen/LexicalScopes.h"
 | |
| #include "llvm/Function.h"
 | |
| #include "llvm/Analysis/DebugInfo.h"
 | |
| #include "llvm/CodeGen/MachineFunction.h"
 | |
| #include "llvm/CodeGen/MachineInstr.h"
 | |
| #include "llvm/Support/Debug.h"
 | |
| #include "llvm/Support/ErrorHandling.h"
 | |
| #include "llvm/Support/FormattedStream.h"
 | |
| using namespace llvm;
 | |
| 
 | |
| LexicalScopes::~LexicalScopes() {
 | |
|   releaseMemory();
 | |
| }
 | |
| 
 | |
| /// releaseMemory - release memory.
 | |
| void LexicalScopes::releaseMemory() {
 | |
|   MF = NULL;
 | |
|   CurrentFnLexicalScope = NULL;
 | |
|   DeleteContainerSeconds(LexicalScopeMap);
 | |
|   DeleteContainerSeconds(AbstractScopeMap);
 | |
|   InlinedLexicalScopeMap.clear();
 | |
|   AbstractScopesList.clear();
 | |
| }
 | |
| 
 | |
| /// initialize - Scan machine function and constuct lexical scope nest.
 | |
| void LexicalScopes::initialize(const MachineFunction &Fn) {
 | |
|   releaseMemory();
 | |
|   MF = &Fn;
 | |
|   SmallVector<InsnRange, 4> MIRanges;
 | |
|   DenseMap<const MachineInstr *, LexicalScope *> MI2ScopeMap;
 | |
|   extractLexicalScopes(MIRanges, MI2ScopeMap);
 | |
|   if (CurrentFnLexicalScope) {
 | |
|     constructScopeNest(CurrentFnLexicalScope);
 | |
|     assignInstructionRanges(MIRanges, MI2ScopeMap);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /// extractLexicalScopes - Extract instruction ranges for each lexical scopes
 | |
| /// for the given machine function.
 | |
| void LexicalScopes::
 | |
| extractLexicalScopes(SmallVectorImpl<InsnRange> &MIRanges,
 | |
|                   DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) {
 | |
| 
 | |
|   // Scan each instruction and create scopes. First build working set of scopes.
 | |
|   for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
 | |
|        I != E; ++I) {
 | |
|     const MachineInstr *RangeBeginMI = NULL;
 | |
|     const MachineInstr *PrevMI = NULL;
 | |
|     DebugLoc PrevDL;
 | |
|     for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
 | |
|          II != IE; ++II) {
 | |
|       const MachineInstr *MInsn = II;
 | |
| 
 | |
|       // Check if instruction has valid location information.
 | |
|       const DebugLoc MIDL = MInsn->getDebugLoc();
 | |
|       if (MIDL.isUnknown()) {
 | |
|         PrevMI = MInsn;
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       // If scope has not changed then skip this instruction.
 | |
|       if (MIDL == PrevDL) {
 | |
|         PrevMI = MInsn;
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       // Ignore DBG_VALUE. It does not contribute to any instruction in output.
 | |
|       if (MInsn->isDebugValue())
 | |
|         continue;
 | |
| 
 | |
|       if (RangeBeginMI) {
 | |
|         // If we have already seen a beginning of an instruction range and
 | |
|         // current instruction scope does not match scope of first instruction
 | |
|         // in this range then create a new instruction range.
 | |
|         InsnRange R(RangeBeginMI, PrevMI);
 | |
|         MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
 | |
|         MIRanges.push_back(R);
 | |
|       }
 | |
| 
 | |
|       // This is a beginning of a new instruction range.
 | |
|       RangeBeginMI = MInsn;
 | |
| 
 | |
|       // Reset previous markers.
 | |
|       PrevMI = MInsn;
 | |
|       PrevDL = MIDL;
 | |
|     }
 | |
| 
 | |
|     // Create last instruction range.
 | |
|     if (RangeBeginMI && PrevMI && !PrevDL.isUnknown()) {
 | |
|       InsnRange R(RangeBeginMI, PrevMI);
 | |
|       MIRanges.push_back(R);
 | |
|       MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /// findLexicalScope - Find lexical scope, either regular or inlined, for the
 | |
| /// given DebugLoc. Return NULL if not found.
 | |
| LexicalScope *LexicalScopes::findLexicalScope(DebugLoc DL) {
 | |
|   MDNode *Scope = NULL;
 | |
|   MDNode *IA = NULL;
 | |
|   DL.getScopeAndInlinedAt(Scope, IA, MF->getFunction()->getContext());
 | |
|   if (!Scope) return NULL;
 | |
| 
 | |
|   // The scope that we were created with could have an extra file - which
 | |
|   // isn't what we care about in this case.
 | |
|   DIDescriptor D = DIDescriptor(Scope);
 | |
|   if (D.isLexicalBlockFile())
 | |
|     Scope = DILexicalBlockFile(Scope).getScope();
 | |
|   
 | |
|   if (IA)
 | |
|     return InlinedLexicalScopeMap.lookup(DebugLoc::getFromDILocation(IA));
 | |
|   return LexicalScopeMap.lookup(Scope);
 | |
| }
 | |
| 
 | |
| /// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If
 | |
| /// not available then create new lexical scope.
 | |
| LexicalScope *LexicalScopes::getOrCreateLexicalScope(DebugLoc DL) {
 | |
|   MDNode *Scope = NULL;
 | |
|   MDNode *InlinedAt = NULL;
 | |
|   DL.getScopeAndInlinedAt(Scope, InlinedAt, MF->getFunction()->getContext());
 | |
| 
 | |
|   if (InlinedAt) {
 | |
|     // Create an abstract scope for inlined function.
 | |
|     getOrCreateAbstractScope(Scope);
 | |
|     // Create an inlined scope for inlined function.
 | |
|     return getOrCreateInlinedScope(Scope, InlinedAt);
 | |
|   }
 | |
|    
 | |
|   return getOrCreateRegularScope(Scope);
 | |
| }
 | |
| 
 | |
| /// getOrCreateRegularScope - Find or create a regular lexical scope.
 | |
| LexicalScope *LexicalScopes::getOrCreateRegularScope(MDNode *Scope) {
 | |
|   DIDescriptor D = DIDescriptor(Scope);
 | |
|   if (D.isLexicalBlockFile()) {
 | |
|     Scope = DILexicalBlockFile(Scope).getScope();
 | |
|     D = DIDescriptor(Scope);
 | |
|   }
 | |
|  
 | |
|   LexicalScope *WScope = LexicalScopeMap.lookup(Scope);
 | |
|   if (WScope)
 | |
|     return WScope;
 | |
| 
 | |
|   LexicalScope *Parent = NULL;
 | |
|   if (D.isLexicalBlock())
 | |
|     Parent = getOrCreateLexicalScope(DebugLoc::getFromDILexicalBlock(Scope));
 | |
|   WScope = new LexicalScope(Parent, DIDescriptor(Scope), NULL, false);
 | |
|   LexicalScopeMap.insert(std::make_pair(Scope, WScope));
 | |
|   if (!Parent && DIDescriptor(Scope).isSubprogram()
 | |
|       && DISubprogram(Scope).describes(MF->getFunction()))
 | |
|     CurrentFnLexicalScope = WScope;
 | |
|   
 | |
|   return WScope;
 | |
| }
 | |
| 
 | |
| /// getOrCreateInlinedScope - Find or create an inlined lexical scope.
 | |
| LexicalScope *LexicalScopes::getOrCreateInlinedScope(MDNode *Scope, 
 | |
|                                                      MDNode *InlinedAt) {
 | |
|   LexicalScope *InlinedScope = LexicalScopeMap.lookup(InlinedAt);
 | |
|   if (InlinedScope)
 | |
|     return InlinedScope;
 | |
| 
 | |
|   DebugLoc InlinedLoc = DebugLoc::getFromDILocation(InlinedAt);
 | |
|   InlinedScope = new LexicalScope(getOrCreateLexicalScope(InlinedLoc),
 | |
|                                   DIDescriptor(Scope), InlinedAt, false);
 | |
|   InlinedLexicalScopeMap[InlinedLoc] = InlinedScope;
 | |
|   LexicalScopeMap[InlinedAt] = InlinedScope;
 | |
|   return InlinedScope;
 | |
| }
 | |
| 
 | |
| /// getOrCreateAbstractScope - Find or create an abstract lexical scope.
 | |
| LexicalScope *LexicalScopes::getOrCreateAbstractScope(const MDNode *N) {
 | |
|   assert(N && "Invalid Scope encoding!");
 | |
| 
 | |
|   DIDescriptor Scope(N);
 | |
|   if (Scope.isLexicalBlockFile())
 | |
|     Scope = DILexicalBlockFile(Scope).getScope();
 | |
|   LexicalScope *AScope = AbstractScopeMap.lookup(N);
 | |
|   if (AScope)
 | |
|     return AScope;
 | |
| 
 | |
|   LexicalScope *Parent = NULL;
 | |
|   if (Scope.isLexicalBlock()) {
 | |
|     DILexicalBlock DB(N);
 | |
|     DIDescriptor ParentDesc = DB.getContext();
 | |
|     Parent = getOrCreateAbstractScope(ParentDesc);
 | |
|   }
 | |
|   AScope = new LexicalScope(Parent, DIDescriptor(N), NULL, true);
 | |
|   AbstractScopeMap[N] = AScope;
 | |
|   if (DIDescriptor(N).isSubprogram())
 | |
|     AbstractScopesList.push_back(AScope);
 | |
|   return AScope;
 | |
| }
 | |
| 
 | |
| /// constructScopeNest
 | |
| void LexicalScopes::constructScopeNest(LexicalScope *Scope) {
 | |
|   assert (Scope && "Unable to calculate scop edominance graph!");
 | |
|   SmallVector<LexicalScope *, 4> WorkStack;
 | |
|   WorkStack.push_back(Scope);
 | |
|   unsigned Counter = 0;
 | |
|   while (!WorkStack.empty()) {
 | |
|     LexicalScope *WS = WorkStack.back();
 | |
|     const SmallVector<LexicalScope *, 4> &Children = WS->getChildren();
 | |
|     bool visitedChildren = false;
 | |
|     for (SmallVector<LexicalScope *, 4>::const_iterator SI = Children.begin(),
 | |
|            SE = Children.end(); SI != SE; ++SI) {
 | |
|       LexicalScope *ChildScope = *SI;
 | |
|       if (!ChildScope->getDFSOut()) {
 | |
|         WorkStack.push_back(ChildScope);
 | |
|         visitedChildren = true;
 | |
|         ChildScope->setDFSIn(++Counter);
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     if (!visitedChildren) {
 | |
|       WorkStack.pop_back();
 | |
|       WS->setDFSOut(++Counter);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /// assignInstructionRanges - Find ranges of instructions covered by each
 | |
| /// lexical scope.
 | |
| void LexicalScopes::
 | |
| assignInstructionRanges(SmallVectorImpl<InsnRange> &MIRanges,
 | |
|                     DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap)
 | |
| {
 | |
|   
 | |
|   LexicalScope *PrevLexicalScope = NULL;
 | |
|   for (SmallVectorImpl<InsnRange>::const_iterator RI = MIRanges.begin(),
 | |
|          RE = MIRanges.end(); RI != RE; ++RI) {
 | |
|     const InsnRange &R = *RI;
 | |
|     LexicalScope *S = MI2ScopeMap.lookup(R.first);
 | |
|     assert (S && "Lost LexicalScope for a machine instruction!");
 | |
|     if (PrevLexicalScope && !PrevLexicalScope->dominates(S))
 | |
|       PrevLexicalScope->closeInsnRange(S);
 | |
|     S->openInsnRange(R.first);
 | |
|     S->extendInsnRange(R.second);
 | |
|     PrevLexicalScope = S;
 | |
|   }
 | |
| 
 | |
|   if (PrevLexicalScope)
 | |
|     PrevLexicalScope->closeInsnRange();
 | |
| }
 | |
| 
 | |
| /// getMachineBasicBlocks - Populate given set using machine basic blocks which
 | |
| /// have machine instructions that belong to lexical scope identified by 
 | |
| /// DebugLoc.
 | |
| void LexicalScopes::
 | |
| getMachineBasicBlocks(DebugLoc DL, 
 | |
|                       SmallPtrSet<const MachineBasicBlock*, 4> &MBBs) {
 | |
|   MBBs.clear();
 | |
|   LexicalScope *Scope = getOrCreateLexicalScope(DL);
 | |
|   if (!Scope)
 | |
|     return;
 | |
|   
 | |
|   if (Scope == CurrentFnLexicalScope) {
 | |
|     for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
 | |
|          I != E; ++I)
 | |
|       MBBs.insert(I);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   SmallVector<InsnRange, 4> &InsnRanges = Scope->getRanges();
 | |
|   for (SmallVector<InsnRange, 4>::iterator I = InsnRanges.begin(),
 | |
|          E = InsnRanges.end(); I != E; ++I) {
 | |
|     InsnRange &R = *I;
 | |
|     MBBs.insert(R.first->getParent());
 | |
|   }
 | |
| }
 | |
| 
 | |
| /// dominates - Return true if DebugLoc's lexical scope dominates at least one
 | |
| /// machine instruction's lexical scope in a given machine basic block.
 | |
| bool LexicalScopes::dominates(DebugLoc DL, MachineBasicBlock *MBB) {
 | |
|   LexicalScope *Scope = getOrCreateLexicalScope(DL);
 | |
|   if (!Scope)
 | |
|     return false;
 | |
| 
 | |
|   // Current function scope covers all basic blocks in the function.
 | |
|   if (Scope == CurrentFnLexicalScope && MBB->getParent() == MF)
 | |
|     return true;
 | |
| 
 | |
|   bool Result = false;
 | |
|   for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end();
 | |
|        I != E; ++I) {
 | |
|     DebugLoc IDL = I->getDebugLoc();
 | |
|     if (IDL.isUnknown())
 | |
|       continue;
 | |
|     if (LexicalScope *IScope = getOrCreateLexicalScope(IDL))
 | |
|       if (Scope->dominates(IScope))
 | |
|         return true;
 | |
|   }
 | |
|   return Result;
 | |
| }
 | |
| 
 | |
| void LexicalScope::anchor() { }
 | |
| 
 | |
| /// dump - Print data structures.
 | |
| void LexicalScope::dump() const {
 | |
| #ifndef NDEBUG
 | |
|   raw_ostream &err = dbgs();
 | |
|   err.indent(IndentLevel);
 | |
|   err << "DFSIn: " << DFSIn << " DFSOut: " << DFSOut << "\n";
 | |
|   const MDNode *N = Desc;
 | |
|   N->dump();
 | |
|   if (AbstractScope)
 | |
|     err << "Abstract Scope\n";
 | |
| 
 | |
|   IndentLevel += 2;
 | |
|   if (!Children.empty())
 | |
|     err << "Children ...\n";
 | |
|   for (unsigned i = 0, e = Children.size(); i != e; ++i)
 | |
|     if (Children[i] != this)
 | |
|       Children[i]->dump();
 | |
| 
 | |
|   IndentLevel -= 2;
 | |
| #endif
 | |
| }
 | |
| 
 |