Index: include/llvm/CodeGen/CommandFlags.h =================================================================== --- include/llvm/CodeGen/CommandFlags.h +++ include/llvm/CodeGen/CommandFlags.h @@ -231,6 +231,17 @@ "Create one table per unique function type."), clEnumValEnd)); +cl::opt +DebuggerTuning("debugger-tune", + cl::desc("Tune debug info for a particular debugger"), + cl::init(DebuggerKind::Default), + cl::values( + clEnumValN(DebuggerKind::GDB, "gdb", "gdb"), + clEnumValN(DebuggerKind::LLDB, "lldb", "lldb"), + clEnumValN(DebuggerKind::SCE, "sce", + "SCE targets (e.g. PS4)"), + clEnumValEnd)); + // Common utility function tightly tied to the options listed here. Initializes // a TargetOptions object with CodeGen flags and returns it. static inline TargetOptions InitTargetOptionsFromCodeGenFlags() { @@ -258,6 +269,7 @@ Options.MCOptions = InitMCTargetOptionsFromFlags(); Options.JTType = JTableType; + Options.DebuggerTuning = DebuggerTuning; Options.ThreadModel = TMModel; Index: include/llvm/Target/TargetOptions.h =================================================================== --- include/llvm/Target/TargetOptions.h +++ include/llvm/Target/TargetOptions.h @@ -58,6 +58,13 @@ }; } + enum class DebuggerKind { + Default, // No specific tuning. + GDB, // Tune debug info for gdb. + LLDB, // Tune debug info for lldb. + SCE // Tune debug info for SCE targets (e.g. PS4). + }; + class TargetOptions { public: TargetOptions() @@ -75,7 +82,8 @@ TrapFuncName(), FloatABIType(FloatABI::Default), AllowFPOpFusion(FPOpFusion::Standard), Reciprocals(TargetRecip()), JTType(JumpTable::Single), - ThreadModel(ThreadModel::POSIX) {} + ThreadModel(ThreadModel::POSIX), + DebuggerTuning(DebuggerKind::Default) {} /// PrintMachineCode - This flag is enabled when the -print-machineinstrs /// option is specified on the command line, and should enable debugging @@ -219,6 +227,9 @@ /// for things like atomics ThreadModel::Model ThreadModel; + /// Which debugger are we expecting to consume the debug info? + DebuggerKind DebuggerTuning; + /// Machine level options. MCTargetOptions MCOptions; }; Index: lib/CodeGen/AsmPrinter/DwarfDebug.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.h +++ lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -33,6 +33,8 @@ #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MachineLocation.h" #include "llvm/Support/Allocator.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" #include namespace llvm { @@ -315,7 +317,6 @@ // True iff there are multiple CUs in this module. bool SingleCU; bool IsDarwin; - bool IsPS4; AddressPool AddrPool; @@ -537,6 +538,35 @@ /// standard DW_OP_form_tls_address opcode bool useGNUTLSOpcode() const { return UseGNUTLSOpcode; } + // The "debugger tuning" concept allows us to present a more intuitive + // interface that unpacks into different sets of defaults for the various + // individual feature-flag settings, that suit the preferences of the + // various debuggers. However, it's worth remembering that debuggers are + // not the only consumers of debug info, and some variations in DWARF might + // better be treated as target/platform issues. Fundamentally, + // o if the feature is useful (or not) to a particular debugger, regardless + // of the target, that's a tuning decision; + // o if the feature is useful (or not) on a particular platform, regardless + // of the debugger, that's a target decision. + // It's not impossible to see both factors in some specific case. + // + /// \defgroup DebuggerTuning Predicates to tune DWARF for a given debugger. + /// + /// The "tuning" predicates should be used to set defaults for individual + /// feature flags in DwarfDebug; if a given feature has a more specific + /// command-line option, that option should take precedence over the tuning. + /// @{ + bool tuneDebugForGDB() const { + return Asm->TM.Options.DebuggerTuning == DebuggerKind::GDB; + } + bool tuneDebugForLLDB() const { + return Asm->TM.Options.DebuggerTuning == DebuggerKind::LLDB; + } + bool tuneDebugForSCE() const { + return Asm->TM.Options.DebuggerTuning == DebuggerKind::SCE; + } + /// @} + // Experimental DWARF5 features. /// \brief Returns whether or not to emit tables that dwarf consumers can Index: lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -197,7 +197,6 @@ UsedNonDefaultText(false), SkeletonHolder(A, "skel_string", DIEValueAllocator), IsDarwin(Triple(A->getTargetTriple()).isOSDarwin()), - IsPS4(Triple(A->getTargetTriple()).isPS4()), AccelNames(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)), AccelObjC(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, @@ -209,8 +208,19 @@ CurFn = nullptr; CurMI = nullptr; + // Make sure we know our "debugger tuning." + bool IsPS4 = Triple(Asm->getTargetTriple()).isPS4CPU(); + if (Asm->TM.Options.DebuggerTuning == DebuggerKind::Default) { + if (IsDarwin) + Asm->TM.Options.DebuggerTuning = DebuggerKind::LLDB; + else if (IsPS4) + Asm->TM.Options.DebuggerTuning = DebuggerKind::SCE; + else + Asm->TM.Options.DebuggerTuning = DebuggerKind::GDB; + } + // Turn on accelerator tables for Darwin by default, pubnames by - // default for non-Darwin/PS4, and handle split dwarf. + // default for GDB, and handle split dwarf. if (DwarfAccelTables == Default) HasDwarfAccelTables = IsDarwin; else @@ -222,7 +232,7 @@ HasSplitDwarf = SplitDwarf == Enable; if (DwarfPubSections == Default) - HasDwarfPubSections = !IsDarwin && !IsPS4; + HasDwarfPubSections = tuneDebugForGDB(); else HasDwarfPubSections = DwarfPubSections == Enable; Index: test/DebugInfo/X86/debugger-tune.ll =================================================================== --- test/DebugInfo/X86/debugger-tune.ll +++ test/DebugInfo/X86/debugger-tune.ll @@ -0,0 +1,33 @@ +; Verify target-based defaults for "debugger tuning," and the ability to +; override defaults. +; We use existence of the .debug_pubnames section to distinguish the GDB case. +; FIXME: Find something to distinguish LLDB from SCE. + +; RUN: llc -mtriple=x86_64-scei-ps4 -filetype=obj < %s | llvm-dwarfdump -debug-dump=pubnames - | FileCheck --check-prefix=NOPUB %s +; RUN: llc -mtriple=x86_64-scei-ps4 -filetype=obj -debugger-tune=gdb < %s | llvm-dwarfdump -debug-dump=pubnames - | FileCheck --check-prefix=YESPUB %s +; RUN: llc -mtriple=x86_64-apple-darwin12 -filetype=obj < %s | llvm-dwarfdump -debug-dump=pubnames - | FileCheck --check-prefix=NOPUB %s +; RUN: llc -mtriple=x86_64-apple-darwin12 -filetype=obj -debugger-tune=gdb < %s | llvm-dwarfdump -debug-dump=pubnames - | FileCheck --check-prefix=YESPUB %s +; RUN: llc -mtriple=x86_64-pc-linux -filetype=obj < %s | llvm-dwarfdump -debug-dump=pubnames - | FileCheck --check-prefix=YESPUB %s +; RUN: llc -mtriple=x86_64-pc-linux -filetype=obj -debugger-tune=lldb < %s | llvm-dwarfdump -debug-dump=pubnames - | FileCheck --check-prefix=NOPUB %s + +; NOPUB: debug_pubnames +; NOPUB-NEXT: {{^$}} + +; YESPUB: debug_pubnames +; YESPUB-NEXT: length + +@globalvar = global i32 0, align 4 + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!6, !7} +!llvm.ident = !{!8} + +!0 = !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.7.0 (trunk 238808)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !2, subprograms: !2, globals: !3, imports: !2) +!1 = !DIFile(filename: "debug-tune-nondefault.cpp", directory: "/home/probinson/projects/scratch") +!2 = !{} +!3 = !{!4} +!4 = !DIGlobalVariable(name: "globalvar", scope: !0, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, variable: i32* @globalvar) +!5 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!6 = !{i32 2, !"Dwarf Version", i32 4} +!7 = !{i32 2, !"Debug Info Version", i32 3} +!8 = !{!"clang version 3.7.0 (trunk 238808)"} Index: test/DebugInfo/X86/dwarf-public-names.ll =================================================================== --- test/DebugInfo/X86/dwarf-public-names.ll +++ test/DebugInfo/X86/dwarf-public-names.ll @@ -39,11 +39,11 @@ ; Darwin and PS4 shouldn't be generating the section by default ; NOPUB: debug_pubnames -; NOPUB: {{^$}} +; NOPUB-NEXT: {{^$}} ; Skip the output to the header of the pubnames section. ; LINUX: debug_pubnames -; LINUX: unit_size = 0x00000128 +; LINUX-NEXT: unit_size = 0x00000128 ; Check for each name in the output. ; LINUX-DAG: "ns"