From 5e06bb83f4d7b1b86659ad851324350afb04f5b0 Mon Sep 17 00:00:00 2001
From: Devang Patel
Date: Fri, 22 Apr 2011 23:10:17 +0000
Subject: [PATCH] Let front-end tie subprogram declaration with subprogram
definition directly.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@130028 91177308-0d34-0410-b5e6-96231b3b80d8
---
docs/SourceLevelDebugging.html | 15 ++---
include/llvm/Analysis/DIBuilder.h | 3 +-
include/llvm/Analysis/DebugInfo.h | 3 +
lib/Analysis/DIBuilder.cpp | 6 +-
lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 88 +++++++++++++++------------
5 files changed, 67 insertions(+), 48 deletions(-)
diff --git a/docs/SourceLevelDebugging.html b/docs/SourceLevelDebugging.html
index 9e6b579e8e6..e4566179ea2 100644
--- a/docs/SourceLevelDebugging.html
+++ b/docs/SourceLevelDebugging.html
@@ -433,15 +433,16 @@ global variables are collected by named metadata !llvm.dbg.gv.
i32, ;; Line number where defined
metadata, ;; Reference to type descriptor
i1, ;; True if the global is local to compile unit (static)
- i1 ;; True if the global is defined in the compile unit (not extern)
- i32 ;; Virtuality, e.g. dwarf::DW_VIRTUALITY__virtual
- i32 ;; Index into a virtual function
+ i1, ;; True if the global is defined in the compile unit (not extern)
+ i32, ;; Virtuality, e.g. dwarf::DW_VIRTUALITY__virtual
+ i32, ;; Index into a virtual function
metadata, ;; indicates which base type contains the vtable pointer for the
;; derived class
- i1 ;; isArtificial
- i1 ;; isOptimized
- Function *;; Pointer to LLVM function
- metadata ;; Lists function template parameters
+ i1, ;; isArtificial
+ i1, ;; isOptimized
+ Function *,;; Pointer to LLVM function
+ metadata, ;; Lists function template parameters
+ metadata ;; Function declaration descriptor
}
diff --git a/include/llvm/Analysis/DIBuilder.h b/include/llvm/Analysis/DIBuilder.h
index a6fcb538b64..9c7d6ffa466 100644
--- a/include/llvm/Analysis/DIBuilder.h
+++ b/include/llvm/Analysis/DIBuilder.h
@@ -401,7 +401,8 @@ namespace llvm {
unsigned Flags = 0,
bool isOptimized = false,
Function *Fn = 0,
- MDNode *TParam = 0);
+ MDNode *TParam = 0,
+ MDNode *Decl = 0);
/// createMethod - Create a new descriptor for the specified C++ method.
/// See comments in DISubprogram for descriptions of these fields.
diff --git a/include/llvm/Analysis/DebugInfo.h b/include/llvm/Analysis/DebugInfo.h
index af20ab20ce7..a5252aaab54 100644
--- a/include/llvm/Analysis/DebugInfo.h
+++ b/include/llvm/Analysis/DebugInfo.h
@@ -538,6 +538,9 @@ namespace llvm {
Function *getFunction() const { return getFunctionField(16); }
DIArray getTemplateParams() const { return getFieldAs(17); }
+ DISubprogram getFunctionDeclaration() const {
+ return getFieldAs(18);
+ }
};
/// DIGlobalVariable - This is a wrapper for a global variable.
diff --git a/lib/Analysis/DIBuilder.cpp b/lib/Analysis/DIBuilder.cpp
index 42f6ad0b876..a5e0078c2c2 100644
--- a/lib/Analysis/DIBuilder.cpp
+++ b/lib/Analysis/DIBuilder.cpp
@@ -672,7 +672,8 @@ DISubprogram DIBuilder::createFunction(DIDescriptor Context,
bool isLocalToUnit, bool isDefinition,
unsigned Flags, bool isOptimized,
Function *Fn,
- MDNode *TParams) {
+ MDNode *TParams,
+ MDNode *Decl) {
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_subprogram),
llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)),
@@ -691,7 +692,8 @@ DISubprogram DIBuilder::createFunction(DIDescriptor Context,
ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized),
Fn,
- TParams
+ TParams,
+ Decl
};
MDNode *Node = MDNode::get(VMContext, Elts);
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index eb6f28f52cd..ffcd2bccb94 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -322,6 +322,21 @@ DIE *DwarfDebug::createSubprogramDIE(DISubprogram SP) {
return SPDie;
SPDie = new DIE(dwarf::DW_TAG_subprogram);
+
+ // DW_TAG_inlined_subroutine may refer to this DIE.
+ SPCU->insertDIE(SP, SPDie);
+
+ // Add to context owner.
+ SPCU->addToContextOwner(SPDie, SP.getContext());
+
+ // Add function template parameters.
+ SPCU->addTemplateParams(*SPDie, SP.getTemplateParams());
+
+ // If this DIE is going to refer declaration info using AT_specification
+ // then there is no need to add other attributes.
+ if (SP.getFunctionDeclaration().isSubprogram())
+ return SPDie;
+
// Constructors and operators for anonymous aggregates do not have names.
if (!SP.getName().empty())
SPCU->addString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string,
@@ -336,7 +351,7 @@ DIE *DwarfDebug::createSubprogramDIE(DISubprogram SP) {
if (SP.isPrototyped())
SPCU->addUInt(SPDie, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1);
-
+
// Add Return Type.
DICompositeType SPTy = SP.getType();
DIArray Args = SPTy.getTypeArray();
@@ -391,15 +406,6 @@ DIE *DwarfDebug::createSubprogramDIE(DISubprogram SP) {
SPCU->addUInt(SPDie, dwarf::DW_AT_APPLE_isa, dwarf::DW_FORM_flag, isa);
}
- // Add function template parameters.
- SPCU->addTemplateParams(*SPDie, SP.getTemplateParams());
-
- // DW_TAG_inlined_subroutine may refer to this DIE.
- SPCU->insertDIE(SP, SPDie);
-
- // Add to context owner.
- SPCU->addToContextOwner(SPDie, SP.getContext());
-
return SPDie;
}
@@ -454,36 +460,42 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(const MDNode *SPNode) {
assert(SPDie && "Unable to find subprogram DIE!");
DISubprogram SP(SPNode);
- // There is not any need to generate specification DIE for a function
- // defined at compile unit level. If a function is defined inside another
- // function then gdb prefers the definition at top level and but does not
- // expect specification DIE in parent function. So avoid creating
- // specification DIE for a function defined inside a function.
- if (SP.isDefinition() && !SP.getContext().isCompileUnit() &&
- !SP.getContext().isFile() &&
- !isSubprogramContext(SP.getContext())) {
- SPCU-> addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
-
- // Add arguments.
- DICompositeType SPTy = SP.getType();
- DIArray Args = SPTy.getTypeArray();
- unsigned SPTag = SPTy.getTag();
- if (SPTag == dwarf::DW_TAG_subroutine_type)
- for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) {
- DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter);
- DIType ATy = DIType(DIType(Args.getElement(i)));
- SPCU->addType(Arg, ATy);
- if (ATy.isArtificial())
- SPCU->addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1);
- SPDie->addChild(Arg);
- }
- DIE *SPDeclDie = SPDie;
- SPDie = new DIE(dwarf::DW_TAG_subprogram);
+ DISubprogram SPDecl = SP.getFunctionDeclaration();
+ if (SPDecl.isSubprogram())
+ // Refer function declaration directly.
SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4,
- SPDeclDie);
- SPCU->addDie(SPDie);
+ createSubprogramDIE(SPDecl));
+ else {
+ // There is not any need to generate specification DIE for a function
+ // defined at compile unit level. If a function is defined inside another
+ // function then gdb prefers the definition at top level and but does not
+ // expect specification DIE in parent function. So avoid creating
+ // specification DIE for a function defined inside a function.
+ if (SP.isDefinition() && !SP.getContext().isCompileUnit() &&
+ !SP.getContext().isFile() &&
+ !isSubprogramContext(SP.getContext())) {
+ SPCU-> addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
+
+ // Add arguments.
+ DICompositeType SPTy = SP.getType();
+ DIArray Args = SPTy.getTypeArray();
+ unsigned SPTag = SPTy.getTag();
+ if (SPTag == dwarf::DW_TAG_subroutine_type)
+ for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) {
+ DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter);
+ DIType ATy = DIType(DIType(Args.getElement(i)));
+ SPCU->addType(Arg, ATy);
+ if (ATy.isArtificial())
+ SPCU->addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1);
+ SPDie->addChild(Arg);
+ }
+ DIE *SPDeclDie = SPDie;
+ SPDie = new DIE(dwarf::DW_TAG_subprogram);
+ SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4,
+ SPDeclDie);
+ SPCU->addDie(SPDie);
+ }
}
-
// Pick up abstract subprogram DIE.
if (DIE *AbsSPDIE = AbstractSPDies.lookup(SPNode)) {
SPDie = new DIE(dwarf::DW_TAG_subprogram);