DebugInfo: Emit ranges for functions with DISubprograms but lacking locations on any instructions

This seems more consistent, and helps tidy up/simplify some other code
in this change.

llvm-svn: 289889
This commit is contained in:
David Blaikie 2016-12-15 23:17:52 +00:00
parent 890e850348
commit 3e3eb33ed7
5 changed files with 63 additions and 30 deletions

View File

@ -568,25 +568,24 @@ DIE *DwarfCompileUnit::createScopeChildrenDIE(LexicalScope *Scope,
return ObjectPointer;
}
void DwarfCompileUnit::constructSubprogramScopeDIE(LexicalScope *Scope) {
assert(Scope && Scope->getScopeNode());
assert(!Scope->getInlinedAt());
assert(!Scope->isAbstractScope());
auto *Sub = cast<DISubprogram>(Scope->getScopeNode());
void DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope) {
DD->getProcessedSPNodes().insert(Sub);
DIE &ScopeDIE = updateSubprogramScopeDIE(Sub);
if (Scope) {
assert(!Scope->getInlinedAt());
assert(!Scope->isAbstractScope());
// Collect lexical scope children first.
// ObjectPointer might be a local (non-argument) local variable if it's a
// block's synthetic this pointer.
if (DIE *ObjectPointer = createAndAddScopeChildren(Scope, ScopeDIE))
addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer);
}
// If this is a variadic function, add an unspecified parameter.
DITypeRefArray FnArgs = Sub->getType()->getTypeArray();
// Collect lexical scope children first.
// ObjectPointer might be a local (non-argument) local variable if it's a
// block's synthetic this pointer.
if (DIE *ObjectPointer = createAndAddScopeChildren(Scope, ScopeDIE))
addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer);
// If we have a single element of null, it is a function that returns void.
// If we have more than one elements and the last one is null, it is a
// variadic function.
@ -678,11 +677,7 @@ void DwarfCompileUnit::finishSubprogramDefinition(const DISubprogram *SP) {
// If this subprogram has an abstract definition, reference that
addDIEEntry(*D, dwarf::DW_AT_abstract_origin, *AbsSPDIE);
} else {
if (!D && !includeMinimalInlineScopes())
// Lazily construct the subprogram if we didn't see either concrete or
// inlined versions during codegen. (except in -gmlt ^ where we want
// to omit these entirely)
D = getOrCreateSubprogramDIE(SP);
assert(D || includeMinimalInlineScopes());
if (D)
// And attach the attributes
applySubprogramAttributesToDefinition(SP, *D);

View File

@ -172,7 +172,7 @@ public:
unsigned *ChildScopeCount = nullptr);
/// \brief Construct a DIE for this subprogram scope.
void constructSubprogramScopeDIE(LexicalScope *Scope);
void constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope);
DIE *createAndAddScopeChildren(LexicalScope *Scope, DIE &ScopeDIE);

View File

@ -1155,18 +1155,14 @@ void DwarfDebug::endFunction(const MachineFunction *MF) {
"endFunction should be called with the same function as beginFunction");
const DISubprogram *SP = MF->getFunction()->getSubprogram();
if (!MMI->hasDebugInfo() || LScopes.empty() || !SP ||
if (!MMI->hasDebugInfo() || !SP ||
SP->getUnit()->getEmissionKind() == DICompileUnit::NoDebug) {
// If we don't have a lexical scope for this function then there will
// be a hole in the range information. Keep note of this by setting the
// previously used section to nullptr.
// If we don't have a subprogram for this function then there will be a hole
// in the range information. Keep note of this by setting the previously
// used section to nullptr.
PrevCU = nullptr;
CurFn = nullptr;
DebugHandlerBase::endFunction(MF);
// Mark functions with no debug info on any instructions, but a
// valid DISubprogram as processed.
if (SP)
ProcessedSPNodes.insert(SP);
return;
}
@ -1174,7 +1170,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) {
Asm->OutStreamer->getContext().setDwarfCompileUnitID(0);
LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
SP = cast<DISubprogram>(FnScope->getScopeNode());
assert(!FnScope || SP == FnScope->getScopeNode());
DwarfCompileUnit &TheCU = *CUMap.lookup(SP->getUnit());
DenseSet<InlinedVariable> ProcessedVars;
@ -1216,11 +1212,11 @@ void DwarfDebug::endFunction(const MachineFunction *MF) {
constructAbstractSubprogramScopeDIE(AScope);
}
TheCU.constructSubprogramScopeDIE(FnScope);
TheCU.constructSubprogramScopeDIE(SP, FnScope);
if (auto *SkelCU = TheCU.getSkeleton())
if (!LScopes.getAbstractScopesList().empty() &&
TheCU.getCUNode()->getSplitDebugInlining())
SkelCU->constructSubprogramScopeDIE(FnScope);
SkelCU->constructSubprogramScopeDIE(SP, FnScope);
// Clear debug info
// Ownership of DbgVariables is a bit subtle - ScopeVariables owns all the

View File

@ -13,7 +13,7 @@ declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32,
!llvm.dbg.cu = !{!2}
!llvm.module.flags = !{!27}
!0 = distinct !DISubprogram(name: "CGRectStandardize", linkageName: "CGRectStandardize", line: 54, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !2, file: !1, scope: null)
!0 = distinct !DISubprogram(name: "CGRectStandardize", linkageName: "CGRectStandardize", line: 54, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !2, file: !1, scope: null, type: !28)
!1 = !DIFile(filename: "GSFusedSilica.m", directory: "/Volumes/Data/Users/sabre/Desktop")
!2 = distinct !DICompileUnit(language: DW_LANG_ObjC, producer: "clang version 2.9 (trunk 115292)", isOptimized: true, runtimeVersion: 1, emissionKind: FullDebug, file: !25, enums: !26, retainedTypes: !26)
!5 = !DIDerivedType(tag: DW_TAG_typedef, name: "CGRect", line: 49, file: !25, baseType: null)
@ -22,3 +22,5 @@ declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32,
!25 = !DIFile(filename: "GSFusedSilica.m", directory: "/Volumes/Data/Users/sabre/Desktop")
!26 = !{}
!27 = !{i32 1, !"Debug Info Version", i32 3}
!28 = !DISubroutineType(types: !29)
!29 = !{null}

View File

@ -0,0 +1,40 @@
; REQUIRES: object-emission
; RUN: %llc_dwarf -O0 -filetype=obj < %s | llvm-dwarfdump - | FileCheck %s
; Just because there are no scopes/locations on any instructions in the
; function doesn't mean we can't describe the address range of the function.
; Check that we do that
; CHECK: DW_TAG_subprogram
; CHECK-NOT: TAG
; CHECK: DW_AT_low_pc
; ModuleID = 'noscopes.c'
source_filename = "noscopes.c"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; Function Attrs: nounwind uwtable
define void @f() #0 !dbg !6 {
entry:
ret void
}
attributes #0 = { nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4}
!llvm.ident = !{!5}
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 289692) (llvm/trunk 289697)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "noscopes.c", directory: "/tmp/dbginfo")
!2 = !{}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{!"clang version 4.0.0 (trunk 289692) (llvm/trunk 289697)"}
!6 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !0, variables: !2)
!7 = !DISubroutineType(types: !8)
!8 = !{null}
!9 = !DILocation(line: 2, column: 1, scope: !6)