mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-15 23:31:37 +00:00
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
This commit is contained in:
parent
19f14dcf6a
commit
fe024d0a62
@ -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<MachineMove> Moves;
|
||||
std::vector<MCCFIInstruction> Instructions;
|
||||
unsigned PersonalityEncoding;
|
||||
unsigned LsdaEncoding;
|
||||
};
|
||||
|
@ -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.
|
||||
|
@ -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,24 +439,79 @@ static int getDataAlignmentFactor(MCStreamer &streamer) {
|
||||
return -size;
|
||||
}
|
||||
|
||||
static void EmitCFIInstruction(MCStreamer &Streamer,
|
||||
const MCCFIInstruction &Instr,
|
||||
bool isEH) {
|
||||
MCContext &context = Streamer.getContext();
|
||||
const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
|
||||
int dataAlignmentFactor = getDataAlignmentFactor(Streamer);
|
||||
|
||||
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);
|
||||
} else {
|
||||
Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1);
|
||||
Streamer.EmitULEB128IntValue(asmInfo.getDwarfRegNum(Src.getReg(),
|
||||
isEH));
|
||||
}
|
||||
|
||||
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));
|
||||
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);
|
||||
} else if (Reg < 64) {
|
||||
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);
|
||||
}
|
||||
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 EmitFrameMoves(MCStreamer &streamer,
|
||||
const std::vector<MachineMove> &Moves,
|
||||
MCSymbol *BaseLabel, 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();
|
||||
static void EmitCFIInstructions(MCStreamer &streamer,
|
||||
const std::vector<MCCFIInstruction> &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.
|
||||
|
||||
const MachineLocation &Dst = Move.getDestination();
|
||||
const MachineLocation &Src = Move.getSource();
|
||||
|
||||
// Advance row if new location.
|
||||
if (BaseLabel && Label) {
|
||||
MCSymbol *ThisSym = Label;
|
||||
@ -465,44 +521,7 @@ static void EmitFrameMoves(MCStreamer &streamer,
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
} else {
|
||||
streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1);
|
||||
streamer.EmitULEB128IntValue(asmInfo.getDwarfRegNum(Src.getReg(),
|
||||
isEH));
|
||||
}
|
||||
|
||||
streamer.EmitULEB128IntValue(-Src.getOffset(), 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
} else if (Reg < 64) {
|
||||
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);
|
||||
}
|
||||
EmitCFIInstruction(streamer, Instr, isEH);
|
||||
}
|
||||
}
|
||||
|
||||
@ -618,8 +637,15 @@ static const MCSymbol &EmitCIE(MCStreamer &streamer,
|
||||
// Initial Instructions
|
||||
|
||||
const std::vector<MachineMove> Moves = asmInfo.getInitialFrameState();
|
||||
std::vector<MCCFIInstruction> Instructions;
|
||||
|
||||
EmitFrameMoves(streamer, Moves, NULL, true);
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
45
test/MC/ELF/cfi-remember.s
Normal file
45
test/MC/ELF/cfi-remember.s
Normal file
@ -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: ),
|
Loading…
x
Reference in New Issue
Block a user