Author: Jon Roelofs Date: 2026-06-18T12:57:21-07:00 New Revision: df9b1f89a4f4f0c7b5afc03d273a825caef268fb
URL: https://github.com/llvm/llvm-project/commit/df9b1f89a4f4f0c7b5afc03d273a825caef268fb DIFF: https://github.com/llvm/llvm-project/commit/df9b1f89a4f4f0c7b5afc03d273a825caef268fb.diff LOG: [clang][Mach-O] Add an option to force UNWIND_*_MODE_DWARF compact unwind info (#204005) The new option value extends: `-femit-dwarf-unwind=dwarf-only`. This is primarily intended as a testing mechanism to ensure coverage on the DWARF-only parts of the unwinder, where previously the compact unwinder would have taken care of most functions. Added: llvm/test/MC/AArch64/compact-unwind-force-dwarf.s llvm/test/MC/X86/compact-unwind-force-dwarf.s Modified: clang/docs/UsersManual.rst clang/include/clang/Options/Options.td clang/test/Driver/femit-dwarf-unwind.c clang/test/Driver/femit-dwarf-unwind.s clang/tools/driver/cc1as_main.cpp llvm/include/llvm/MC/MCTargetOptions.h llvm/lib/MC/MCObjectFileInfo.cpp llvm/lib/MC/MCTargetOptionsCommandFlags.cpp llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp llvm/test/MC/MachO/ARM/compact-unwind-armv7k.s Removed: ################################################################################ diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 3f4b1585e5935..77f644f221a17 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -940,6 +940,8 @@ Clang options that don't fit neatly into other categories. * ``no-compact-unwind`` - Only emit DWARF unwind when compact unwind encodings aren't available. This is the default for arm64. * ``always`` - Always emit DWARF unwind regardless. + * ``dwarf-only`` - Always emit DWARF unwind, and force compact unwind to defer + to DWARF. * ``default`` - Use the platform-specific default (``always`` for all non-arm64-platforms). diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 22e730ac58fb1..5028684731b2d 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -5045,8 +5045,8 @@ defm force_dwarf_frame : BoolFOption<"force-dwarf-frame", def femit_dwarf_unwind_EQ : Joined<["-"], "femit-dwarf-unwind=">, Group<f_Group>, Visibility<[ClangOption, CC1Option, CC1AsOption]>, HelpText<"When to emit DWARF unwind (EH frame) info">, - Values<"always,no-compact-unwind,default">, - NormalizedValues<["Always", "NoCompactUnwind", "Default"]>, + Values<"always,no-compact-unwind,dwarf-only,default">, + NormalizedValues<["Always", "NoCompactUnwind", "DwarfOnly", "Default"]>, NormalizedValuesScope<"llvm::EmitDwarfUnwindType">, MarshallingInfoEnum<CodeGenOpts<"EmitDwarfUnwind">, "Default">; defm emit_compact_unwind_non_canonical : BoolFOption<"emit-compact-unwind-non-canonical", diff --git a/clang/test/Driver/femit-dwarf-unwind.c b/clang/test/Driver/femit-dwarf-unwind.c index 89e733462c2c9..ee8e3964fef4e 100644 --- a/clang/test/Driver/femit-dwarf-unwind.c +++ b/clang/test/Driver/femit-dwarf-unwind.c @@ -1,11 +1,22 @@ // REQUIRES: x86-registered-target // RUN: rm -rf %t; mkdir %t -// RUN: %clang -target x86_64-apple-macos11.0 -c %s -o %t/x86_64.o -femit-compact-unwind-non-canonical -// RUN: %clang -target x86_64-apple-macos11.0 -femit-dwarf-unwind=no-compact-unwind -femit-compact-unwind-non-canonical -c %s -o %t/x86_64-no-dwarf.o + +// RUN: %clang --target=x86_64-apple-macos11.0 -c %s -o %t/x86_64.o -femit-compact-unwind-non-canonical // RUN: llvm-objdump --macho --dwarf=frames %t/x86_64.o | FileCheck %s --check-prefix=WITH-FDE + +// RUN: %clang --target=x86_64-apple-macos11.0 -femit-dwarf-unwind=no-compact-unwind -femit-compact-unwind-non-canonical -c %s -o %t/x86_64-no-dwarf.o // RUN: llvm-objdump --macho --dwarf=frames %t/x86_64-no-dwarf.o | FileCheck %s --check-prefix=NO-FDE +// RUN: %clang --target=x86_64-apple-macos11.0 -femit-dwarf-unwind=dwarf-only -c %s -o %t/x86_64-dwarf-only.o +// RUN: llvm-objdump --macho --dwarf=frames --unwind-info %t/x86_64-dwarf-only.o | FileCheck %s --check-prefix=CU-DWARF + +// CU-DWARF: Contents of __compact_unwind section: +// CU-DWARF-NEXT: Entry at offset 0x0: +// CU-DWARF-NEXT: start: 0x0 _foo +// CU-DWARF-NEXT: length: 0xb +// CU-DWARF-NEXT: compact encoding: 0x04000000 + // WITH-FDE: FDE // NO-FDE-NOT: FDE diff --git a/clang/test/Driver/femit-dwarf-unwind.s b/clang/test/Driver/femit-dwarf-unwind.s index 41951352eeafd..32d972abf0a21 100644 --- a/clang/test/Driver/femit-dwarf-unwind.s +++ b/clang/test/Driver/femit-dwarf-unwind.s @@ -1,11 +1,22 @@ // REQUIRES: x86-registered-target // RUN: rm -rf %t; mkdir %t + // RUN: %clang -target x86_64-apple-macos11.0 -c %s -o %t/x86_64.o -femit-compact-unwind-non-canonical -// RUN: %clang -target x86_64-apple-macos11.0 -femit-dwarf-unwind=no-compact-unwind -c %s -o %t/x86_64-no-dwarf.o -femit-compact-unwind-non-canonical // RUN: llvm-objdump --macho --dwarf=frames %t/x86_64.o | FileCheck %s --check-prefix=WITH-FDE + +// RUN: %clang -target x86_64-apple-macos11.0 -femit-dwarf-unwind=no-compact-unwind -c %s -o %t/x86_64-no-dwarf.o -femit-compact-unwind-non-canonical // RUN: llvm-objdump --macho --dwarf=frames %t/x86_64-no-dwarf.o | FileCheck %s --check-prefix=NO-FDE +// RUN: %clang -target x86_64-apple-macos11.0 -femit-dwarf-unwind=dwarf-only -c %s -o %t/x86_64-dwarf-only.o +// RUN: llvm-objdump --macho --dwarf=frames --unwind-info %t/x86_64-dwarf-only.o | FileCheck %s --check-prefixes=WITH-FDE,CU-DWARF + +// CU-DWARF: Contents of __compact_unwind section: +// CU-DWARF-NEXT: Entry at offset 0x0: +// CU-DWARF-NEXT: start: 0x0 _foo +// CU-DWARF-NEXT: length: 0x1 +// CU-DWARF-NEXT: compact encoding: 0x04000000 + // WITH-FDE: FDE // NO-FDE-NOT: FDE diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp index 33c34dd04d0e6..077cd69ce4e2c 100644 --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -389,6 +389,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, llvm::StringSwitch<EmitDwarfUnwindType>(A->getValue()) .Case("always", EmitDwarfUnwindType::Always) .Case("no-compact-unwind", EmitDwarfUnwindType::NoCompactUnwind) + .Case("dwarf-only", EmitDwarfUnwindType::DwarfOnly) .Case("default", EmitDwarfUnwindType::Default); } diff --git a/llvm/include/llvm/MC/MCTargetOptions.h b/llvm/include/llvm/MC/MCTargetOptions.h index 2f24608b5f6ba..e3d1a8cc763b7 100644 --- a/llvm/include/llvm/MC/MCTargetOptions.h +++ b/llvm/include/llvm/MC/MCTargetOptions.h @@ -21,6 +21,7 @@ namespace llvm { enum class EmitDwarfUnwindType { Always, // Always emit dwarf unwind NoCompactUnwind, // Only emit if compact unwind isn't available + DwarfOnly, // Force compact unwind to reference DWARF Default, // Default behavior is based on the target }; diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp index ab8ae43d22940..cc95fd8bf8ac9 100644 --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -77,6 +77,7 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) { switch (Ctx->emitDwarfUnwindInfo()) { case EmitDwarfUnwindType::Always: + case EmitDwarfUnwindType::DwarfOnly: OmitDwarfIfHaveCompactUnwind = false; break; case EmitDwarfUnwindType::NoCompactUnwind: diff --git a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp index 359c1bceb25b1..32f6983ed95a9 100644 --- a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp +++ b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp @@ -102,6 +102,8 @@ llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() { "no-compact-unwind", "Only emit EH frame entries when compact unwind is " "not available"), + clEnumValN(EmitDwarfUnwindType::DwarfOnly, "dwarf-only", + "Force compact unwind to reference DWARF"), clEnumValN(EmitDwarfUnwindType::Default, "default", "Use target platform default"))); MCBINDOPT(EmitDwarfUnwind); diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp index eece54692e18c..98fd4fd4a451b 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp @@ -575,6 +575,9 @@ class DarwinAArch64AsmBackend : public AArch64AsmBackend { /// Generate the compact unwind encoding from the CFI directives. uint64_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, const MCContext *Ctxt) const override { + if (Ctxt->emitDwarfUnwindInfo() == EmitDwarfUnwindType::DwarfOnly) + return CU::UNWIND_ARM64_MODE_DWARF; + // MTE-tagged frames must use DWARF unwinding because compact unwind // doesn't handle MTE tags if (FI->IsMTETaggedFrame) diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 7c9f130024342..7da862d26c091 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -1185,6 +1185,9 @@ uint64_t ARMAsmBackendDarwin::generateCompactUnwindEncoding( if (Subtype != MachO::CPU_SUBTYPE_ARM_V7K) return 0; + if (Ctxt->emitDwarfUnwindInfo() == EmitDwarfUnwindType::DwarfOnly) + return CU::UNWIND_ARM_MODE_DWARF; + // Signal frames cannot be encoded in compact unwind. if (FI->IsSignalFrame) return CU::UNWIND_ARM_MODE_DWARF; diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index 7515c75ab33e1..0b3da6582d907 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -28,6 +28,7 @@ #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCTargetOptions.h" #include "llvm/MC/MCValue.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/CommandLine.h" @@ -1306,6 +1307,9 @@ class DarwinX86AsmBackend : public X86AsmBackend { /// for the CFI instructions. uint64_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, const MCContext *Ctxt) const override { + if (Ctxt->emitDwarfUnwindInfo() == EmitDwarfUnwindType::DwarfOnly) + return CU::UNWIND_MODE_DWARF; + // Signal frames cannot be encoded in compact unwind. if (FI->IsSignalFrame) return CU::UNWIND_MODE_DWARF; diff --git a/llvm/test/MC/AArch64/compact-unwind-force-dwarf.s b/llvm/test/MC/AArch64/compact-unwind-force-dwarf.s new file mode 100644 index 0000000000000..d5a52f664c253 --- /dev/null +++ b/llvm/test/MC/AArch64/compact-unwind-force-dwarf.s @@ -0,0 +1,42 @@ +// RUN: llvm-mc -triple arm64-apple-macos10.6 -filetype=obj %s -o %t.compact.o +// RUN: llvm-objdump --macho --unwind-info --dwarf=frames %t.compact.o | FileCheck %s --check-prefixes=CHECK,COMPACT +// RUN: llvm-mc -triple arm64-apple-macos10.6 -filetype=obj --emit-dwarf-unwind dwarf-only %s -o %t.dwarf.o +// RUN: llvm-objdump --macho --unwind-info --dwarf=frames %t.dwarf.o | FileCheck %s --check-prefixes=CHECK,DWARF + +_f: + .cfi_startproc + ret + .cfi_endproc + +// On arm64, a compact unwind encoding of 0x03000000 indicates +// "fall back on DWARF unwind". + +// CHECK: Contents of __compact_unwind section: +// CHECK: Entry at offset 0x0: +// CHECK: start: 0x0 ltmp0 +// CHECK: length: 0x4 +// COMPACT: compact encoding: 0x02000000 +// DWARF: compact encoding: 0x03000000 + +// CHECK: .eh_frame contents: + +// DWARF: 00000000 00000010 00000000 CIE +// DWARF: Format: DWARF32 +// DWARF: Version: 1 +// DWARF: Augmentation: "zR" +// DWARF: Code alignment factor: 1 +// DWARF: Data alignment factor: -8 +// DWARF: Return address column: 30 +// DWARF: Augmentation data: 10 + +// DWARF: DW_CFA_def_cfa: reg31 +0 + +// DWARF: CFA=reg31 + +// DWARF: FDE cie=00000000 +// DWARF: Format: DWARF32 +// DWARF: DW_CFA_nop: +// DWARF: DW_CFA_nop: +// DWARF: DW_CFA_nop: + +// DWARF: CFA=reg31 diff --git a/llvm/test/MC/MachO/ARM/compact-unwind-armv7k.s b/llvm/test/MC/MachO/ARM/compact-unwind-armv7k.s index 65890bcae750f..226aa99614b11 100644 --- a/llvm/test/MC/MachO/ARM/compact-unwind-armv7k.s +++ b/llvm/test/MC/MachO/ARM/compact-unwind-armv7k.s @@ -1,4 +1,5 @@ -@ RUN: llvm-mc -triple=thumbv7k-apple-watchos2.0.0 -emit-compact-unwind-non-canonical=true -filetype=obj -o %t < %s && llvm-objdump --unwind-info %t | FileCheck %s +@ RUN: llvm-mc -triple=thumbv7k-apple-watchos2.0.0 -emit-compact-unwind-non-canonical=true -filetype=obj -o %t < %s && llvm-objdump --unwind-info %t | FileCheck %s --check-prefixes=CHECK,COMPACT +@ RUN: llvm-mc -triple=thumbv7k-apple-watchos2.0.0 --emit-dwarf-unwind dwarf-only -filetype=obj -o %t < %s && llvm-objdump --unwind-info %t | FileCheck %s --check-prefixes=CHECK,DWARF @ CHECK: Contents of __compact_unwind section: @@ -6,8 +7,12 @@ .align 2 .code 16 +@ On armv7k, a compact unwind entry of 0x04000000 indicates +@ "fall back on DWARF unwind" + @ CHECK-LABEL: start: {{.*}} _test_r4_r5_r6 -@ CHECK: compact encoding: 0x01000007 +@ COMPACT: compact encoding: 0x01000007 +@ DWARF: compact encoding: 0x04000000 .thumb_func _test_r4_r5_r6 _test_r4_r5_r6: .cfi_startproc @@ -24,7 +29,8 @@ _test_r4_r5_r6: @ CHECK-LABEL: start: {{.*}} _test_r4_r5_r10_r11 -@ CHECK: compact encoding: 0x01000063 +@ COMPACT: compact encoding: 0x01000063 +@ DWARF: compact encoding: 0x04000000 .thumb_func _test_r4_r5_r10_r11 _test_r4_r5_r10_r11: .cfi_startproc @@ -42,7 +48,8 @@ _test_r4_r5_r10_r11: @ CHECK-LABEL: start: {{.*}} _test_d8 -@ CHECK: compact encoding: 0x02000000 +@ COMPACT: compact encoding: 0x02000000 +@ DWARF: compact encoding: 0x04000000 .thumb_func _test_d8 _test_d8: .cfi_startproc @@ -57,7 +64,8 @@ _test_d8: @ CHECK-LABEL: start: {{.*}} _test_d8_d10_d12_d14 -@ CHECK: compact encoding: 0x02000300 +@ COMPACT: compact encoding: 0x02000300 +@ DWARF: compact encoding: 0x04000000 .thumb_func _test_d8_d10_d12_d14 _test_d8_d10_d12_d14: .cfi_startproc @@ -77,7 +85,8 @@ _test_d8_d10_d12_d14: .cfi_endproc @ CHECK-LABEL: start: {{.*}} _test_varargs -@ CHECK: compact encoding: 0x01c00001 +@ COMPACT: compact encoding: 0x01c00001 +@ DWARF: compact encoding: 0x04000000 .thumb_func _test_varargs _test_varargs: .cfi_startproc @@ -94,7 +103,8 @@ _test_varargs: .cfi_endproc @ CHECK-LABEL: start: {{.*}} _test_missing_lr -@ CHECK: compact encoding: 0x04000000 +@ COMPACT: compact encoding: 0x04000000 +@ DWARF: compact encoding: 0x04000000 .thumb_func _test_missing_lr _test_missing_lr: .cfi_startproc @@ -106,7 +116,8 @@ _test_missing_lr: .cfi_endproc @ CHECK-LABEL: start: {{.*}} _test_swapped_offsets -@ CHECK: compact encoding: 0x04000000 +@ COMPACT: compact encoding: 0x04000000 +@ DWARF: compact encoding: 0x04000000 .thumb_func _test_swapped_offsets _test_swapped_offsets: .cfi_startproc diff --git a/llvm/test/MC/X86/compact-unwind-force-dwarf.s b/llvm/test/MC/X86/compact-unwind-force-dwarf.s new file mode 100644 index 0000000000000..37c4c4324d354 --- /dev/null +++ b/llvm/test/MC/X86/compact-unwind-force-dwarf.s @@ -0,0 +1,54 @@ +// RUN: llvm-mc -triple x86_64-apple-macos10.6 -filetype=obj --emit-dwarf-unwind dwarf-only %s -o %t.dwarf.o +// RUN: llvm-objdump --macho --unwind-info --dwarf=frames %t.dwarf.o | FileCheck %s --check-prefixes=CHECK,DWARF +// RUN: llvm-mc -triple x86_64-apple-macos10.6 -filetype=obj %s -o %t.compact.o +// RUN: llvm-objdump --macho --unwind-info --dwarf=frames %t.compact.o | FileCheck %s --check-prefixes=CHECK,COMPACT + +_f: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + popq %rbp + ret + .cfi_endproc + +// On x86, a compact unwind encoding of 0x04000000 indicates +// "fall back on DWARF unwind" + +// CHECK: Contents of __compact_unwind section: +// CHECK: Entry at offset 0x0: +// CHECK: start: 0x[[#%x,F:]] _f +// CHECK: length: 0x6 +// COMPACT: compact encoding: 0x01000000 +// DWARF: compact encoding: 0x04000000 + +// CHECK: .eh_frame contents: +// CHECK: 00000000 00000014 00000000 CIE +// CHECK: Format: DWARF32 +// CHECK: Version: 1 +// CHECK: Augmentation: "zR" +// CHECK: Code alignment factor: 1 +// CHECK: Data alignment factor: -8 +// CHECK: Return address column: 16 +// CHECK: Augmentation data: 10 + +// CHECK: DW_CFA_def_cfa: reg7 +8 +// CHECK: DW_CFA_offset: reg16 -8 +// CHECK: DW_CFA_nop: +// CHECK: DW_CFA_nop: + +// CHECK: CFA=reg7+8: reg16=[CFA-8] + +// CHECK: FDE cie=00000000 pc=00000000...00000006 +// CHECK: Format: DWARF32 +// CHECK: DW_CFA_advance_loc: 1 to 0x1 +// CHECK: DW_CFA_def_cfa_offset: +16 +// CHECK: DW_CFA_offset: reg6 -16 +// CHECK: DW_CFA_advance_loc: 3 to 0x4 +// CHECK: DW_CFA_def_cfa_register: reg6 + +// CHECK: 0x0: CFA=reg7+8: reg16=[CFA-8] +// CHECK: 0x1: CFA=reg7+16: reg6=[CFA-16], reg16=[CFA-8] +// CHECK: 0x4: CFA=reg6+16: reg6=[CFA-16], reg16=[CFA-8] _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
