diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 66 | ||||
-rw-r--r-- | lib/CodeGen/CGDebugInfo.h | 15 | ||||
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 2 |
4 files changed, 83 insertions, 1 deletions
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index fdc8a35d9d..753cdcddd2 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -1349,6 +1349,8 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, llvm::StringRef Name; llvm::StringRef LinkageName; + FnBeginRegionCount.push_back(RegionStack.size()); + const Decl *D = GD.getDecl(); if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { // If there is a DISubprogram for this function available then use it. @@ -1392,6 +1394,9 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, llvm::MDNode *SPN = SP; RegionStack.push_back(SPN); RegionMap[D] = llvm::WeakVH(SP); + + // Clear stack used to keep track of #line directives. + LineDirectiveFiles.clear(); } @@ -1417,6 +1422,55 @@ void CGDebugInfo::EmitStopPoint(CGBuilderTy &Builder) { Scope)); } +/// UpdateLineDirectiveRegion - Update region stack only if #line directive +/// has introduced scope change. +void CGDebugInfo::UpdateLineDirectiveRegion(CGBuilderTy &Builder) { + if (CurLoc.isInvalid() || CurLoc.isMacroID() || + PrevLoc.isInvalid() || PrevLoc.isMacroID()) + return; + SourceManager &SM = CGM.getContext().getSourceManager(); + PresumedLoc PCLoc = SM.getPresumedLoc(CurLoc); + PresumedLoc PPLoc = SM.getPresumedLoc(PrevLoc); + + if (!strcmp(PPLoc.getFilename(), PCLoc.getFilename())) + return; + + // If #line directive stack is empty then we are entering a new scope. + if (LineDirectiveFiles.empty()) { + EmitRegionStart(Builder); + LineDirectiveFiles.push_back(PCLoc.getFilename()); + return; + } + + assert (RegionStack.size() >= LineDirectiveFiles.size() + && "error handling #line regions!"); + + bool SeenThisFile = false; + for(std::vector<const char *>::iterator I = LineDirectiveFiles.begin(), + E = LineDirectiveFiles.end(); I != E; ++I) + if (!strcmp(PPLoc.getFilename(), *I)) { + SeenThisFile = true; + break; + } + + // If #line for this file is seen earlier then pop out #line regions. + if (SeenThisFile) { + while (!LineDirectiveFiles.empty()) { + const char *LastFile = LineDirectiveFiles.back(); + RegionStack.pop_back(); + LineDirectiveFiles.pop_back(); + if (!strcmp(PPLoc.getFilename(), LastFile)) + break; + } + return; + } + + // .. otherwise insert new #line region. + EmitRegionStart(Builder); + LineDirectiveFiles.push_back(PCLoc.getFilename()); + + return; +} /// EmitRegionStart- Constructs the debug code for entering a declarative /// region - "llvm.dbg.region.start.". void CGDebugInfo::EmitRegionStart(CGBuilderTy &Builder) { @@ -1442,6 +1496,18 @@ void CGDebugInfo::EmitRegionEnd(CGBuilderTy &Builder) { RegionStack.pop_back(); } +/// EmitFunctionEnd - Constructs the debug code for exiting a function. +void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) { + assert(!RegionStack.empty() && "Region stack mismatch, stack empty!"); + unsigned RCount = FnBeginRegionCount.back(); + assert(RCount <= RegionStack.size() && "Region stack mismatch"); + + // Pop all regions for this function. + while (RegionStack.size() != RCount) + EmitRegionEnd(Builder); + FnBeginRegionCount.pop_back(); +} + // EmitTypeForVarWithBlocksAttr - Build up structure info for the byref. // See BuildByRefType. llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index ed18a44c08..fdfd3dca57 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -58,6 +58,14 @@ class CGDebugInfo { std::vector<llvm::TrackingVH<llvm::MDNode> > RegionStack; llvm::DenseMap<const Decl *, llvm::WeakVH> RegionMap; + // FnBeginRegionCount - Keep track of RegionStack counter at the beginning + // of a function. This is used to pop unbalanced regions at the end of a + // function. + std::vector<unsigned> FnBeginRegionCount; + + /// LineDirectiveFiles - This stack is used to keep track of + /// scopes introduced by #line directives. + std::vector<const char *> LineDirectiveFiles; /// DebugInfoNames - This is a storage for names that are /// constructed on demand. For example, C++ destructors, C++ operators etc.. @@ -134,6 +142,13 @@ public: void EmitFunctionStart(GlobalDecl GD, QualType FnType, llvm::Function *Fn, CGBuilderTy &Builder); + /// EmitFunctionEnd - Constructs the debug code for exiting a function. + void EmitFunctionEnd(CGBuilderTy &Builder); + + /// UpdateLineDirectiveRegion - Update region stack only if #line directive + /// has introduced scope change. + void UpdateLineDirectiveRegion(CGBuilderTy &Builder); + /// EmitRegionStart - Emit a call to llvm.dbg.region.start to indicate start /// of a new block. void EmitRegionStart(CGBuilderTy &Builder); diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 8609ed5a5e..f1740104fd 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -34,6 +34,7 @@ void CodeGenFunction::EmitStopPoint(const Stmt *S) { DI->setLocation(S->getLocEnd()); else DI->setLocation(S->getLocStart()); + DI->UpdateLineDirectiveRegion(Builder); DI->EmitStopPoint(Builder); } } diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index fe374ef9f6..dbebd136ba 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -139,7 +139,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { // Emit debug descriptor for function end. if (CGDebugInfo *DI = getDebugInfo()) { DI->setLocation(EndLoc); - DI->EmitRegionEnd(Builder); + DI->EmitFunctionEnd(Builder); } EmitFunctionEpilog(*CurFnInfo); |