While inlining, clone llvm.dbg.func.start intrinsic and adjust

llvm.dbg.region.end instrinsic. This nested llvm.dbg.func.start/llvm.dbg.region.end pair now enables DW_TAG_inlined_subroutine support in code generator.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@69118 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Devang Patel
2009-04-15 00:17:06 +00:00
parent d25bff6d52
commit 517576d6f9
3 changed files with 52 additions and 89 deletions

View File

@ -17,9 +17,11 @@
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Intrinsics.h"
#include "llvm/Attributes.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
@ -199,6 +201,31 @@ static void UpdateCallGraphAfterInlining(CallSite CS,
CallerNode->removeCallEdgeFor(CS);
}
/// findFnRegionEndMarker - This is a utility routine that is used by
/// InlineFunction. Return llvm.dbg.region.end intrinsic that corresponds
/// to the llvm.dbg.func.start of the function F. Otherwise return NULL.
static const DbgRegionEndInst *findFnRegionEndMarker(const Function *F) {
GlobalVariable *FnStart = NULL;
const DbgRegionEndInst *FnEnd = NULL;
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 (FnStart == NULL) {
if (const DbgFuncStartInst *FSI = dyn_cast<DbgFuncStartInst>(BI)) {
DISubprogram SP(cast<GlobalVariable>(FSI->getSubprogram()));
assert (SP.isNull() == false && "Invalid llvm.dbg.func.start");
if (SP.describes(F))
FnStart = SP.getGV();
}
} else {
if (const DbgRegionEndInst *REI = dyn_cast<DbgRegionEndInst>(BI))
if (REI->getContext() == FnStart)
FnEnd = REI;
}
}
return FnEnd;
}
// InlineFunction - This function inlines the called function into the basic
// block of the caller. This returns false if it is not possible to inline this
@ -320,6 +347,24 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG, const TargetData *TD) {
ValueMap[I] = ActualArg;
}
// Adjust llvm.dbg.region.end. If the CalledFunc has region end
// marker then clone that marker after next stop point at the
// call site. The function body cloner does not clone original
// region end marker from the CalledFunc. This will ensure that
// inlined function's scope ends at the right place.
const DbgRegionEndInst *DREI = findFnRegionEndMarker(CalledFunc);
if (DREI) {
for (BasicBlock::iterator BI = TheCall,
BE = TheCall->getParent()->end(); BI != BE; ++BI) {
if (DbgStopPointInst *DSPI = dyn_cast<DbgStopPointInst>(BI)) {
if (DbgRegionEndInst *NewDREI =
dyn_cast<DbgRegionEndInst>(DREI->clone()))
NewDREI->insertAfter(DSPI);
break;
}
}
}
// We want the inliner to prune the code as it copies. We would LOVE to
// have no dead or constant instructions leftover after inlining occurs
// (which can happen, e.g., because an argument was constant), but we'll be