diff options
author | Adrian Prantl <aprantl@apple.com> | 2019-04-08 19:13:55 +0000 |
---|---|---|
committer | Adrian Prantl <aprantl@apple.com> | 2019-04-08 19:13:55 +0000 |
commit | 6ed5706a2beab0bcde2a24e36751ea30cd5b4009 (patch) | |
tree | 195ed1cd96bbf559da9b94807b61b4a6094fb258 /llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | |
parent | 6cf7b715a0e5c8a6a5eab621fe490d5330d049fd (diff) | |
download | bcm5719-llvm-6ed5706a2beab0bcde2a24e36751ea30cd5b4009.tar.gz bcm5719-llvm-6ed5706a2beab0bcde2a24e36751ea30cd5b4009.zip |
Add LLVM IR debug info support for Fortran COMMON blocks
COMMON blocks are a feature of Fortran that has no direct analog in C languages, but they are similar to data sections in assembly language programming. A COMMON block is a named area of memory that holds a collection of variables. Fortran subprograms may map the COMMON block memory area to their own, possibly distinct, non-empty list of variables. A Fortran COMMON block might look like the following example.
COMMON /ALPHA/ I, J
For this construct, the compiler generates a new scope-like DI construct (!DICommonBlock) into which variables (see I, J above) can be placed. As the common block implies a range of storage with global lifetime, the !DICommonBlock refers to a !DIGlobalVariable. The Fortran variable that comprise the COMMON block are also linked via metadata to offsets within the global variable that stands for the entire common block.
@alpha_ = common global %alphabytes_ zeroinitializer, align 64, !dbg !27, !dbg !30, !dbg !33
!14 = distinct !DISubprogram(…)
!20 = distinct !DICommonBlock(scope: !14, declaration: !25, name: "alpha")
!25 = distinct !DIGlobalVariable(scope: !20, name: "common alpha", type: !24)
!27 = !DIGlobalVariableExpression(var: !25, expr: !DIExpression())
!29 = distinct !DIGlobalVariable(scope: !20, name: "i", file: !3, type: !28)
!30 = !DIGlobalVariableExpression(var: !29, expr: !DIExpression())
!31 = distinct !DIGlobalVariable(scope: !20, name: "j", file: !3, type: !28)
!32 = !DIExpression(DW_OP_plus_uconst, 4)
!33 = !DIGlobalVariableExpression(var: !31, expr: !32)
The DWARF generated for this is as follows.
DW_TAG_common_block:
DW_AT_name: alpha
DW_AT_location: @alpha_+0
DW_TAG_variable:
DW_AT_name: common alpha
DW_AT_type: array of 8 bytes
DW_AT_location: @alpha_+0
DW_TAG_variable:
DW_AT_name: i
DW_AT_type: integer*4
DW_AT_location: @Alpha+0
DW_TAG_variable:
DW_AT_name: j
DW_AT_type: integer*4
DW_AT_location: @Alpha+4
Patch by Eric Schweitz!
Differential Revision: https://reviews.llvm.org/D54327
llvm-svn: 357934
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index fbb7a5773e7..c1e8ffec75a 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -123,7 +123,9 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE( // Construct the context before querying for the existence of the DIE in // case such construction creates the DIE. - DIE *ContextDIE = getOrCreateContextDIE(GVContext); + auto *CB = GVContext ? dyn_cast<DICommonBlock>(GVContext) : nullptr; + DIE *ContextDIE = CB ? getOrCreateCommonBlock(CB, GlobalExprs) + : getOrCreateContextDIE(GVContext); // Add to map. DIE *VariableDIE = &createAndAddDIE(GV->getTag(), *ContextDIE, GV); @@ -166,6 +168,13 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE( addTemplateParams(*VariableDIE, DINodeArray(TP)); // Add location. + addLocationAttribute(VariableDIE, GV, GlobalExprs); + + return VariableDIE; +} + +void DwarfCompileUnit::addLocationAttribute( + DIE *VariableDIE, const DIGlobalVariable *GV, ArrayRef<GlobalExpr> GlobalExprs) { bool addToAccelTable = false; DIELoc *Loc = nullptr; Optional<unsigned> NVPTXAddressSpace; @@ -288,8 +297,25 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE( DD->useAllLinkageNames()) DD->addAccelName(*CUNode, GV->getLinkageName(), *VariableDIE); } +} - return VariableDIE; +DIE *DwarfCompileUnit::getOrCreateCommonBlock( + const DICommonBlock *CB, ArrayRef<GlobalExpr> GlobalExprs) { + // Construct the context before querying for the existence of the DIE in case + // such construction creates the DIE. + DIE *ContextDIE = getOrCreateContextDIE(CB->getScope()); + + if (DIE *NDie = getDIE(CB)) + return NDie; + DIE &NDie = createAndAddDIE(dwarf::DW_TAG_common_block, *ContextDIE, CB); + StringRef Name = CB->getName().empty() ? "_BLNK_" : CB->getName(); + addString(NDie, dwarf::DW_AT_name, Name); + addGlobalName(Name, NDie, CB->getScope()); + if (CB->getFile()) + addSourceLine(NDie, CB->getLineNo(), CB->getFile()); + if (DIGlobalVariable *V = CB->getDecl()) + getCU().addLocationAttribute(&NDie, V, GlobalExprs); + return &NDie; } void DwarfCompileUnit::addRange(RangeSpan Range) { |