mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-30 05:29:47 +00:00
Let me tell you a tale... Originally committed in r211723 after discovering a nasty case of weird scoping due to inlining, this was reverted in r211724 after it fired in ASan/compiler-rt. (minor diversion where I accidentally committed/reverted again in r211871/r211873) After further testing and fixing bugs in ArgumentPromotion (r211872) and Inlining (r212065) it was recommitted in r212085. Reverted in r212089 after the sanitizer buildbots still showed problems. Fixed another bug in ArgumentPromotion (r212128) found by this assertion. Recommitted in r212205, reverted in r212226 after it crashed some more on sanitizer buildbots. Fix clang some more in r212761. Recommitted in r212776, reverted in r212793. ASan failures. Recommitted in r213391, reverted in r213432, trying to reproduce flakey ASan build failure. Fixed bugs in r213805 (ArgPromo + DebugInfo), r213952 (LiveDebugVariables strips dbg_value intrinsics in functions not described by debug info). Recommitted in r214761, reverted in r214999, flakey failure on Windows buildbot. Fixed DeadArgElimination + DebugInfo bug in r219210. Recommitted in r219215, reverted in r219512, failure on ObjC++ atomic properties in the test-suite on Darwin. Fixed ObjC++ atomic properties issue in Clang in r219690. [This commit is provided 'as is' with no hope that this is the last time I commit this change either expressed or implied] git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219702 91177308-0d34-0410-b5e6-96231b3b80d8
357 lines
12 KiB
C++
357 lines
12 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.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/CodeGen/LexicalScopes.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/MachineInstr.h"
|
|
#include "llvm/IR/DebugInfo.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/FormattedStream.h"
|
|
using namespace llvm;
|
|
|
|
#define DEBUG_TYPE "lexicalscopes"
|
|
|
|
/// reset - Reset the instance so that it's prepared for another function.
|
|
void LexicalScopes::reset() {
|
|
MF = nullptr;
|
|
CurrentFnLexicalScope = nullptr;
|
|
LexicalScopeMap.clear();
|
|
AbstractScopeMap.clear();
|
|
InlinedLexicalScopeMap.clear();
|
|
AbstractScopesList.clear();
|
|
}
|
|
|
|
/// initialize - Scan machine function and constuct lexical scope nest.
|
|
void LexicalScopes::initialize(const MachineFunction &Fn) {
|
|
reset();
|
|
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 (const auto &MBB : *MF) {
|
|
const MachineInstr *RangeBeginMI = nullptr;
|
|
const MachineInstr *PrevMI = nullptr;
|
|
DebugLoc PrevDL;
|
|
for (const auto &MInsn : MBB) {
|
|
// 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);
|
|
}
|
|
}
|
|
}
|
|
|
|
LexicalScope *LexicalScopes::findInlinedScope(DebugLoc DL) {
|
|
MDNode *Scope = nullptr;
|
|
MDNode *IA = nullptr;
|
|
DL.getScopeAndInlinedAt(Scope, IA, MF->getFunction()->getContext());
|
|
auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA));
|
|
return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr;
|
|
}
|
|
|
|
/// findLexicalScope - Find lexical scope, either regular or inlined, for the
|
|
/// given DebugLoc. Return NULL if not found.
|
|
LexicalScope *LexicalScopes::findLexicalScope(DebugLoc DL) {
|
|
MDNode *Scope = nullptr;
|
|
MDNode *IA = nullptr;
|
|
DL.getScopeAndInlinedAt(Scope, IA, MF->getFunction()->getContext());
|
|
if (!Scope)
|
|
return nullptr;
|
|
|
|
// 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) {
|
|
auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA));
|
|
return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr;
|
|
}
|
|
return findLexicalScope(Scope);
|
|
}
|
|
|
|
/// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If
|
|
/// not available then create new lexical scope.
|
|
LexicalScope *LexicalScopes::getOrCreateLexicalScope(DebugLoc DL) {
|
|
if (DL.isUnknown())
|
|
return nullptr;
|
|
MDNode *Scope = nullptr;
|
|
MDNode *InlinedAt = nullptr;
|
|
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);
|
|
}
|
|
|
|
auto I = LexicalScopeMap.find(Scope);
|
|
if (I != LexicalScopeMap.end())
|
|
return &I->second;
|
|
|
|
LexicalScope *Parent = nullptr;
|
|
if (D.isLexicalBlock())
|
|
Parent = getOrCreateLexicalScope(DebugLoc::getFromDILexicalBlock(Scope));
|
|
// FIXME: Use forward_as_tuple instead of make_tuple, once MSVC2012
|
|
// compatibility is no longer required.
|
|
I = LexicalScopeMap.emplace(std::piecewise_construct, std::make_tuple(Scope),
|
|
std::make_tuple(Parent, DIDescriptor(Scope),
|
|
nullptr, false)).first;
|
|
|
|
if (!Parent) {
|
|
assert(DIDescriptor(Scope).isSubprogram());
|
|
assert(DISubprogram(Scope).describes(MF->getFunction()));
|
|
assert(!CurrentFnLexicalScope);
|
|
CurrentFnLexicalScope = &I->second;
|
|
}
|
|
|
|
return &I->second;
|
|
}
|
|
|
|
/// getOrCreateInlinedScope - Find or create an inlined lexical scope.
|
|
LexicalScope *LexicalScopes::getOrCreateInlinedScope(MDNode *ScopeNode,
|
|
MDNode *InlinedAt) {
|
|
std::pair<const MDNode*, const MDNode*> P(ScopeNode, InlinedAt);
|
|
auto I = InlinedLexicalScopeMap.find(P);
|
|
if (I != InlinedLexicalScopeMap.end())
|
|
return &I->second;
|
|
|
|
LexicalScope *Parent;
|
|
DILexicalBlock Scope(ScopeNode);
|
|
if (Scope.isSubprogram())
|
|
Parent = getOrCreateLexicalScope(DebugLoc::getFromDILocation(InlinedAt));
|
|
else
|
|
Parent = getOrCreateInlinedScope(Scope.getContext(), InlinedAt);
|
|
|
|
// FIXME: Use forward_as_tuple instead of make_tuple, once MSVC2012
|
|
// compatibility is no longer required.
|
|
I = InlinedLexicalScopeMap.emplace(std::piecewise_construct,
|
|
std::make_tuple(P),
|
|
std::make_tuple(Parent, Scope, InlinedAt,
|
|
false)).first;
|
|
return &I->second;
|
|
}
|
|
|
|
/// 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();
|
|
auto I = AbstractScopeMap.find(Scope);
|
|
if (I != AbstractScopeMap.end())
|
|
return &I->second;
|
|
|
|
LexicalScope *Parent = nullptr;
|
|
if (Scope.isLexicalBlock()) {
|
|
DILexicalBlock DB(Scope);
|
|
DIDescriptor ParentDesc = DB.getContext();
|
|
Parent = getOrCreateAbstractScope(ParentDesc);
|
|
}
|
|
I = AbstractScopeMap.emplace(std::piecewise_construct,
|
|
std::forward_as_tuple(Scope),
|
|
std::forward_as_tuple(Parent, Scope,
|
|
nullptr, true)).first;
|
|
if (Scope.isSubprogram())
|
|
AbstractScopesList.push_back(&I->second);
|
|
return &I->second;
|
|
}
|
|
|
|
/// constructScopeNest
|
|
void LexicalScopes::constructScopeNest(LexicalScope *Scope) {
|
|
assert(Scope && "Unable to calculate scope dominance graph!");
|
|
SmallVector<LexicalScope *, 4> WorkStack;
|
|
WorkStack.push_back(Scope);
|
|
unsigned Counter = 0;
|
|
while (!WorkStack.empty()) {
|
|
LexicalScope *WS = WorkStack.back();
|
|
const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren();
|
|
bool visitedChildren = false;
|
|
for (SmallVectorImpl<LexicalScope *>::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 = nullptr;
|
|
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, SmallPtrSetImpl<const MachineBasicBlock *> &MBBs) {
|
|
MBBs.clear();
|
|
LexicalScope *Scope = getOrCreateLexicalScope(DL);
|
|
if (!Scope)
|
|
return;
|
|
|
|
if (Scope == CurrentFnLexicalScope) {
|
|
for (const auto &MBB : *MF)
|
|
MBBs.insert(&MBB);
|
|
return;
|
|
}
|
|
|
|
SmallVectorImpl<InsnRange> &InsnRanges = Scope->getRanges();
|
|
for (SmallVectorImpl<InsnRange>::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;
|
|
}
|
|
|
|
/// dump - Print data structures.
|
|
void LexicalScope::dump(unsigned Indent) const {
|
|
#ifndef NDEBUG
|
|
raw_ostream &err = dbgs();
|
|
err.indent(Indent);
|
|
err << "DFSIn: " << DFSIn << " DFSOut: " << DFSOut << "\n";
|
|
const MDNode *N = Desc;
|
|
err.indent(Indent);
|
|
N->dump();
|
|
if (AbstractScope)
|
|
err << std::string(Indent, ' ') << "Abstract Scope\n";
|
|
|
|
if (!Children.empty())
|
|
err << std::string(Indent + 2, ' ') << "Children ...\n";
|
|
for (unsigned i = 0, e = Children.size(); i != e; ++i)
|
|
if (Children[i] != this)
|
|
Children[i]->dump(Indent + 2);
|
|
#endif
|
|
}
|