Index: include/llvm/IR/Attributes.td =================================================================== --- include/llvm/IR/Attributes.td +++ include/llvm/IR/Attributes.td @@ -179,6 +179,7 @@ def NoNansFPMath : StrBoolAttr<"no-nans-fp-math">; def UnsafeFPMath : StrBoolAttr<"unsafe-fp-math">; def NoJumpTables : StrBoolAttr<"no-jump-tables">; +def DebugInfoForProfiling : StrBoolAttr<"debug-info-for-profiling">; class CompatRule { // The name of the function called to check the attribute of the caller and @@ -210,4 +211,5 @@ def : MergeRule<"setAND">; def : MergeRule<"setOR">; def : MergeRule<"setOR">; +def : MergeRule<"setOR">; def : MergeRule<"adjustCallerSSPLevel">; Index: include/llvm/IR/Function.h =================================================================== --- include/llvm/IR/Function.h +++ include/llvm/IR/Function.h @@ -465,6 +465,11 @@ return hasFnAttribute(Attribute::OptimizeForSize) || optForMinSize(); } + /// Emit debug info for profiling. + bool debugInfoForProfiling() const { + return getFnAttribute("debug-info-for-profiling").getValueAsString() == "true"; + } + /// copyAttributesFrom - copy all additional attributes (those not needed to /// create a Function) from the Function Src to this one. void copyAttributesFrom(const GlobalValue *Src) override; Index: lib/CodeGen/AsmPrinter/DwarfDebug.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.h +++ lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -263,6 +263,9 @@ bool HasAppleExtensionAttributes; bool HasSplitDwarf; + /// Emit debug info for profiling + bool HasDebugInfoForProfiling; + /// Separated Dwarf Variables /// In general these will all be for bits that are left in the /// original object file, rather than things that are meant @@ -513,6 +516,9 @@ /// split dwarf proposal support. bool useSplitDwarf() const { return HasSplitDwarf; } + /// Returns whether or not to emit debug info for profiling. + bool useDebugInfoForProfiling() const { return HasDebugInfoForProfiling; } + /// Returns the Dwarf Version. uint16_t getDwarfVersion() const; Index: lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -245,6 +245,8 @@ else HasSplitDwarf = SplitDwarf == Enable; + HasDebugInfoForProfiling = false; + // Pubnames/pubtypes on by default for GDB. if (DwarfPubSections == Default) HasDwarfPubSections = tuneForGDB(); @@ -1131,6 +1133,9 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { CurFn = MF; + if (MF->getFunction()->debugInfoForProfiling()) + HasDebugInfoForProfiling=true; + // If there's no debug info for the function we're not going to do anything. if (!MMI->hasDebugInfo()) return; @@ -1213,7 +1218,7 @@ // Under -gmlt, skip building the subprogram if there are no inlined // subroutines inside it. But with -fdebug-info-for-profiling, the subprogram // is still needed as we need its source location. - if (!Asm->TM.Options.DebugInfoForProfiling && + if (!MF->getFunction()->debugInfoForProfiling() && TheCU.getCUNode()->getEmissionKind() == DICompileUnit::LineTablesOnly && LScopes.getAbstractScopesList().empty() && !IsDarwin) { assert(InfoHolder.getScopeVariables().empty()); Index: lib/CodeGen/AsmPrinter/DwarfUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1184,7 +1184,7 @@ // If -fdebug-info-for-profiling is enabled, need to emit the subprogram // and its source location. bool SkipSPSourceLocation = SkipSPAttributes && - !Asm->TM.Options.DebugInfoForProfiling; + !DD->useDebugInfoForProfiling(); if (!SkipSPSourceLocation) if (applySubprogramDefinitionAttributes(SP, SPDie)) return; Index: test/DebugInfo/Generic/gmlt.test =================================================================== --- test/DebugInfo/Generic/gmlt.test +++ test/DebugInfo/Generic/gmlt.test @@ -1,6 +1,6 @@ ; REQUIRES: object-emission ; RUN: %llc_dwarf -O0 -filetype=obj < %S/../Inputs/gmlt.ll | llvm-dwarfdump - | FileCheck %S/../Inputs/gmlt.ll -; RUN: %llc_dwarf -O0 -filetype=obj -debug-info-for-profiling < %S/../Inputs/gmlt.ll | llvm-dwarfdump - | FileCheck %S/../Inputs/gmlt.ll --check-prefixes=PROFILING +; RUN: %llc_dwarf -O0 -filetype=obj < %S/../Inputs/gmlt_profiling.ll | llvm-dwarfdump - | FileCheck %S/../Inputs/gmlt_profiling.ll ; There's a darwin specific test in X86/gmlt, so it's okay to XFAIL this here. ; XFAIL: darwin Index: test/DebugInfo/Inputs/gmlt.ll =================================================================== --- test/DebugInfo/Inputs/gmlt.ll +++ test/DebugInfo/Inputs/gmlt.ll @@ -76,13 +76,6 @@ ; CHECK-NOT: {{DW_TAG|DW_AT}} ; CHECK: NULL -; PROFILING: DW_TAG_subprogram -; PROFILING: DW_AT_name {{.*}} "f1" -; With -debug-info-for-profiling, we need to emit decl_file a-nd decl_line -; of the subprogram. -; PROFILING: DW_AT_decl_file -; PROFILING: DW_AT_decl_line - ; CHECK: .debug_ranges contents: ; ... some addresses (depends on platform (such as platforms with function Index: test/DebugInfo/Inputs/gmlt_profiling.ll =================================================================== --- /dev/null +++ test/DebugInfo/Inputs/gmlt_profiling.ll @@ -0,0 +1,68 @@ +; REQUIRES: object-emission + +; Generated from the following source compiled with clang++ -gmlt: +; void f1() {} +; void __attribute__((section("__TEXT,__bar"))) f2() {} +; void __attribute__((always_inline)) f3() { f1(); } +; void f4() { f3(); } + +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name {{.*}} "f1" +; With debug-info-for-profiling attribute, we need to emit decl_file and +; decl_line of the subprogram. +; CHECK: DW_AT_decl_file +; CHECK: DW_AT_decl_line + +; Function Attrs: nounwind uwtable +define void @_Z2f1v() #0 !dbg !4 { +entry: + ret void, !dbg !13 +} + +; Function Attrs: nounwind uwtable +define void @_Z2f2v() #0 section "__TEXT,__bar" !dbg !7 { +entry: + ret void, !dbg !14 +} + +; Function Attrs: alwaysinline nounwind uwtable +define void @_Z2f3v() #1 !dbg !8 { +entry: + call void @_Z2f1v(), !dbg !15 + ret void, !dbg !16 +} + +; Function Attrs: nounwind uwtable +define void @_Z2f4v() #0 !dbg !9 { +entry: + call void @_Z2f1v() #2, !dbg !17 + ret void, !dbg !19 +} + +attributes #0 = { nounwind uwtable "debug-info-for-profiling"="true" "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" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { alwaysinline 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" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!10, !11} +!llvm.ident = !{!12} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.6.0 ", isOptimized: false, emissionKind: LineTablesOnly, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) +!1 = !DIFile(filename: "gmlt.cpp", directory: "/tmp/dbginfo") +!2 = !{} +!4 = distinct !DISubprogram(name: "f1", line: 1, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 1, file: !1, scope: !5, type: !6, variables: !2) +!5 = !DIFile(filename: "gmlt.cpp", directory: "/tmp/dbginfo") +!6 = !DISubroutineType(types: !2) +!7 = distinct !DISubprogram(name: "f2", line: 2, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 2, file: !1, scope: !5, type: !6, variables: !2) +!8 = distinct !DISubprogram(name: "f3", line: 3, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 3, file: !1, scope: !5, type: !6, variables: !2) +!9 = distinct !DISubprogram(name: "f4", line: 4, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 4, file: !1, scope: !5, type: !6, variables: !2) +!10 = !{i32 2, !"Dwarf Version", i32 4} +!11 = !{i32 2, !"Debug Info Version", i32 3} +!12 = !{!"clang version 3.6.0 "} +!13 = !DILocation(line: 1, column: 12, scope: !4) +!14 = !DILocation(line: 2, column: 53, scope: !7) +!15 = !DILocation(line: 3, column: 44, scope: !8) +!16 = !DILocation(line: 3, column: 50, scope: !8) +!17 = !DILocation(line: 3, column: 44, scope: !8, inlinedAt: !18) +!18 = !DILocation(line: 4, column: 13, scope: !9) +!19 = !DILocation(line: 4, column: 19, scope: !9)