Add support for .cfi_signal_frame. Fixes pr11762.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@148733 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola 2012-01-23 21:51:52 +00:00
parent e55bbfe145
commit 16d7d437e0
7 changed files with 75 additions and 8 deletions

View File

@ -312,7 +312,8 @@ namespace llvm {
struct MCDwarfFrameInfo {
MCDwarfFrameInfo() : Begin(0), End(0), Personality(0), Lsda(0),
Function(0), Instructions(), PersonalityEncoding(),
LsdaEncoding(0), CompactUnwindEncoding(0) {}
LsdaEncoding(0), CompactUnwindEncoding(0),
IsSignalFrame(false) {}
MCSymbol *Begin;
MCSymbol *End;
const MCSymbol *Personality;
@ -322,6 +323,7 @@ namespace llvm {
unsigned PersonalityEncoding;
unsigned LsdaEncoding;
uint32_t CompactUnwindEncoding;
bool IsSignalFrame;
};
class MCDwarfFrameEmitter {

View File

@ -555,6 +555,7 @@ namespace llvm {
virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset);
virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment);
virtual void EmitCFIEscape(StringRef Values);
virtual void EmitCFISignalFrame();
virtual void EmitWin64EHStartProc(const MCSymbol *Symbol);
virtual void EmitWin64EHEndProc();

View File

@ -222,6 +222,7 @@ public:
virtual void EmitCFISameValue(int64_t Register);
virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset);
virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment);
virtual void EmitCFISignalFrame();
virtual void EmitWin64EHStartProc(const MCSymbol *Symbol);
virtual void EmitWin64EHEndProc();
@ -993,6 +994,16 @@ void MCAsmStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) {
EmitEOL();
}
void MCAsmStreamer::EmitCFISignalFrame() {
MCStreamer::EmitCFISignalFrame();
if (!UseCFI)
return;
OS << "\t.cif_signal_frame";
EmitEOL();
}
void MCAsmStreamer::EmitWin64EHStartProc(const MCSymbol *Symbol) {
MCStreamer::EmitWin64EHStartProc(Symbol);

View File

@ -840,6 +840,7 @@ namespace {
const MCSymbol *personality,
unsigned personalityEncoding,
const MCSymbol *lsda,
bool IsSignalFrame,
unsigned lsdaEncoding);
MCSymbol *EmitFDE(MCStreamer &streamer,
const MCSymbol &cieStart,
@ -1111,6 +1112,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer,
const MCSymbol *personality,
unsigned personalityEncoding,
const MCSymbol *lsda,
bool IsSignalFrame,
unsigned lsdaEncoding) {
MCContext &context = streamer.getContext();
const MCRegisterInfo &MRI = context.getRegisterInfo();
@ -1153,6 +1155,8 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer,
if (lsda)
Augmentation += "L";
Augmentation += "R";
if (IsSignalFrame)
Augmentation += "S";
streamer.EmitBytes(Augmentation.str(), 0);
}
streamer.EmitIntValue(0, 1);
@ -1312,17 +1316,18 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer,
namespace {
struct CIEKey {
static const CIEKey getEmptyKey() { return CIEKey(0, 0, -1); }
static const CIEKey getTombstoneKey() { return CIEKey(0, -1, 0); }
static const CIEKey getEmptyKey() { return CIEKey(0, 0, -1, false); }
static const CIEKey getTombstoneKey() { return CIEKey(0, -1, 0, false); }
CIEKey(const MCSymbol* Personality_, unsigned PersonalityEncoding_,
unsigned LsdaEncoding_) : Personality(Personality_),
PersonalityEncoding(PersonalityEncoding_),
LsdaEncoding(LsdaEncoding_) {
unsigned LsdaEncoding_, bool IsSignalFrame_) :
Personality(Personality_), PersonalityEncoding(PersonalityEncoding_),
LsdaEncoding(LsdaEncoding_), IsSignalFrame(IsSignalFrame_) {
}
const MCSymbol* Personality;
unsigned PersonalityEncoding;
unsigned LsdaEncoding;
bool IsSignalFrame;
};
}
@ -1340,13 +1345,15 @@ namespace llvm {
ID.AddPointer(Key.Personality);
ID.AddInteger(Key.PersonalityEncoding);
ID.AddInteger(Key.LsdaEncoding);
ID.AddBoolean(Key.IsSignalFrame);
return ID.ComputeHash();
}
static bool isEqual(const CIEKey &LHS,
const CIEKey &RHS) {
return LHS.Personality == RHS.Personality &&
LHS.PersonalityEncoding == RHS.PersonalityEncoding &&
LHS.LsdaEncoding == RHS.LsdaEncoding;
LHS.LsdaEncoding == RHS.LsdaEncoding &&
LHS.IsSignalFrame == RHS.IsSignalFrame;
}
};
}
@ -1382,11 +1389,12 @@ void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer,
for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) {
const MCDwarfFrameInfo &Frame = FrameArray[i];
CIEKey Key(Frame.Personality, Frame.PersonalityEncoding,
Frame.LsdaEncoding);
Frame.LsdaEncoding, Frame.IsSignalFrame);
const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey;
if (!CIEStart)
CIEStart = &Emitter.EmitCIE(Streamer, Frame.Personality,
Frame.PersonalityEncoding, Frame.Lsda,
Frame.IsSignalFrame,
Frame.LsdaEncoding);
FDEEnd = Emitter.EmitFDE(Streamer, *CIEStart, Frame);

