Add basic support for .cfi_personality.
authorRafael Espindola <rafael.espindola@gmail.com>
Sun, 26 Dec 2010 20:20:31 +0000 (20:20 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Sun, 26 Dec 2010 20:20:31 +0000 (20:20 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122566 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCStreamer.h
lib/MC/MCDwarf.cpp
lib/MC/MCELFStreamer.cpp
lib/MC/MCParser/AsmParser.cpp
test/MC/ELF/cfi.s

index b85ea3fae11234a98b549794ffd0d2e7fd110225..e6da43ba2075b50268e4eed52abf289d75aa2798 100644 (file)
@@ -52,6 +52,10 @@ namespace llvm {
     void EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
                          bool isPCRel, unsigned AddrSpace);
 
+    std::vector<MCDwarfFrameInfo> FrameInfos;
+    MCDwarfFrameInfo *getCurrentFrameInfo();
+    void EnsureValidFrame();
+
   protected:
     MCStreamer(MCContext &Ctx);
 
@@ -63,10 +67,6 @@ namespace llvm {
     /// is kept up to date by SwitchSection.
     const MCSection *PrevSection;
 
-    std::vector<MCDwarfFrameInfo> FrameInfos;
-    MCDwarfFrameInfo *getCurrentFrameInfo();
-    void EnsureValidFrame();
-
   public:
     virtual ~MCStreamer();
 
index 24ddc8256381ca28c52ebe40bb62e6be7dce1567..a4d34f386aa43cace18ff9d1327b1e4337c2856f 100644 (file)
@@ -475,8 +475,8 @@ static void EmitFrameMoves(MCStreamer &streamer,
         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),
-                                     1);
+        streamer.EmitULEB128IntValue(asmInfo.getDwarfRegNum(Src.getReg(),
+                                                            isEH));
       }
 
       streamer.EmitULEB128IntValue(-Src.getOffset(), 1);
@@ -508,7 +508,8 @@ static void EmitFrameMoves(MCStreamer &streamer,
   }
 }
 
