aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp66
-rw-r--r--lib/CodeGen/CGDebugInfo.h15
-rw-r--r--lib/CodeGen/CGStmt.cpp1
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp2
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);