Skip to content
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

[MC] Support .cfi_label #97922

Merged
merged 3 commits into from
Jul 7, 2024
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: 3 additions & 0 deletions bolt/lib/Core/BinaryFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2538,6 +2538,7 @@ struct CFISnapshot {
case MCCFIInstruction::OpWindowSave:
case MCCFIInstruction::OpNegateRAState:
case MCCFIInstruction::OpLLVMDefAspaceCfa:
case MCCFIInstruction::OpLabel:
llvm_unreachable("unsupported CFI opcode");
break;
case MCCFIInstruction::OpRememberState:
Expand Down Expand Up @@ -2675,6 +2676,7 @@ struct CFISnapshotDiff : public CFISnapshot {
case MCCFIInstruction::OpWindowSave:
case MCCFIInstruction::OpNegateRAState:
case MCCFIInstruction::OpLLVMDefAspaceCfa:
case MCCFIInstruction::OpLabel:
llvm_unreachable("unsupported CFI opcode");
return false;
case MCCFIInstruction::OpRememberState:
Expand Down Expand Up @@ -2823,6 +2825,7 @@ BinaryFunction::unwindCFIState(int32_t FromState, int32_t ToState,
case MCCFIInstruction::OpWindowSave:
case MCCFIInstruction::OpNegateRAState:
case MCCFIInstruction::OpLLVMDefAspaceCfa:
case MCCFIInstruction::OpLabel:
llvm_unreachable("unsupported CFI opcode");
break;
case MCCFIInstruction::OpGnuArgsSize:
Expand Down
20 changes: 19 additions & 1 deletion llvm/include/llvm/MC/MCDwarf.h
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,8 @@ class MCCFIInstruction {
OpRegister,
OpWindowSave,
OpNegateRAState,
OpGnuArgsSize
OpGnuArgsSize,
OpLabel,
};

private:
Expand All @@ -519,6 +520,7 @@ class MCCFIInstruction {
unsigned Register;
unsigned Register2;
} RR;
MCSymbol *CfiLabel;
} U;
OpType Operation;
SMLoc Loc;
Expand All @@ -544,6 +546,12 @@ class MCCFIInstruction {
U.RIA = {R, O, AS};
}

MCCFIInstruction(OpType Op, MCSymbol *L, MCSymbol *CfiLabel, SMLoc Loc)
: Label(L), Operation(Op), Loc(Loc) {
assert(Op == OpLabel);
U.CfiLabel = CfiLabel;
}

public:
/// .cfi_def_cfa defines a rule for computing CFA as: take address from
/// Register and add Offset to it.
Expand Down Expand Up @@ -664,6 +672,11 @@ class MCCFIInstruction {
return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, Loc);
}

static MCCFIInstruction createLabel(MCSymbol *L, MCSymbol *CfiLabel,
SMLoc Loc) {
return MCCFIInstruction(OpLabel, L, CfiLabel, Loc);
}

OpType getOperation() const { return Operation; }
MCSymbol *getLabel() const { return Label; }

Expand Down Expand Up @@ -698,6 +711,11 @@ class MCCFIInstruction {
return U.RI.Offset;
}

MCSymbol *getCfiLabel() const {
assert(Operation == OpLabel);
return U.CfiLabel;
}

StringRef getValues() const {
assert(Operation == OpEscape);
return StringRef(&Values[0], Values.size());
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/MC/MCStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -1019,6 +1019,7 @@ class MCStreamer {
SMLoc Loc = {});
virtual void emitCFIWindowSave(SMLoc Loc = {});
virtual void emitCFINegateRAState(SMLoc Loc = {});
virtual void emitCFILabelDirective(SMLoc Loc, StringRef Name);

virtual void emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc = SMLoc());
virtual void emitWinCFIEndProc(SMLoc Loc = SMLoc());
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/CodeGen/CFIInstrInserter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
case MCCFIInstruction::OpWindowSave:
case MCCFIInstruction::OpNegateRAState:
case MCCFIInstruction::OpGnuArgsSize:
case MCCFIInstruction::OpLabel:
break;
}
if (CSRReg || CSROffset) {
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/MC/MCAsmStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ class MCAsmStreamer final : public MCStreamer {
void emitCFIWindowSave(SMLoc Loc) override;
void emitCFINegateRAState(SMLoc Loc) override;
void emitCFIReturnColumn(int64_t Register) override;
void emitCFILabelDirective(SMLoc Loc, StringRef Name) override;

void emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override;
void emitWinCFIEndProc(SMLoc Loc) override;
Expand Down Expand Up @@ -2126,6 +2127,12 @@ void MCAsmStreamer::emitCFIReturnColumn(int64_t Register) {
EmitEOL();
}

void MCAsmStreamer::emitCFILabelDirective(SMLoc Loc, StringRef Name) {
MCStreamer::emitCFILabelDirective(Loc, Name);
OS << "\t.cfi_label " << Name;
EmitEOL();
}

void MCAsmStreamer::emitCFIBKeyFrame() {
MCStreamer::emitCFIBKeyFrame();
OS << "\t.cfi_b_key_frame";
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/MC/MCDwarf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1465,6 +1465,9 @@ void FrameEmitterImpl::emitCFIInstruction(const MCCFIInstruction &Instr) {
case MCCFIInstruction::OpEscape:
Streamer.emitBytes(Instr.getValues());
return;
case MCCFIInstruction::OpLabel:
Streamer.emitLabel(Instr.getCfiLabel(), Instr.getLoc());
return;
}
llvm_unreachable("Unhandled case in switch");
}
Expand Down
18 changes: 18 additions & 0 deletions llvm/lib/MC/MCParser/AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,7 @@ class AsmParser : public MCAsmParser {
DK_CFI_UNDEFINED,
DK_CFI_REGISTER,
DK_CFI_WINDOW_SAVE,
DK_CFI_LABEL,
DK_CFI_B_KEY_FRAME,
DK_MACROS_ON,
DK_MACROS_OFF,
Expand Down Expand Up @@ -622,6 +623,7 @@ class AsmParser : public MCAsmParser {
bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);
bool parseDirectiveCFISignalFrame(SMLoc DirectiveLoc);
bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
bool parseDirectiveCFILabel(SMLoc DirectiveLoc);

// macro directives
bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
Expand Down Expand Up @@ -2224,6 +2226,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
return parseDirectiveCFIRegister(IDLoc);
case DK_CFI_WINDOW_SAVE:
return parseDirectiveCFIWindowSave(IDLoc);
case DK_CFI_LABEL:
return parseDirectiveCFILabel(IDLoc);
case DK_MACROS_ON:
case DK_MACROS_OFF:
return parseDirectiveMacrosOnOff(IDVal);
Expand Down Expand Up @@ -4488,6 +4492,19 @@ bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
return false;
}

/// parseDirectiveCFILabel
/// ::= .cfi_label label
bool AsmParser::parseDirectiveCFILabel(SMLoc Loc) {
StringRef Name;
Loc = Lexer.getLoc();
if (parseIdentifier(Name))
return TokError("expected identifier");
if (parseEOL())
return true;
getStreamer().emitCFILabelDirective(Loc, Name);
return false;
}

/// parseDirectiveAltmacro
/// ::= .altmacro
/// ::= .noaltmacro
Expand Down Expand Up @@ -5560,6 +5577,7 @@ void AsmParser::initializeDirectiveKindMap() {
DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
DirectiveKindMap[".cfi_label"] = DK_CFI_LABEL;
DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
DirectiveKindMap[".cfi_mte_tagged_frame"] = DK_CFI_MTE_TAGGED_FRAME;
DirectiveKindMap[".macros_on"] = DK_MACROS_ON;
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/MC/MCStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,13 @@ void MCStreamer::emitCFIReturnColumn(int64_t Register) {
CurFrame->RAReg = Register;
}

void MCStreamer::emitCFILabelDirective(SMLoc Loc, StringRef Name) {
MCSymbol *Label = emitCFILabel();
MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
if (MCDwarfFrameInfo *F = getCurrentDwarfFrameInfo())
F->Instructions.push_back(MCCFIInstruction::createLabel(Label, Sym, Loc));
}

WinEH::FrameInfo *MCStreamer::EnsureValidWinFrameInfo(SMLoc Loc) {
const MCAsmInfo *MAI = Context.getAsmInfo();
if (!MAI->usesWindowsCFI()) {
Expand Down
61 changes: 61 additions & 0 deletions llvm/test/MC/ELF/cfi-label.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# RUN: llvm-mc -triple x86_64 %s | FileCheck %s --check-prefix=ASM
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t
# RUN: llvm-readelf -sX %t | FileCheck %s --check-prefix=SYMTAB
# RUN: llvm-dwarfdump --eh-frame %t | FileCheck %s

# RUN: not llvm-mc -filetype=obj -triple=x86_64 --defsym ERR=1 %s -o /dev/null 2>&1 | \
# RUN: FileCheck %s --check-prefix=ERR --implicit-check-not=error:

# ASM: nop
# ASM-NEXT: .cfi_label cfi1
# ASM-NEXT: .cfi_escape 0x00
# ASM: .globl cfi2
# ASM-NEXT: .cfi_label cfi2
# ASM: nop
# ASM-NEXT: .cfi_label .Lcfi3

# SYMTAB: 000000000000002b 0 NOTYPE LOCAL DEFAULT 3 (.eh_frame) cfi1
# SYMTAB: 000000000000002d 0 NOTYPE GLOBAL DEFAULT 3 (.eh_frame) cfi2
# SYMTAB-NOT: {{.}}

# CHECK: DW_CFA_remember_state:
# CHECK-NEXT: DW_CFA_advance_loc: 1 to 0x1
# CHECK-NEXT: DW_CFA_nop:
# CHECK-NEXT: DW_CFA_advance_loc: 1 to 0x2
# CHECK-NEXT: DW_CFA_nop:
# CHECK-NEXT: DW_CFA_nop:
# CHECK-NEXT: DW_CFA_advance_loc: 1 to 0x3
# CHECK-NEXT: DW_CFA_nop:
# CHECK-NEXT: DW_CFA_nop:
# CHECK-NEXT: DW_CFA_nop:
# CHECK-NEXT: DW_CFA_restore_state:

.globl foo
foo:
.cfi_startproc
.cfi_remember_state
nop
.cfi_label cfi1
.cfi_escape 0
nop
.globl cfi2
.cfi_label cfi2
.cfi_escape 0, 0
nop
.cfi_label .Lcfi3
.cfi_escape 0, 0, 0
.cfi_restore_state
ret

# ERR: [[#@LINE+10]]:1: error: this directive must appear between .cfi_startproc and .cfi_endproc directives
.ifdef ERR
# ERR: [[#@LINE+1]]:12: error: symbol 'foo' is already defined
.cfi_label foo
# ERR: [[#@LINE+1]]:12: error: symbol '.Lcfi3' is already defined
.cfi_label .Lcfi3
.endif
.cfi_endproc

.ifdef ERR
.cfi_label after_endproc
.endif
Loading