class DbgValueInst;
class Module;
-/// \brief Find subprogram that is enclosing this scope.
+/// Find subprogram that is enclosing this scope.
DISubprogram *getDISubprogram(const MDNode *Scope);
-/// \brief Strip debug info in the module if it exists.
+/// Strip debug info in the module if it exists.
///
/// To do this, we remove all calls to the debugger intrinsics and any named
/// metadata for debugging. We also remove debug locations for instructions.
/// All debug type metadata nodes are unreachable and garbage collected.
bool stripNonLineTableDebugInfo(Module &M);
-/// \brief Return Debug Info Metadata Version by checking module flags.
+/// Return Debug Info Metadata Version by checking module flags.
unsigned getDebugMetadataVersionFromModule(const Module &M);
-/// \brief Utility to find all debug info in a module.
+/// Utility to find all debug info in a module.
///
/// DebugInfoFinder tries to list all debug info MDNodes used in a module. To
/// list debug info MDNodes used by an instruction, DebugInfoFinder uses
/// used by the CUs.
class DebugInfoFinder {
public:
- /// \brief Process entire module and collect debug info anchors.
+ /// Process entire module and collect debug info anchors.
void processModule(const Module &M);
+ /// Process a single instruction and collect debug info anchors.
+ void processInstruction(const Module &M, const Instruction &I);
- /// \brief Process DbgDeclareInst.
+ /// Process DbgDeclareInst.
void processDeclare(const Module &M, const DbgDeclareInst *DDI);
- /// \brief Process DbgValueInst.
+ /// Process DbgValueInst.
void processValue(const Module &M, const DbgValueInst *DVI);
- /// \brief Process debug info location.
+ /// Process debug info location.
void processLocation(const Module &M, const DILocation *Loc);
- /// \brief Clear all lists.
+ /// Clear all lists.
void reset();
private:
void InitializeTypeMap(const Module &M);
- void processType(DIType *DT);
- void processSubprogram(DISubprogram *SP);
void processCompileUnit(DICompileUnit *CU);
void processScope(DIScope *Scope);
+ void processSubprogram(DISubprogram *SP);
+ void processType(DIType *DT);
bool addCompileUnit(DICompileUnit *CU);
bool addGlobalVariable(DIGlobalVariableExpression *DIG);
+ bool addScope(DIScope *Scope);
bool addSubprogram(DISubprogram *SP);
bool addType(DIType *DT);
- bool addScope(DIScope *Scope);
public:
using compile_unit_iterator =
}
void DebugInfoFinder::processModule(const Module &M) {
- for (auto *CU : M.debug_compile_units()) {
- addCompileUnit(CU);
- for (auto DIG : CU->getGlobalVariables()) {
- if (!addGlobalVariable(DIG))
- continue;
- auto *GV = DIG->getVariable();
- processScope(GV->getScope());
- processType(GV->getType().resolve());
- }
- for (auto *ET : CU->getEnumTypes())
- processType(ET);
- for (auto *RT : CU->getRetainedTypes())
- if (auto *T = dyn_cast<DIType>(RT))
- processType(T);
- else
- processSubprogram(cast<DISubprogram>(RT));
- for (auto *Import : CU->getImportedEntities()) {
- auto *Entity = Import->getEntity().resolve();
- 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());
- else
- llvm_unreachable("unexpected imported entity type");
- }
- }
+ for (auto *CU : M.debug_compile_units())
+ processCompileUnit(CU);
for (auto &F : M.functions()) {
if (auto *SP = cast_or_null<DISubprogram>(F.getSubprogram()))
processSubprogram(SP);
// There could be subprograms from inlined functions referenced from
// instructions only. Walk the function to find them.
- for (const BasicBlock &BB : F) {
- for (const Instruction &I : BB) {
- if (auto *DDI = dyn_cast<DbgDeclareInst>(&I))
- processDeclare(M, DDI);
- else if (auto *DVI = dyn_cast<DbgValueInst>(&I))
- processValue(M, DVI);
-
- if (auto DbgLoc = I.getDebugLoc())
- processLocation(M, DbgLoc.get());
- }
- }
+ for (const BasicBlock &BB : F)
+ for (const Instruction &I : BB)
+ processInstruction(M, I);
}
}
}
}
+void DebugInfoFinder::processInstruction(const Module &M,
+ const Instruction &I) {
+ if (auto *DDI = dyn_cast<DbgDeclareInst>(&I))
+ processDeclare(M, DDI);
+ else if (auto *DVI = dyn_cast<DbgValueInst>(&I))
+ processValue(M, DVI);
+
+ if (auto DbgLoc = I.getDebugLoc())
+ processLocation(M, DbgLoc.get());
+}
+
void DebugInfoFinder::processLocation(const Module &M, const DILocation *Loc) {
if (!Loc)
return;
DebugInfoFinder *DIFinder) {
DenseMap<const MDNode *, MDNode *> Cache;
BasicBlock *NewBB = BasicBlock::Create(BB->getContext(), "", F);
- if (BB->hasName()) NewBB->setName(BB->getName()+NameSuffix);
+ if (BB->hasName())
+ NewBB->setName(BB->getName() + NameSuffix);
bool hasCalls = false, hasDynamicAllocas = false, hasStaticAllocas = false;
Module *TheModule = F ? F->getParent() : nullptr;
// Loop over all instructions, and copy them over.
- for (BasicBlock::const_iterator II = BB->begin(), IE = BB->end();
- II != IE; ++II) {
-
- if (DIFinder && TheModule) {
- if (auto *DDI = dyn_cast<DbgDeclareInst>(II))
- DIFinder->processDeclare(*TheModule, DDI);
- else if (auto *DVI = dyn_cast<DbgValueInst>(II))
- DIFinder->processValue(*TheModule, DVI);
-
- if (auto DbgLoc = II->getDebugLoc())
- DIFinder->processLocation(*TheModule, DbgLoc.get());
- }
+ for (const Instruction &I : *BB) {
+ if (DIFinder && TheModule)
+ DIFinder->processInstruction(*TheModule, I);
- Instruction *NewInst = II->clone();
- if (II->hasName())
- NewInst->setName(II->getName()+NameSuffix);
+ Instruction *NewInst = I.clone();
+ if (I.hasName())
+ NewInst->setName(I.getName() + NameSuffix);
NewBB->getInstList().push_back(NewInst);
- VMap[&*II] = NewInst; // Add instruction map to value.
+ VMap[&I] = NewInst; // Add instruction map to value.
- hasCalls |= (isa<CallInst>(II) && !isa<DbgInfoIntrinsic>(II));
- if (const AllocaInst *AI = dyn_cast<AllocaInst>(II)) {
+ hasCalls |= (isa<CallInst>(I) && !isa<DbgInfoIntrinsic>(I));
+ if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
if (isa<ConstantInt>(AI->getArraySize()))
hasStaticAllocas = true;
else
hasDynamicAllocas = true;
}
}
-
+
if (CodeInfo) {
CodeInfo->ContainsCalls |= hasCalls;
CodeInfo->ContainsDynamicAllocas |= hasDynamicAllocas;
- CodeInfo->ContainsDynamicAllocas |= hasStaticAllocas &&
+ CodeInfo->ContainsDynamicAllocas |= hasStaticAllocas &&
BB != &BB->getParent()->getEntryBlock();
}
return NewBB;
Returns.push_back(RI);
}
- for (DISubprogram *ISP : DIFinder.subprograms()) {
- if (ISP != SP) {
+ for (DISubprogram *ISP : DIFinder.subprograms())
+ if (ISP != SP)
VMap.MD()[ISP].reset(ISP);
- }
- }
for (DICompileUnit *CU : DIFinder.compile_units())
VMap.MD()[CU].reset(CU);
- for (auto *Type : DIFinder.types()) {
+ for (DIType *Type : DIFinder.types())
VMap.MD()[Type].reset(Type);
- }
// Loop over all of the instructions in the function, fixing up operand
// references as we go. This uses VMap to do all the hard work.
// a stream to write to them. Note that llc does something similar and it
// may be worth to abstract this out in the future.
SmallVector<char, 0> Buffer;
- SmallVector<char, 0> CompileTwiceBuffer;
+ SmallVector<char, 0> FirstRunBuffer;
std::unique_ptr<raw_svector_ostream> BOS;
raw_ostream *OS = nullptr;
// Run all passes on the original module first, so the second run processes
// the clone to catch CloneModule bugs.
Passes.run(*M);
- CompileTwiceBuffer = Buffer;
+ FirstRunBuffer = Buffer;
Buffer.clear();
Passes.run(*M2);
// Compare the two outputs and make sure they're the same
assert(Out);
- if (Buffer.size() != CompileTwiceBuffer.size() ||
- (memcmp(Buffer.data(), CompileTwiceBuffer.data(), Buffer.size()) !=
- 0)) {
- errs() << "Running the pass manager twice changed the output.\n"
- "Writing the result of the second run to the specified output.\n"
- "To generate the one-run comparison binary, just run without\n"
- "the compile-twice option\n";
+ if (Buffer.size() != FirstRunBuffer.size() ||
+ (memcmp(Buffer.data(), FirstRunBuffer.data(), Buffer.size()) != 0)) {
+ errs()
+ << "Running the pass manager twice changed the output.\n"
+ "Writing the result of the second run to the specified output.\n"
+ "To generate the one-run comparison binary, just run without\n"
+ "the compile-twice option\n";
Out->os() << BOS->str();
Out->keep();
if (OptRemarkFile)