diff options
author | Devang Patel <dpatel@apple.com> | 2009-04-15 00:17:06 +0000 |
---|---|---|
committer | Devang Patel <dpatel@apple.com> | 2009-04-15 00:17:06 +0000 |
commit | 41f6045588b3f2516c5542b3202cea32fc970d67 (patch) | |
tree | ab5c846b6eaa3fed369ecdbf96b01335d5d8e3e0 /lib/Transforms | |
parent | 9625db7760a9fa91261ac578826f6b05b49c6d13 (diff) | |
download | external_llvm-41f6045588b3f2516c5542b3202cea32fc970d67.zip external_llvm-41f6045588b3f2516c5542b3202cea32fc970d67.tar.gz external_llvm-41f6045588b3f2516c5542b3202cea32fc970d67.tar.bz2 |
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
Diffstat (limited to 'lib/Transforms')
-rw-r--r-- | lib/Transforms/Utils/CloneFunction.cpp | 10 | ||||
-rw-r--r-- | lib/Transforms/Utils/InlineFunction.cpp | 45 |
2 files changed, 52 insertions, 3 deletions
diff --git a/lib/Transforms/Utils/CloneFunction.cpp b/lib/Transforms/Utils/CloneFunction.cpp index d7b4bd3..d0fdefa 100644 --- a/lib/Transforms/Utils/CloneFunction.cpp +++ b/lib/Transforms/Utils/CloneFunction.cpp @@ -24,6 +24,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Transforms/Utils/ValueMapper.h" #include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/DebugInfo.h" #include "llvm/ADT/SmallVector.h" #include <map> using namespace llvm; @@ -233,10 +234,13 @@ void PruningFunctionCloner::CloneBlock(const BasicBlock *BB, continue; } - // Do not clone llvm.dbg.func.start and corresponding llvm.dbg.region.end. + // Do not clone llvm.dbg.region.end. It will be adjusted by the inliner. if (const DbgFuncStartInst *DFSI = dyn_cast<DbgFuncStartInst>(II)) { - DbgFnStart = DFSI->getSubprogram(); - continue; + if (DbgFnStart == NULL) { + DISubprogram SP(cast<GlobalVariable>(DFSI->getSubprogram())); + if (SP.describes(BB->getParent())) + DbgFnStart = DFSI->getSubprogram(); + } } if (const DbgRegionEndInst *DREIS = dyn_cast<DbgRegionEndInst>(II)) { if (DREIS->getContext() == DbgFnStart) diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp index 1b677fb..a8cba6b 100644 --- a/lib/Transforms/Utils/InlineFunction.cpp +++ b/lib/Transforms/Utils/InlineFunction.cpp @@ -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 |