mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-28 04:33:05 +00:00
Implement support to debug inlined functions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@86748 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0a26870d92
commit
53bb5c95af
@ -693,12 +693,6 @@ bool getLocationInfo(const Value *V, std::string &DisplayName,
|
|||||||
DebugLoc ExtractDebugLocation(DbgFuncStartInst &FSI,
|
DebugLoc ExtractDebugLocation(DbgFuncStartInst &FSI,
|
||||||
DebugLocTracker &DebugLocInfo);
|
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 {
|
class DebugInfoFinder {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -104,14 +104,8 @@ public:
|
|||||||
/// be emitted.
|
/// be emitted.
|
||||||
bool ShouldEmitDwarfDebug() const;
|
bool ShouldEmitDwarfDebug() const;
|
||||||
|
|
||||||
//// RecordInlinedFnStart - Indicate the start of a inlined function.
|
void BeginScope(const MachineInstr *MI, unsigned Label);
|
||||||
unsigned RecordInlinedFnStart(DISubprogram SP, DICompileUnit CU,
|
void EndScope(const MachineInstr *MI);
|
||||||
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);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end llvm namespace
|
} // end llvm namespace
|
||||||
|
@ -150,7 +150,8 @@ class MachineModuleInfo : public ImmutablePass {
|
|||||||
public:
|
public:
|
||||||
static char ID; // Pass identification, replacement for typeid
|
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;
|
||||||
VariableDbgInfoMapTy VariableDbgInfo;
|
VariableDbgInfoMapTy VariableDbgInfo;
|
||||||
|
|
||||||
@ -336,8 +337,8 @@ public:
|
|||||||
|
|
||||||
/// setVariableDbgInfo - Collect information used to emit debugging information
|
/// setVariableDbgInfo - Collect information used to emit debugging information
|
||||||
/// of a variable.
|
/// of a variable.
|
||||||
void setVariableDbgInfo(MDNode *N, unsigned S) {
|
void setVariableDbgInfo(MDNode *N, unsigned Slot, MDNode *Scope) {
|
||||||
VariableDbgInfo.push_back(std::make_pair(N, S));
|
VariableDbgInfo.push_back(std::make_pair(N, std::make_pair(Slot, Scope)));
|
||||||
}
|
}
|
||||||
|
|
||||||
VariableDbgInfoMapTy &getVariableDbgInfo() { return VariableDbgInfo; }
|
VariableDbgInfoMapTy &getVariableDbgInfo() { return VariableDbgInfo; }
|
||||||
|
@ -24,6 +24,7 @@ namespace llvm {
|
|||||||
|
|
||||||
class Module;
|
class Module;
|
||||||
class Function;
|
class Function;
|
||||||
|
class Instruction;
|
||||||
class Pass;
|
class Pass;
|
||||||
class LPPassManager;
|
class LPPassManager;
|
||||||
class BasicBlock;
|
class BasicBlock;
|
||||||
@ -154,7 +155,8 @@ void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
|
|||||||
SmallVectorImpl<ReturnInst*> &Returns,
|
SmallVectorImpl<ReturnInst*> &Returns,
|
||||||
const char *NameSuffix = "",
|
const char *NameSuffix = "",
|
||||||
ClonedCodeInfo *CodeInfo = 0,
|
ClonedCodeInfo *CodeInfo = 0,
|
||||||
const TargetData *TD = 0);
|
const TargetData *TD = 0,
|
||||||
|
Instruction *TheCall = 0);
|
||||||
|
|
||||||
/// InlineFunction - This function inlines the called function into the basic
|
/// InlineFunction - This function inlines the called function into the basic
|
||||||
/// block of the caller. This returns false if it is not possible to inline
|
/// 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);
|
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.
|
/// instruction's DebugLoc.
|
||||||
void AsmPrinter::processDebugLoc(const MachineInstr *MI,
|
void AsmPrinter::processDebugLoc(const MachineInstr *MI,
|
||||||
bool BeforePrintingInsn) {
|
bool BeforePrintingInsn) {
|
||||||
if (!MAI || !DW)
|
if (!MAI || !DW || !MAI->doesSupportDebugInformation()
|
||||||
|
|| !DW->ShouldEmitDwarfDebug())
|
||||||
return;
|
return;
|
||||||
DebugLoc DL = MI->getDebugLoc();
|
DebugLoc DL = MI->getDebugLoc();
|
||||||
if (MAI->doesSupportDebugInformation() && DW->ShouldEmitDwarfDebug()) {
|
if (DL.isUnknown())
|
||||||
if (!DL.isUnknown()) {
|
return;
|
||||||
DebugLocTuple CurDLT = MF->getDebugLocTuple(DL);
|
DebugLocTuple CurDLT = MF->getDebugLocTuple(DL);
|
||||||
if (BeforePrintingInsn) {
|
if (CurDLT.Scope == 0)
|
||||||
if (CurDLT.Scope != 0 && PrevDLT != CurDLT) {
|
return;
|
||||||
unsigned L = DW->RecordSourceLine(CurDLT.Line, CurDLT.Col,
|
|
||||||
CurDLT.Scope);
|
if (BeforePrintingInsn) {
|
||||||
printLabel(L);
|
if (CurDLT != PrevDLT) {
|
||||||
O << '\n';
|
unsigned L = DW->RecordSourceLine(CurDLT.Line, CurDLT.Col,
|
||||||
#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
|
CurDLT.Scope);
|
||||||
DW->SetDbgScopeBeginLabels(MI, L);
|
printLabel(L);
|
||||||
#endif
|
DW->BeginScope(MI, L);
|
||||||
} else {
|
|
||||||
#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
|
|
||||||
DW->SetDbgScopeEndLabels(MI, 0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PrevDLT = CurDLT;
|
PrevDLT = CurDLT;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// After printing instruction
|
||||||
|
DW->EndScope(MI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// printInlineAsm - This method formats and prints the specified machine
|
/// printInlineAsm - This method formats and prints the specified machine
|
||||||
/// instruction that is an inline asm.
|
/// instruction that is an inline asm.
|
||||||
void AsmPrinter::printInlineAsm(const MachineInstr *MI) const {
|
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;
|
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.
|
/// DbgScopeMap - Tracks the scopes in the current function.
|
||||||
|
///
|
||||||
ValueMap<MDNode *, DbgScope *> DbgScopeMap;
|
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.
|
/// ScopedGVs - Tracks global variables that are not at file scope.
|
||||||
/// For example void f() { static int b = 42; }
|
/// For example void f() { static int b = 42; }
|
||||||
SmallVector<WeakVH, 4> ScopedGVs;
|
SmallVector<WeakVH, 4> ScopedGVs;
|
||||||
|
|
||||||
typedef DenseMap<const MachineInstr *, SmallVector<DbgScope *, 2> >
|
typedef SmallVector<DbgScope *, 2> ScopeVector;
|
||||||
|
typedef DenseMap<const MachineInstr *, ScopeVector>
|
||||||
InsnToDbgScopeMapTy;
|
InsnToDbgScopeMapTy;
|
||||||
|
|
||||||
/// DbgScopeBeginMap - Maps instruction with a list DbgScopes it starts.
|
/// DbgScopeBeginMap - Maps instruction with a list of DbgScopes it starts.
|
||||||
InsnToDbgScopeMapTy DbgScopeBeginMap;
|
InsnToDbgScopeMapTy DbgScopeBeginMap;
|
||||||
|
|
||||||
/// DbgScopeEndMap - Maps instruction with a list DbgScopes it ends.
|
/// DbgScopeEndMap - Maps instruction with a list DbgScopes it ends.
|
||||||
InsnToDbgScopeMapTy DbgScopeEndMap;
|
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
|
/// InlineInfo - Keep track of inlined functions and their location. This
|
||||||
/// information is used to populate debug_inlined section.
|
/// information is used to populate debug_inlined section.
|
||||||
ValueMap<MDNode *, SmallVector<unsigned, 4> > InlineInfo;
|
typedef std::pair<unsigned, DIE *> InlineInfoLabels;
|
||||||
|
ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> > InlineInfo;
|
||||||
/// AbstractInstanceRootMap - Map of abstract instance roots of inlined
|
SmallVector<MDNode *, 4> InlinedSPNodes;
|
||||||
/// 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;
|
|
||||||
|
|
||||||
/// CompileUnitOffsets - A vector of the offsets of the compile units. This is
|
/// CompileUnitOffsets - A vector of the offsets of the compile units. This is
|
||||||
/// used when calculating the "origin" of a concrete instance of an inlined
|
/// 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);
|
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 *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.
|
/// ConstructDbgScope - Construct the components of a scope.
|
||||||
///
|
///
|
||||||
@ -372,10 +386,10 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf {
|
|||||||
unsigned ParentStartID, unsigned ParentEndID,
|
unsigned ParentStartID, unsigned ParentEndID,
|
||||||
DIE *ParentDie, CompileUnit *Unit);
|
DIE *ParentDie, CompileUnit *Unit);
|
||||||
|
|
||||||
/// ConstructFunctionDbgScope - Construct the scope for the subprogram.
|
/// ConstructCurrentFnDbgScope - Construct the scope for the subprogram.
|
||||||
///
|
///
|
||||||
void ConstructFunctionDbgScope(DbgScope *RootScope,
|
void ConstructCurrentFnDbgScope(DbgScope *RootScope,
|
||||||
bool AbstractScope = false);
|
bool AbstractScope = false);
|
||||||
|
|
||||||
/// ConstructDefaultDbgScope - Construct a default scope for the subprogram.
|
/// ConstructDefaultDbgScope - Construct a default scope for the subprogram.
|
||||||
///
|
///
|
||||||
@ -544,13 +558,6 @@ public:
|
|||||||
/// RecordVariable - Indicate the declaration of a local variable.
|
/// RecordVariable - Indicate the declaration of a local variable.
|
||||||
void RecordVariable(MDNode *N, unsigned FrameIndex);
|
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
|
/// ExtractScopeInformation - Scan machine instructions in this function
|
||||||
/// and collect DbgScopes. Return true, if atleast one scope was found.
|
/// and collect DbgScopes. Return true, if atleast one scope was found.
|
||||||
bool ExtractScopeInformation(MachineFunction *MF);
|
bool ExtractScopeInformation(MachineFunction *MF);
|
||||||
@ -558,15 +565,16 @@ public:
|
|||||||
/// CollectVariableInfo - Populate DbgScope entries with variables' info.
|
/// CollectVariableInfo - Populate DbgScope entries with variables' info.
|
||||||
void CollectVariableInfo();
|
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
|
/// SetDbgScopeEndLabels - Update DbgScope end labels for the scopes that
|
||||||
/// end with this machine instruction.
|
/// end with this machine instruction.
|
||||||
void SetDbgScopeEndLabels(const MachineInstr *MI, unsigned Label);
|
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
|
} // End of namespace llvm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -108,20 +108,9 @@ bool DwarfWriter::ShouldEmitDwarfDebug() const {
|
|||||||
return DD && DD->ShouldEmitDwarfDebug();
|
return DD && DD->ShouldEmitDwarfDebug();
|
||||||
}
|
}
|
||||||
|
|
||||||
//// RecordInlinedFnStart
|
void DwarfWriter::BeginScope(const MachineInstr *MI, unsigned L) {
|
||||||
unsigned DwarfWriter::RecordInlinedFnStart(DISubprogram SP, DICompileUnit CU,
|
DD->BeginScope(MI, L);
|
||||||
unsigned Line, unsigned Col) {
|
|
||||||
return DD->RecordInlinedFnStart(SP, CU, Line, Col);
|
|
||||||
}
|
}
|
||||||
|
void DwarfWriter::EndScope(const MachineInstr *MI) {
|
||||||
/// RecordInlinedFnEnd - Indicate the end of inlined subroutine.
|
DD->EndScope(MI);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include "llvm/GlobalVariable.h"
|
#include "llvm/GlobalVariable.h"
|
||||||
#include "llvm/Instructions.h"
|
#include "llvm/Instructions.h"
|
||||||
#include "llvm/IntrinsicInst.h"
|
#include "llvm/IntrinsicInst.h"
|
||||||
|
#include "llvm/LLVMContext.h"
|
||||||
#include "llvm/CodeGen/FastISel.h"
|
#include "llvm/CodeGen/FastISel.h"
|
||||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||||
@ -347,21 +348,9 @@ bool FastISel::SelectCall(User *I) {
|
|||||||
&& DW->ShouldEmitDwarfDebug()) {
|
&& DW->ShouldEmitDwarfDebug()) {
|
||||||
unsigned ID = 0;
|
unsigned ID = 0;
|
||||||
DISubprogram Subprogram(REI->getContext());
|
DISubprogram Subprogram(REI->getContext());
|
||||||
if (isInlinedFnEnd(*REI, MF.getFunction())) {
|
const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL);
|
||||||
// This is end of an inlined function.
|
ID = DW->RecordRegionEnd(REI->getContext());
|
||||||
const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL);
|
BuildMI(MBB, DL, II).addImm(ID);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -371,28 +360,6 @@ bool FastISel::SelectCall(User *I) {
|
|||||||
|| !DW->ShouldEmitDwarfDebug())
|
|| !DW->ShouldEmitDwarfDebug())
|
||||||
return true;
|
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.
|
// This is a beginning of a new function.
|
||||||
MF.setDefaultDebugLoc(ExtractDebugLocation(*FSI, MF.getDebugLocInfo()));
|
MF.setDefaultDebugLoc(ExtractDebugLocation(*FSI, MF.getDebugLocInfo()));
|
||||||
|
|
||||||
@ -416,8 +383,13 @@ bool FastISel::SelectCall(User *I) {
|
|||||||
StaticAllocaMap.find(AI);
|
StaticAllocaMap.find(AI);
|
||||||
if (SI == StaticAllocaMap.end()) break; // VLAs.
|
if (SI == StaticAllocaMap.end()) break; // VLAs.
|
||||||
int FI = SI->second;
|
int FI = SI->second;
|
||||||
if (MMI)
|
if (MMI) {
|
||||||
MMI->setVariableDbgInfo(DI->getVariable(), FI);
|
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
|
#ifndef ATTACH_DEBUG_INFO_TO_AN_INSN
|
||||||
DW->RecordVariable(DI->getVariable(), FI);
|
DW->RecordVariable(DI->getVariable(), FI);
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "llvm/Instructions.h"
|
#include "llvm/Instructions.h"
|
||||||
#include "llvm/Intrinsics.h"
|
#include "llvm/Intrinsics.h"
|
||||||
#include "llvm/IntrinsicInst.h"
|
#include "llvm/IntrinsicInst.h"
|
||||||
|
#include "llvm/LLVMContext.h"
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/CodeGen/FastISel.h"
|
#include "llvm/CodeGen/FastISel.h"
|
||||||
#include "llvm/CodeGen/GCStrategy.h"
|
#include "llvm/CodeGen/GCStrategy.h"
|
||||||
@ -3931,25 +3932,8 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
|
|||||||
|| !DW->ShouldEmitDwarfDebug())
|
|| !DW->ShouldEmitDwarfDebug())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
MachineFunction &MF = DAG.getMachineFunction();
|
|
||||||
DISubprogram Subprogram(REI.getContext());
|
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 =
|
unsigned LabelID =
|
||||||
DW->RecordRegionEnd(REI.getContext());
|
DW->RecordRegionEnd(REI.getContext());
|
||||||
DAG.setRoot(DAG.getLabel(ISD::DBG_LABEL, getCurDebugLoc(),
|
DAG.setRoot(DAG.getLabel(ISD::DBG_LABEL, getCurDebugLoc(),
|
||||||
@ -3963,37 +3947,6 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
MachineFunction &MF = DAG.getMachineFunction();
|
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()));
|
MF.setDefaultDebugLoc(ExtractDebugLocation(FSI, MF.getDebugLocInfo()));
|
||||||
|
|
||||||
if (!DW || !DW->ShouldEmitDwarfDebug())
|
if (!DW || !DW->ShouldEmitDwarfDebug())
|
||||||
@ -4028,8 +3981,13 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
|
|||||||
int FI = SI->second;
|
int FI = SI->second;
|
||||||
#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
|
#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
|
||||||
MachineModuleInfo *MMI = DAG.getMachineModuleInfo();
|
MachineModuleInfo *MMI = DAG.getMachineModuleInfo();
|
||||||
if (MMI)
|
if (MMI) {
|
||||||
MMI->setVariableDbgInfo(Variable, FI);
|
MetadataContext &TheMetadata =
|
||||||
|
DI.getParent()->getContext().getMetadata();
|
||||||
|
unsigned MDDbgKind = TheMetadata.getMDKind("dbg");
|
||||||
|
MDNode *Dbg = TheMetadata.getMD(MDDbgKind, &DI);
|
||||||
|
MMI->setVariableDbgInfo(Variable, FI, Dbg);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
DW->RecordVariable(Variable, FI);
|
DW->RecordVariable(Variable, FI);
|
||||||
#endif
|
#endif
|
||||||
|
@ -387,13 +387,14 @@ void SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB,
|
|||||||
if (MDDbgKind) {
|
if (MDDbgKind) {
|
||||||
// Update DebugLoc if debug information is attached with this
|
// Update DebugLoc if debug information is attached with this
|
||||||
// instruction.
|
// instruction.
|
||||||
if (MDNode *Dbg = TheMetadata.getMD(MDDbgKind, I)) {
|
if (!isa<DbgInfoIntrinsic>(I))
|
||||||
DILocation DILoc(Dbg);
|
if (MDNode *Dbg = TheMetadata.getMD(MDDbgKind, I)) {
|
||||||
DebugLoc Loc = ExtractDebugLocation(DILoc, MF->getDebugLocInfo());
|
DILocation DILoc(Dbg);
|
||||||
SDL->setCurDebugLoc(Loc);
|
DebugLoc Loc = ExtractDebugLocation(DILoc, MF->getDebugLocInfo());
|
||||||
if (MF->getDefaultDebugLoc().isUnknown())
|
SDL->setCurDebugLoc(Loc);
|
||||||
MF->setDefaultDebugLoc(Loc);
|
if (MF->getDefaultDebugLoc().isUnknown())
|
||||||
}
|
MF->setDefaultDebugLoc(Loc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!isa<TerminatorInst>(I))
|
if (!isa<TerminatorInst>(I))
|
||||||
SDL->visit(*I);
|
SDL->visit(*I);
|
||||||
@ -750,14 +751,15 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn,
|
|||||||
if (MDDbgKind) {
|
if (MDDbgKind) {
|
||||||
// Update DebugLoc if debug information is attached with this
|
// Update DebugLoc if debug information is attached with this
|
||||||
// instruction.
|
// instruction.
|
||||||
if (MDNode *Dbg = TheMetadata.getMD(MDDbgKind, BI)) {
|
if (!isa<DbgInfoIntrinsic>(BI))
|
||||||
DILocation DILoc(Dbg);
|
if (MDNode *Dbg = TheMetadata.getMD(MDDbgKind, BI)) {
|
||||||
DebugLoc Loc = ExtractDebugLocation(DILoc,
|
DILocation DILoc(Dbg);
|
||||||
MF.getDebugLocInfo());
|
DebugLoc Loc = ExtractDebugLocation(DILoc,
|
||||||
FastIS->setCurDebugLoc(Loc);
|
MF.getDebugLocInfo());
|
||||||
if (MF.getDefaultDebugLoc().isUnknown())
|
FastIS->setCurDebugLoc(Loc);
|
||||||
MF.setDefaultDebugLoc(Loc);
|
if (MF.getDefaultDebugLoc().isUnknown())
|
||||||
}
|
MF.setDefaultDebugLoc(Loc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just before the terminator instruction, insert instructions to
|
// Just before the terminator instruction, insert instructions to
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "llvm/IntrinsicInst.h"
|
#include "llvm/IntrinsicInst.h"
|
||||||
#include "llvm/GlobalVariable.h"
|
#include "llvm/GlobalVariable.h"
|
||||||
#include "llvm/Function.h"
|
#include "llvm/Function.h"
|
||||||
|
#include "llvm/LLVMContext.h"
|
||||||
#include "llvm/Support/CFG.h"
|
#include "llvm/Support/CFG.h"
|
||||||
#include "llvm/Transforms/Utils/ValueMapper.h"
|
#include "llvm/Transforms/Utils/ValueMapper.h"
|
||||||
#include "llvm/Analysis/ConstantFolding.h"
|
#include "llvm/Analysis/ConstantFolding.h"
|
||||||
@ -346,6 +347,27 @@ ConstantFoldMappedInstruction(const Instruction *I) {
|
|||||||
Ops.size(), TD);
|
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,
|
/// CloneAndPruneFunctionInto - This works exactly like CloneFunctionInto,
|
||||||
/// except that it does some simple constant prop and DCE on the fly. The
|
/// 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
|
/// 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,
|
SmallVectorImpl<ReturnInst*> &Returns,
|
||||||
const char *NameSuffix,
|
const char *NameSuffix,
|
||||||
ClonedCodeInfo *CodeInfo,
|
ClonedCodeInfo *CodeInfo,
|
||||||
const TargetData *TD) {
|
const TargetData *TD,
|
||||||
|
Instruction *TheCall) {
|
||||||
assert(NameSuffix && "NameSuffix cannot be null!");
|
assert(NameSuffix && "NameSuffix cannot be null!");
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#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.
|
// references as we go. This uses ValueMap to do all the hard work.
|
||||||
//
|
//
|
||||||
BasicBlock::iterator I = NewBB->begin();
|
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
|
// Handle PHI nodes specially, as we have to remove references to dead
|
||||||
// blocks.
|
// blocks.
|
||||||
if (PHINode *PN = dyn_cast<PHINode>(I)) {
|
if (PHINode *PN = dyn_cast<PHINode>(I)) {
|
||||||
// Skip over all PHI nodes, remembering them for later.
|
// Skip over all PHI nodes, remembering them for later.
|
||||||
BasicBlock::const_iterator OldI = BI->begin();
|
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));
|
PHIToResolve.push_back(cast<PHINode>(OldI));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, remap the rest of the instructions normally.
|
// 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);
|
RemapInstruction(I, ValueMap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defer PHI resolution until rest of function is resolved, PHI resolution
|
// 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
|
// (which can happen, e.g., because an argument was constant), but we'll be
|
||||||
// happy with whatever the cloner can do.
|
// happy with whatever the cloner can do.
|
||||||
CloneAndPruneFunctionInto(Caller, CalledFunc, ValueMap, Returns, ".i",
|
CloneAndPruneFunctionInto(Caller, CalledFunc, ValueMap, Returns, ".i",
|
||||||
&InlinedFunctionInfo, TD);
|
&InlinedFunctionInfo, TD, TheCall);
|
||||||
|
|
||||||
// Remember the first block that is newly cloned over.
|
// Remember the first block that is newly cloned over.
|
||||||
FirstNewBlock = LastBlock; ++FirstNewBlock;
|
FirstNewBlock = LastBlock; ++FirstNewBlock;
|
||||||
|
Loading…
Reference in New Issue
Block a user