Skip to content

Support SFrame command-line and .cfi_section syntax #149935

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion llvm/include/llvm/MC/MCObjectStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class MCObjectStreamer : public MCStreamer {
std::unique_ptr<MCAssembler> Assembler;
bool EmitEHFrame;
bool EmitDebugFrame;
bool EmitSFrame;

struct PendingAssignment {
MCSymbol *Symbol;
Expand Down Expand Up @@ -70,7 +71,7 @@ class MCObjectStreamer : public MCStreamer {

void emitFrames(MCAsmBackend *MAB);
MCSymbol *emitCFILabel() override;
void emitCFISections(bool EH, bool Debug) override;
void emitCFISections(bool EH, bool Debug, bool SFrame) override;

public:
void visitUsedSymbol(const MCSymbol &Sym) override;
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/MC/MCStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -986,7 +986,7 @@ class LLVM_ABI MCStreamer {
const MCSymbol *Lo);

virtual MCSymbol *getDwarfLineTableSymbol(unsigned CUID);
virtual void emitCFISections(bool EH, bool Debug);
virtual void emitCFISections(bool EH, bool Debug, bool SFrame);
void emitCFIStartProc(bool IsSimple, SMLoc Loc = SMLoc());
void emitCFIEndProc();
virtual void emitCFIDefCfa(int64_t Register, int64_t Offset, SMLoc Loc = {});
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/MC/MCTargetOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ class MCTargetOptions {
// functions on Darwins.
bool EmitCompactUnwindNonCanonical : 1;

// Whether to emit SFrame unwind sections.
bool EmitSFrameUnwind : 1;

// Whether or not to use full register names on PowerPC.
bool PPCUseFullRegisterNames : 1;

Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ LLVM_ABI EmitDwarfUnwindType getEmitDwarfUnwind();

LLVM_ABI bool getEmitCompactUnwindNonCanonical();

LLVM_ABI bool getEmitSFrameUnwind();

LLVM_ABI bool getShowMCInst();

LLVM_ABI bool getFatalWarnings();
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/AsmPrinter/ARMException.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void ARMException::beginFunction(const MachineFunction *MF) {
if (CFISecType == AsmPrinter::CFISection::Debug) {
if (!hasEmittedCFISections) {
if (Asm->getModuleCFISectionType() == AsmPrinter::CFISection::Debug)
Asm->OutStreamer->emitCFISections(false, true);
Asm->OutStreamer->emitCFISections(false, true, false);
hasEmittedCFISections = true;
}

Expand Down
6 changes: 4 additions & 2 deletions llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,11 @@ void DwarfCFIException::beginBasicBlockSection(const MachineBasicBlock &MBB) {
// chose not to be verbose in that case. And with `ForceDwarfFrameSection`,
// we should always emit .debug_frame.
if (CFISecType == AsmPrinter::CFISection::Debug ||
Asm->TM.Options.ForceDwarfFrameSection)
Asm->TM.Options.ForceDwarfFrameSection ||
Asm->TM.Options.MCOptions.EmitSFrameUnwind)
Asm->OutStreamer->emitCFISections(
CFISecType == AsmPrinter::CFISection::EH, true);
CFISecType == AsmPrinter::CFISection::EH, true,
Asm->TM.Options.MCOptions.EmitSFrameUnwind);
hasEmittedCFISections = true;
}

Expand Down
21 changes: 15 additions & 6 deletions llvm/lib/MC/MCAsmStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ class MCAsmStreamer final : public MCStreamer {
void emitIdent(StringRef IdentString) override;
void emitCFIBKeyFrame() override;
void emitCFIMTETaggedFrame() override;
void emitCFISections(bool EH, bool Debug) override;
void emitCFISections(bool EH, bool Debug, bool SFrame) override;
void emitCFIDefCfa(int64_t Register, int64_t Offset, SMLoc Loc) override;
void emitCFIDefCfaOffset(int64_t Offset, SMLoc Loc) override;
void emitCFIDefCfaRegister(int64_t Register, SMLoc Loc) override;
Expand Down Expand Up @@ -1906,15 +1906,24 @@ void MCAsmStreamer::emitIdent(StringRef IdentString) {
EmitEOL();
}

void MCAsmStreamer::emitCFISections(bool EH, bool Debug) {
MCStreamer::emitCFISections(EH, Debug);
void MCAsmStreamer::emitCFISections(bool EH, bool Debug, bool SFrame) {
MCStreamer::emitCFISections(EH, Debug, SFrame);
OS << "\t.cfi_sections ";
bool C = false;
if (EH) {
OS << ".eh_frame";
if (Debug)
OS << ", .debug_frame";
} else if (Debug) {
C = true;
}
if (Debug) {
if (C)
OS << ", ";
OS << ".debug_frame";
C = true;
}
if (SFrame) {
if (C)
OS << ", ";
OS << ".sframe";
}

EmitEOL();
Expand Down
5 changes: 3 additions & 2 deletions llvm/lib/MC/MCObjectStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,11 @@ void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) {
Assembler->registerSymbol(Sym);
}

void MCObjectStreamer::emitCFISections(bool EH, bool Debug) {
MCStreamer::emitCFISections(EH, Debug);
void MCObjectStreamer::emitCFISections(bool EH, bool Debug, bool SFrame) {
MCStreamer::emitCFISections(EH, Debug, SFrame);
EmitEHFrame = EH;
EmitDebugFrame = Debug;
EmitSFrame = SFrame;
}

void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
Expand Down
9 changes: 6 additions & 3 deletions llvm/lib/MC/MCParser/AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4093,27 +4093,30 @@ bool AsmParser::parseDirectiveCVFPOData() {
}

/// parseDirectiveCFISections
/// ::= .cfi_sections section [, section]
/// ::= .cfi_sections section [, section][, section]
bool AsmParser::parseDirectiveCFISections() {
StringRef Name;
bool EH = false;
bool Debug = false;
bool SFrame = false;

if (!parseOptionalToken(AsmToken::EndOfStatement)) {
for (;;) {
if (parseIdentifier(Name))
return TokError("expected .eh_frame or .debug_frame");
return TokError("expected .eh_frame, .debug_frame, or .sframe");
if (Name == ".eh_frame")
EH = true;
else if (Name == ".debug_frame")
Debug = true;
else if (Name == ".sframe")
SFrame = true;
if (parseOptionalToken(AsmToken::EndOfStatement))
break;
if (parseComma())
return true;
}
}
getStreamer().emitCFISections(EH, Debug);
getStreamer().emitCFISections(EH, Debug, SFrame);
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/MC/MCStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ void MCStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
void MCStreamer::emitConditionalAssignment(MCSymbol *Symbol,
const MCExpr *Value) {}

void MCStreamer::emitCFISections(bool EH, bool Debug) {}
void MCStreamer::emitCFISections(bool EH, bool Debug, bool SFrame) {}

void MCStreamer::emitCFIStartProc(bool IsSimple, SMLoc Loc) {
if (!FrameInfoStack.empty() &&
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ MCOPT(int, DwarfVersion)
MCOPT(bool, Dwarf64)
MCOPT(EmitDwarfUnwindType, EmitDwarfUnwind)
MCOPT(bool, EmitCompactUnwindNonCanonical)
MCOPT(bool, EmitSFrameUnwind)
MCOPT(bool, ShowMCInst)
MCOPT(bool, FatalWarnings)
MCOPT(bool, NoWarn)
Expand Down Expand Up @@ -105,6 +106,11 @@ llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() {
false)); // By default, use DWARF for non-canonical personalities.
MCBINDOPT(EmitCompactUnwindNonCanonical);

static cl::opt<bool> EmitSFrameUnwind(
"gsframe", cl::desc("Whether to emit .sframe unwind sections."),
cl::init(false));
MCBINDOPT(EmitSFrameUnwind);

static cl::opt<bool> ShowMCInst(
"asm-show-inst",
cl::desc("Emit internal instruction representation to assembly file"));
Expand Down Expand Up @@ -188,6 +194,7 @@ MCTargetOptions llvm::mc::InitMCTargetOptionsFromFlags() {
Options.X86Sse2Avx = getX86Sse2Avx();
Options.EmitDwarfUnwind = getEmitDwarfUnwind();
Options.EmitCompactUnwindNonCanonical = getEmitCompactUnwindNonCanonical();
Options.EmitSFrameUnwind = getEmitSFrameUnwind();
Options.AsSecureLogFile = getAsSecureLogFile();

return Options;
Expand Down
4 changes: 3 additions & 1 deletion llvm/test/MC/ELF/AArch64/cfi.s
Original file line number Diff line number Diff line change
Expand Up @@ -557,12 +557,14 @@ f37:
// CHECK-NEXT: }

.ifdef ERR
// ERR: [[#@LINE+1]]:15: error: expected .eh_frame or .debug_frame
// ERR: [[#@LINE+1]]:15: error: expected .eh_frame, .debug_frame, or .sframe
.cfi_sections $
// ERR: [[#@LINE+1]]:28: error: expected comma
.cfi_sections .debug_frame $
// ERR: [[#@LINE+1]]:39: error: expected comma
.cfi_sections .debug_frame, .eh_frame $
// ERR: [[#@LINE+1]]:48: error: expected comma
.cfi_sections .debug_frame, .eh_frame, .sframe $

// ERR: [[#@LINE+1]]:16: error: unexpected token
.cfi_startproc $
Expand Down
4 changes: 3 additions & 1 deletion llvm/test/MC/ELF/cfi.s
Original file line number Diff line number Diff line change
Expand Up @@ -445,12 +445,14 @@ f37:
// CHECK: }

.ifdef ERR
// ERR: [[#@LINE+1]]:15: error: expected .eh_frame or .debug_frame
// ERR: [[#@LINE+1]]:15: error: expected .eh_frame, .debug_frame, or .sframe
.cfi_sections $
// ERR: [[#@LINE+1]]:28: error: expected comma
.cfi_sections .debug_frame $
// ERR: [[#@LINE+1]]:39: error: expected comma
.cfi_sections .debug_frame, .eh_frame $
// ERR: [[#@LINE+1]]:48: error: expected comma
.cfi_sections .debug_frame, .eh_frame, .sframe $

// ERR: [[#@LINE+1]]:16: error: unexpected token
.cfi_startproc $
Expand Down
Loading