]> granicus.if.org Git - llvm/commitdiff
MC: add support for cfi_return_column
authorSaleem Abdulrasool <compnerd@compnerd.org>
Fri, 28 Jul 2017 03:39:19 +0000 (03:39 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Fri, 28 Jul 2017 03:39:19 +0000 (03:39 +0000)
This adds support for the CFI pseudo-op return_column.  This specifies
the frame table column which contains the return address.

Addresses PR33953!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@309360 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCDwarf.h
include/llvm/MC/MCStreamer.h
lib/MC/MCAsmStreamer.cpp
lib/MC/MCDwarf.cpp
lib/MC/MCParser/AsmParser.cpp
lib/MC/MCStreamer.cpp
test/Assembler/return-column.s [new file with mode: 0644]

index 79f1b9525019c82b4fb98c2f991ceef24d105893..88ffa04128e6261872240ef69f505067a6e83791 100644 (file)
@@ -509,6 +509,7 @@ struct MCDwarfFrameInfo {
   uint32_t CompactUnwindEncoding = 0;
   bool IsSignalFrame = false;
   bool IsSimple = false;
+  unsigned RAReg = static_cast<unsigned>(INT_MAX);
 };
 
 class MCDwarfFrameEmitter {
index e1f9446f067151a6ed347c8aec9f1f7246ab617e..91f234217b165d34469849d331744b17093932ce 100644 (file)
@@ -797,6 +797,7 @@ public:
   virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset);
   virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment);
   virtual void EmitCFIEscape(StringRef Values);
+  virtual void EmitCFIReturnColumn(int64_t Register);
   virtual void EmitCFIGnuArgsSize(int64_t Size);
   virtual void EmitCFISignalFrame();
   virtual void EmitCFIUndefined(int64_t Register);
index 9e5553fa8d422ac53ff560dd31d1912c428df318..7cc0bcdaaf0c0ec1d38620d3f9bb63b59e80ea24 100644 (file)
@@ -265,6 +265,7 @@ public:
   void EmitCFIUndefined(int64_t Register) override;
   void EmitCFIRegister(int64_t Register1, int64_t Register2) override;
   void EmitCFIWindowSave() override;
+  void EmitCFIReturnColumn(int64_t Register) override;
 
   void EmitWinCFIStartProc(const MCSymbol *Symbol) override;
   void EmitWinCFIEndProc() override;
@@ -1398,6 +1399,12 @@ void MCAsmStreamer::EmitCFIWindowSave() {
   EmitEOL();
 }
 
+void MCAsmStreamer::EmitCFIReturnColumn(int64_t Register) {
+  MCStreamer::EmitCFIReturnColumn(Register);
+  OS << "\t.cfi_return_column " << Register;
+  EmitEOL();
+}
+
 void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) {
   MCStreamer::EmitWinCFIStartProc(Symbol);
 
index a2beee32f2cb133dbaf3907d6645cf7d3ec8c186..a038e0aa9512cbade16f5db9de66508bd3bd0098 100644 (file)
@@ -1037,7 +1037,7 @@ public:
   const MCSymbol &EmitCIE(const MCSymbol *personality,
                           unsigned personalityEncoding, const MCSymbol *lsda,
                           bool IsSignalFrame, unsigned lsdaEncoding,
-                          bool IsSimple);
+                          bool IsSimple, unsigned RAReg);
   void EmitFDE(const MCSymbol &cieStart, const MCDwarfFrameInfo &frame,
                bool LastInSection, const MCSymbol &SectionStart);
   void EmitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,
@@ -1277,8 +1277,8 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCSymbol *personality,
                                           unsigned personalityEncoding,
                                           const MCSymbol *lsda,
                                           bool IsSignalFrame,
