mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
Implement support to debug inlined functions.
llvm-svn: 86748
This commit is contained in:
parent
958f41d9a4
commit
5c983cb2ab
@ -693,12 +693,6 @@ bool getLocationInfo(const Value *V, std::string &DisplayName,
|
||||
DebugLoc ExtractDebugLocation(DbgFuncStartInst &FSI,
|
||||
DebugLocTracker &DebugLocInfo);
|
||||
|
||||
/// isInlinedFnStart - Return true if FSI is starting an inlined function.
|
||||
bool isInlinedFnStart(DbgFuncStartInst &FSI, const Function *CurrentFn);
|
||||
|
||||
/// isInlinedFnEnd - Return true if REI is ending an inlined function.
|
||||
bool isInlinedFnEnd(DbgRegionEndInst &REI, const Function *CurrentFn);
|
||||
/// DebugInfoFinder - This object collects DebugInfo from a module.
|
||||
class DebugInfoFinder {
|
||||
|
||||
public:
|
||||
|
@ -104,14 +104,8 @@ public:
|
||||
/// be emitted.
|
||||
bool ShouldEmitDwarfDebug() const;
|
||||
|
||||
//// RecordInlinedFnStart - Indicate the start of a inlined function.
|
||||
unsigned RecordInlinedFnStart(DISubprogram SP, DICompileUnit CU,
|
||||
unsigned Line, unsigned Col);
|
||||
|
||||
/// RecordInlinedFnEnd - Indicate the end of inlined subroutine.
|
||||
unsigned RecordInlinedFnEnd(DISubprogram SP);
|
||||
void SetDbgScopeBeginLabels(const MachineInstr *MI, unsigned L);
|
||||
void SetDbgScopeEndLabels(const MachineInstr *MI, unsigned L);
|
||||
void BeginScope(const MachineInstr *MI, unsigned Label);
|
||||
void EndScope(const MachineInstr *MI);
|
||||
};
|
||||
|
||||
} // end llvm namespace
|
||||
|
@ -150,7 +150,8 @@ class MachineModuleInfo : public ImmutablePass {
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
|
||||
typedef SmallVector< std::pair<TrackingVH<MDNode>, unsigned>, 4 >
|
||||
typedef std::pair<unsigned, TrackingVH<MDNode> > UnsignedAndMDNodePair;
|
||||
typedef SmallVector< std::pair<TrackingVH<MDNode>, UnsignedAndMDNodePair>, 4>
|
||||
VariableDbgInfoMapTy;
|
||||
VariableDbgInfoMapTy VariableDbgInfo;
|
||||
|
||||
@ -336,8 +337,8 @@ public:
|
||||
|
||||
/// setVariableDbgInfo - Collect information used to emit debugging information
|
||||
/// of a variable.
|
||||
void setVariableDbgInfo(MDNode *N, unsigned S) {
|
||||
VariableDbgInfo.push_back(std::make_pair(N, S));
|
||||
void setVariableDbgInfo(MDNode *N, unsigned Slot, MDNode *Scope) {
|
||||
VariableDbgInfo.push_back(std::make_pair(N, std::make_pair(Slot, Scope)));
|
||||
}
|
||||
|
||||
VariableDbgInfoMapTy &getVariableDbgInfo() { return VariableDbgInfo; }
|
||||
|
@ -24,6 +24,7 @@ namespace llvm {
|
||||
|
||||
class Module;
|
||||
class Function;
|
||||
class Instruction;
|
||||
class Pass;
|
||||
class LPPassManager;
|
||||
class BasicBlock;
|
||||
@ -154,7 +155,8 @@ void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
|
||||
SmallVectorImpl<ReturnInst*> &Returns,
|
||||
const char *NameSuffix = "",
|
||||
ClonedCodeInfo *CodeInfo = 0,
|
||||
const TargetData *TD = 0);
|
||||
const TargetData *TD = 0,
|
||||
Instruction *TheCall = 0);
|
||||
|
||||
/// InlineFunction - This function inlines the called function into the basic
|
||||
/// block of the caller. This returns false if it is not possible to inline
|
||||
|
@ -1487,22 +1487,4 @@ bool getLocationInfo(const Value *V, std::string &DisplayName,
|
||||
|
||||
return DebugLoc::get(Id);
|
||||
}
|
||||
|
||||
/// isInlinedFnStart - Return true if FSI is starting an inlined function.
|
||||
bool isInlinedFnStart(DbgFuncStartInst &FSI, const Function *CurrentFn) {
|
||||
DISubprogram Subprogram(cast<MDNode>(FSI.getSubprogram()));
|
||||
if (Subprogram.describes(CurrentFn))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// isInlinedFnEnd - Return true if REI is ending an inlined function.
|
||||
bool isInlinedFnEnd(DbgRegionEndInst &REI, const Function *CurrentFn) {
|
||||
DISubprogram Subprogram(cast<MDNode>(REI.getContext()));
|
||||
if (Subprogram.isNull() || Subprogram.describes(CurrentFn))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1357,32 +1357,31 @@ void AsmPrinter::PrintSpecial(const MachineInstr *MI, const char *Code) const {
|
||||
/// instruction's DebugLoc.
|
||||
void AsmPrinter::processDebugLoc(const MachineInstr *MI,
|
||||
bool BeforePrintingInsn) {
|
||||
if (!MAI || !DW)
|
||||
if (!MAI || !DW || !MAI->doesSupportDebugInformation()
|
||||
|| !DW->ShouldEmitDwarfDebug())
|
||||
return;
|
||||
DebugLoc DL = MI->getDebugLoc();
|
||||
if (MAI->doesSupportDebugInformation() && DW->ShouldEmitDwarfDebug()) {
|
||||
if (!DL.isUnknown()) {
|
||||
DebugLocTuple CurDLT = MF->getDebugLocTuple(DL);
|
||||
if (BeforePrintingInsn) {
|
||||
if (CurDLT.Scope != 0 && PrevDLT != CurDLT) {
|
||||
unsigned L = DW->RecordSourceLine(CurDLT.Line, CurDLT.Col,
|
||||
CurDLT.Scope);
|
||||
printLabel(L);
|
||||
O << '\n';
|
||||
#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
|
||||
DW->SetDbgScopeBeginLabels(MI, L);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
|
||||
DW->SetDbgScopeEndLabels(MI, 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (DL.isUnknown())
|
||||
return;
|
||||
DebugLocTuple CurDLT = MF->getDebugLocTuple(DL);
|
||||
if (CurDLT.Scope == 0)
|
||||
return;
|
||||
|
||||
if (BeforePrintingInsn) {
|
||||
if (CurDLT != PrevDLT) {
|
||||
unsigned L = DW->RecordSourceLine(CurDLT.Line, CurDLT.Col,
|
||||
CurDLT.Scope);
|
||||
printLabel(L);
|
||||
DW->BeginScope(MI, L);
|
||||
PrevDLT = CurDLT;
|
||||
}
|
||||
} else {
|
||||
// After printing instruction
|
||||
DW->EndScope(MI);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// printInlineAsm - This method formats and prints the specified machine
|
||||
/// instruction that is an inline asm.
|
||||
void AsmPrinter::printInlineAsm(const MachineInstr *MI) const {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -134,52 +134,52 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf {
|
||||
///
|
||||
bool shouldEmit;
|
||||
|
||||
// FunctionDbgScope - Top level scope for the current function.
|
||||
// CurrentFnDbgScope - Top level scope for the current function.
|
||||
//
|
||||
DbgScope *FunctionDbgScope;
|
||||
DbgScope *CurrentFnDbgScope;
|
||||
|
||||
/// DbgScopeMap - Tracks the scopes in the current function.
|
||||
///
|
||||
ValueMap<MDNode *, DbgScope *> DbgScopeMap;
|
||||
|
||||
/// ConcreteScopes - Tracks the concrete scopees in the current function.
|
||||
/// These scopes are also included in DbgScopeMap.
|
||||
ValueMap<MDNode *, DbgScope *> ConcreteScopes;
|
||||
|
||||
/// AbstractScopes - Tracks the abstract scopes a module. These scopes are
|
||||
/// not included DbgScopeMap.
|
||||
ValueMap<MDNode *, DbgScope *> AbstractScopes;
|
||||
SmallVector<DbgScope *, 4>AbstractScopesList;
|
||||
|
||||
/// AbstractVariables - Collection on abstract variables.
|
||||
ValueMap<MDNode *, DbgVariable *> AbstractVariables;
|
||||
|
||||
/// InliendSubprogramDIEs - Collection of subprgram DIEs that are marked
|
||||
/// (at the end of the module) as DW_AT_inline.
|
||||
SmallPtrSet<DIE *, 4> InlinedSubprogramDIEs;
|
||||
|
||||
/// AbstractSubprogramDIEs - Collection of abstruct subprogram DIEs.
|
||||
SmallPtrSet<DIE *, 4> AbstractSubprogramDIEs;
|
||||
|
||||
/// ScopedGVs - Tracks global variables that are not at file scope.
|
||||
/// For example void f() { static int b = 42; }
|
||||
SmallVector<WeakVH, 4> ScopedGVs;
|
||||
|
||||
typedef DenseMap<const MachineInstr *, SmallVector<DbgScope *, 2> >
|
||||
typedef SmallVector<DbgScope *, 2> ScopeVector;
|
||||
typedef DenseMap<const MachineInstr *, ScopeVector>
|
||||
InsnToDbgScopeMapTy;
|
||||
|
||||
/// DbgScopeBeginMap - Maps instruction with a list DbgScopes it starts.
|
||||
/// DbgScopeBeginMap - Maps instruction with a list of DbgScopes it starts.
|
||||
InsnToDbgScopeMapTy DbgScopeBeginMap;
|
||||
|
||||
/// DbgScopeEndMap - Maps instruction with a list DbgScopes it ends.
|
||||
InsnToDbgScopeMapTy DbgScopeEndMap;
|
||||
|
||||
/// DbgAbstractScopeMap - Tracks abstract instance scopes in the current
|
||||
/// function.
|
||||
ValueMap<MDNode *, DbgScope *> DbgAbstractScopeMap;
|
||||
|
||||
/// DbgConcreteScopeMap - Tracks concrete instance scopes in the current
|
||||
/// function.
|
||||
ValueMap<MDNode *,
|
||||
SmallVector<DbgScope *, 8> > DbgConcreteScopeMap;
|
||||
|
||||
/// InlineInfo - Keep track of inlined functions and their location. This
|
||||
/// information is used to populate debug_inlined section.
|
||||
ValueMap<MDNode *, SmallVector<unsigned, 4> > InlineInfo;
|
||||
|
||||
/// AbstractInstanceRootMap - Map of abstract instance roots of inlined
|
||||
/// functions. These are subroutine entries that contain a DW_AT_inline
|
||||
/// attribute.
|
||||
DenseMap<const MDNode *, DbgScope *> AbstractInstanceRootMap;
|
||||
|
||||
/// AbstractInstanceRootList - List of abstract instance roots of inlined
|
||||
/// functions. These are subroutine entries that contain a DW_AT_inline
|
||||
/// attribute.
|
||||
SmallVector<DbgScope *, 32> AbstractInstanceRootList;
|
||||
|
||||
/// LexicalScopeStack - A stack of lexical scopes. The top one is the current
|
||||
/// scope.
|
||||
SmallVector<DbgScope *, 16> LexicalScopeStack;
|
||||
typedef std::pair<unsigned, DIE *> InlineInfoLabels;
|
||||
ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> > InlineInfo;
|
||||
SmallVector<MDNode *, 4> InlinedSPNodes;
|
||||
|
||||
/// CompileUnitOffsets - A vector of the offsets of the compile units. This is
|
||||
/// used when calculating the "origin" of a concrete instance of an inlined
|
||||
@ -361,10 +361,24 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf {
|
||||
///
|
||||
DIE *CreateDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit);
|
||||
|
||||
/// getDbgScope - Returns the scope associated with the given descriptor.
|
||||
///
|
||||
/// getUpdatedDbgScope - Find or create DbgScope assicated with
|
||||
/// the instruction. Initialize scope and update scope hierarchy.
|
||||
DbgScope *getUpdatedDbgScope(MDNode *N, const MachineInstr *MI, MDNode *InlinedAt);
|
||||
|
||||
/// createDbgScope - Create DbgScope for the scope.
|
||||
void createDbgScope(MDNode *Scope, MDNode *InlinedAt);
|
||||
DbgScope *getOrCreateScope(MDNode *N);
|
||||
DbgScope *getDbgScope(MDNode *N, const MachineInstr *MI, MDNode *InlinedAt);
|
||||
DbgScope *getOrCreateAbstractScope(MDNode *N);
|
||||
|
||||
/// findAbstractVariable - Find abstract variable associated with Var.
|
||||
DbgVariable *findAbstractVariable(DIVariable &Var, unsigned FrameIdx,
|
||||
DILocation &Loc);
|
||||
|
||||
DIE *UpdateSubprogramScopeDIE(MDNode *SPNode);
|
||||
DIE *ConstructLexicalScopeDIE(DbgScope *Scope);
|
||||
DIE *ConstructScopeDIE(DbgScope *Scope);
|
||||
DIE *ConstructInlinedScopeDIE(DbgScope *Scope);
|
||||
DIE *ConstructVariableDIE(DbgVariable *DV, DbgScope *S, CompileUnit *Unit);
|
||||
|
||||
/// ConstructDbgScope - Construct the components of a scope.
|
||||
///
|
||||
@ -372,10 +386,10 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf {
|
||||
unsigned ParentStartID, unsigned ParentEndID,
|
||||
DIE *ParentDie, CompileUnit *Unit);
|
||||
|
||||
/// ConstructFunctionDbgScope - Construct the scope for the subprogram.
|
||||
/// ConstructCurrentFnDbgScope - Construct the scope for the subprogram.
|
||||
///
|
||||
void ConstructFunctionDbgScope(DbgScope *RootScope,
|
||||
bool AbstractScope = false);
|
||||
void ConstructCurrentFnDbgScope(DbgScope *RootScope,
|
||||
bool AbstractScope = false);
|
||||
|
||||
/// ConstructDefaultDbgScope - Construct a default scope for the subprogram.
|
||||
///
|
||||
@ -544,13 +558,6 @@ public:
|
||||
/// RecordVariable - Indicate the declaration of a local variable.
|
||||
void RecordVariable(MDNode *N, unsigned FrameIndex);
|
||||
|
||||
//// RecordInlinedFnStart - Indicate the start of inlined subroutine.
|
||||
unsigned RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU,
|
||||
unsigned Line, unsigned Col);
|
||||
|
||||
/// RecordInlinedFnEnd - Indicate the end of inlined subroutine.
|
||||
unsigned RecordInlinedFnEnd(DISubprogram &SP);
|
||||
|
||||
/// ExtractScopeInformation - Scan machine instructions in this function
|
||||
/// and collect DbgScopes. Return true, if atleast one scope was found.
|
||||
bool ExtractScopeInformation(MachineFunction *MF);
|
||||
@ -558,15 +565,16 @@ public:
|
||||
/// CollectVariableInfo - Populate DbgScope entries with variables' info.
|
||||
void CollectVariableInfo();
|
||||
|
||||
/// SetDbgScopeBeginLabels - Update DbgScope begin labels for the scopes that
|
||||
/// start with this machine instruction.
|
||||
void SetDbgScopeBeginLabels(const MachineInstr *MI, unsigned Label);
|
||||
|
||||
/// SetDbgScopeEndLabels - Update DbgScope end labels for the scopes that
|
||||
/// end with this machine instruction.
|
||||
void SetDbgScopeEndLabels(const MachineInstr *MI, unsigned Label);
|
||||
};
|
||||
|
||||
/// BeginScope - Process beginning of a scope starting at Label.
|
||||
void BeginScope(const MachineInstr *MI, unsigned Label);
|
||||
|
||||
/// EndScope - Prcess end of a scope.
|
||||
void EndScope(const MachineInstr *MI);
|
||||
};
|
||||
} // End of namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -108,20 +108,9 @@ bool DwarfWriter::ShouldEmitDwarfDebug() const {
|
||||
return DD && DD->ShouldEmitDwarfDebug();
|
||||
}
|
||||
|
||||
//// RecordInlinedFnStart
|
||||
unsigned DwarfWriter::RecordInlinedFnStart(DISubprogram SP, DICompileUnit CU,
|
||||
unsigned Line, unsigned Col) {
|
||||
return DD->RecordInlinedFnStart(SP, CU, Line, Col);
|
||||
void DwarfWriter::BeginScope(const MachineInstr *MI, unsigned L) {
|
||||
DD->BeginScope(MI, L);
|
||||
}
|
||||
|
||||
/// RecordInlinedFnEnd - Indicate the end of inlined subroutine.
|
||||
unsigned DwarfWriter::RecordInlinedFnEnd(DISubprogram SP) {
|
||||
return DD->RecordInlinedFnEnd(SP);
|
||||
}
|
||||
|
||||
void DwarfWriter::SetDbgScopeBeginLabels(const MachineInstr *MI, unsigned L) {
|
||||
DD->SetDbgScopeEndLabels(MI, L);
|
||||
}
|
||||
void DwarfWriter::SetDbgScopeEndLabels(const MachineInstr *MI, unsigned L) {
|
||||
DD->SetDbgScopeBeginLabels(MI, L);
|
||||
void DwarfWriter::EndScope(const MachineInstr *MI) {
|
||||
DD->EndScope(MI);
|
||||
}
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "llvm/GlobalVariable.h"
|
||||
#include "llvm/Instructions.h"
|
||||
#include "llvm/IntrinsicInst.h"
|
||||
#include "llvm/LLVMContext.h"
|
||||
#include "llvm/CodeGen/FastISel.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
@ -347,21 +348,9 @@ bool FastISel::SelectCall(User *I) {
|
||||
&& DW->ShouldEmitDwarfDebug()) {
|
||||
unsigned ID = 0;
|
||||
DISubprogram Subprogram(REI->getContext());
|
||||
if (isInlinedFnEnd(*REI, MF.getFunction())) {
|
||||
// This is end of an inlined function.
|
||||
const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL);
|
||||
ID = DW->RecordInlinedFnEnd(Subprogram);
|
||||
if (ID)
|
||||
// Returned ID is 0 if this is unbalanced "end of inlined
|
||||
// scope". This could happen if optimizer eats dbg intrinsics
|
||||
// or "beginning of inlined scope" is not recoginized due to
|
||||
// missing location info. In such cases, ignore this region.end.
|
||||
BuildMI(MBB, DL, II).addImm(ID);
|
||||
} else {
|
||||
const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL);
|
||||
ID = DW->RecordRegionEnd(REI->getContext());
|
||||
BuildMI(MBB, DL, II).addImm(ID);
|
||||
}
|
||||
const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL);
|
||||
ID = DW->RecordRegionEnd(REI->getContext());
|
||||
BuildMI(MBB, DL, II).addImm(ID);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -371,28 +360,6 @@ bool FastISel::SelectCall(User *I) {
|
||||
|| !DW->ShouldEmitDwarfDebug())
|
||||
return true;
|
||||
|
||||
if (isInlinedFnStart(*FSI, MF.getFunction())) {
|
||||
// This is a beginning of an inlined function.
|
||||
|
||||
// If llvm.dbg.func.start is seen in a new block before any
|
||||
// llvm.dbg.stoppoint intrinsic then the location info is unknown.
|
||||
// FIXME : Why DebugLoc is reset at the beginning of each block ?
|
||||
DebugLoc PrevLoc = DL;
|
||||
if (PrevLoc.isUnknown())
|
||||
return true;
|
||||
// Record the source line.
|
||||
setCurDebugLoc(ExtractDebugLocation(*FSI, MF.getDebugLocInfo()));
|
||||
|
||||
DebugLocTuple PrevLocTpl = MF.getDebugLocTuple(PrevLoc);
|
||||
DISubprogram SP(FSI->getSubprogram());
|
||||
unsigned LabelID =
|
||||
DW->RecordInlinedFnStart(SP,DICompileUnit(PrevLocTpl.Scope),
|
||||
PrevLocTpl.Line, PrevLocTpl.Col);
|
||||
const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL);
|
||||
BuildMI(MBB, DL, II).addImm(LabelID);
|
||||
return true;
|
||||
}
|
||||
|
||||
// This is a beginning of a new function.
|
||||
MF.setDefaultDebugLoc(ExtractDebugLocation(*FSI, MF.getDebugLocInfo()));
|
||||
|
||||
@ -416,8 +383,13 @@ bool FastISel::SelectCall(User *I) {
|
||||
StaticAllocaMap.find(AI);
|
||||
if (SI == StaticAllocaMap.end()) break; // VLAs.
|
||||
int FI = SI->second;
|
||||
if (MMI)
|
||||
MMI->setVariableDbgInfo(DI->getVariable(), FI);
|
||||
if (MMI) {
|
||||
MetadataContext &TheMetadata =
|
||||
DI->getParent()->getContext().getMetadata();
|
||||
unsigned MDDbgKind = TheMetadata.getMDKind("dbg");
|
||||
MDNode *Dbg = TheMetadata.getMD(MDDbgKind, DI);
|
||||
MMI->setVariableDbgInfo(DI->getVariable(), FI, Dbg);
|
||||
}
|
||||
#ifndef ATTACH_DEBUG_INFO_TO_AN_INSN
|
||||
DW->RecordVariable(DI->getVariable(), FI);
|
||||
#endif
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "llvm/Instructions.h"
|
||||
#include "llvm/Intrinsics.h"
|
||||
#include "llvm/IntrinsicInst.h"
|
||||
#include "llvm/LLVMContext.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/CodeGen/FastISel.h"
|
||||
#include "llvm/CodeGen/GCStrategy.h"
|
||||
@ -3931,25 +3932,8 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
|
||||
|| !DW->ShouldEmitDwarfDebug())
|
||||
return 0;
|
||||
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
DISubprogram Subprogram(REI.getContext());
|
||||
|
||||
if (isInlinedFnEnd(REI, MF.getFunction())) {
|
||||
// This is end of inlined function. Debugging information for inlined
|
||||
// function is not handled yet (only supported by FastISel).
|
||||
if (OptLevel == CodeGenOpt::None) {
|
||||
unsigned ID = DW->RecordInlinedFnEnd(Subprogram);
|
||||
if (ID != 0)
|
||||
// Returned ID is 0 if this is unbalanced "end of inlined
|
||||
// scope". This could happen if optimizer eats dbg intrinsics or
|
||||
// "beginning of inlined scope" is not recoginized due to missing
|
||||
// location info. In such cases, do ignore this region.end.
|
||||
DAG.setRoot(DAG.getLabel(ISD::DBG_LABEL, getCurDebugLoc(),
|
||||
getRoot(), ID));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned LabelID =
|
||||
DW->RecordRegionEnd(REI.getContext());
|
||||
DAG.setRoot(DAG.getLabel(ISD::DBG_LABEL, getCurDebugLoc(),
|
||||
@ -3963,37 +3947,6 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
|
||||
return 0;
|
||||
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
// This is a beginning of an inlined function.
|
||||
if (isInlinedFnStart(FSI, MF.getFunction())) {
|
||||
if (OptLevel != CodeGenOpt::None)
|
||||
// FIXME: Debugging informaation for inlined function is only
|
||||
// supported at CodeGenOpt::Node.
|
||||
return 0;
|
||||
|
||||
DebugLoc PrevLoc = CurDebugLoc;
|
||||
// If llvm.dbg.func.start is seen in a new block before any
|
||||
// llvm.dbg.stoppoint intrinsic then the location info is unknown.
|
||||
// FIXME : Why DebugLoc is reset at the beginning of each block ?
|
||||
if (PrevLoc.isUnknown())
|
||||
return 0;
|
||||
|
||||
// Record the source line.
|
||||
setCurDebugLoc(ExtractDebugLocation(FSI, MF.getDebugLocInfo()));
|
||||
|
||||
if (!DW || !DW->ShouldEmitDwarfDebug())
|
||||
return 0;
|
||||
DebugLocTuple PrevLocTpl = MF.getDebugLocTuple(PrevLoc);
|
||||
DISubprogram SP(FSI.getSubprogram());
|
||||
DICompileUnit CU(PrevLocTpl.Scope);
|
||||
unsigned LabelID = DW->RecordInlinedFnStart(SP, CU,
|
||||
PrevLocTpl.Line,
|
||||
PrevLocTpl.Col);
|
||||
DAG.setRoot(DAG.getLabel(ISD::DBG_LABEL, getCurDebugLoc(),
|
||||
getRoot(), LabelID));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This is a beginning of a new function.
|
||||
MF.setDefaultDebugLoc(ExtractDebugLocation(FSI, MF.getDebugLocInfo()));
|
||||
|
||||
if (!DW || !DW->ShouldEmitDwarfDebug())
|
||||
@ -4028,8 +3981,13 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
|
||||
int FI = SI->second;
|
||||
#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
|
||||
MachineModuleInfo *MMI = DAG.getMachineModuleInfo();
|
||||
if (MMI)
|
||||
MMI->setVariableDbgInfo(Variable, FI);
|
||||
if (MMI) {
|
||||
MetadataContext &TheMetadata =
|
||||
DI.getParent()->getContext().getMetadata();
|
||||
unsigned MDDbgKind = TheMetadata.getMDKind("dbg");
|
||||
MDNode *Dbg = TheMetadata.getMD(MDDbgKind, &DI);
|
||||
MMI->setVariableDbgInfo(Variable, FI, Dbg);
|
||||
}
|
||||
#else
|
||||
DW->RecordVariable(Variable, FI);
|
||||
#endif
|
||||
|
@ -387,13 +387,14 @@ void SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB,
|
||||
if (MDDbgKind) {
|
||||
// Update DebugLoc if debug information is attached with this
|
||||
// instruction.
|
||||
if (MDNode *Dbg = TheMetadata.getMD(MDDbgKind, I)) {
|
||||
DILocation DILoc(Dbg);
|
||||
DebugLoc Loc = ExtractDebugLocation(DILoc, MF->getDebugLocInfo());
|
||||
SDL->setCurDebugLoc(Loc);
|
||||
if (MF->getDefaultDebugLoc().isUnknown())
|
||||
MF->setDefaultDebugLoc(Loc);
|
||||
}
|
||||
if (!isa<DbgInfoIntrinsic>(I))
|
||||
if (MDNode *Dbg = TheMetadata.getMD(MDDbgKind, I)) {
|
||||
DILocation DILoc(Dbg);
|
||||
DebugLoc Loc = ExtractDebugLocation(DILoc, MF->getDebugLocInfo());
|
||||
SDL->setCurDebugLoc(Loc);
|
||||
if (MF->getDefaultDebugLoc().isUnknown())
|
||||
MF->setDefaultDebugLoc(Loc);
|
||||
}
|
||||
}
|
||||
if (!isa<TerminatorInst>(I))
|
||||
SDL->visit(*I);
|
||||
@ -750,14 +751,15 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn,
|
||||
if (MDDbgKind) {
|
||||
// Update DebugLoc if debug information is attached with this
|
||||
// instruction.
|
||||
if (MDNode *Dbg = TheMetadata.getMD(MDDbgKind, BI)) {
|
||||
DILocation DILoc(Dbg);
|
||||
DebugLoc Loc = ExtractDebugLocation(DILoc,
|
||||
MF.getDebugLocInfo());
|
||||
FastIS->setCurDebugLoc(Loc);
|
||||
if (MF.getDefaultDebugLoc().isUnknown())
|
||||
MF.setDefaultDebugLoc(Loc);
|
||||
}
|
||||
if (!isa<DbgInfoIntrinsic>(BI))
|
||||
if (MDNode *Dbg = TheMetadata.getMD(MDDbgKind, BI)) {
|
||||
DILocation DILoc(Dbg);
|
||||
DebugLoc Loc = ExtractDebugLocation(DILoc,
|
||||
MF.getDebugLocInfo());
|
||||
FastIS->setCurDebugLoc(Loc);
|
||||
if (MF.getDefaultDebugLoc().isUnknown())
|
||||
MF.setDefaultDebugLoc(Loc);
|
||||
}
|
||||
}
|
||||
|
||||
// Just before the terminator instruction, insert instructions to
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "llvm/IntrinsicInst.h"
|
||||
#include "llvm/GlobalVariable.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/LLVMContext.h"
|
||||
#include "llvm/Support/CFG.h"
|
||||
#include "llvm/Transforms/Utils/ValueMapper.h"
|
||||
#include "llvm/Analysis/ConstantFolding.h"
|
||||
@ -346,6 +347,27 @@ ConstantFoldMappedInstruction(const Instruction *I) {
|
||||
Ops.size(), TD);
|
||||
}
|
||||
|
||||
static MDNode *UpdateInlinedAtInfo(MDNode *InsnMD, MDNode *TheCallMD,
|
||||
LLVMContext &Context) {
|
||||
DILocation ILoc(InsnMD);
|
||||
if (ILoc.isNull()) return InsnMD;
|
||||
|
||||
DILocation CallLoc(TheCallMD);
|
||||
if (CallLoc.isNull()) return InsnMD;
|
||||
|
||||
DILocation OrigLocation = ILoc.getOrigLocation();
|
||||
MDNode *NewLoc = TheCallMD;
|
||||
if (!OrigLocation.isNull())
|
||||
NewLoc = UpdateInlinedAtInfo(OrigLocation.getNode(), TheCallMD, Context);
|
||||
|
||||
SmallVector<Value *, 4> MDVs;
|
||||
MDVs.push_back(InsnMD->getElement(0)); // Line
|
||||
MDVs.push_back(InsnMD->getElement(1)); // Col
|
||||
MDVs.push_back(InsnMD->getElement(2)); // Scope
|
||||
MDVs.push_back(NewLoc);
|
||||
return MDNode::get(Context, MDVs.data(), MDVs.size());
|
||||
}
|
||||
|
||||
/// CloneAndPruneFunctionInto - This works exactly like CloneFunctionInto,
|
||||
/// except that it does some simple constant prop and DCE on the fly. The
|
||||
/// effect of this is to copy significantly less code in cases where (for
|
||||
@ -358,7 +380,8 @@ void llvm::CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
|
||||
SmallVectorImpl<ReturnInst*> &Returns,
|
||||
const char *NameSuffix,
|
||||
ClonedCodeInfo *CodeInfo,
|
||||
const TargetData *TD) {
|
||||
const TargetData *TD,
|
||||
Instruction *TheCall) {
|
||||
assert(NameSuffix && "NameSuffix cannot be null!");
|
||||
|
||||
#ifndef NDEBUG
|
||||
@ -397,19 +420,49 @@ void llvm::CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
|
||||
// references as we go. This uses ValueMap to do all the hard work.
|
||||
//
|
||||
BasicBlock::iterator I = NewBB->begin();
|
||||
|
||||
LLVMContext &Context = OldFunc->getContext();
|
||||
unsigned DbgKind = Context.getMetadata().getMDKind("dbg");
|
||||
MDNode *TheCallMD = NULL;
|
||||
SmallVector<Value *, 4> MDVs;
|
||||
if (TheCall && TheCall->hasMetadata())
|
||||
TheCallMD = Context.getMetadata().getMD(DbgKind, TheCall);
|
||||
|
||||
// Handle PHI nodes specially, as we have to remove references to dead
|
||||
// blocks.
|
||||
if (PHINode *PN = dyn_cast<PHINode>(I)) {
|
||||
// Skip over all PHI nodes, remembering them for later.
|
||||
BasicBlock::const_iterator OldI = BI->begin();
|
||||
for (; (PN = dyn_cast<PHINode>(I)); ++I, ++OldI)
|
||||
for (; (PN = dyn_cast<PHINode>(I)); ++I, ++OldI) {
|
||||
if (I->hasMetadata())
|
||||
if (TheCallMD) {
|
||||
if (MDNode *IMD = Context.getMetadata().getMD(DbgKind, I)) {
|
||||
MDNode *NewMD = UpdateInlinedAtInfo(IMD, TheCallMD, Context);
|
||||
Context.getMetadata().addMD(DbgKind, NewMD, I);
|
||||
}
|
||||
} else
|
||||
// The cloned instruction has dbg info but the call instruction
|
||||
// does not have dbg info. Remove dbg info from cloned instruction.
|
||||
Context.getMetadata().removeMD(DbgKind, I);
|
||||
PHIToResolve.push_back(cast<PHINode>(OldI));
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, remap the rest of the instructions normally.
|
||||
for (; I != NewBB->end(); ++I)
|
||||
for (; I != NewBB->end(); ++I) {
|
||||
if (I->hasMetadata())
|
||||
if (TheCallMD) {
|
||||
if (MDNode *IMD = Context.getMetadata().getMD(DbgKind, I)) {
|
||||
MDNode *NewMD = UpdateInlinedAtInfo(IMD, TheCallMD, Context);
|
||||
Context.getMetadata().addMD(DbgKind, NewMD, I);
|
||||
}
|
||||
} else
|
||||
// The cloned instruction has dbg info but the call instruction
|
||||
// does not have dbg info. Remove dbg info from cloned instruction.
|
||||
Context.getMetadata().removeMD(DbgKind, I);
|
||||
|
||||
RemapInstruction(I, ValueMap);
|
||||
}
|
||||
}
|
||||
|
||||
// Defer PHI resolution until rest of function is resolved, PHI resolution
|
||||
|
@ -386,7 +386,7 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG, const TargetData *TD,
|
||||
// (which can happen, e.g., because an argument was constant), but we'll be
|
||||
// happy with whatever the cloner can do.
|
||||
CloneAndPruneFunctionInto(Caller, CalledFunc, ValueMap, Returns, ".i",
|
||||
&InlinedFunctionInfo, TD);
|
||||
&InlinedFunctionInfo, TD, TheCall);
|
||||
|
||||
// Remember the first block that is newly cloned over.
|
||||
FirstNewBlock = LastBlock; ++FirstNewBlock;
|
||||
|
Loading…
Reference in New Issue
Block a user