Skip to content

Commit

Permalink
[MC][re-land] Omit DWARF unwind info if compact unwind is present whe…
Browse files Browse the repository at this point in the history
…re eligible

This reverts commit d941d59.

Differential Revision: https://reviews.llvm.org/D122258
  • Loading branch information
int3 committed Jun 12, 2022
1 parent 775a22e commit d4bcb45
Show file tree
Hide file tree
Showing 23 changed files with 204 additions and 14 deletions.
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/CodeGenOptions.def
Expand Up @@ -114,6 +114,10 @@ CODEGENOPT(StackSizeSection , 1, 0) ///< Set when -fstack-size-section is enabl
CODEGENOPT(ForceDwarfFrameSection , 1, 0) ///< Set when -fforce-dwarf-frame is
///< enabled.

///< Set when -femit-dwarf-unwind is passed.
ENUM_CODEGENOPT(EmitDwarfUnwind, llvm::EmitDwarfUnwindType, 2,
llvm::EmitDwarfUnwindType::Default)

///< Set when -fxray-always-emit-customevents is enabled.
CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0)

Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Driver/Options.td
Expand Up @@ -3044,6 +3044,13 @@ def fmacro_prefix_map_EQ
defm force_dwarf_frame : BoolFOption<"force-dwarf-frame",
CodeGenOpts<"ForceDwarfFrameSection">, DefaultFalse,
PosFlag<SetTrue, [CC1Option], "Always emit a debug frame section">, NegFlag<SetFalse>>;
def femit_dwarf_unwind_EQ : Joined<["-"], "femit-dwarf-unwind=">,
Group<f_Group>, Flags<[CC1Option, CC1AsOption]>,
HelpText<"When to emit DWARF unwind (EH frame) info">,
Values<"always,no-compact-unwind,default">,
NormalizedValues<["Always", "NoCompactUnwind", "Default"]>,
NormalizedValuesScope<"llvm::EmitDwarfUnwindType">,
MarshallingInfoEnum<CodeGenOpts<"EmitDwarfUnwind">, "Default">;
def g_Flag : Flag<["-"], "g">, Group<g_Group>,
HelpText<"Generate source-level debug information">;
def gline_tables_only : Flag<["-"], "gline-tables-only">, Group<gN_Group>,
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CodeGen/BackendUtil.cpp
Expand Up @@ -453,6 +453,7 @@ static bool initTargetOptions(DiagnosticsEngine &Diags,
}

Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile;
Options.MCOptions.EmitDwarfUnwind = CodeGenOpts.getEmitDwarfUnwind();
Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll;
Options.MCOptions.MCSaveTempLabels = CodeGenOpts.SaveTempLabels;
Options.MCOptions.MCUseDwarfDirectory =
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Expand Up @@ -2518,6 +2518,8 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
DefaultIncrementalLinkerCompatible))
CmdArgs.push_back("-mincremental-linker-compatible");

Args.AddLastArg(CmdArgs, options::OPT_femit_dwarf_unwind_EQ);

// If you add more args here, also add them to the block below that
// starts with "// If CollectArgsForIntegratedAssembler() isn't called below".

Expand Down Expand Up @@ -4622,6 +4624,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
Args.ClaimAllArgs(options::OPT_Wa_COMMA);
Args.ClaimAllArgs(options::OPT_Xassembler);
Args.ClaimAllArgs(options::OPT_femit_dwarf_unwind_EQ);
}