-                                          unsigned lsdaEncoding,
-                                          bool IsSimple) {
+                                          unsigned lsdaEncoding, bool IsSimple,
+                                          unsigned RAReg) {
   MCContext &context = Streamer.getContext();
   const MCRegisterInfo *MRI = context.getRegisterInfo();
   const MCObjectFileInfo *MOFI = context.getObjectFileInfo();
@@ -1331,13 +1331,15 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(const MCSymbol *personality,
   Streamer.EmitSLEB128IntValue(getDataAlignmentFactor(Streamer));
 
   // Return Address Register
+  if (RAReg == static_cast<unsigned>(INT_MAX))
+    RAReg = MRI->getDwarfRegNum(MRI->getRARegister(), IsEH);
+
   if (CIEVersion == 1) {
-    assert(MRI->getRARegister() <= 255 &&
+    assert(RAReg <= 255 &&
            "DWARF 2 encodes return_address_register in one byte");
-    Streamer.EmitIntValue(MRI->getDwarfRegNum(MRI->getRARegister(), IsEH), 1);
+    Streamer.EmitIntValue(RAReg, 1);
   } else {
-    Streamer.EmitULEB128IntValue(
-        MRI->getDwarfRegNum(MRI->getRARegister(), IsEH));
+    Streamer.EmitULEB128IntValue(RAReg);
   }
 
   // Augmentation Data Length (optional)
@@ -1563,9 +1565,9 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB,
                Frame.LsdaEncoding, Frame.IsSignalFrame, Frame.IsSimple);
     const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey;
     if (!CIEStart)
-      CIEStart = &Emitter.EmitCIE(Frame.Personality, Frame.PersonalityEncoding,
-                                  Frame.Lsda, Frame.IsSignalFrame,
-                                  Frame.LsdaEncoding, Frame.IsSimple);
+      CIEStart = &Emitter.EmitCIE(
+          Frame.Personality, Frame.PersonalityEncoding, Frame.Lsda,
+          Frame.IsSignalFrame, Frame.LsdaEncoding, Frame.IsSimple, Frame.RAReg);
 
     Emitter.EmitFDE(*CIEStart, Frame, I == E, *SectionStart);
   }
index e6013c7e5ae73c4629d56c261dec8693c781a83f..2756cb71ed94f52ea3d9df1bf7c5b7d1dac9ed40 100644 (file)
@@ -517,6 +517,7 @@ private:
     DK_CFI_SAME_VALUE,
     DK_CFI_RESTORE,
     DK_CFI_ESCAPE,
+    DK_CFI_RETURN_COLUMN,
     DK_CFI_SIGNAL_FRAME,
     DK_CFI_UNDEFINED,
     DK_CFI_REGISTER,
@@ -594,6 +595,7 @@ private:
   bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);
   bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);
   bool parseDirectiveCFIEscape();
+  bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);
   bool parseDirectiveCFISignalFrame();
   bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
 
@@ -2065,6 +2067,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
       return parseDirectiveCFIRestore(IDLoc);
     case DK_CFI_ESCAPE:
       return parseDirectiveCFIEscape();
+    case DK_CFI_RETURN_COLUMN:
+      return parseDirectiveCFIReturnColumn(IDLoc);
     case DK_CFI_SIGNAL_FRAME:
       return parseDirectiveCFISignalFrame();
     case DK_CFI_UNDEFINED:
@@ -4019,6 +4023,16 @@ bool AsmParser::parseDirectiveCFIEscape() {
   return false;
 }
 
+/// parseDirectiveCFIReturnColumn
+/// ::= .cfi_return_column register
+bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
+  int64_t Register = 0;
+  if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
+    return true;
+  getStreamer().EmitCFIReturnColumn(Register);
+  return false;
+}
+
 /// parseDirectiveCFISignalFrame
 /// ::= .cfi_signal_frame
 bool AsmParser::parseDirectiveCFISignalFrame() {
@@ -5138,6 +5152,7 @@ void AsmParser::initializeDirectiveKindMap() {
   DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
   DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
   DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
+  DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
   DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
   DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
   DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
index 2bfb9a63eedbd6cb10f4a14ba5e11610f934106f..e35907f77e10fa7a3cb23f7a7194d4c35a4c474d 100644 (file)
@@ -508,6 +508,12 @@ void MCStreamer::EmitCFIWindowSave() {
   CurFrame->Instructions.push_back(Instruction);
 }
 
+void MCStreamer::EmitCFIReturnColumn(int64_t Register) {
+  EnsureValidDwarfFrame();
+  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
+  CurFrame->RAReg = Register;
+}
+
 void MCStreamer::EnsureValidWinFrameInfo() {
   const MCAsmInfo *MAI = Context.getAsmInfo();
   if (!MAI->usesWindowsCFI())
diff --git a/test/Assembler/return-column.s b/test/Assembler/return-column.s
new file mode 100644 (file)
index 0000000..d3b4623
--- /dev/null
@@ -0,0 +1,17 @@
+// RUN: llvm-mc -triple i686-unknown-linux-gnu -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-ASM-ROUNDTRIP
+// RUN: llvm-mc -triple i686-unknown-linux-gnu -filetype obj -o - %s | llvm-objdump -s -j .eh_frame - | FileCheck %s -check-prefix CHECK-EH_FRAME
+
+       .text
+
+proc:
+       .cfi_startproc
+       .cfi_return_column 0
+       .cfi_endproc
+
+// CHECK-ASM-ROUNDTRIP: .cfi_startproc
+// CHECK-ASM-ROUNDTRIP-NEXT: .cfi_return_column 0
+// CHECK-ASM-ROUNDTRIP: .cfi_endproc
+
+// CHECK-EH_FRAME: Contents of section .eh_frame:
+// CHECK-EH_FRAME:  0000 14000000 00000000 017a5200 017c0001  .........zR..|..
+