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:
Devang Patel 2009-11-10 23:06:00 +00:00
parent 0a26870d92
commit 53bb5c95af
14 changed files with 664 additions and 586 deletions

View File

@ -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:

View File

@ -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

View File

@ -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; }

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;