forked from OSchip/llvm-project
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! llvm-svn: 309360
This commit is contained in:
parent
b3c70c09e3
commit
a219b3d8d1
|
@ -509,6 +509,7 @@ struct MCDwarfFrameInfo {
|
|||
uint32_t CompactUnwindEncoding = 0;
|
||||
bool IsSignalFrame = false;
|
||||
bool IsSimple = false;
|
||||
unsigned RAReg = static_cast<unsigned>(INT_MAX);
|
||||
};
|
||||
|
||||
class MCDwarfFrameEmitter {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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<MCCFIInstruction> 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<unsigned>(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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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..|..
|
||||
|
Loading…
Reference in New Issue