Keep track of artificial scopes introduced by line directives. For example,

#line 41 "bar.c"
  dummy (1, i);
#line 24 "bar.h"
  i = f2 (i);
#line 44 "bar.c"

This is tested by step-line.exp in gdb testsuite.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109189 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Devang Patel 2010-07-22 22:29:16 +00:00
Родитель db2cfecf0e
Коммит 5a6fbcfd8c
4 изменённых файлов: 83 добавлений и 1 удалений

Просмотреть файл

@ -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,

Просмотреть файл

@ -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);

Просмотреть файл

@ -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);
}
}

Просмотреть файл

@ -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);