From 517576d6f96a0acde9bab79553d89f4ceba20cf6 Mon Sep 17 00:00:00 2001 From: Devang Patel Date: Wed, 15 Apr 2009 00:17:06 +0000 Subject: 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 --- lib/Transforms/Utils/InlineFunction.cpp | 45 +++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'lib/Transforms/Utils/InlineFunction.cpp') diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp index 1b677fbc2b..a8cba6b9a7 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(BI)) { + DISubprogram SP(cast(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(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(BI)) { + if (DbgRegionEndInst *NewDREI = + dyn_cast(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 -- cgit v1.2.3-18-g5258