summaryrefslogtreecommitdiff
path: root/lib/MC
diff options
context:
space:
mode:
authorJake Ehrlich <jakehehrlich@google.com>2017-12-01 21:44:27 +0000
committerJake Ehrlich <jakehehrlich@google.com>2017-12-01 21:44:27 +0000
commit977b537d0fcb82508f879ded21fb8a53810b2337 (patch)
treedc5b2003a345ed2160659d759264533dff78f17f /lib/MC
parent0fed3ad4cb880f52a5385d695ac7367c074c09c5 (diff)
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@319586 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/MC')
-rw-r--r--lib/MC/MCAsmStreamer.cpp13
-rw-r--r--lib/MC/MCDwarf.cpp12
-rw-r--r--lib/MC/MCRegisterInfo.cpp28
3 files changed, 43 insertions, 10 deletions
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index 44bac8eabdc..d1b475f2ca0 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/lib/MC/MCAsmStreamer.cpp
@@ -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) {
diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp
index a36ff4cb907..3dc0786e445 100644
--- a/lib/MC/MCDwarf.cpp
+++ b/lib/MC/MCDwarf.cpp
@@ -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;
}
diff --git a/lib/MC/MCRegisterInfo.cpp b/lib/MC/MCRegisterInfo.cpp
index 0f76c1838b5..8e47963b441 100644
--- a/lib/MC/MCRegisterInfo.cpp
+++ b/lib/MC/MCRegisterInfo.cpp
@@ -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;