From e69917f16624d3d3531753a02291a6da9ef4befb Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Thu, 14 Mar 2019 16:29:54 +0000 Subject: [PATCH] Add IR debug info support for Elemental, Pure, and Recursive Procedures. Patch by Eric Schweitz! Differential Revision: https://reviews.llvm.org/D54043 llvm-svn: 356163 --- llvm/docs/SourceLevelDebugging.rst | 31 +++++++++++++++++++++++ llvm/include/llvm/IR/DebugInfoFlags.def | 5 +++- llvm/include/llvm/IR/DebugInfoMetadata.h | 3 +++ llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 6 +++++ llvm/test/Assembler/disubprogram.ll | 15 +++++++++-- 5 files changed, 57 insertions(+), 3 deletions(-) diff --git a/llvm/docs/SourceLevelDebugging.rst b/llvm/docs/SourceLevelDebugging.rst index 03259645780dd..87076b09b606d 100644 --- a/llvm/docs/SourceLevelDebugging.rst +++ b/llvm/docs/SourceLevelDebugging.rst @@ -670,6 +670,37 @@ a C/C++ front-end would generate the following descriptors: ... } +Fortran specific debug information +================================== + +Fortran function information +---------------------------- + +There are a few DWARF attributes defined to support client debugging of Fortran programs. LLVM can generate (or omit) the appropriate DWARF attributes for the prefix-specs of ELEMENTAL, PURE, IMPURE, RECURSIVE, and NON_RECURSIVE. This is done by using the spFlags values: DISPFlagElemental, DISPFlagPure, and DISPFlagRecursive. + +.. code-block:: fortran + + elemental function elem_func(a) + +a Fortran front-end would generate the following descriptors: + +.. code-block:: text + + !11 = distinct !DISubprogram(name: "subroutine2", scope: !1, file: !1, + line: 5, type: !8, scopeLine: 6, + spFlags: DISPFlagDefinition | DISPFlagElemental, unit: !0, + retainedNodes: !2) + +and this will materialize an additional DWARF attribute as: + +.. code-block:: text + + DW_TAG_subprogram [3] + DW_AT_low_pc [DW_FORM_addr] (0x0000000000000010 ".text") + DW_AT_high_pc [DW_FORM_data4] (0x00000001) + ... + DW_AT_elemental [DW_FORM_flag_present] (true) + Debugging information format ============================ diff --git a/llvm/include/llvm/IR/DebugInfoFlags.def b/llvm/include/llvm/IR/DebugInfoFlags.def index 9525e24b4cd33..c190124642d39 100644 --- a/llvm/include/llvm/IR/DebugInfoFlags.def +++ b/llvm/include/llvm/IR/DebugInfoFlags.def @@ -85,11 +85,14 @@ HANDLE_DISP_FLAG(2u, PureVirtual) HANDLE_DISP_FLAG((1u << 2), LocalToUnit) HANDLE_DISP_FLAG((1u << 3), Definition) HANDLE_DISP_FLAG((1u << 4), Optimized) +HANDLE_DISP_FLAG((1u << 5), Pure) +HANDLE_DISP_FLAG((1u << 6), Elemental) +HANDLE_DISP_FLAG((1u << 7), Recursive) #ifdef DISP_FLAG_LARGEST_NEEDED // Intended to be used with ADT/BitmaskEnum.h. // NOTE: Always must be equal to largest flag, check this when adding new flags. -HANDLE_DISP_FLAG((1 << 4), Largest) +HANDLE_DISP_FLAG((1 << 7), Largest) #undef DISP_FLAG_LARGEST_NEEDED #endif diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index 385f6e7a65f36..8448b67bcb401 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -1801,6 +1801,9 @@ class DISubprogram : public DILocalScope { return getFlags() & FlagAllCallsDescribed; } bool isMainSubprogram() const { return getFlags() & FlagMainSubprogram; } + bool isPure() const { return getSPFlags() & SPFlagPure; } + bool isElemental() const { return getSPFlags() & SPFlagElemental; } + bool isRecursive() const { return getSPFlags() & SPFlagRecursive; } /// Check if this is reference-qualified. /// diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index e03e210a0d32f..b19dc4b2506f7 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1267,6 +1267,12 @@ void DwarfUnit::applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie, if (SP->isMainSubprogram()) addFlag(SPDie, dwarf::DW_AT_main_subprogram); + if (SP->isPure()) + addFlag(SPDie, dwarf::DW_AT_pure); + if (SP->isElemental()) + addFlag(SPDie, dwarf::DW_AT_elemental); + if (SP->isRecursive()) + addFlag(SPDie, dwarf::DW_AT_recursive); } void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR, diff --git a/llvm/test/Assembler/disubprogram.ll b/llvm/test/Assembler/disubprogram.ll index df97efb417c7a..10bd5520d84dc 100644 --- a/llvm/test/Assembler/disubprogram.ll +++ b/llvm/test/Assembler/disubprogram.ll @@ -6,8 +6,8 @@ define void @_Z3foov() !dbg !9 { ret void } -; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15} -!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15} +; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19} +!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !17, !19, !20, !21} !0 = !{null} !1 = distinct !DICompositeType(tag: DW_TAG_structure_type) @@ -81,3 +81,14 @@ define void @_Z3foov() !dbg !9 { !16 = !{i32 1, !"Debug Info Version", i32 3} !llvm.module.flags = !{!16} !llvm.dbg.cu = !{!8} + +; CHECK: !DISubprogram({{.*}}subroutine1{{.*}}, spFlags: DISPFlagDefinition | DISPFlagPure, +; CHECK: !DISubprogram({{.*}}subroutine2{{.*}}, spFlags: DISPFlagDefinition | DISPFlagElemental, +; CHECK: !DISubprogram({{.*}}subroutine3{{.*}}, spFlags: DISPFlagDefinition | DISPFlagRecursive, +; CHECK: !DISubprogram({{.*}}subroutine4{{.*}}, spFlags: DISPFlagDefinition | DISPFlagPure | DISPFlagElemental | DISPFlagRecursive, + +!17 = distinct !DISubprogram(name: "subroutine1", scope: !1, file: !2, line: 1, type: !18, scopeLine: 2, spFlags: DISPFlagDefinition | DISPFlagPure, unit: !8, retainedNodes: !6) +!18 = !DISubroutineType(types: !0) +!19 = distinct !DISubprogram(name: "subroutine2", scope: !1, file: !2, line: 5, type: !18, scopeLine: 6, spFlags: DISPFlagDefinition | DISPFlagElemental, unit: !8, retainedNodes: !6) +!20 = distinct !DISubprogram(name: "subroutine3", scope: !1, file: !2, line: 9, type: !18, scopeLine: 10, spFlags: DISPFlagDefinition | DISPFlagRecursive, unit: !8, retainedNodes: !6) +!21 = distinct !DISubprogram(name: "subroutine4", scope: !1, file: !2, line: 13, type: !18, scopeLine: 14, spFlags: DISPFlagDefinition | DISPFlagPure | DISPFlagElemental | DISPFlagRecursive, unit: !8, retainedNodes: !6)