Index: include/llvm-c/DebugInfo.h =================================================================== --- include/llvm-c/DebugInfo.h +++ include/llvm-c/DebugInfo.h @@ -44,7 +44,6 @@ LLVMDIFlagStaticMember = 1 << 12, LLVMDIFlagLValueReference = 1 << 13, LLVMDIFlagRValueReference = 1 << 14, - LLVMDIFlagReserved = 1 << 15, LLVMDIFlagSingleInheritance = 1 << 16, LLVMDIFlagMultipleInheritance = 2 << 16, LLVMDIFlagVirtualInheritance = 3 << 16, @@ -59,6 +58,10 @@ LLVMDIFlagTrivial = 1 << 26, LLVMDIFlagBigEndian = 1 << 27, LLVMDIFlagLittleEndian = 1 << 28, + LLVMDIFlagExtraSubprogram = 1 << 15, + LLVMDIFlagPure = (1 << 15) | (1 << 9), + LLVMDIFlagElemental = (1 << 15) | (1 << 19), + LLVMDIFlagRecursive = (1 << 15) | (1 << 22), LLVMDIFlagIndirectVirtualBase = (1 << 2) | (1 << 5), LLVMDIFlagAccessibility = LLVMDIFlagPrivate | LLVMDIFlagProtected | LLVMDIFlagPublic, Index: include/llvm/IR/DebugInfoFlags.def =================================================================== --- include/llvm/IR/DebugInfoFlags.def +++ include/llvm/IR/DebugInfoFlags.def @@ -35,7 +35,6 @@ HANDLE_DI_FLAG((1 << 13), LValueReference) HANDLE_DI_FLAG((1 << 14), RValueReference) // 15 was formerly ExternalTypeRef, but this was never used. -HANDLE_DI_FLAG((1 << 15), Reserved) HANDLE_DI_FLAG((1 << 16), SingleInheritance) HANDLE_DI_FLAG((2 << 16), MultipleInheritance) HANDLE_DI_FLAG((3 << 16), VirtualInheritance) @@ -52,6 +51,14 @@ HANDLE_DI_FLAG((1 << 28), LittleEndian) HANDLE_DI_FLAG((1 << 29), AllCallsDescribed) +// Additional subprogram flags: use bit 15 to indicate it's an extended +// subprogram flag and then overload some flags that otherwise have no semantics +// with respect to DISubprogram's member functions +HANDLE_DI_FLAG((1 << 15), ExtraSubprogram) +HANDLE_DI_FLAG((1 << 15)|(1 << 9), Pure) +HANDLE_DI_FLAG((1 << 15)|(1 << 19), Elemental) +HANDLE_DI_FLAG((1 << 15)|(1 << 22), Recursive) + // To avoid needing a dedicated value for IndirectVirtualBase, we use // the bitwise or of Virtual and FwdDecl, which does not otherwise // make sense for inheritance. Index: include/llvm/IR/DebugInfoMetadata.h =================================================================== --- include/llvm/IR/DebugInfoMetadata.h +++ include/llvm/IR/DebugInfoMetadata.h @@ -1740,6 +1740,13 @@ return getFlags() & FlagAllCallsDescribed; } bool isMainSubprogram() const { return getFlags() & FlagMainSubprogram; } + bool isPure() const { return (getFlags() & FlagPure) == FlagPure; } + bool isElemental() const { + return (getFlags() & FlagElemental) == FlagElemental; + } + bool isRecursive() const { + return (getFlags() & FlagRecursive) == FlagRecursive; + } /// Check if this is reference-qualified. /// Index: lib/CodeGen/AsmPrinter/DwarfUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1261,6 +1261,12 @@ 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, Index: lib/IR/DebugInfoMetadata.cpp =================================================================== --- lib/IR/DebugInfoMetadata.cpp +++ lib/IR/DebugInfoMetadata.cpp @@ -153,6 +153,15 @@ SplitFlags.push_back(FlagVirtualInheritance); Flags &= ~R; } + if (Flags & FlagExtraSubprogram) { + if ((Flags & FlagPure) == FlagPure) + SplitFlags.push_back(FlagPure); + if ((Flags & FlagElemental) == FlagElemental) + SplitFlags.push_back(FlagElemental); + if ((Flags & FlagRecursive) == FlagRecursive) + SplitFlags.push_back(FlagRecursive); + Flags &= ~(FlagPure|FlagElemental|FlagRecursive); + } if ((Flags & FlagIndirectVirtualBase) == FlagIndirectVirtualBase) { Flags &= ~FlagIndirectVirtualBase; SplitFlags.push_back(FlagIndirectVirtualBase); Index: test/DebugInfo/Generic/more-subprogram-attr.ll =================================================================== --- /dev/null +++ test/DebugInfo/Generic/more-subprogram-attr.ll @@ -0,0 +1,37 @@ +; REQUIRES: object-emission + +; RUN: %llc_dwarf -O0 -filetype=obj < %s > %t +; RUN: llvm-dwarfdump -v -debug-info %t | FileCheck %s + +; Make sure we're emitting DW_AT_main_subprogram. +; CHECK: DW_TAG_subprogram +; CHECK-NOT: {{DW_TAG|NULL}} +; CHECK: DW_AT_name {{.*}} "main" +; CHECK-NOT: {{DW_TAG|NULL}} +; CHECK: DW_AT_pure [DW_FORM_flag_present] (true) +; CHECK: DW_AT_elemental [DW_FORM_flag_present] (true) +; CHECK: DW_AT_recursive [DW_FORM_flag_present] (true) + +define i32 @main() #0 !dbg !4 { +entry: + %retval = alloca i32, align 4 + store i32 0, i32* %retval + ret i32 0, !dbg !10 +} + +attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!9, !11} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.4 (trunk 185475)", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) +!1 = !DIFile(filename: "CodeGen/dwarf-version.c", directory: "test") +!2 = !{} +!4 = distinct !DISubprogram(name: "main", line: 6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPure | DIFlagElemental | DIFlagRecursive, isOptimized: false, unit: !0, scopeLine: 6, file: !1, scope: !5, type: !6, retainedNodes: !2) +!5 = !DIFile(filename: "CodeGen/dwarf-version.c", directory: "test") +!6 = !DISubroutineType(types: !7) +!7 = !{!8} +!8 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!9 = !{i32 2, !"Dwarf Version", i32 4} +!10 = !DILocation(line: 7, scope: !4) +!11 = !{i32 1, !"Debug Info Version", i32 3} Index: test/DebugInfo/fortran-subprogram-at.ll =================================================================== --- /dev/null +++ test/DebugInfo/fortran-subprogram-at.ll @@ -0,0 +1,24 @@ +; Test for DIFlagPure, DIFlagElement and DIFlagRecursive. These three +; DIFlags are used to attach DW_AT_pure, DW_AT_element, and DW_AT_recursive +; attributes to DW_TAG_subprogram DIEs. + +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s +; CHECK: !DISubprogram({{.*}}, flags: DIFlagPure | DIFlagElemental | DIFlagRecursive, + +!llvm.module.flags = !{!0, !1} +!llvm.dbg.cu = !{!2} + +define void @subprgm() !dbg !6 { +L: + ret void +} + +!0 = !{i32 2, !"Dwarf Version", i32 2} +!1 = !{i32 1, !"Debug Info Version", i32 3} +!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: "Flang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !4, globals: !4, imports: !4) +!3 = !DIFile(filename: "fortran-subprogram-at.f", directory: "/") +!4 = !{} +!5 = !DIBasicType(name: "real", size: 32, align: 32, encoding: DW_ATE_float) +!6 = distinct !DISubprogram(name: "subprgm", scope: !2, file: !3, line: 256, type: !7, isLocal: false, isDefinition: true, scopeLine: 256, flags: DIFlagPure|DIFlagElemental|DIFlagRecursive, isOptimized: false, unit: !2) +!7 = !DISubroutineType(types: !8) +!8 = !{null, !5}