if (isa<AnalyzeJobAction>(JA)) {
Expand Down
14 changes: 14 additions & 0 deletions clang/test/Driver/femit-dwarf-unwind.c
@@ -0,0 +1,14 @@
// 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
// RUN: %clang -target x86_64-apple-macos11.0 -femit-dwarf-unwind=no-compact-unwind -c %s -o %t/x86_64-no-dwarf.o
// RUN: llvm-objdump --macho --dwarf=frames %t/x86_64.o | FileCheck %s --check-prefix=WITH-FDE
// RUN: llvm-objdump --macho --dwarf=frames %t/x86_64-no-dwarf.o | FileCheck %s --check-prefix=NO-FDE

// WITH-FDE: FDE
// NO-FDE-NOT: FDE

int foo() {
return 1;
}
17 changes: 17 additions & 0 deletions clang/test/Driver/femit-dwarf-unwind.s
@@ -0,0 +1,17 @@
// 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
// RUN: %clang -target x86_64-apple-macos11.0 -femit-dwarf-unwind=no-compact-unwind -c %s -o %t/x86_64-no-dwarf.o
// RUN: llvm-objdump --macho --dwarf=frames %t/x86_64.o | FileCheck %s --check-prefix=WITH-FDE
// RUN: llvm-objdump --macho --dwarf=frames %t/x86_64-no-dwarf.o | FileCheck %s --check-prefix=NO-FDE

// WITH-FDE: FDE
// NO-FDE-NOT: FDE

.text
_foo:
.cfi_startproc
.cfi_def_cfa_offset 8
ret
.cfi_endproc
13 changes: 13 additions & 0 deletions clang/tools/driver/cc1as_main.cpp
Expand Up @@ -137,6 +137,9 @@ struct AssemblerInvocation {
unsigned IncrementalLinkerCompatible : 1;
unsigned EmbedBitcode : 1;

/// Whether to emit DWARF unwind info.
EmitDwarfUnwindType EmitDwarfUnwind;

/// The name of the relocation model to use.
std::string RelocationModel;

Expand Down Expand Up @@ -317,6 +320,14 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
.Default(0);
}

if (auto *A = Args.getLastArg(OPT_femit_dwarf_unwind_EQ)) {
Opts.EmitDwarfUnwind =
llvm::StringSwitch<EmitDwarfUnwindType>(A->getValue())
.Case("always", EmitDwarfUnwindType::Always)
.Case("no-compact-unwind", EmitDwarfUnwindType::NoCompactUnwind)
.Case("default", EmitDwarfUnwindType::Default);
}

return Success;
}

Expand Down Expand Up @@ -367,6 +378,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
assert(MRI && "Unable to create target register info!");

MCTargetOptions MCOptions;
MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind;

std::unique_ptr<MCAsmInfo> MAI(
TheTarget->createMCAsmInfo(*MRI, Opts.Triple, MCOptions));
assert(MAI && "Unable to create target asm info!");
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/MC/MCContext.h
Expand Up @@ -67,6 +67,7 @@ template <typename T> class SmallVectorImpl;
class SMDiagnostic;
class SMLoc;
class SourceMgr;
enum class EmitDwarfUnwindType;

