diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -97,6 +97,8 @@ CODEGENOPT(XRayInstrumentFunctions , 1, 0) ///< Set when -fxray-instrument is ///< enabled. CODEGENOPT(StackSizeSection , 1, 0) ///< Set when -fstack-size-section is enabled. +CODEGENOPT(ForceDwarfFrameSection , 1, 0) ///< Set when -fforce-dwarf-frame is + ///< enabled. ///< Set when -fxray-always-emit-customevents is enabled. CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1950,6 +1950,10 @@ : Joined<["-"], "fdebug-prefix-map=">, Group, Flags<[CC1Option,CC1AsOption]>, HelpText<"remap file source paths in debug info">; +def fforce_dwarf_frame : Flag<["-"], "fforce-dwarf-frame">, Group, Flags<[CC1Option]>, + HelpText<"Always emit a debug frame section">; +def fno_force_dwarf_frame : Flag<["-"], "fno-force-dwarf-frame">, Group, Flags<[CC1Option]>, + HelpText<"Don't always emit a debug frame section">; def g_Flag : Flag<["-"], "g">, Group, HelpText<"Generate source-level debug information">; def gline_tables_only : Flag<["-"], "gline-tables-only">, Group, diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -485,6 +485,7 @@ Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection; Options.EmitAddrsig = CodeGenOpts.Addrsig; Options.EnableDebugEntryValues = CodeGenOpts.EnableDebugEntryValues; + Options.ForceDwarfFrameSection = CodeGenOpts.ForceDwarfFrameSection; Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile; Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3339,6 +3339,10 @@ CmdArgs.push_back("-generate-arange-section"); } + if (Args.hasFlag(options::OPT_fforce_dwarf_frame, + options::OPT_fno_force_dwarf_frame, false)) + CmdArgs.push_back("-fforce-dwarf-frame"); + if (Args.hasFlag(options::OPT_fdebug_types_section, options::OPT_fno_debug_types_section, false)) { if (!T.isOSBinFormatELF()) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -769,6 +769,9 @@ Opts.DebugFwdTemplateParams = Args.hasArg(OPT_debug_forward_template_params); Opts.EmbedSource = Args.hasArg(OPT_gembed_source); + Opts.ForceDwarfFrameSection = + Args.hasFlag(OPT_fforce_dwarf_frame, OPT_fno_force_dwarf_frame, false); + for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) Opts.DebugPrefixMap.insert(StringRef(Arg).split('=')); diff --git a/clang/test/Driver/fforce-dwarf-frame.c b/clang/test/Driver/fforce-dwarf-frame.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/fforce-dwarf-frame.c @@ -0,0 +1,6 @@ +// RUN: %clang -target arm -c -### %s -fforce-dwarf-frame 2>&1 | FileCheck --check-prefix=CHECK-ALWAYS %s +// RUN: %clang -target arm -c -### %s -fno-force-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: -fforce-dwarf-frame +// CHECK-NO-ALWAYS-NOT: -fforce-dwarf-frame diff --git a/llvm/include/llvm/CodeGen/CommandFlags.inc b/llvm/include/llvm/CodeGen/CommandFlags.inc --- a/llvm/include/llvm/CodeGen/CommandFlags.inc +++ b/llvm/include/llvm/CodeGen/CommandFlags.inc @@ -276,6 +276,11 @@ cl::desc("Emit debug info about parameter's entry values"), cl::init(false)); +static cl::opt + ForceDwarfFrameSection("force-dwarf-frame-section", + cl::desc("Always emit a debug frame section."), + 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 +311,7 @@ Options.EmitStackSizeSection = EnableStackSizeSection; Options.EmitAddrsig = EnableAddrsig; Options.EnableDebugEntryValues = EnableDebugEntryValues; + Options.ForceDwarfFrameSection = ForceDwarfFrameSection; Options.MCOptions = InitMCTargetOptionsFromFlags(); diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h --- a/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/llvm/include/llvm/CodeGen/MachineFunction.h @@ -560,6 +560,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; } diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h --- a/llvm/include/llvm/Target/TargetOptions.h +++ b/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), ForceDwarfFrameSection(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 debug frame section. + unsigned ForceDwarfFrameSection : 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 diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -935,7 +935,7 @@ MF->getFunction().needsUnwindTableEntry()) return CFI_M_EH; - if (MMI->hasDebugInfo()) + if (MMI->hasDebugInfo() || MF->getTarget().Options.ForceDwarfFrameSection) return CFI_M_Debug; return CFI_M_None; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ b/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.ForceDwarfFrameSection) + Asm->OutStreamer->EmitCFISections(true, true); hasEmittedCFISections = true; } diff --git a/llvm/lib/CodeGen/CFIInstrInserter.cpp b/llvm/lib/CodeGen/CFIInstrInserter.cpp --- a/llvm/lib/CodeGen/CFIInstrInserter.cpp +++ b/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()); diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -520,6 +520,13 @@ 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.ForceDwarfFrameSection || + F.needsUnwindTableEntry(); +} + namespace llvm { template<> diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -844,8 +844,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; diff --git a/llvm/lib/Target/ARC/ARCRegisterInfo.cpp b/llvm/lib/Target/ARC/ARCRegisterInfo.cpp --- a/llvm/lib/Target/ARC/ARCRegisterInfo.cpp +++ b/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 * diff --git a/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp b/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp --- a/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp +++ b/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; diff --git a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp +++ b/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(); diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/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 diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp --- a/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/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, diff --git a/llvm/lib/Target/XCore/XCoreRegisterInfo.cpp b/llvm/lib/Target/XCore/XCoreRegisterInfo.cpp --- a/llvm/lib/Target/XCore/XCoreRegisterInfo.cpp +++ b/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 * diff --git a/llvm/test/CodeGen/ARM/dwarf-frame.ll b/llvm/test/CodeGen/ARM/dwarf-frame.ll new file mode 100644 --- /dev/null +++ b/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 -force-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