Merge pull request #911 from aguskov/master
Fix for DWARF debug info generation pipeline
This commit is contained in:
91
module.cpp
91
module.cpp
@@ -109,10 +109,12 @@
|
|||||||
#if !defined(LLVM_3_2) && !defined(LLVM_3_3) && !defined(LLVM_3_4) // LLVM 3.5+
|
#if !defined(LLVM_3_2) && !defined(LLVM_3_3) && !defined(LLVM_3_4) // LLVM 3.5+
|
||||||
#include <llvm/IR/Verifier.h>
|
#include <llvm/IR/Verifier.h>
|
||||||
#include <llvm/IR/IRPrintingPasses.h>
|
#include <llvm/IR/IRPrintingPasses.h>
|
||||||
|
#include <llvm/IR/InstIterator.h>
|
||||||
#include <llvm/IR/CFG.h>
|
#include <llvm/IR/CFG.h>
|
||||||
#else
|
#else
|
||||||
#include <llvm/Analysis/Verifier.h>
|
#include <llvm/Analysis/Verifier.h>
|
||||||
#include <llvm/Assembly/PrintModulePass.h>
|
#include <llvm/Assembly/PrintModulePass.h>
|
||||||
|
#include <llvm/Support/InstIterator.h>
|
||||||
#include <llvm/Support/CFG.h>
|
#include <llvm/Support/CFG.h>
|
||||||
#endif
|
#endif
|
||||||
#include <clang/Frontend/CompilerInstance.h>
|
#include <clang/Frontend/CompilerInstance.h>
|
||||||
@@ -165,6 +167,44 @@ lStripUnusedDebugInfo(llvm::Module *module) {
|
|||||||
if (g->generateDebuggingSymbols == false)
|
if (g->generateDebuggingSymbols == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
std::set<llvm::Value *> SPall;
|
||||||
|
|
||||||
|
// OK, now we are to determine which functions actually survived the
|
||||||
|
// optimization. We will now read all IR instructions in the module.
|
||||||
|
//
|
||||||
|
// for every function in the module
|
||||||
|
for (llvm::Module::const_iterator
|
||||||
|
f = module->begin(), fe = module->end(); f != fe; ++f) {
|
||||||
|
/// for every instruction in the function
|
||||||
|
for (llvm::const_inst_iterator
|
||||||
|
i = llvm::inst_begin(&(*f)),
|
||||||
|
ie = llvm::inst_end(&(*f)); i != ie; ++i) {
|
||||||
|
const llvm::Instruction *inst = &(*i);
|
||||||
|
// get the instruction`s debugging metadata
|
||||||
|
llvm::MDNode *node = inst->getMetadata(llvm::LLVMContext::MD_dbg);
|
||||||
|
while (node) {
|
||||||
|
llvm::DILocation dloc(node);
|
||||||
|
// get the scope of the current instruction`s location
|
||||||
|
llvm::DIScope scope = dloc.getScope();
|
||||||
|
// node becomes NULL if this was the original location
|
||||||
|
node = dloc.getOrigLocation();
|
||||||
|
// now following a chain of nested scopes
|
||||||
|
while (!0) {
|
||||||
|
if (scope.isLexicalBlockFile())
|
||||||
|
scope = llvm::DILexicalBlockFile(scope).getScope();
|
||||||
|
else if (scope.isLexicalBlock())
|
||||||
|
scope = llvm::DILexicalBlock(scope).getContext();
|
||||||
|
else if (scope.isNameSpace())
|
||||||
|
scope = llvm::DINameSpace(scope).getContext();
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
if (scope.isSubprogram()) {
|
||||||
|
// good, the chain ended with a function; adding
|
||||||
|
SPall.insert(scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// loop over the compile units that contributed to the final module
|
// loop over the compile units that contributed to the final module
|
||||||
if (llvm::NamedMDNode *cuNodes = module->getNamedMetadata("llvm.dbg.cu")) {
|
if (llvm::NamedMDNode *cuNodes = module->getNamedMetadata("llvm.dbg.cu")) {
|
||||||
for (unsigned i = 0, ie = cuNodes->getNumOperands(); i != ie; ++i) {
|
for (unsigned i = 0, ie = cuNodes->getNumOperands(); i != ie; ++i) {
|
||||||
@@ -175,30 +215,20 @@ lStripUnusedDebugInfo(llvm::Module *module) {
|
|||||||
#endif
|
#endif
|
||||||
llvm::DICompileUnit cu(cuNode);
|
llvm::DICompileUnit cu(cuNode);
|
||||||
llvm::DIArray subprograms = cu.getSubprograms();
|
llvm::DIArray subprograms = cu.getSubprograms();
|
||||||
std::vector<llvm::Value *> usedSubprograms;
|
|
||||||
|
|
||||||
if (subprograms.getNumElements() == 0)
|
if (subprograms.getNumElements() == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// And now loop over the subprograms inside each compile unit.
|
std::set<llvm::Value *> SPset;
|
||||||
for (unsigned j = 0, je = subprograms.getNumElements(); j != je; ++j) {
|
std::vector<llvm::Value *> usedSubprograms;
|
||||||
llvm::MDNode *spNode =
|
|
||||||
llvm::dyn_cast<llvm::MDNode>(subprograms->getOperand(j));
|
|
||||||
Assert(spNode != NULL);
|
|
||||||
llvm::DISubprogram sp(spNode);
|
|
||||||
|
|
||||||
// Get the name of the subprogram. Start with the mangled
|
// determine what functions of those extracted belong to the unit
|
||||||
// name; if that's empty then we have an export'ed
|
for (unsigned j = 0, je = subprograms.getNumElements(); j != je; ++j)
|
||||||
// function, so grab the unmangled name in that case.
|
SPset.insert(subprograms->getOperand(j));
|
||||||
std::string name = sp.getLinkageName();
|
|
||||||
if (name == "")
|
|
||||||
name = sp.getName();
|
|
||||||
|
|
||||||
// Does the llvm::Function for this function survive in the
|
std::set_intersection(SPall.begin(), SPall.end(),
|
||||||
// module?
|
SPset.begin(), SPset.end(),
|
||||||
if (module->getFunction(name) != NULL)
|
std::back_inserter(usedSubprograms));
|
||||||
usedSubprograms.push_back(sp);
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug(SourcePos(), "%d / %d functions left in module with debug "
|
Debug(SourcePos(), "%d / %d functions left in module with debug "
|
||||||
"info.", (int)usedSubprograms.size(),
|
"info.", (int)usedSubprograms.size(),
|
||||||
@@ -241,7 +271,7 @@ lStripUnusedDebugInfo(llvm::Module *module) {
|
|||||||
llvm::MDNode *replNode =
|
llvm::MDNode *replNode =
|
||||||
llvm::MDNode::get(*g->ctx, llvm::ArrayRef<llvm::Value *>(usedSubprogramsArray));
|
llvm::MDNode::get(*g->ctx, llvm::ArrayRef<llvm::Value *>(usedSubprogramsArray));
|
||||||
cuNode->replaceOperandWith(12, replNode);
|
cuNode->replaceOperandWith(12, replNode);
|
||||||
#else // LLVM 3.3+
|
#elif defined(LLVM_3_3) || defined(LLVM_3_4) || defined(LLVM_3_5)
|
||||||
llvm::MDNode *nodeSPMDArray =
|
llvm::MDNode *nodeSPMDArray =
|
||||||
llvm::dyn_cast<llvm::MDNode>(cuNode->getOperand(9));
|
llvm::dyn_cast<llvm::MDNode>(cuNode->getOperand(9));
|
||||||
Assert(nodeSPMDArray != NULL);
|
Assert(nodeSPMDArray != NULL);
|
||||||
@@ -255,6 +285,16 @@ lStripUnusedDebugInfo(llvm::Module *module) {
|
|||||||
llvm::MDNode *replNode =
|
llvm::MDNode *replNode =
|
||||||
m->diBuilder->getOrCreateArray(llvm::ArrayRef<llvm::Value *>(usedSubprograms));
|
m->diBuilder->getOrCreateArray(llvm::ArrayRef<llvm::Value *>(usedSubprograms));
|
||||||
cuNode->replaceOperandWith(9, replNode);
|
cuNode->replaceOperandWith(9, replNode);
|
||||||
|
#else // LLVM 3.6+
|
||||||
|
llvm::DIArray nodeSPs = cu.getSubprograms();
|
||||||
|
Assert(nodeSPs.getNumElements() == subprograms.getNumElements());
|
||||||
|
for (int i = 0; i < (int)nodeSPs.getNumElements(); ++i)
|
||||||
|
Assert(nodeSPs.getElement(i) == subprograms.getElement(i));
|
||||||
|
|
||||||
|
// And now we can go and stuff it into the unit with some
|
||||||
|
// confidence...
|
||||||
|
llvm::MDNode *replNode = llvm::MDNode::get(module->getContext(), usedSubprograms);
|
||||||
|
cu.replaceSubprograms(llvm::DIArray(replNode));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -270,12 +310,6 @@ lStripUnusedDebugInfo(llvm::Module *module) {
|
|||||||
}
|
}
|
||||||
for (int i = 0; i < (int)toErase.size(); ++i)
|
for (int i = 0; i < (int)toErase.size(); ++i)
|
||||||
module->eraseNamedMetadata(toErase[i]);
|
module->eraseNamedMetadata(toErase[i]);
|
||||||
|
|
||||||
// Wrap up by running the LLVM pass to remove anything left that's
|
|
||||||
// unused.
|
|
||||||
llvm::PassManager pm;
|
|
||||||
pm.add(llvm::createStripDeadDebugInfoPass());
|
|
||||||
pm.run(*module);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -405,6 +439,8 @@ Module::CompileFile() {
|
|||||||
|
|
||||||
ast->GenerateIR();
|
ast->GenerateIR();
|
||||||
|
|
||||||
|
if (diBuilder)
|
||||||
|
diBuilder->finalize();
|
||||||
if (errorCount == 0)
|
if (errorCount == 0)
|
||||||
Optimize(module, g->opt.level);
|
Optimize(module, g->opt.level);
|
||||||
|
|
||||||
@@ -1033,11 +1069,8 @@ Module::AddExportedTypes(const std::vector<std::pair<const Type *,
|
|||||||
bool
|
bool
|
||||||
Module::writeOutput(OutputType outputType, const char *outFileName,
|
Module::writeOutput(OutputType outputType, const char *outFileName,
|
||||||
const char *includeFileName, DispatchHeaderInfo *DHI) {
|
const char *includeFileName, DispatchHeaderInfo *DHI) {
|
||||||
if (diBuilder != NULL && (outputType != Header && outputType != Deps)) {
|
if (diBuilder && (outputType != Header) && (outputType != Deps))
|
||||||
diBuilder->finalize();
|
|
||||||
|
|
||||||
lStripUnusedDebugInfo(module);
|
lStripUnusedDebugInfo(module);
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(LLVM_3_2) && !defined(LLVM_3_3) // LLVM 3.4+
|
#if !defined(LLVM_3_2) && !defined(LLVM_3_3) // LLVM 3.4+
|
||||||
// In LLVM_3_4 after r195494 and r195504 revisions we should pass
|
// In LLVM_3_4 after r195494 and r195504 revisions we should pass
|
||||||
|
|||||||
Reference in New Issue
Block a user