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