/// Context object for machine code objects. This class owns all of the
/// sections that it creates.
Expand Down Expand Up @@ -772,6 +773,7 @@ class MCContext {
bool getGenDwarfForAssembly() { return GenDwarfForAssembly; }
void setGenDwarfForAssembly(bool Value) { GenDwarfForAssembly = Value; }
unsigned getGenDwarfFileNumber() { return GenDwarfFileNumber; }
EmitDwarfUnwindType emitDwarfUnwindInfo() const;

void setGenDwarfFileNumber(unsigned FileNumber) {
GenDwarfFileNumber = FileNumber;
Expand Down
9 changes: 9 additions & 0 deletions llvm/include/llvm/MC/MCTargetOptions.h
Expand Up @@ -31,6 +31,12 @@ enum class DebugCompressionType {
Z, ///< zlib style complession
};

enum class EmitDwarfUnwindType {
Always, // Always emit dwarf unwind
NoCompactUnwind, // Only emit if compact unwind isn't available
Default, // Default behavior is based on the target
};

class StringRef;

class MCTargetOptions {
Expand All @@ -56,6 +62,9 @@ class MCTargetOptions {
bool PreserveAsmComments : 1;

bool Dwarf64 : 1;

EmitDwarfUnwindType EmitDwarfUnwind;

int DwarfVersion = 0;

enum DwarfDirectory {
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
Expand Up @@ -20,6 +20,7 @@
namespace llvm {

class MCTargetOptions;
enum class EmitDwarfUnwindType;

namespace mc {

Expand All @@ -32,6 +33,8 @@ int getDwarfVersion();

bool getDwarf64();

EmitDwarfUnwindType getEmitDwarfUnwind();

bool getShowMCInst();

bool getFatalWarnings();
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/CodeGen/LLVMTargetMachine.cpp
Expand Up @@ -264,6 +264,9 @@ bool LLVMTargetMachine::addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx,
"Cannot emit MC with limited codegen pipeline");

Ctx = &MMIWP->getMMI().getContext();
// libunwind is unable to load compact unwind dynamically, so we must generate
// DWARF unwind info for the JIT.
Options.MCOptions.EmitDwarfUnwind = EmitDwarfUnwindType::Always;
if (Options.MCOptions.MCSaveTempLabels)
Ctx->setAllowTemporaryLabels(false);

Expand Down
6 changes: 3 additions & 3 deletions llvm/lib/CodeGen/MachineModuleInfo.cpp
Expand Up @@ -60,7 +60,7 @@ MachineModuleInfo::MachineModuleInfo(MachineModuleInfo &&MMI)
: TM(std::move(MMI.TM)),
Context(MMI.TM.getTargetTriple(), MMI.TM.getMCAsmInfo(),
MMI.TM.getMCRegisterInfo(), MMI.TM.getMCSubtargetInfo(), nullptr,
nullptr, false),
&MMI.TM.Options.MCOptions, false),
MachineFunctions(std::move(MMI.MachineFunctions)) {
Context.setObjectFileInfo(MMI.TM.getObjFileLowering());
ObjFileMMI = MMI.ObjFileMMI;
Expand All @@ -72,7 +72,7 @@ MachineModuleInfo::MachineModuleInfo(MachineModuleInfo &&MMI)
MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM)
: TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(),
TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(),
nullptr, nullptr, false) {
nullptr, &TM->Options.MCOptions, false) {
Context.setObjectFileInfo(TM->getObjFileLowering());
initialize();
}
Expand All @@ -81,7 +81,7 @@ MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM,
MCContext *ExtContext)
: TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(),
TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(),
nullptr, nullptr, false),
nullptr, &TM->Options.MCOptions, false),
ExternalContext(ExtContext) {
Context.setObjectFileInfo(TM->getObjFileLowering());
initialize();
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp
Expand Up @@ -19,6 +19,7 @@
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCContext.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/DynamicLibrary.h"
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp
Expand Up @@ -12,6 +12,7 @@
#include "llvm/ExecutionEngine/ObjectCache.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCContext.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
Expand Down
6 changes: 2 additions & 4 deletions llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp
Expand Up @@ -95,18 +95,16 @@ void RTDyldMemoryManager::registerEHFramesInProcess(uint8_t *Addr,
// and projects/libunwind/src/UnwindLevel1-gcc-ext.c.
const char *P = (const char *)Addr;
const char *End = P + Size;
do {
while (P != End)
P = processFDE(P, false);
} while(P != End);
}

void RTDyldMemoryManager::deregisterEHFramesInProcess(uint8_t *Addr,
size_t Size) {
const char *P = (const char *)Addr;
const char *End = P + Size;
do {
while (P != End)
P = processFDE(P, true);
} while(P != End);
}

#else
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/MC/MCContext.cpp
Expand Up @@ -877,6 +877,12 @@ void MCContext::RemapDebugPaths() {
// Dwarf Management
//===----------------------------------------------------------------------===//

EmitDwarfUnwindType MCContext::emitDwarfUnwindInfo() const {
if (!TargetOptions)
return EmitDwarfUnwindType::Default;
return TargetOptions->EmitDwarfUnwind;
}

void MCContext::setGenDwarfRootFile(StringRef InputFileName, StringRef Buffer) {
// MCDwarf needs the root file as well as the compilation directory.
// If we find a '.file 0' directive that will supersede these values.
Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/MC/MCDwarf.cpp
Expand Up @@ -1842,8 +1842,6 @@ template <> struct DenseMapInfo<CIEKey> {

void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB,
bool IsEH) {
Streamer.generateCompactUnwindEncodings(MAB);

MCContext &Context = Streamer.getContext();
const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();
const MCAsmInfo *AsmInfo = Context.getAsmInfo();
Expand All @@ -1853,6 +1851,7 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB,
// Emit the compact unwind info if available.
bool NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame();
if (IsEH && MOFI->getCompactUnwindSection()) {
Streamer.generateCompactUnwindEncodings(MAB);
bool SectionEmitted = false;
for (const MCDwarfFrameInfo &Frame : FrameArray) {
if (Frame.CompactUnwindEncoding == 0) continue;
Expand Down
12 changes: 11 additions & 1 deletion llvm/lib/MC/MCObjectFileInfo.cpp
Expand Up @@ -64,8 +64,18 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
(T.getArch() == Triple::aarch64 || T.getArch() == Triple::aarch64_32))
SupportsCompactUnwindWithoutEHFrame = true;

if (T.isWatchABI())
switch (Ctx->emitDwarfUnwindInfo()) {
case EmitDwarfUnwindType::Always:
OmitDwarfIfHaveCompactUnwind = false;
break;
case EmitDwarfUnwindType::NoCompactUnwind:
OmitDwarfIfHaveCompactUnwind = true;
break;
case EmitDwarfUnwindType::Default:
OmitDwarfIfHaveCompactUnwind =
T.isWatchABI() || SupportsCompactUnwindWithoutEHFrame;
break;
}

FDECFIEncoding = dwarf::DW_EH_PE_pcrel;

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/MC/MCTargetOptions.cpp
Expand Up @@ -17,6 +17,7 @@ MCTargetOptions::MCTargetOptions()
MCSaveTempLabels(false), MCIncrementalLinkerCompatible(false),
ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false),
PreserveAsmComments(true), Dwarf64(false),
EmitDwarfUnwind(EmitDwarfUnwindType::Default),
MCUseDwarfDirectory(DefaultDwarfDirectory) {}

StringRef MCTargetOptions::getABIName() const {
Expand Down
19 changes: 17 additions & 2 deletions llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
@@ -1,5 +1,4 @@
//===-- MCTargetOptionsCommandFlags.cpp --------------------------*- C++
//-*-===//
//===-- MCTargetOptionsCommandFlags.cpp -----------------------*- C++ //-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
Expand Down Expand Up @@ -39,6 +38,7 @@ MCOPT_EXP(bool, RelaxAll)
MCOPT(bool, IncrementalLinkerCompatible)
MCOPT(int, DwarfVersion)
MCOPT(bool, Dwarf64)
MCOPT(EmitDwarfUnwindType, EmitDwarfUnwind)
MCOPT(bool, ShowMCInst)
MCOPT(bool, FatalWarnings)
MCOPT(bool, NoWarn)
Expand Down Expand Up @@ -73,6 +73,19 @@ llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() {
cl::desc("Generate debugging info in the 64-bit DWARF format"));
MCBINDOPT(Dwarf64);

static cl::opt<EmitDwarfUnwindType> EmitDwarfUnwind(
"emit-dwarf-unwind", cl::desc("Whether to emit DWARF EH frame entries."),
cl::init(EmitDwarfUnwindType::Default),
cl::values(clEnumValN(EmitDwarfUnwindType::Always, "always",
"Always emit EH frame entries"),
clEnumValN(EmitDwarfUnwindType::NoCompactUnwind,
"no-compact-unwind",
"Only emit EH frame entries when compact unwind is "
"not available"),
clEnumValN(EmitDwarfUnwindType::Default, "default",
"Use target platform default")));
MCBINDOPT(EmitDwarfUnwind);

static cl::opt<bool> ShowMCInst(
"asm-show-inst",
cl::desc("Emit internal instruction representation to assembly file"));
Expand Down Expand Up @@ -116,5 +129,7 @@ MCTargetOptions llvm::mc::InitMCTargetOptionsFromFlags() {
Options.MCNoWarn = getNoWarn();
Options.MCNoDeprecatedWarn = getNoDeprecatedWarn();
Options.MCNoTypeCheck = getNoTypeCheck();
Options.EmitDwarfUnwind = getEmitDwarfUnwind();

return Options;
}
4 changes: 2 additions & 2 deletions llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
Expand Up @@ -1377,7 +1377,7 @@ class DarwinX86AsmBackend : public X86AsmBackend {
default:
// Any other CFI directives indicate a frame that we aren't prepared
// to represent via compact unwind, so just bail out.
return 0;
return CU::UNWIND_MODE_DWARF;
case MCCFIInstruction::OpDefCfaRegister: {
// Defines a frame pointer. E.g.
//
Expand All @@ -1391,7 +1391,7 @@ class DarwinX86AsmBackend : public X86AsmBackend {
// generate a compact unwinding representation, so bail out.
if (*MRI.getLLVMRegNum(Inst.getRegister(), true) !=
(Is64Bit ? X86::RBP : X86::EBP))
return 0;
return CU::UNWIND_MODE_DWARF;

// Reset the counts.
memset(SavedRegs, 0, sizeof(SavedRegs));
Expand Down
33 changes: 33 additions & 0 deletions llvm/test/MC/MachO/AArch64/emit-dwarf-unwind.s
@@ -0,0 +1,33 @@
// RUN: rm -rf %t; mkdir %t
// RUN: llvm-mc -triple x86_64-apple-macos11.0 %s -filetype=obj -o %t/x86_64.o
// RUN: llvm-objdump --macho --dwarf=frames %t/x86_64.o | FileCheck %s --check-prefix TWO-FDES
// RUN: llvm-mc -triple arm64-apple-macos11.0 %s -filetype=obj -o %t/arm64.o
// RUN: llvm-objdump --macho --dwarf=frames %t/arm64.o | FileCheck %s --check-prefix ONE-FDE
// RUN: llvm-mc -triple x86_64-apple-macos11.0 %s -filetype=obj --emit-dwarf-unwind no-compact-unwind -o %t/x86_64-no-dwarf.o
// RUN: llvm-objdump --macho --dwarf=frames %t/x86_64-no-dwarf.o | FileCheck %s --check-prefix ONE-FDE
// RUN: llvm-mc -triple arm64-apple-macos11.0 %s -filetype=obj --emit-dwarf-unwind always -o %t/arm64-dwarf.o
// RUN: llvm-objdump --macho --dwarf=frames %t/arm64-dwarf.o | FileCheck %s --check-prefix TWO-FDES

// TWO-FDES: FDE
// TWO-FDES: FDE

// ONE-FDE-NOT: FDE
// ONE-FDE: FDE
// ONE-FDE-NOT: FDE

_main:
.cfi_startproc
.cfi_def_cfa_offset 16
ret
.cfi_endproc

_foo:
.cfi_startproc
.cfi_def_cfa_offset 16
/// This encodes DW_CFA_GNU_args_size which cannot be expressed using compact
/// unwind, so we must use DWARf unwind for this function.
.cfi_escape 0x2e, 0x10
ret
.cfi_endproc

.subsections_via_symbols

0 comments on commit d4bcb45

Please sign in to comment.