Index: clang/include/clang/Basic/CodeGenOptions.def =================================================================== --- clang/include/clang/Basic/CodeGenOptions.def +++ clang/include/clang/Basic/CodeGenOptions.def @@ -96,6 +96,7 @@ CODEGENOPT(XRayInstrumentFunctions , 1, 0) ///< Set when -fxray-instrument is ///< enabled. CODEGENOPT(StackSizeSection , 1, 0) ///< Set when -fstack-size-section is enabled. +CODEGENOPT(DwarfFrameSection , 1, 0) ///< Set when -gdwarf-frame is enabled. ///< Set when -fxray-always-emit-customevents is enabled. CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0) Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -1972,6 +1972,10 @@ def gpubnames : Flag<["-"], "gpubnames">, Group, Flags<[CC1Option]>; def gno_pubnames : Flag<["-"], "gno-pubnames">, Group, Flags<[CC1Option]>; def gdwarf_aranges : Flag<["-"], "gdwarf-aranges">, Group; +def gdwarf_frame : Flag<["-"], "gdwarf-frame">, Group, Flags<[CC1Option]>, + HelpText<"Emit debug frame section without generating other debug info">; +def gno_dwarf_frame : Flag<["-"], "gno-dwarf-frame">, Group, Flags<[CC1Option]>, + HelpText<"Don't emit debug frame section without generating other debug info">; def gmodules : Flag <["-"], "gmodules">, Group, HelpText<"Generate debug info with external references to clang modules" " or precompiled headers">; Index: clang/lib/CodeGen/BackendUtil.cpp =================================================================== --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -485,6 +485,7 @@ Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection; Options.EmitAddrsig = CodeGenOpts.Addrsig; Options.EnableDebugEntryValues = CodeGenOpts.EnableDebugEntryValues; + Options.EmitDwarfFrameSection = CodeGenOpts.DwarfFrameSection; Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile; Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll; Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -3429,6 +3429,10 @@ CmdArgs.push_back("-generate-arange-section"); } + if (Args.hasFlag(options::OPT_gdwarf_frame, + options::OPT_gno_dwarf_frame, false)) + CmdArgs.push_back("-gdwarf-frame"); + if (Args.hasFlag(options::OPT_fdebug_types_section, options::OPT_fno_debug_types_section, false)) { if (!T.isOSBinFormatELF()) { Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -766,6 +766,9 @@ Opts.DebugExplicitImport = Args.hasArg(OPT_dwarf_explicit_import); Opts.DebugFwdTemplateParams = Args.hasArg(OPT_debug_forward_template_params); Opts.EmbedSource = Args.hasArg(OPT_gembed_source); + + Opts.DwarfFrameSection = + Args.hasFlag(OPT_gdwarf_frame, OPT_gno_dwarf_frame, false); for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) Opts.DebugPrefixMap.insert(StringRef(Arg).split('=')); Index: clang/test/Driver/gdwarf-frame.c =================================================================== --- /dev/null +++ clang/test/Driver/gdwarf-frame.c @@ -0,0 +1,6 @@ +// RUN: %clang -target arm -c -### %s -gdwarf-frame 2>&1 | FileCheck --check-prefix=CHECK-ALWAYS %s +// RUN: %clang -target arm -c -### %s -gno-dwarf-frame 2>&1 | FileCheck --check-prefix=CHECK-NO-ALWAYS %s +// RUN: %clang -target arm -c -### %s 2>&1 | FileCheck --check-prefix=CHECK-NO-ALWAYS %s + +// CHECK-ALWAYS: -gdwarf-frame +// CHECK-NO-ALWAYS-NOT: -gdwarf-frame Index: llvm/include/llvm/CodeGen/CommandFlags.inc =================================================================== --- llvm/include/llvm/CodeGen/CommandFlags.inc +++ llvm/include/llvm/CodeGen/CommandFlags.inc @@ -276,6 +276,8 @@ cl::desc("Emit debug info about parameter's entry values"), cl::init(false)); +static cl::opt DwarfFrameSection("dwarf-frame-section", cl::desc("Emit debug frame section without generating other debug info"), cl::init(false)); + // Common utility function tightly tied to the options listed here. Initializes // a TargetOptions object with CodeGen flags and returns it. static TargetOptions InitTargetOptionsFromCodeGenFlags() { @@ -306,6 +308,7 @@ Options.EmitStackSizeSection = EnableStackSizeSection; Options.EmitAddrsig = EnableAddrsig; Options.EnableDebugEntryValues = EnableDebugEntryValues; + Options.EmitDwarfFrameSection = DwarfFrameSection; Options.MCOptions = InitMCTargetOptionsFromFlags(); Index: llvm/include/llvm/CodeGen/MachineFunction.h =================================================================== --- llvm/include/llvm/CodeGen/MachineFunction.h +++ llvm/include/llvm/CodeGen/MachineFunction.h @@ -548,6 +548,9 @@ } void setHasWinCFI(bool v) { HasWinCFI = v; } + /// True if this function needs frame moves for debug or exceptions. + bool needsFrameMoves() const; + /// Get the function properties const MachineFunctionProperties &getProperties() const { return Properties; } MachineFunctionProperties &getProperties() { return Properties; } Index: llvm/include/llvm/Target/TargetOptions.h =================================================================== --- llvm/include/llvm/Target/TargetOptions.h +++ llvm/include/llvm/Target/TargetOptions.h @@ -119,7 +119,7 @@ ExplicitEmulatedTLS(false), EnableIPRA(false), EmitStackSizeSection(false), EnableMachineOutliner(false), SupportsDefaultOutlining(false), EmitAddrsig(false), - EnableDebugEntryValues(false) {} + EnableDebugEntryValues(false), EmitDwarfFrameSection(false) {} /// PrintMachineCode - This flag is enabled when the -print-machineinstrs /// option is specified on the command line, and should enable debugging @@ -256,6 +256,9 @@ /// Emit debug info about parameter's entry values. unsigned EnableDebugEntryValues : 1; + /// Emit Dwarf unwinding information. + unsigned EmitDwarfFrameSection : 1; + /// FloatABIType - This setting is set by -float-abi=xxx option is specfied /// on the command line. This setting may either be Default, Soft, or Hard. /// Default selects the target's default behavior. Soft selects the ABI for Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -940,7 +940,7 @@ MF->getFunction().needsUnwindTableEntry()) return CFI_M_EH; - if (MMI->hasDebugInfo()) + if (MMI->hasDebugInfo() || MF->getTarget().Options.EmitDwarfFrameSection) return CFI_M_Debug; return CFI_M_None; Index: llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -29,6 +29,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" using namespace llvm; @@ -133,6 +134,8 @@ if (!hasEmittedCFISections) { if (Asm->needsOnlyDebugCFIMoves()) Asm->OutStreamer->EmitCFISections(false, true); + else if (Asm->TM.Options.EmitDwarfFrameSection) + Asm->OutStreamer->EmitCFISections(true, true); hasEmittedCFISections = true; } Index: llvm/lib/CodeGen/CFIInstrInserter.cpp =================================================================== --- llvm/lib/CodeGen/CFIInstrInserter.cpp +++ llvm/lib/CodeGen/CFIInstrInserter.cpp @@ -48,8 +48,7 @@ } bool runOnMachineFunction(MachineFunction &MF) override { - if (!MF.getMMI().hasDebugInfo() && - !MF.getFunction().needsUnwindTableEntry()) + if (!MF.needsFrameMoves()) return false; MBBVector.resize(MF.getNumBlockIDs()); Index: llvm/lib/CodeGen/MachineFunction.cpp =================================================================== --- llvm/lib/CodeGen/MachineFunction.cpp +++ llvm/lib/CodeGen/MachineFunction.cpp @@ -521,6 +521,12 @@ OS << "\n# End machine code for function " << getName() << ".\n\n"; } +/// True if this function needs frame moves for debug or exceptions. +bool MachineFunction::needsFrameMoves() const { + return getMMI().hasDebugInfo() || getTarget().Options.EmitDwarfFrameSection || + F.needsUnwindTableEntry(); +} + namespace llvm { template<> Index: llvm/lib/Target/AArch64/AArch64FrameLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -841,8 +841,8 @@ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineModuleInfo &MMI = MF.getMMI(); AArch64FunctionInfo *AFI = MF.getInfo(); - bool needsFrameMoves = (MMI.hasDebugInfo() || F.needsUnwindTableEntry()) && - !MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); + bool needsFrameMoves = + MF.needsFrameMoves() && !MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); bool HasFP = hasFP(MF); bool NeedsWinCFI = needsWinCFI(MF); bool HasWinCFI = false; Index: llvm/lib/Target/ARC/ARCRegisterInfo.cpp =================================================================== --- llvm/lib/Target/ARC/ARCRegisterInfo.cpp +++ llvm/lib/Target/ARC/ARCRegisterInfo.cpp @@ -128,7 +128,7 @@ ARCRegisterInfo::ARCRegisterInfo() : ARCGenRegisterInfo(ARC::BLINK) {} bool ARCRegisterInfo::needsFrameMoves(const MachineFunction &MF) { - return MF.getMMI().hasDebugInfo() || MF.getFunction().needsUnwindTableEntry(); + return MF.needsFrameMoves(); } const MCPhysReg * Index: llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp =================================================================== --- llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp +++ llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp @@ -223,8 +223,7 @@ bool HexagonCallFrameInformation::runOnMachineFunction(MachineFunction &MF) { auto &HFI = *MF.getSubtarget().getFrameLowering(); - bool NeedCFI = MF.getMMI().hasDebugInfo() || - MF.getFunction().needsUnwindTableEntry(); + bool NeedCFI = MF.needsFrameMoves(); if (!NeedCFI) return false; Index: llvm/lib/Target/PowerPC/PPCFrameLowering.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCFrameLowering.cpp +++ llvm/lib/Target/PowerPC/PPCFrameLowering.cpp @@ -782,8 +782,7 @@ MachineModuleInfo &MMI = MF.getMMI(); const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); DebugLoc dl; - bool needsCFI = MMI.hasDebugInfo() || - MF.getFunction().needsUnwindTableEntry(); + bool needsCFI = MF.needsFrameMoves(); // Get processor type. bool isPPC64 = Subtarget.isPPC64(); Index: llvm/lib/Target/X86/X86FrameLowering.cpp =================================================================== --- llvm/lib/Target/X86/X86FrameLowering.cpp +++ llvm/lib/Target/X86/X86FrameLowering.cpp @@ -993,8 +993,7 @@ bool NeedsWinFPO = !IsFunclet && STI.isTargetWin32() && MMI.getModule()->getCodeViewFlag(); bool NeedsWinCFI = NeedsWin64CFI || NeedsWinFPO; - bool NeedsDwarfCFI = - !IsWin64Prologue && (MMI.hasDebugInfo() || Fn.needsUnwindTableEntry()); + bool NeedsDwarfCFI = !IsWin64Prologue && MF.needsFrameMoves(); Register FramePtr = TRI->getFrameRegister(MF); const Register MachineFramePtr = STI.isTarget64BitILP32() @@ -1614,10 +1613,9 @@ bool HasFP = hasFP(MF); uint64_t NumBytes = 0; - bool NeedsDwarfCFI = - (!MF.getTarget().getTargetTriple().isOSDarwin() && - !MF.getTarget().getTargetTriple().isOSWindows()) && - (MF.getMMI().hasDebugInfo() || MF.getFunction().needsUnwindTableEntry()); + bool NeedsDwarfCFI = (!MF.getTarget().getTargetTriple().isOSDarwin() && + !MF.getTarget().getTargetTriple().isOSWindows()) && + MF.needsFrameMoves(); if (IsFunclet) { assert(HasFP && "EH funclets without FP not yet implemented"); @@ -2812,11 +2810,9 @@ unsigned StackAlign = getStackAlignment(); Amount = alignTo(Amount, StackAlign); - MachineModuleInfo &MMI = MF.getMMI(); const Function &F = MF.getFunction(); bool WindowsCFI = MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); - bool DwarfCFI = !WindowsCFI && - (MMI.hasDebugInfo() || F.needsUnwindTableEntry()); + bool DwarfCFI = !WindowsCFI && MF.needsFrameMoves(); // If we have any exception handlers in this function, and we adjust // the SP before calls, we may need to indicate this to the unwinder Index: llvm/lib/Target/X86/X86InstrInfo.cpp =================================================================== --- llvm/lib/Target/X86/X86InstrInfo.cpp +++ llvm/lib/Target/X86/X86InstrInfo.cpp @@ -3963,9 +3963,7 @@ MachineFunction &MF = *MBB.getParent(); const X86FrameLowering *TFL = Subtarget.getFrameLowering(); bool IsWin64Prologue = MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); - bool NeedsDwarfCFI = - !IsWin64Prologue && - (MF.getMMI().hasDebugInfo() || MF.getFunction().needsUnwindTableEntry()); + bool NeedsDwarfCFI = !IsWin64Prologue && MF.needsFrameMoves(); bool EmitCFI = !TFL->hasFP(MF) && NeedsDwarfCFI; if (EmitCFI) { TFL->BuildCFI(MBB, I, DL, Index: llvm/lib/Target/XCore/XCoreRegisterInfo.cpp =================================================================== --- llvm/lib/Target/XCore/XCoreRegisterInfo.cpp +++ llvm/lib/Target/XCore/XCoreRegisterInfo.cpp @@ -203,7 +203,7 @@ } bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) { - return MF.getMMI().hasDebugInfo() || MF.getFunction().needsUnwindTableEntry(); + return MF.needsFrameMoves(); } const MCPhysReg * Index: llvm/test/CodeGen/ARM/dwarf-frame.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/ARM/dwarf-frame.ll @@ -0,0 +1,38 @@ +; RUN: llc -mtriple armv7-unknown -frame-pointer=all -filetype=asm -o - %s | FileCheck %s --check-prefix=CHECK-NO-CFI +; RUN: llc -mtriple armv7-unknown -frame-pointer=all -filetype=asm -dwarf-frame-section -o - %s | FileCheck %s --check-prefix=CHECK-ALWAYS-CFI + +declare void @dummy_use(i32*, i32) + +define void @test_basic() #0 { + %mem = alloca i32, i32 10 + call void @dummy_use (i32* %mem, i32 10) + ret void +} + +; CHECK-NO-CFI-LABEL: test_basic: +; CHECK-NO-CFI: .fnstart +; CHECK-NO-CFI-NOT: .cfi_sections .debug_frame +; CHECK-NO-CFI-NOT: .cfi_startproc +; CHECK-NO-CFI: @ %bb.0: +; CHECK-NO-CFI: push {r11, lr} +; CHECK-NO-CFI-NOT: .cfi_def_cfa_offset 8 +; CHECK-NO-CFI-NOT: .cfi_offset lr, -4 +; CHECK-NO-CFI-NOT: .cfi_offset r11, -8 +; CHECK-NO-CFI: mov r11, sp +; CHECK-NO-CFI-NOT: .cfi_def_cfa_register r11 +; CHECK-NO-CFI-NOT: .cfi_endproc +; CHECK-NO-CFI: .fnend + +; CHECK-ALWAYS-CFI-LABEL: test_basic: +; CHECK-ALWAYS-CFI: .fnstart +; CHECK-ALWAYS-CFI: .cfi_sections .debug_frame +; CHECK-ALWAYS-CFI: .cfi_startproc +; CHECK-ALWAYS-CFI: @ %bb.0: +; CHECK-ALWAYS-CFI: push {r11, lr} +; CHECK-ALWAYS-CFI: .cfi_def_cfa_offset 8 +; CHECK-ALWAYS-CFI: .cfi_offset lr, -4 +; CHECK-ALWAYS-CFI: .cfi_offset r11, -8 +; CHECK-ALWAYS-CFI: mov r11, sp +; CHECK-ALWAYS-CFI: .cfi_def_cfa_register r11 +; CHECK-ALWAYS-CFI: .cfi_endproc +; CHECK-ALWAYS-CFI: .fnend