David van Moolenbroek 3e457fe321 Import magic pass from llvm-apps
Change-Id: I19535b913b50f2ff24aeb80ddefc92e305c31fe8
2015-09-17 13:57:53 +00:00

173 lines
6.1 KiB
C++

#include <pass.h>
#include <magic/support/Backports.h>
#include <magic/support/EDIType.h>
#include <magic/support/SmartType.h>
using namespace llvm;
namespace llvm {
//===----------------------------------------------------------------------===//
// Public static methods
//===----------------------------------------------------------------------===//
/// Find the debug info descriptor corresponding to this global variable.
Value *Backports::findDbgGlobalDeclare(GlobalVariable *V) {
return PassUtil::findDbgGlobalDeclare(V);
}
/// Find the debug info descriptor corresponding to this function.
Value *Backports::findDbgSubprogramDeclare(Function *V) {
return PassUtil::findDbgSubprogramDeclare(V);
}
/// Finds the llvm.dbg.declare intrinsic corresponding to this value if any.
/// It looks through pointer casts too.
const DbgDeclareInst *Backports::findDbgDeclare(const Value *V) {
V = V->stripPointerCasts();
if (!isa<Instruction>(V) && !isa<Argument>(V))
return 0;
const Function *F = NULL;
if (const Instruction *I = dyn_cast<Instruction>(V))
F = I->getParent()->getParent();
else if (const Argument *A = dyn_cast<Argument>(V))
F = A->getParent();
for (Function::const_iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI)
for (BasicBlock::const_iterator BI = (*FI).begin(), BE = (*FI).end();
BI != BE; ++BI)
if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI))
if (DDI->getAddress() == V)
return DDI;
return 0;
}
/// FindAllocaDbgDeclare - Finds the llvm.dbg.declare intrinsic describing the
/// alloca 'V', if any.
DbgDeclareInst *Backports::FindAllocaDbgDeclare(Value *V) {
#if LLVM_VERSION >= 33
if (MDNode *DebugNode = MDNode::getIfExists(V->getContext(), V))
for (Value::use_iterator UI = DebugNode->use_begin(),
E = DebugNode->use_end(); UI != E; ++UI)
if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(*UI))
return DDI;
return 0;
#else
///
/// There is an unfixed bug (http://llvm.org/bugs/show_bug.cgi?id=10887)
/// that drops debug information references for local variables at linking time.
/// This is way the method FindAllocaDbgDeclare() will always return NULL and
/// we need to resort to some ugly workaround.
///
AllocaInst *AI = dyn_cast<AllocaInst>(V);
if(!AI) {
return NULL;
}
BasicBlock *varParent = AI->getParent();
Function *varFunc = varParent->getParent();
if(!AI->hasName() || !AI->getName().compare("retval")) {
return NULL;
}
StringRef varName = AI->getName();
bool isInlinedVar = false;
bool isScopedVar = false;
DIType aDIType, aAddrDIType, tmpDIType;
DbgDeclareInst *DDI = NULL, *addrDDI = NULL;
SmallVector< StringRef, 8 > vector;
varName.split(vector, ".");
if(vector.size() >= 2 && vector[1][0] == 'i') {
isInlinedVar = true;
varName = vector[0];
}
if(!isInlinedVar) {
//for non-inlined variables we have to look in the first bb first.
for(BasicBlock::iterator i=varParent->begin(), e=varParent->end();i!=e;i++) {
if(DbgDeclareInst *DI = dyn_cast<DbgDeclareInst>(i)) {
MDNode *node = DI->getVariable();
assert(node);
DIVariable DIV(node);
if(!DIV.getName().compare(varName)) {
aDIType = DIV.getType();
DDI = DI;
break;
}
StringRef addrVarName(DIV.getName().str() + "_addr");
if(!addrVarName.compare(varName)) {
aAddrDIType = DIV.getType();
addrDDI = DI;
break;
}
}
}
if(!DDI && !addrDDI) {
//not found? probably a scoped variable, look anywhere else.
isScopedVar = true;
}
}
if(isInlinedVar || isScopedVar) {
//for inlined/scoped variables we have to look everywhere in the function and name clashing could also occur.
bool isDuplicate = false;
for (inst_iterator it = inst_begin(varFunc), et = inst_end(varFunc); it != et; ++it) {
Instruction *inst = &(*it);
if(DbgDeclareInst *DI = dyn_cast<DbgDeclareInst>(inst)) {
MDNode *node = DI->getVariable();
assert(node);
DIVariable DIV(node);
StringRef addrVarName(DIV.getName().str() + "_addr");
if(!DIV.getName().compare(varName) || !addrVarName.compare(varName)) {
tmpDIType = DIV.getType();
EDIType tmpEDIType(tmpDIType);
if(!SmartType::isTypeConsistent(AI->getAllocatedType(), &tmpEDIType)) {
continue;
}
bool skipDIType = false;
if(DDI) {
EDIType aEDIType(aDIType);
skipDIType = true;
if(!aEDIType.equals(&tmpEDIType)) {
isDuplicate = true;
}
}
if(addrDDI) {
EDIType aAddrEDIType(aAddrDIType);
skipDIType = true;
if(!aAddrEDIType.equals(&tmpEDIType)) {
isDuplicate = true;
}
}
if(!skipDIType && !DIV.getName().compare(varName)) {
aDIType = tmpDIType;
DDI = DI;
continue;
}
if(!skipDIType && !addrVarName.compare(varName)) {
aAddrDIType = tmpDIType;
addrDDI = DI;
continue;
}
}
}
}
if(isDuplicate) {
//name clashing problem with inline/scoped variables, pretend nothing was found
DDI = NULL;
addrDDI = NULL;
}
}
if(!DDI && !addrDDI) {
return (DbgDeclareInst*)-1;
}
assert((DDI && !addrDDI) || (!DDI && addrDDI));
DDI = DDI ? DDI : addrDDI;
return DDI;
#endif
}
}