From: Rafael Espindola Date: Tue, 28 Dec 2010 18:36:23 +0000 (+0000) Subject: Implement .cfi_remember_state and .cfi_restore_state. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=fe024d0a624404ada11fb330e7360abc5f88742e;p=oota-llvm.git Implement .cfi_remember_state and .cfi_restore_state. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122602 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 00b94c9e6ae..07a7bad15b1 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -228,14 +228,39 @@ namespace llvm { int64_t LineDelta, uint64_t AddrDelta); }; + class MCCFIInstruction { + public: + enum OpType { Remember, Restore, Move }; + private: + OpType Operation; + MCSymbol *Label; + // Move to & from location. + MachineLocation Destination; + MachineLocation Source; + public: + MCCFIInstruction(OpType Op, MCSymbol *L) + : Operation(Op), Label(L) { + assert(Op == Remember || Op == Restore); + } + MCCFIInstruction(MCSymbol *L, const MachineLocation &D, + const MachineLocation &S) + : Operation(Move), Label(L), Destination(D), Source(S) { + } + OpType getOperation() const { return Operation; } + MCSymbol *getLabel() const { return Label; } + const MachineLocation &getDestination() const { return Destination; } + const MachineLocation &getSource() const { return Source; } + }; + struct MCDwarfFrameInfo { - MCDwarfFrameInfo() : Begin(0), End(0), Personality(0), Lsda(0), Moves(), - PersonalityEncoding(0), LsdaEncoding(0) {} + MCDwarfFrameInfo() : Begin(0), End(0), Personality(0), Lsda(0), + Instructions(), PersonalityEncoding(0), + LsdaEncoding(0) {} MCSymbol *Begin; MCSymbol *End; const MCSymbol *Personality; const MCSymbol *Lsda; - std::vector Moves; + std::vector Instructions; unsigned PersonalityEncoding; unsigned LsdaEncoding; }; diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 345f40109f3..f75e9100d77 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -401,6 +401,8 @@ namespace llvm { virtual bool EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding); virtual bool EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); + virtual bool EmitCFIRememberState(); + virtual bool EmitCFIRestoreState(); /// EmitInstruction - Emit the given @p Instruction into the current /// section. diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index 96ba69aaea2..93a447ceae5 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -18,6 +18,7 @@ #include "llvm/MC/MCObjectWriter.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetAsmBackend.h" #include "llvm/Target/TargetAsmInfo.h" @@ -438,71 +439,89 @@ static int getDataAlignmentFactor(MCStreamer &streamer) { return -size; } -/// EmitFrameMoves - Emit frame instructions to describe the layout of the -/// frame. -static void EmitFrameMoves(MCStreamer &streamer, - const std::vector &Moves, - MCSymbol *BaseLabel, bool isEH) { - MCContext &context = streamer.getContext(); +static void EmitCFIInstruction(MCStreamer &Streamer, + const MCCFIInstruction &Instr, + bool isEH) { + MCContext &context = Streamer.getContext(); const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); - int dataAlignmentFactor = getDataAlignmentFactor(streamer); - - for (unsigned i = 0, N = Moves.size(); i < N; ++i) { - const MachineMove &Move = Moves[i]; - MCSymbol *Label = Move.getLabel(); - // Throw out move if the label is invalid. - if (Label && !Label->isDefined()) continue; // Not emitted, in dead code. - - const MachineLocation &Dst = Move.getDestination(); - const MachineLocation &Src = Move.getSource(); + int dataAlignmentFactor = getDataAlignmentFactor(Streamer); - // Advance row if new location. - if (BaseLabel && Label) { - MCSymbol *ThisSym = Label; - if (ThisSym != BaseLabel) { - streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym); - BaseLabel = ThisSym; - } - } + switch (Instr.getOperation()) { + case MCCFIInstruction::Move: { + const MachineLocation &Dst = Instr.getDestination(); + const MachineLocation &Src = Instr.getSource(); // If advancing cfa. if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { assert(!Src.isReg() && "Machine move not supported yet."); if (Src.getReg() == MachineLocation::VirtualFP) { - streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1); + Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1); } else { - streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1); - streamer.EmitULEB128IntValue(asmInfo.getDwarfRegNum(Src.getReg(), + Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1); + Streamer.EmitULEB128IntValue(asmInfo.getDwarfRegNum(Src.getReg(), isEH)); } - streamer.EmitULEB128IntValue(-Src.getOffset(), 1); - continue; + Streamer.EmitULEB128IntValue(-Src.getOffset(), 1); + return; } if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) { assert(Dst.isReg() && "Machine move not supported yet."); - streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1); - streamer.EmitULEB128IntValue(asmInfo.getDwarfRegNum(Dst.getReg(), isEH)); - continue; + Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1); + Streamer.EmitULEB128IntValue(asmInfo.getDwarfRegNum(Dst.getReg(), isEH)); + return; } unsigned Reg = asmInfo.getDwarfRegNum(Src.getReg(), isEH); int Offset = Dst.getOffset() / dataAlignmentFactor; if (Offset < 0) { - streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1); - streamer.EmitULEB128IntValue(Reg); - streamer.EmitSLEB128IntValue(Offset); + Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1); + Streamer.EmitULEB128IntValue(Reg); + Streamer.EmitSLEB128IntValue(Offset); } else if (Reg < 64) { - streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1); - streamer.EmitULEB128IntValue(Offset, 1); + Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1); + Streamer.EmitULEB128IntValue(Offset, 1); } else { - streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1); - streamer.EmitULEB128IntValue(Reg, 1); - streamer.EmitULEB128IntValue(Offset, 1); + Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1); + Streamer.EmitULEB128IntValue(Reg, 1); + Streamer.EmitULEB128IntValue(Offset, 1); + } + return; + } + case MCCFIInstruction::Remember: + Streamer.EmitIntValue(dwarf::DW_CFA_remember_state, 1); + return; + case MCCFIInstruction::Restore: + Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1); + return; + } + llvm_unreachable("Unhandled case in switch"); +} + +/// EmitFrameMoves - Emit frame instructions to describe the layout of the +/// frame. +static void EmitCFIInstructions(MCStreamer &streamer, + const std::vector &Instrs, + MCSymbol *BaseLabel, bool isEH) { + for (unsigned i = 0, N = Instrs.size(); i < N; ++i) { + const MCCFIInstruction &Instr = Instrs[i]; + MCSymbol *Label = Instr.getLabel(); + // Throw out move if the label is invalid. + if (Label && !Label->isDefined()) continue; // Not emitted, in dead code. + + // Advance row if new location. + if (BaseLabel && Label) { + MCSymbol *ThisSym = Label; + if (ThisSym != BaseLabel) { + streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym); + BaseLabel = ThisSym; + } } + + EmitCFIInstruction(streamer, Instr, isEH); } } @@ -618,8 +637,15 @@ static const MCSymbol &EmitCIE(MCStreamer &streamer, // Initial Instructions const std::vector Moves = asmInfo.getInitialFrameState(); + std::vector Instructions; + + for (int i = 0, n = Moves.size(); i != n; ++i) { + MCCFIInstruction Inst(Moves[i].getLabel(), Moves[i].getDestination(), + Moves[i].getSource()); + Instructions.push_back(Inst); + } - EmitFrameMoves(streamer, Moves, NULL, true); + EmitCFIInstructions(streamer, Instructions, NULL, true); // Padding streamer.EmitValueToAlignment(4); @@ -668,7 +694,7 @@ static MCSymbol *EmitFDE(MCStreamer &streamer, streamer.EmitLabel(augmentationEnd); // Call Frame Instructions - EmitFrameMoves(streamer, frame.Moves, frame.Begin, true); + EmitCFIInstructions(streamer, frame.Instructions, frame.Begin, true); // Padding streamer.EmitValueToAlignment(4); diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 27b2dced554..76c309e0276 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -254,6 +254,10 @@ public: &GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda>(".cfi_personality"); AddDirectiveHandler< &GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda>(".cfi_lsda"); + AddDirectiveHandler< + &GenericAsmParser::ParseDirectiveCFIRememberState>(".cfi_remember_state"); + AddDirectiveHandler< + &GenericAsmParser::ParseDirectiveCFIRestoreState>(".cfi_restore_state"); // Macro directives. AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacrosOnOff>( @@ -278,6 +282,8 @@ public: bool ParseDirectiveCFIDefCfaRegister(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIPersonalityOrLsda(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFIRememberState(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFIRestoreState(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveMacrosOnOff(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveMacro(StringRef, SMLoc DirectiveLoc); @@ -2261,6 +2267,20 @@ bool GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda(StringRef IDVal, } } +/// ParseDirectiveCFIRememberState +/// ::= .cfi_remember_state +bool GenericAsmParser::ParseDirectiveCFIRememberState(StringRef IDVal, + SMLoc DirectiveLoc) { + return getStreamer().EmitCFIRememberState(); +} + +/// ParseDirectiveCFIRestoreState +/// ::= .cfi_remember_state +bool GenericAsmParser::ParseDirectiveCFIRestoreState(StringRef IDVal, + SMLoc DirectiveLoc) { + return getStreamer().EmitCFIRestoreState(); +} + /// ParseDirectiveMacrosOnOff /// ::= .macros_on /// ::= .macros_off diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 048e8866bde..9a85707590c 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -179,8 +179,8 @@ bool MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) { EmitLabel(Label); MachineLocation Dest(MachineLocation::VirtualFP); MachineLocation Source(MachineLocation::VirtualFP, -Offset); - MachineMove Move(Label, Dest, Source); - CurFrame->Moves.push_back(Move); + MCCFIInstruction Instruction(Label, Dest, Source); + CurFrame->Instructions.push_back(Instruction); return false; } @@ -211,6 +211,27 @@ bool MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { return false; } +bool MCStreamer::EmitCFIRememberState() { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCSymbol *Label = getContext().CreateTempSymbol(); + EmitLabel(Label); + MCCFIInstruction Instruction(MCCFIInstruction::Remember, Label); + CurFrame->Instructions.push_back(Instruction); + return false; +} + +bool MCStreamer::EmitCFIRestoreState() { + // FIXME: Error if there is no matching cfi_remember_state. + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCSymbol *Label = getContext().CreateTempSymbol(); + EmitLabel(Label); + MCCFIInstruction Instruction(MCCFIInstruction::Restore, Label); + CurFrame->Instructions.push_back(Instruction); + return false; +} + /// EmitRawText - If this file is backed by an assembly streamer, this dumps /// the specified string in the output .s file. This capability is /// indicated by the hasRawTextSupport() predicate. diff --git a/test/MC/ELF/cfi-remember.s b/test/MC/ELF/cfi-remember.s new file mode 100644 index 00000000000..b5b380368f0 --- /dev/null +++ b/test/MC/ELF/cfi-remember.s @@ -0,0 +1,45 @@ +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump --dump-section-data | FileCheck %s + +f: + .cfi_startproc + nop + .cfi_remember_state + nop + .cfi_restore_state + nop + .cfi_endproc + +// CHECK: # Section 0x00000004 +// CHECK-NEXT: (('sh_name', 0x00000012) # '.eh_frame' +// CHECK-NEXT: ('sh_type', 0x00000001) +// CHECK-NEXT: ('sh_flags', 0x00000002) +// CHECK-NEXT: ('sh_addr', 0x00000000) +// CHECK-NEXT: ('sh_offset', 0x00000048) +// CHECK-NEXT: ('sh_size', 0x00000030) +// CHECK-NEXT: ('sh_link', 0x00000000) +// CHECK-NEXT: ('sh_info', 0x00000000) +// CHECK-NEXT: ('sh_addralign', 0x00000008) +// CHECK-NEXT: ('sh_entsize', 0x00000000) +// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 14000000 1c000000 00000000 03000000 00410a41 0b000000') +// CHECK-NEXT: ), + +// CHECK: # Section 0x00000008 +// CHECK-NEXT: (('sh_name', 0x00000036) # '.rela.eh_frame' +// CHECK-NEXT: ('sh_type', 0x00000004) +// CHECK-NEXT: ('sh_flags', 0x00000000) +// CHECK-NEXT: ('sh_addr', 0x00000000) +// CHECK-NEXT: ('sh_offset', 0x00000158) +// CHECK-NEXT: ('sh_size', 0x00000018) +// CHECK-NEXT: ('sh_link', 0x00000006) +// CHECK-NEXT: ('sh_info', 0x00000004) +// CHECK-NEXT: ('sh_addralign', 0x00000008) +// CHECK-NEXT: ('sh_entsize', 0x00000018) +// CHECK-NEXT: ('_relocations', [ +// CHECK-NEXT: # Relocation 0x00000000 +// CHECK-NEXT: (('r_offset', 0x00000020) +// CHECK-NEXT: ('r_sym', 0x00000002) +// CHECK-NEXT: ('r_type', 0x00000002) +// CHECK-NEXT: ('r_addend', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: ]) +// CHECK-NEXT: ),