llvm-6502/lib/IR/DebugInfo.cpp

393 lines
11 KiB
C++
Raw Normal View History

//===--- DebugInfo.cpp - Debug Information Helper Classes -----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the helper classes used to build and interpret debug
// information in LLVM IR form.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/DebugInfo.h"
#include "LLVMContextImpl.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/GVMaterializer.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace llvm::dwarf;
DISubprogram *llvm::getDISubprogram(const MDNode *Scope) {
if (auto *LocalScope = dyn_cast_or_null<DILocalScope>(Scope))
return LocalScope->getSubprogram();
return nullptr;
}
DISubprogram *llvm::getDISubprogram(const Function *F) {
// We look for the first instr that has a debug annotation leading back to F.
for (auto &BB : *F) {
auto Inst = std::find_if(BB.begin(), BB.end(), [](const Instruction &Inst) {
return Inst.getDebugLoc();
});
if (Inst == BB.end())
continue;
DebugLoc DLoc = Inst->getDebugLoc();
const MDNode *Scope = DLoc.getInlinedAtScope();
auto *Subprogram = getDISubprogram(Scope);
return Subprogram->describes(F) ? Subprogram : nullptr;
}
return nullptr;
}
DICompositeTypeBase *llvm::getDICompositeType(DIType *T) {
if (auto *C = dyn_cast_or_null<DICompositeTypeBase>(T))
return C;
if (auto *D = dyn_cast_or_null<DIDerivedTypeBase>(T)) {
// This function is currently used by dragonegg and dragonegg does
// not generate identifier for types, so using an empty map to resolve
// DerivedFrom should be fine.
DITypeIdentifierMap EmptyMap;
return getDICompositeType(D->getBaseType().resolve(EmptyMap));
}
return nullptr;
}
DITypeIdentifierMap
llvm::generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes) {
DITypeIdentifierMap Map;
for (unsigned CUi = 0, CUe = CU_Nodes->getNumOperands(); CUi != CUe; ++CUi) {
auto *CU = cast<DICompileUnit>(CU_Nodes->getOperand(CUi));
DINodeArray Retain = CU->getRetainedTypes();
for (unsigned Ti = 0, Te = Retain.size(); Ti != Te; ++Ti) {
if (!isa<DICompositeType>(Retain[Ti]))
continue;
auto *Ty = cast<DICompositeType>(Retain[Ti]);
if (MDString *TypeId = Ty->getRawIdentifier()) {
// Definition has priority over declaration.
// Try to insert (TypeId, Ty) to Map.
std::pair<DITypeIdentifierMap::iterator, bool> P =
Map.insert(std::make_pair(TypeId, Ty));
// If TypeId already exists in Map and this is a definition, replace
// whatever we had (declaration or definition) with the definition.
if (!P.second && !Ty->isForwardDecl())
P.first->second = Ty;
}
}
}
return Map;
}
//===----------------------------------------------------------------------===//
// DebugInfoFinder implementations.
//===----------------------------------------------------------------------===//
void DebugInfoFinder::reset() {
CUs.clear();
SPs.clear();
GVs.clear();
TYs.clear();
Scopes.clear();
NodesSeen.clear();
TypeIdentifierMap.clear();
TypeMapInitialized = false;
}
void DebugInfoFinder::InitializeTypeMap(const Module &M) {
if (!TypeMapInitialized)
if (NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu")) {
TypeIdentifierMap = generateDITypeIdentifierMap(CU_Nodes);
TypeMapInitialized = true;
}
}
void DebugInfoFinder::processModule(const Module &M) {
InitializeTypeMap(M);
if (NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu")) {
for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
auto *CU = cast<DICompileUnit>(CU_Nodes->getOperand(i));
addCompileUnit(CU);
for (auto *DIG : CU->getGlobalVariables()) {
if (addGlobalVariable(DIG)) {
processScope(DIG->getScope());
processType(DIG->getType().resolve(TypeIdentifierMap));
}
}
for (auto *SP : CU->getSubprograms())
processSubprogram(SP);
for (auto *ET : CU->getEnumTypes())
processType(ET);
for (auto *RT : CU->getRetainedTypes())
processType(RT);
for (auto *Import : CU->getImportedEntities()) {
auto *Entity = Import->getEntity().resolve(TypeIdentifierMap);
if (auto *T = dyn_cast<DIType>(Entity))
processType(T);
else if (auto *SP = dyn_cast<DISubprogram>(Entity))
processSubprogram(SP);
else if (auto *NS = dyn_cast<DINamespace>(Entity))
processScope(NS->getScope());
else if (auto *M = dyn_cast<DIModule>(Entity))
processScope(M->getScope());
}
}
}
}
void DebugInfoFinder::processLocation(const Module &M, const DILocation *Loc) {
if (!Loc)
return;
InitializeTypeMap(M);
processScope(Loc->getScope());
processLocation(M, Loc->getInlinedAt());
}
void DebugInfoFinder::processType(DIType *DT) {
if (!addType(DT))
return;
processScope(DT->getScope().resolve(TypeIdentifierMap));
if (auto *DCT = dyn_cast<DICompositeTypeBase>(DT)) {
processType(DCT->getBaseType().resolve(TypeIdentifierMap));
if (auto *ST = dyn_cast<DISubroutineType>(DCT)) {
for (DITypeRef Ref : ST->getTypeArray())
processType(Ref.resolve(TypeIdentifierMap));
return;
}
for (Metadata *D : DCT->getElements()) {
if (auto *T = dyn_cast<DIType>(D))
processType(T);
else if (auto *SP = dyn_cast<DISubprogram>(D))
processSubprogram(SP);
}
} else if (auto *DDT = dyn_cast<DIDerivedTypeBase>(DT)) {
processType(DDT->getBaseType().resolve(TypeIdentifierMap));
}
}
void DebugInfoFinder::processScope(DIScope *Scope) {
if (!Scope)
return;
if (auto *Ty = dyn_cast<DIType>(Scope)) {
processType(Ty);
return;
}
if (auto *CU = dyn_cast<DICompileUnit>(Scope)) {
addCompileUnit(CU);
return;
}
if (auto *SP = dyn_cast<DISubprogram>(Scope)) {
processSubprogram(SP);
return;
}
if (!addScope(Scope))
return;
if (auto *LB = dyn_cast<DILexicalBlockBase>(Scope)) {
processScope(LB->getScope());
} else if (auto *NS = dyn_cast<DINamespace>(Scope)) {
processScope(NS->getScope());
} else if (auto *M = dyn_cast<DIModule>(Scope)) {
processScope(M->getScope());
}
}
void DebugInfoFinder::processSubprogram(DISubprogram *SP) {
if (!addSubprogram(SP))
return;
processScope(SP->getScope().resolve(TypeIdentifierMap));
processType(SP->getType());
for (auto *Element : SP->getTemplateParams()) {
if (auto *TType = dyn_cast<DITemplateTypeParameter>(Element)) {
processType(TType->getType().resolve(TypeIdentifierMap));
} else if (auto *TVal = dyn_cast<DITemplateValueParameter>(Element)) {
processType(TVal->getType().resolve(TypeIdentifierMap));
}
}
}
void DebugInfoFinder::processDeclare(const Module &M,
const DbgDeclareInst *DDI) {
auto *N = dyn_cast<MDNode>(DDI->getVariable());
if (!N)
return;
InitializeTypeMap(M);
auto *DV = dyn_cast<DILocalVariable>(N);
if (!DV)
return;
if (!NodesSeen.insert(DV).second)
return;
processScope(DV->getScope());
processType(DV->getType().resolve(TypeIdentifierMap));
}
void DebugInfoFinder::processValue(const Module &M, const DbgValueInst *DVI) {
auto *N = dyn_cast<MDNode>(DVI->getVariable());
if (!N)
return;
InitializeTypeMap(M);
auto *DV = dyn_cast<DILocalVariable>(N);
if (!DV)
return;
if (!NodesSeen.insert(DV).second)
return;
processScope(DV->getScope());
processType(DV->getType().resolve(TypeIdentifierMap));
}
bool DebugInfoFinder::addType(DIType *DT) {
if (!DT)
return false;
if (!NodesSeen.insert(DT).second)
return false;
TYs.push_back(const_cast<DIType *>(DT));
return true;
}
bool DebugInfoFinder::addCompileUnit(DICompileUnit *CU) {
if (!CU)
return false;
if (!NodesSeen.insert(CU).second)
return false;
CUs.push_back(CU);
return true;
}
bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable *DIG) {
if (!DIG)
return false;
if (!NodesSeen.insert(DIG).second)
return false;
GVs.push_back(DIG);
return true;
}
bool DebugInfoFinder::addSubprogram(DISubprogram *SP) {
if (!SP)
return false;
if (!NodesSeen.insert(SP).second)
return false;
SPs.push_back(SP);
return true;
}
bool DebugInfoFinder::addScope(DIScope *Scope) {
if (!Scope)
return false;
// FIXME: Ocaml binding generates a scope with no content, we treat it
// as null for now.
if (Scope->getNumOperands() == 0)
return false;
if (!NodesSeen.insert(Scope).second)
return false;
Scopes.push_back(Scope);
return true;
}
bool llvm::stripDebugInfo(Function &F) {
bool Changed = false;
for (BasicBlock &BB : F) {
for (Instruction &I : BB) {
if (I.getDebugLoc()) {
Changed = true;
I.setDebugLoc(DebugLoc());
}
}
}
return Changed;
}
bool llvm::StripDebugInfo(Module &M) {
bool Changed = false;
// Remove all of the calls to the debugger intrinsics, and remove them from
// the module.
if (Function *Declare = M.getFunction("llvm.dbg.declare")) {
while (!Declare->use_empty()) {
[C++11] Add range based accessors for the Use-Def chain of a Value. This requires a number of steps. 1) Move value_use_iterator into the Value class as an implementation detail 2) Change it to actually be a *Use* iterator rather than a *User* iterator. 3) Add an adaptor which is a User iterator that always looks through the Use to the User. 4) Wrap these in Value::use_iterator and Value::user_iterator typedefs. 5) Add the range adaptors as Value::uses() and Value::users(). 6) Update *all* of the callers to correctly distinguish between whether they wanted a use_iterator (and to explicitly dig out the User when needed), or a user_iterator which makes the Use itself totally opaque. Because #6 requires churning essentially everything that walked the Use-Def chains, I went ahead and added all of the range adaptors and switched them to range-based loops where appropriate. Also because the renaming requires at least churning every line of code, it didn't make any sense to split these up into multiple commits -- all of which would touch all of the same lies of code. The result is still not quite optimal. The Value::use_iterator is a nice regular iterator, but Value::user_iterator is an iterator over User*s rather than over the User objects themselves. As a consequence, it fits a bit awkwardly into the range-based world and it has the weird extra-dereferencing 'operator->' that so many of our iterators have. I think this could be fixed by providing something which transforms a range of T&s into a range of T*s, but that *can* be separated into another patch, and it isn't yet 100% clear whether this is the right move. However, this change gets us most of the benefit and cleans up a substantial amount of code around Use and User. =] git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203364 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-09 03:16:01 +00:00
CallInst *CI = cast<CallInst>(Declare->user_back());
CI->eraseFromParent();
}
Declare->eraseFromParent();
Changed = true;
}
if (Function *DbgVal = M.getFunction("llvm.dbg.value")) {
while (!DbgVal->use_empty()) {
[C++11] Add range based accessors for the Use-Def chain of a Value. This requires a number of steps. 1) Move value_use_iterator into the Value class as an implementation detail 2) Change it to actually be a *Use* iterator rather than a *User* iterator. 3) Add an adaptor which is a User iterator that always looks through the Use to the User. 4) Wrap these in Value::use_iterator and Value::user_iterator typedefs. 5) Add the range adaptors as Value::uses() and Value::users(). 6) Update *all* of the callers to correctly distinguish between whether they wanted a use_iterator (and to explicitly dig out the User when needed), or a user_iterator which makes the Use itself totally opaque. Because #6 requires churning essentially everything that walked the Use-Def chains, I went ahead and added all of the range adaptors and switched them to range-based loops where appropriate. Also because the renaming requires at least churning every line of code, it didn't make any sense to split these up into multiple commits -- all of which would touch all of the same lies of code. The result is still not quite optimal. The Value::use_iterator is a nice regular iterator, but Value::user_iterator is an iterator over User*s rather than over the User objects themselves. As a consequence, it fits a bit awkwardly into the range-based world and it has the weird extra-dereferencing 'operator->' that so many of our iterators have. I think this could be fixed by providing something which transforms a range of T&s into a range of T*s, but that *can* be separated into another patch, and it isn't yet 100% clear whether this is the right move. However, this change gets us most of the benefit and cleans up a substantial amount of code around Use and User. =] git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203364 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-09 03:16:01 +00:00
CallInst *CI = cast<CallInst>(DbgVal->user_back());
CI->eraseFromParent();
}
DbgVal->eraseFromParent();
Changed = true;
}
for (Module::named_metadata_iterator NMI = M.named_metadata_begin(),
NME = M.named_metadata_end(); NMI != NME;) {
NamedMDNode *NMD = NMI;
++NMI;
if (NMD->getName().startswith("llvm.dbg.")) {
NMD->eraseFromParent();
Changed = true;
}
}
for (Function &F : M)
Changed |= stripDebugInfo(F);
if (GVMaterializer *Materializer = M.getMaterializer())
Materializer->setStripDebugInfo();
return Changed;
}
unsigned llvm::getDebugMetadataVersionFromModule(const Module &M) {
if (auto *Val = mdconst::dyn_extract_or_null<ConstantInt>(
IR: Split Metadata from Value Split `Metadata` away from the `Value` class hierarchy, as part of PR21532. Assembly and bitcode changes are in the wings, but this is the bulk of the change for the IR C++ API. I have a follow-up patch prepared for `clang`. If this breaks other sub-projects, I apologize in advance :(. Help me compile it on Darwin I'll try to fix it. FWIW, the errors should be easy to fix, so it may be simpler to just fix it yourself. This breaks the build for all metadata-related code that's out-of-tree. Rest assured the transition is mechanical and the compiler should catch almost all of the problems. Here's a quick guide for updating your code: - `Metadata` is the root of a class hierarchy with three main classes: `MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from the `Value` class hierarchy. It is typeless -- i.e., instances do *not* have a `Type`. - `MDNode`'s operands are all `Metadata *` (instead of `Value *`). - `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively. If you're referring solely to resolved `MDNode`s -- post graph construction -- just use `MDNode*`. - `MDNode` (and the rest of `Metadata`) have only limited support for `replaceAllUsesWith()`. As long as an `MDNode` is pointing at a forward declaration -- the result of `MDNode::getTemporary()` -- it maintains a side map of its uses and can RAUW itself. Once the forward declarations are fully resolved RAUW support is dropped on the ground. This means that uniquing collisions on changing operands cause nodes to become "distinct". (This already happened fairly commonly, whenever an operand went to null.) If you're constructing complex (non self-reference) `MDNode` cycles, you need to call `MDNode::resolveCycles()` on each node (or on a top-level node that somehow references all of the nodes). Also, don't do that. Metadata cycles (and the RAUW machinery needed to construct them) are expensive. - An `MDNode` can only refer to a `Constant` through a bridge called `ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`). As a side effect, accessing an operand of an `MDNode` that is known to be, e.g., `ConstantInt`, takes three steps: first, cast from `Metadata` to `ConstantAsMetadata`; second, extract the `Constant`; third, cast down to `ConstantInt`. The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have metadata schema owners transition away from using `Constant`s when the type isn't important (and they don't care about referring to `GlobalValue`s). In the meantime, I've added transitional API to the `mdconst` namespace that matches semantics with the old code, in order to avoid adding the error-prone three-step equivalent to every call site. If your old code was: MDNode *N = foo(); bar(isa <ConstantInt>(N->getOperand(0))); baz(cast <ConstantInt>(N->getOperand(1))); bak(cast_or_null <ConstantInt>(N->getOperand(2))); bat(dyn_cast <ConstantInt>(N->getOperand(3))); bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4))); you can trivially match its semantics with: MDNode *N = foo(); bar(mdconst::hasa <ConstantInt>(N->getOperand(0))); baz(mdconst::extract <ConstantInt>(N->getOperand(1))); bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2))); bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3))); bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4))); and when you transition your metadata schema to `MDInt`: MDNode *N = foo(); bar(isa <MDInt>(N->getOperand(0))); baz(cast <MDInt>(N->getOperand(1))); bak(cast_or_null <MDInt>(N->getOperand(2))); bat(dyn_cast <MDInt>(N->getOperand(3))); bay(dyn_cast_or_null<MDInt>(N->getOperand(4))); - A `CallInst` -- specifically, intrinsic instructions -- can refer to metadata through a bridge called `MetadataAsValue`. This is a subclass of `Value` where `getType()->isMetadataTy()`. `MetadataAsValue` is the *only* class that can legally refer to a `LocalAsMetadata`, which is a bridged form of non-`Constant` values like `Argument` and `Instruction`. It can also refer to any other `Metadata` subclass. (I'll break all your testcases in a follow-up commit, when I propagate this change to assembly.) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@223802 91177308-0d34-0410-b5e6-96231b3b80d8
2014-12-09 18:38:53 +00:00
M.getModuleFlag("Debug Info Version")))
return Val->getZExtValue();
return 0;
}
DenseMap<const llvm::Function *, DISubprogram *>
llvm::makeSubprogramMap(const Module &M) {
DenseMap<const Function *, DISubprogram *> R;
NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu");
if (!CU_Nodes)
return R;
for (MDNode *N : CU_Nodes->operands()) {
auto *CUNode = cast<DICompileUnit>(N);
for (auto *SP : CUNode->getSubprograms()) {
if (Function *F = SP->getFunction())
R.insert(std::make_pair(F, SP));
}
}
return R;
}