-static const MCSymbol &EmitCIE(MCStreamer &streamer) {
+static const MCSymbol &EmitCIE(MCStreamer &streamer,
+                               const MCSymbol *personality) {
   MCContext &context = streamer.getContext();
   const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
   const MCSection &section = *asmInfo.getEHFrameSection();
@@ -530,7 +531,10 @@ static const MCSymbol &EmitCIE(MCStreamer &streamer) {
 
   // Augmentation String
   SmallString<8> Augmentation;
-  Augmentation += "zR";
+  Augmentation += "z";
+  if (personality)
+    Augmentation += "P";
+  Augmentation += "R";
   streamer.EmitBytes(Augmentation.str(), 0);
   streamer.EmitIntValue(0, 1);
 
@@ -553,6 +557,13 @@ static const MCSymbol &EmitCIE(MCStreamer &streamer) {
 
   // Augmentation Data (optional)
   streamer.EmitLabel(augmentationStart);
+  if (personality) {
+    // Personality Encoding
+    streamer.EmitIntValue(dwarf::DW_EH_PE_absptr, 1);
+    // Personality
+    streamer.EmitSymbolValue(personality, 8);
+  }
+  // Encoding of the FDE pointers
   streamer.EmitIntValue(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4, 1);
   streamer.EmitLabel(augmentationEnd);
 
@@ -563,7 +574,7 @@ static const MCSymbol &EmitCIE(MCStreamer &streamer) {
   EmitFrameMoves(streamer, Moves, NULL, true);
 
   // Padding
-  streamer.EmitValueToAlignment(asmInfo.getPointerSize());
+  streamer.EmitValueToAlignment(4);
 
   streamer.EmitLabel(sectionEnd);
   return *sectionStart;
@@ -608,13 +619,19 @@ static MCSymbol *EmitFDE(MCStreamer &streamer,
 void MCDwarfFrameEmitter::Emit(MCStreamer &streamer) {
   const MCContext &context = streamer.getContext();
   const TargetAsmInfo &asmInfo = context.getTargetAsmInfo();
-  const MCSymbol &cieStart = EmitCIE(streamer);
   MCSymbol *fdeEnd = NULL;
+  DenseMap<const MCSymbol*, const MCSymbol*> Personalities;
+
   for (unsigned i = 0, n = streamer.getNumFrameInfos(); i < n; ++i) {
-    fdeEnd = EmitFDE(streamer, cieStart, streamer.getFrameInfo(i));
+    const MCDwarfFrameInfo &frame = streamer.getFrameInfo(i);
+    const MCSymbol *&cieStart = Personalities[frame.Personality];
+    if (!cieStart)
+      cieStart = &EmitCIE(streamer, frame.Personality);
+    fdeEnd = EmitFDE(streamer, *cieStart, frame);
     if (i != n - 1)
       streamer.EmitLabel(fdeEnd);
   }
+
   streamer.EmitValueToAlignment(asmInfo.getPointerSize());
   if (fdeEnd)
     streamer.EmitLabel(fdeEnd);
index 4636e2a1f0ecae5d055481d7d836b9c929093cd5..23698212044615dd831a3dc7dd307687f71221d1 100644 (file)
@@ -488,7 +488,7 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst) {
 }
 
 void MCELFStreamer::Finish() {
-  if (!FrameInfos.empty())
+  if (getNumFrameInfos())
     MCDwarfFrameEmitter::Emit(*this);
 
   for (std::vector<LocalCommon>::const_iterator i = LocalCommons.begin(),
index aac55351555bcccf8aafbf873e7d2f5a4cfc5aed..cf11ca9c5a8cb1ff3f408d97bb4f992c33c17f16 100644 (file)
@@ -2206,6 +2206,29 @@ bool GenericAsmParser::ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc) {
   return getStreamer().EmitCFIOffset(Register, Offset);
 }
 
+static bool isValidEncoding(int64_t Encoding) {
+  if (Encoding & ~0xff)
+    return false;
+
+  if (Encoding == dwarf::DW_EH_PE_omit)
+    return true;
+
+  const unsigned Format = Encoding & 0xf;
+  if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
+      Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
+      Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
+      Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
+    return false;
+
+  const unsigned Application = Encoding & 0xf0;
+  if (Application != dwarf::DW_EH_PE_absptr &&
+      Application != dwarf::DW_EH_PE_pcrel &&
+      Application != dwarf::DW_EH_PE_indirect)
+    return false;
+
+  return true;
+}
+
 /// ParseDirectiveCFIPersonalityOrLsda
 /// ::= .cfi_personality encoding, [symbol_name]
 /// ::= .cfi_lsda encoding, [symbol_name]
@@ -2214,10 +2237,10 @@ bool GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda(StringRef IDVal,
   int64_t Encoding = 0;
   if (getParser().ParseAbsoluteExpression(Encoding))
     return true;
-  if (Encoding == 255)
+  if (Encoding == dwarf::DW_EH_PE_omit)
     return false;
 
-  if (Encoding != 0)
+  if (!isValidEncoding(Encoding))
     return TokError("unsupported encoding.");
 
   if (getLexer().isNot(AsmToken::Comma))
index 5657925ce5c8c23e0ff90ff3c7d3359f970387e8..3075e43d8b321a7baa2ab15fbd0ac8ddef181220 100644 (file)
@@ -7,6 +7,18 @@ f1:
 
 f2:
         .cfi_startproc
+        .cfi_personality 0x00, foo
+        nop
+        .cfi_endproc
+
+f3:
+        .cfi_startproc
+        nop
+        .cfi_endproc
+
+f4:
+        .cfi_startproc
+        .cfi_personality 0x00, foo
         nop
         .cfi_endproc
 
@@ -16,12 +28,12 @@ f2:
 // CHECK-NEXT:  ('sh_flags', 0x00000002)
 // CHECK-NEXT:  ('sh_addr', 0x00000000)
 // CHECK-NEXT:  ('sh_offset', 0x00000048)
-// CHECK-NEXT:  ('sh_size', 0x00000040)
+// CHECK-NEXT:  ('sh_size', 0x00000088)
 // 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 10000000 1c000000 00000000 01000000 00000000 10000000 30000000 00000000 01000000 00000000')
+// CHECK-NEXT:  ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 10000000 1c000000 00000000 01000000 00000000 1c000000 00000000 017a5052 00017810 0a000000 00000000 00001b0c 07089001 10000000 24000000 00000000 01000000 00000000 10000000 64000000 00000000 01000000 00000000 10000000 4c000000 00000000 01000000 00000000')
 // CHECK-NEXT: ),
 
 // CHECK:      # Section 0x00000008
@@ -29,8 +41,8 @@ f2:
 // CHECK-NEXT:  ('sh_type', 0x00000004)
 // CHECK-NEXT:  ('sh_flags', 0x00000000)
 // CHECK-NEXT:  ('sh_addr', 0x00000000)
-// CHECK-NEXT:  ('sh_offset', 0x00000180)
-// CHECK-NEXT:  ('sh_size', 0x00000030)
+// CHECK-NEXT:  ('sh_offset', 0x00000220)
+// CHECK-NEXT:  ('sh_size', 0x00000078)
 // CHECK-NEXT:  ('sh_link', 0x00000006)
 // CHECK-NEXT:  ('sh_info', 0x00000004)
 // CHECK-NEXT:  ('sh_addralign', 0x00000008)
@@ -38,15 +50,33 @@ f2:
 // CHECK-NEXT:  ('_relocations', [
 // CHECK-NEXT:   # Relocation 0x00000000
 // CHECK-NEXT:   (('r_offset', 0x00000020)
-// CHECK-NEXT:    ('r_sym', 0x00000003)
+// CHECK-NEXT:    ('r_sym', 0x00000005)
 // CHECK-NEXT:    ('r_type', 0x00000002)
 // CHECK-NEXT:    ('r_addend', 0x00000000)
 // CHECK-NEXT:   ),
 // CHECK-NEXT:   # Relocation 0x00000001
-// CHECK-NEXT:   (('r_offset', 0x00000034)
-// CHECK-NEXT:    ('r_sym', 0x00000003)
+// CHECK-NEXT:   (('r_offset', 0x0000003e)
+// CHECK-NEXT:    ('r_sym', 0x00000009)
+// CHECK-NEXT:    ('r_type', 0x00000001)
+// CHECK-NEXT:    ('r_addend', 0x00000000)
+// CHECK-NEXT:   ),
+// CHECK-NEXT:   # Relocation 0x00000002
+// CHECK-NEXT:   (('r_offset', 0x00000054)
+// CHECK-NEXT:    ('r_sym', 0x00000005)
 // CHECK-NEXT:    ('r_type', 0x00000002)
 // CHECK-NEXT:    ('r_addend', 0x00000001)
 // CHECK-NEXT:   ),
+// CHECK-NEXT:   # Relocation 0x00000003
+// CHECK-NEXT:   (('r_offset', 0x00000068)
+// CHECK-NEXT:    ('r_sym', 0x00000005)
+// CHECK-NEXT:    ('r_type', 0x00000002)
+// CHECK-NEXT:    ('r_addend', 0x00000002)
+// CHECK-NEXT:   ),
+// CHECK-NEXT:   # Relocation 0x00000004
+// CHECK-NEXT:   (('r_offset', 0x0000007c)
+// CHECK-NEXT:    ('r_sym', 0x00000005)
+// CHECK-NEXT:    ('r_type', 0x00000002)
+// CHECK-NEXT:    ('r_addend', 0x00000003)
+// CHECK-NEXT:   ),
 // CHECK-NEXT:  ])
 // CHECK-NEXT: ),