[llvm] r319586 - [MC] Handle unknown literal register numbers in .cfi_* directives

Jake Ehrlich via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 1 13:44:28 PST 2017


Author: jakehehrlich
Date: Fri Dec  1 13:44:27 2017
New Revision: 319586

URL: http://llvm.org/viewvc/llvm-project?rev=319586&view=rev
Log:
[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

Added:
    llvm/trunk/test/MC/AsmParser/cfi-unknown-register.s
Modified:
    llvm/trunk/include/llvm/MC/MCRegisterInfo.h
    llvm/trunk/lib/MC/MCAsmStreamer.cpp
    llvm/trunk/lib/MC/MCDwarf.cpp
    llvm/trunk/lib/MC/MCRegisterInfo.cpp

Modified: llvm/trunk/include/llvm/MC/MCRegisterInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCRegisterInfo.h?rev=319586&r1=319585&r2=319586&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCRegisterInfo.h (original)
+++ llvm/trunk/include/llvm/MC/MCRegisterInfo.h Fri Dec  1 13:44:27 2017
@@ -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;

Modified: llvm/trunk/lib/MC/MCAsmStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAsmStreamer.cpp?rev=319586&r1=319585&r2=319586&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCAsmStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCAsmStreamer.cpp Fri Dec  1 13:44:27 2017
@@ -1296,12 +1296,17 @@ void MCAsmStreamer::EmitCFIEndProcImpl(M
 
 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) {

Modified: llvm/trunk/lib/MC/MCDwarf.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCDwarf.cpp?rev=319586&r1=319585&r2=319586&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCDwarf.cpp (original)
+++ llvm/trunk/lib/MC/MCDwarf.cpp Fri Dec  1 13:44:27 2017
@@ -1057,8 +1057,8 @@ void FrameEmitterImpl::EmitCFIInstructio
     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::EmitCFIInstructio
   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::EmitCFIInstructio
   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::EmitCFIInstructio
 
     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::EmitCFIInstructio
   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;
   }

Modified: llvm/trunk/lib/MC/MCRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCRegisterInfo.cpp?rev=319586&r1=319585&r2=319586&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCRegisterInfo.cpp (original)
+++ llvm/trunk/lib/MC/MCRegisterInfo.cpp Fri Dec  1 13:44:27 2017
@@ -88,6 +88,34 @@ int MCRegisterInfo::getLLVMRegNum(unsign
   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;

Added: llvm/trunk/test/MC/AsmParser/cfi-unknown-register.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AsmParser/cfi-unknown-register.s?rev=319586&view=auto
==============================================================================
--- llvm/trunk/test/MC/AsmParser/cfi-unknown-register.s (added)
+++ llvm/trunk/test/MC/AsmParser/cfi-unknown-register.s Fri Dec  1 13:44:27 2017
@@ -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




More information about the llvm-commits mailing list