View File

@ -306,6 +306,8 @@ public:
&GenericAsmParser::ParseDirectiveCFIRestore>(".cfi_restore");
AddDirectiveHandler<
&GenericAsmParser::ParseDirectiveCFIEscape>(".cfi_escape");
AddDirectiveHandler<
&GenericAsmParser::ParseDirectiveCFISignalFrame>(".cfi_signal_frame");
// Macro directives.
AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacrosOnOff>(
@ -341,6 +343,7 @@ public:
bool ParseDirectiveCFISameValue(StringRef, SMLoc DirectiveLoc);
bool ParseDirectiveCFIRestore(StringRef, SMLoc DirectiveLoc);
bool ParseDirectiveCFIEscape(StringRef, SMLoc DirectiveLoc);
bool ParseDirectiveCFISignalFrame(StringRef, SMLoc DirectiveLoc);
bool ParseDirectiveMacrosOnOff(StringRef, SMLoc DirectiveLoc);
bool ParseDirectiveMacro(StringRef, SMLoc DirectiveLoc);
@ -2855,6 +2858,19 @@ bool GenericAsmParser::ParseDirectiveCFIEscape(StringRef IDVal,
return false;
}
/// ParseDirectiveCFISignalFrame
/// ::= .cfi_signal_frame
bool GenericAsmParser::ParseDirectiveCFISignalFrame(StringRef Directive,
SMLoc DirectiveLoc) {
if (getLexer().isNot(AsmToken::EndOfStatement))
return Error(getLexer().getLoc(),
"unexpected token in '" + Directive + "' directive");
getStreamer().EmitCFISignalFrame();
return false;
}
/// ParseDirectiveMacrosOnOff
/// ::= .macros_on
/// ::= .macros_off

View File

@ -439,6 +439,12 @@ void MCStreamer::EmitCFIEscape(StringRef Values) {
CurFrame->Instructions.push_back(Instruction);
}
void MCStreamer::EmitCFISignalFrame() {
EnsureValidFrame();
MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
CurFrame->IsSignalFrame = true;
}
void MCStreamer::setCurrentW64UnwindInfo(MCWin64EHUnwindInfo *Frame) {
W64UnwindInfos.push_back(Frame);
CurrentW64UnwindInfo = W64UnwindInfos.back();

View File

@ -0,0 +1,23 @@
// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump --dump-section-data | FileCheck %s
f:
.cfi_startproc
.cfi_signal_frame
.cfi_endproc
g:
.cfi_startproc
.cfi_endproc
// CHECK: (('sh_name', 0x00000011) # '.eh_frame'
// CHECK-NEXT: ('sh_type', 0x00000001)
// CHECK-NEXT: ('sh_flags', 0x0000000000000002)
// CHECK-NEXT: ('sh_addr', 0x0000000000000000)
// CHECK-NEXT: ('sh_offset', 0x0000000000000040)
// CHECK-NEXT: ('sh_size', 0x0000000000000058)
// CHECK-NEXT: ('sh_link', 0x00000000)
// CHECK-NEXT: ('sh_info', 0x00000000)
// CHECK-NEXT: ('sh_addralign', 0x0000000000000008)
// CHECK-NEXT: ('sh_entsize', 0x0000000000000000)
// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5253 00017810 011b0c07 08900100 10000000 1c000000 00000000 00000000 00000000 14000000 00000000 017a5200 01781001 1b0c0708 90010000 10000000 1c000000 00000000 00000000 00000000')
// CHECK-NEXT: ),