mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-19 11:41:53 +00:00
[MC] Handle unknown literal register numbers in .cfi_* directives
r230670 introduced a step to map EH register numbers to standard DWARF register numbers. This failed to consider the case when a user .cfi_* directive uses an integer literal rather than a register name, to specify a DWARF register number that has no corresponding LLVM register number (e.g. a special register that the compiler and assembler have no name for). Fixes PR34028. Patch by Roland McGrath Differential Revision: https://reviews.llvm.org/D36493 llvm-svn: 319586
This commit is contained in:
parent
ffc60424d9
commit
9a7dac2fce
@ -407,6 +407,15 @@ public:
|
||||
/// \brief Map a dwarf register back to a target register.
|
||||
int getLLVMRegNum(unsigned RegNum, bool isEH) const;
|
||||
|
||||
/// \brief Map a DWARF EH register back to a target register (same as
|
||||
/// getLLVMRegNum(RegNum, true)) but return -1 if there is no mapping,
|
||||
/// rather than asserting that there must be one.
|
||||
int getLLVMRegNumFromEH(unsigned RegNum) const;
|
||||
|
||||
/// \brief Map a target EH register number to an equivalent DWARF register
|
||||
/// number.
|
||||
int getDwarfRegNumFromDwarfEHRegNum(unsigned RegNum) const;
|
||||
|
||||
/// \brief Map a target register to an equivalent SEH register
|
||||
/// number. Returns LLVM register number if there is no equivalent value.
|
||||
int getSEHRegNum(unsigned RegNum) const;
|
||||
|
@ -1296,12 +1296,17 @@ void MCAsmStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
|
||||
|
||||
void MCAsmStreamer::EmitRegisterName(int64_t Register) {
|
||||
if (!MAI->useDwarfRegNumForCFI()) {
|
||||
// User .cfi_* directives can use arbitrary DWARF register numbers, not
|
||||
// just ones that map to LLVM register numbers and have known names.
|
||||
// Fall back to using the original number directly if no name is known.
|
||||
const MCRegisterInfo *MRI = getContext().getRegisterInfo();
|
||||
unsigned LLVMRegister = MRI->getLLVMRegNum(Register, true);
|
||||
InstPrinter->printRegName(OS, LLVMRegister);
|
||||
} else {
|
||||
OS << Register;
|
||||
int LLVMRegister = MRI->getLLVMRegNumFromEH(Register);
|
||||
if (LLVMRegister != -1) {
|
||||
InstPrinter->printRegName(OS, LLVMRegister);
|
||||
return;
|
||||
}
|
||||
}
|
||||
OS << Register;
|
||||
}
|
||||
|
||||
void MCAsmStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) {
|
||||
|
@ -1057,8 +1057,8 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
|
||||
unsigned Reg1 = Instr.getRegister();
|
||||
unsigned Reg2 = Instr.getRegister2();
|
||||
if (!IsEH) {
|
||||
Reg1 = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg1, true), false);
|
||||
Reg2 = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg2, true), false);
|
||||
Reg1 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg1);
|
||||
Reg2 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg2);
|
||||
}
|
||||
Streamer.EmitIntValue(dwarf::DW_CFA_register, 1);
|
||||
Streamer.EmitULEB128IntValue(Reg1);
|
||||
@ -1094,7 +1094,7 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
|
||||
case MCCFIInstruction::OpDefCfa: {
|
||||
unsigned Reg = Instr.getRegister();
|
||||
if (!IsEH)
|
||||
Reg = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
|
||||
Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
|
||||
Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1);
|
||||
Streamer.EmitULEB128IntValue(Reg);
|
||||
CFAOffset = -Instr.getOffset();
|
||||
@ -1105,7 +1105,7 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
|
||||
case MCCFIInstruction::OpDefCfaRegister: {
|
||||
unsigned Reg = Instr.getRegister();
|
||||
if (!IsEH)
|
||||
Reg = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
|
||||
Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
|
||||
Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1);
|
||||
Streamer.EmitULEB128IntValue(Reg);
|
||||
|
||||
@ -1118,7 +1118,7 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
|
||||
|
||||
unsigned Reg = Instr.getRegister();
|
||||
if (!IsEH)
|
||||
Reg = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
|
||||
Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
|
||||
|
||||
int Offset = Instr.getOffset();
|
||||
if (IsRelative)
|
||||
@ -1154,7 +1154,7 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) {
|
||||
case MCCFIInstruction::OpRestore: {
|
||||
unsigned Reg = Instr.getRegister();
|
||||
if (!IsEH)
|
||||
Reg = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
|
||||
Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
|
||||
Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1);
|
||||
return;
|
||||
}
|
||||
|
@ -88,6 +88,34 @@ int MCRegisterInfo::getLLVMRegNum(unsigned RegNum, bool isEH) const {
|
||||
return I->ToReg;
|
||||
}
|
||||
|
||||
int MCRegisterInfo::getLLVMRegNumFromEH(unsigned RegNum) const {
|
||||
const DwarfLLVMRegPair *M = EHDwarf2LRegs;
|
||||
unsigned Size = EHDwarf2LRegsSize;
|
||||
|
||||
if (!M)
|
||||
return -1;
|
||||
DwarfLLVMRegPair Key = { RegNum, 0 };
|
||||
const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, Key);
|
||||
if (I == M+Size || I->FromReg != RegNum)
|
||||
return -1;
|
||||
return I->ToReg;
|
||||
}
|
||||
|
||||
int MCRegisterInfo::getDwarfRegNumFromDwarfEHRegNum(unsigned RegNum) const {
|
||||
// On ELF platforms, DWARF EH register numbers are the same as DWARF
|
||||
// other register numbers. On Darwin x86, they differ and so need to be
|
||||
// mapped. The .cfi_* directives accept integer literals as well as
|
||||
// register names and should generate exactly what the assembly code
|
||||
// asked for, so there might be DWARF/EH register numbers that don't have
|
||||
// a corresponding LLVM register number at all. So if we can't map the
|
||||
// EH register number to an LLVM register number, assume it's just a
|
||||
// valid DWARF register number as is.
|
||||
int LRegNum = getLLVMRegNumFromEH(RegNum);
|
||||
if (LRegNum != -1)
|
||||
return getDwarfRegNum(LRegNum, false);
|
||||
return RegNum;
|
||||
}
|
||||
|
||||
int MCRegisterInfo::getSEHRegNum(unsigned RegNum) const {
|
||||
const DenseMap<unsigned, int>::const_iterator I = L2SEHRegs.find(RegNum);
|
||||
if (I == L2SEHRegs.end()) return (int)RegNum;
|
||||
|
7
test/MC/AsmParser/cfi-unknown-register.s
Normal file
7
test/MC/AsmParser/cfi-unknown-register.s
Normal file
@ -0,0 +1,7 @@
|
||||
// RUN: llvm-mc -filetype=asm -triple x86_64-pc-linux-gnu %s 2>&1 | FileCheck %s
|
||||
|
||||
.cfi_sections .debug_frame
|
||||
.cfi_startproc
|
||||
.cfi_rel_offset 99, 0
|
||||
// CHECK: .cfi_rel_offset 99, 0
|
||||
.cfi_endproc
|
Loading…
x
Reference in New Issue
Block a user