From: Saleem Abdulrasool Date: Fri, 28 Jul 2017 03:39:19 +0000 (+0000) Subject: MC: add support for cfi_return_column X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=86b02f9e7604d659d5004c09c6df066f38f788ff;p=llvm MC: add support for cfi_return_column This adds support for the CFI pseudo-op return_column. This specifies the frame table column which contains the return address. Addresses PR33953! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@309360 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 79f1b952501..88ffa04128e 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -509,6 +509,7 @@ struct MCDwarfFrameInfo { uint32_t CompactUnwindEncoding = 0; bool IsSignalFrame = false; bool IsSimple = false; + unsigned RAReg = static_cast(INT_MAX); }; class MCDwarfFrameEmitter { diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index e1f9446f067..91f234217b1 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -797,6 +797,7 @@ public: virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset); virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment); virtual void EmitCFIEscape(StringRef Values); + virtual void EmitCFIReturnColumn(int64_t Register); virtual void EmitCFIGnuArgsSize(int64_t Size); virtual void EmitCFISignalFrame(); virtual void EmitCFIUndefined(int64_t Register); diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 9e5553fa8d4..7cc0bcdaaf0 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -265,6 +265,7 @@ public: void EmitCFIUndefined(int64_t Register) override; void EmitCFIRegister(int64_t Register1, int64_t Register2) override; void EmitCFIWindowSave() override; + void EmitCFIReturnColumn(int64_t Register) override; void EmitWinCFIStartProc(const MCSymbol *Symbol) override; void EmitWinCFIEndProc() override; @@ -1398,6 +1399,12 @@ void MCAsmStreamer::EmitCFIWindowSave() { EmitEOL(); } +void MCAsmStreamer::EmitCFIReturnColumn(int64_t Register) { + MCStreamer::EmitCFIReturnColumn(Register); + OS << "\t.cfi_return_column " << Register; + EmitEOL(); +} + void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) { MCStreamer::EmitWinCFIStartProc(Symbol); diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index a2beee32f2c..a038e0aa951 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -1037,7 +1037,7 @@ public: const MCSymbol &EmitCIE(const MCSymbol *personality, unsigned personalityEncoding, const MCSymbol *lsda, bool IsSignalFrame, unsigned lsdaEncoding, - bool IsSimple); + bool IsSimple, unsigned RAReg); void EmitFDE(const MCSymbol &cieStart, const MCDwarfFrameInfo &frame, bool LastInSection, const MCSymbol &SectionStart); void EmitCFIInstructions(ArrayRef Instrs, @@ -1277,8 +1277,8 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCSymbol *personality, unsigned personalityEncoding, const MCSymbol *lsda, bool IsSignalFrame, - unsigned lsdaEncoding, - bool IsSimple) { + unsigned lsdaEncoding, bool IsSimple, + unsigned RAReg) { MCContext &context = Streamer.getContext(); const MCRegisterInfo *MRI = context.getRegisterInfo(); const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); @@ -1331,13 +1331,15 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCSymbol *personality, Streamer.EmitSLEB128IntValue(getDataAlignmentFactor(Streamer)); // Return Address Register + if (RAReg == static_cast(INT_MAX)) + RAReg = MRI->getDwarfRegNum(MRI->getRARegister(), IsEH); + if (CIEVersion == 1) { - assert(MRI->getRARegister() <= 255 && + assert(RAReg <= 255 && "DWARF 2 encodes return_address_register in one byte"); - Streamer.EmitIntValue(MRI->getDwarfRegNum(MRI->getRARegister(), IsEH), 1); + Streamer.EmitIntValue(RAReg, 1); } else { - Streamer.EmitULEB128IntValue( - MRI->getDwarfRegNum(MRI->getRARegister(), IsEH)); + Streamer.EmitULEB128IntValue(RAReg); } // Augmentation Data Length (optional) @@ -1563,9 +1565,9 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB, Frame.LsdaEncoding, Frame.IsSignalFrame, Frame.IsSimple); const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey; if (!CIEStart) - CIEStart = &Emitter.EmitCIE(Frame.Personality, Frame.PersonalityEncoding, - Frame.Lsda, Frame.IsSignalFrame, - Frame.LsdaEncoding, Frame.IsSimple); + CIEStart = &Emitter.EmitCIE( + Frame.Personality, Frame.PersonalityEncoding, Frame.Lsda, + Frame.IsSignalFrame, Frame.LsdaEncoding, Frame.IsSimple, Frame.RAReg); Emitter.EmitFDE(*CIEStart, Frame, I == E, *SectionStart); } diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index e6013c7e5ae..2756cb71ed9 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -517,6 +517,7 @@ private: DK_CFI_SAME_VALUE, DK_CFI_RESTORE, DK_CFI_ESCAPE, + DK_CFI_RETURN_COLUMN, DK_CFI_SIGNAL_FRAME, DK_CFI_UNDEFINED, DK_CFI_REGISTER, @@ -594,6 +595,7 @@ private: bool parseDirectiveCFISameValue(SMLoc DirectiveLoc); bool parseDirectiveCFIRestore(SMLoc DirectiveLoc); bool parseDirectiveCFIEscape(); + bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc); bool parseDirectiveCFISignalFrame(); bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc); @@ -2065,6 +2067,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, return parseDirectiveCFIRestore(IDLoc); case DK_CFI_ESCAPE: return parseDirectiveCFIEscape(); + case DK_CFI_RETURN_COLUMN: + return parseDirectiveCFIReturnColumn(IDLoc); case DK_CFI_SIGNAL_FRAME: return parseDirectiveCFISignalFrame(); case DK_CFI_UNDEFINED: @@ -4019,6 +4023,16 @@ bool AsmParser::parseDirectiveCFIEscape() { return false; } +/// parseDirectiveCFIReturnColumn +/// ::= .cfi_return_column register +bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) { + int64_t Register = 0; + if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) + return true; + getStreamer().EmitCFIReturnColumn(Register); + return false; +} + /// parseDirectiveCFISignalFrame /// ::= .cfi_signal_frame bool AsmParser::parseDirectiveCFISignalFrame() { @@ -5138,6 +5152,7 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE; DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE; DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE; + DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN; DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME; DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED; DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER; diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 2bfb9a63eed..e35907f77e1 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -508,6 +508,12 @@ void MCStreamer::EmitCFIWindowSave() { CurFrame->Instructions.push_back(Instruction); } +void MCStreamer::EmitCFIReturnColumn(int64_t Register) { + EnsureValidDwarfFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); + CurFrame->RAReg = Register; +} + void MCStreamer::EnsureValidWinFrameInfo() { const MCAsmInfo *MAI = Context.getAsmInfo(); if (!MAI->usesWindowsCFI()) diff --git a/test/Assembler/return-column.s b/test/Assembler/return-column.s new file mode 100644 index 00000000000..d3b462358fb --- /dev/null +++ b/test/Assembler/return-column.s @@ -0,0 +1,17 @@ +// RUN: llvm-mc -triple i686-unknown-linux-gnu -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-ASM-ROUNDTRIP +// RUN: llvm-mc -triple i686-unknown-linux-gnu -filetype obj -o - %s | llvm-objdump -s -j .eh_frame - | FileCheck %s -check-prefix CHECK-EH_FRAME + + .text + +proc: + .cfi_startproc + .cfi_return_column 0 + .cfi_endproc + +// CHECK-ASM-ROUNDTRIP: .cfi_startproc +// CHECK-ASM-ROUNDTRIP-NEXT: .cfi_return_column 0 +// CHECK-ASM-ROUNDTRIP: .cfi_endproc + +// CHECK-EH_FRAME: Contents of section .eh_frame: +// CHECK-EH_FRAME: 0000 14000000 00000000 017a5200 017c0001 .........zR..|.. +