[llvm] r179591 - Implement ARM unwind opcode assembler.

Logan Chien tzuhsiang.chien at gmail.com
Wed Apr 17 00:43:17 PDT 2013


Hi Jim,

  Currently, I can't use llvm-mc to run the test because ARMAsmParser can't
parse unwind directives yet.
I am working on this issue.  I will add more .s test after the ARMAsmParser
is ready.  Thanks.

FYI.
https://github.com/loganchien/llvm/compare/master...add-arm-unwind-directives

Sincerely,
Logan


On Wed, Apr 17, 2013 at 1:34 PM, Jim Grosbach <grosbach at apple.com> wrote:

> Hi Logan,
>
> Why is this test case a .ll file? Normally, anything at the MC level
> should have test cases as .s files.
>
> -Jim
>
>
> On Apr 16, 2013, at 5:02 AM, Logan Chien <tzuhsiang.chien at gmail.com>
> wrote:
>
> Author: logan
> Date: Tue Apr 16 07:02:21 2013
> New Revision: 179591
>
> URL: http://llvm.org/viewvc/llvm-project?rev=179591&view=rev
> Log:
> Implement ARM unwind opcode assembler.
>
> Added:
>    llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp
>    llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h
>    llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr0.ll
>    llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr1.ll
> Modified:
>    llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
>    llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h
>    llvm/trunk/lib/Target/ARM/MCTargetDesc/CMakeLists.txt
>    llvm/trunk/test/CodeGen/ARM/ehabi-mc-section-group.ll
>    llvm/trunk/test/CodeGen/ARM/ehabi-mc-section.ll
>    llvm/trunk/test/CodeGen/ARM/ehabi-mc.ll
>
> Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp?rev=179591&r1=179590&r2=179591&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp (original)
> +++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp Tue Apr 16
> 07:02:21 2013
> @@ -13,7 +13,9 @@
> //
>
> //===----------------------------------------------------------------------===//
>
> +#include "ARMRegisterInfo.h"
> #include "ARMUnwindOp.h"
> +#include "ARMUnwindOpAsm.h"
> #include "llvm/ADT/SmallPtrSet.h"
> #include "llvm/ADT/Twine.h"
> #include "llvm/MC/MCAsmBackend.h"
> @@ -26,6 +28,7 @@
> #include "llvm/MC/MCExpr.h"
> #include "llvm/MC/MCInst.h"
> #include "llvm/MC/MCObjectStreamer.h"
> +#include "llvm/MC/MCRegisterInfo.h"
> #include "llvm/MC/MCSection.h"
> #include "llvm/MC/MCSectionELF.h"
> #include "llvm/MC/MCStreamer.h"
> @@ -33,11 +36,15 @@
> #include "llvm/MC/MCValue.h"
> #include "llvm/Support/Debug.h"
> #include "llvm/Support/ELF.h"
> -#include "llvm/Support/ErrorHandling.h"
> #include "llvm/Support/raw_ostream.h"
>
> using namespace llvm;
>
> +static std::string GetAEABIUnwindPersonalityName(unsigned Index) {
> +  assert(Index < NUM_PERSONALITY_INDEX && "Invalid personality index");
> +  return (Twine("__aeabi_unwind_cpp_pr") + Twine(Index)).str();
> +}
> +
> namespace {
>
> /// Extend the generic ELFStreamer class so that it can emit mapping
> symbols at
> @@ -57,8 +64,9 @@ public:
>   ARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS,
>                  MCCodeEmitter *Emitter, bool IsThumb)
>       : MCELFStreamer(SK_ARMELFStreamer, Context, TAB, OS, Emitter),
> -        IsThumb(IsThumb), MappingSymbolCounter(0), LastEMS(EMS_None),
> ExTab(0),
> -        FnStart(0), Personality(0), CantUnwind(false) {}
> +        IsThumb(IsThumb), MappingSymbolCounter(0), LastEMS(EMS_None) {
> +    Reset();
> +  }
>
>   ~ARMELFStreamer() {}
>
> @@ -194,6 +202,7 @@ private:
>   void Reset();
>
>   void EmitPersonalityFixup(StringRef Name);
> +  void CollectUnwindOpcodes();
>
>   void SwitchToEHSection(const char *Prefix, unsigned Type, unsigned Flags,
>                          SectionKind Kind, const MCSymbol &Fn);
> @@ -210,9 +219,16 @@ private:
>   MCSymbol *ExTab;
>   MCSymbol *FnStart;
>   const MCSymbol *Personality;
> +  uint32_t VFPRegSave; // Register mask for {d31-d0}
> +  uint32_t RegSave; // Register mask for {r15-r0}
> +  int64_t SPOffset;
> +  uint16_t FPReg;
> +  int64_t FPOffset;
> +  bool UsedFP;
>   bool CantUnwind;
> +  UnwindOpcodeAssembler UnwindOpAsm;
> };
> -}
> +} // end anonymous namespace
>
> inline void ARMELFStreamer::SwitchToEHSection(const char *Prefix,
>                                               unsigned Type,
> @@ -238,7 +254,7 @@ inline void ARMELFStreamer::SwitchToEHSe
>   } else {
>     EHSection = getContext().getELFSection(EHSecName, Type, Flags, Kind);
>   }
> -  assert(EHSection);
> +  assert(EHSection && "Failed to get the required EH section");
>
>   // Switch to .ARM.extab or .ARM.exidx section
>   SwitchSection(EHSection);
> @@ -262,10 +278,20 @@ inline void ARMELFStreamer::SwitchToExId
> }
>
> void ARMELFStreamer::Reset() {
> +  const MCRegisterInfo &MRI = getContext().getRegisterInfo();
> +
>   ExTab = NULL;
>   FnStart = NULL;
>   Personality = NULL;
> +  VFPRegSave = 0;
> +  RegSave = 0;
> +  FPReg = MRI.getEncodingValue(ARM::SP);
> +  FPOffset = 0;
> +  SPOffset = 0;
> +  UsedFP = false;
>   CantUnwind = false;
> +
> +  UnwindOpAsm.Reset();
> }
>
> // Add the R_ARM_NONE fixup at the same position
> @@ -284,6 +310,18 @@ void ARMELFStreamer::EmitPersonalityFixu
>                     MCFixup::getKindForSize(4, false)));
> }
>
> +void ARMELFStreamer::CollectUnwindOpcodes() {
> +  if (UsedFP) {
> +    UnwindOpAsm.EmitSetFP(FPReg);
> +    UnwindOpAsm.EmitSPOffset(-FPOffset);
> +  } else {
> +    UnwindOpAsm.EmitSPOffset(SPOffset);
> +  }
> +  UnwindOpAsm.EmitVFPRegSave(VFPRegSave);
> +  UnwindOpAsm.EmitRegSave(RegSave);
> +  UnwindOpAsm.Finalize();
> +}
> +
> void ARMELFStreamer::EmitFnStart() {
>   assert(FnStart == 0);
>   FnStart = getContext().CreateTempSymbol();
> @@ -294,35 +332,29 @@ void ARMELFStreamer::EmitFnEnd() {
>   assert(FnStart && ".fnstart must preceeds .fnend");
>
>   // Emit unwind opcodes if there is no .handlerdata directive
> -  int PersonalityIndex = -1;
>   if (!ExTab && !CantUnwind) {
> -    // For __aeabi_unwind_cpp_pr1, we have to emit opcodes in .ARM.extab.
> -    SwitchToExTabSection(*FnStart);
> -
> -    // Create .ARM.extab label for offset in .ARM.exidx
> -    ExTab = getContext().CreateTempSymbol();
> -    EmitLabel(ExTab);
> -
> -    PersonalityIndex = 1;
> -
> -    uint32_t Entry = 0;
> -    uint32_t NumExtraEntryWords = 0;
> -    Entry |= NumExtraEntryWords << 24;
> -    Entry |= (EHT_COMPACT | PersonalityIndex) << 16;
> -
> -    // TODO: This should be generated according to .save, .vsave, .setfp
> -    // directives.  Currently, we are simply generating FINISH opcode.
> -    Entry |= UNWIND_OPCODE_FINISH << 8;
> -    Entry |= UNWIND_OPCODE_FINISH;
> +    CollectUnwindOpcodes();
>
> -    EmitIntValue(Entry, 4, 0);
> +    unsigned PersonalityIndex = UnwindOpAsm.getPersonalityIndex();
> +    if (PersonalityIndex == AEABI_UNWIND_CPP_PR1 ||
> +        PersonalityIndex == AEABI_UNWIND_CPP_PR2) {
> +      // For the __aeabi_unwind_cpp_pr1 and __aeabi_unwind_cpp_pr2, we
> have to
> +      // emit the unwind opcodes in the corresponding ".ARM.extab"
> section, and
> +      // then emit a reference to these unwind opcodes in the second word
> of
> +      // the exception index table entry.
> +      SwitchToExTabSection(*FnStart);
> +      ExTab = getContext().CreateTempSymbol();
> +      EmitLabel(ExTab);
> +      EmitBytes(UnwindOpAsm.data(), 0);
> +    }
>   }
>
>   // Emit the exception index table entry
>   SwitchToExIdxSection(*FnStart);
>
> -  if (PersonalityIndex == 1)
> -    EmitPersonalityFixup("__aeabi_unwind_cpp_pr1");
> +  unsigned PersonalityIndex = UnwindOpAsm.getPersonalityIndex();
> +  if (PersonalityIndex < NUM_PERSONALITY_INDEX)
> +    EmitPersonalityFixup(GetAEABIUnwindPersonalityName(PersonalityIndex));
>
>   const MCSymbolRefExpr *FnStartRef =
>     MCSymbolRefExpr::Create(FnStart,
> @@ -333,12 +365,22 @@ void ARMELFStreamer::EmitFnEnd() {
>
>   if (CantUnwind) {
>     EmitIntValue(EXIDX_CANTUNWIND, 4, 0);
> -  } else {
> +  } else if (ExTab) {
> +    // Emit a reference to the unwind opcodes in the ".ARM.extab" section.
>     const MCSymbolRefExpr *ExTabEntryRef =
>       MCSymbolRefExpr::Create(ExTab,
>                               MCSymbolRefExpr::VK_ARM_PREL31,
>                               getContext());
>     EmitValue(ExTabEntryRef, 4, 0);
> +  } else {
> +    // For the __aeabi_unwind_cpp_pr0, we have to emit the unwind opcodes
> in
> +    // the second word of exception index table entry.  The size of the
> unwind
> +    // opcodes should always be 4 bytes.
> +    assert(PersonalityIndex == AEABI_UNWIND_CPP_PR0 &&
> +           "Compact model must use __aeabi_cpp_unwind_pr0 as
> personality");
> +    assert(UnwindOpAsm.size() == 4u &&
> +           "Unwind opcode size for __aeabi_cpp_unwind_pr0 must be equal
> to 4");
> +    EmitBytes(UnwindOpAsm.data(), 0);
>   }
>
>   // Clean exception handling frame information
> @@ -368,36 +410,50 @@ void ARMELFStreamer::EmitHandlerData() {
>   EmitValue(PersonalityRef, 4, 0);
>
>   // Emit unwind opcodes
> -  uint32_t Entry = 0;
> -  uint32_t NumExtraEntryWords = 0;
> -
> -  // TODO: This should be generated according to .save, .vsave, .setfp
> -  // directives.  Currently, we are simply generating FINISH opcode.
> -  Entry |= NumExtraEntryWords << 24;
> -  Entry |= UNWIND_OPCODE_FINISH << 16;
> -  Entry |= UNWIND_OPCODE_FINISH << 8;
> -  Entry |= UNWIND_OPCODE_FINISH;
> -
> -  EmitIntValue(Entry, 4, 0);
> +  CollectUnwindOpcodes();
> +  EmitBytes(UnwindOpAsm.data(), 0);
> }
>
> void ARMELFStreamer::EmitPersonality(const MCSymbol *Per) {
>   Personality = Per;
> +  UnwindOpAsm.setPersonality(Per);
> }
>
> -void ARMELFStreamer::EmitSetFP(unsigned NewFpReg,
> -                               unsigned NewSpReg,
> +void ARMELFStreamer::EmitSetFP(unsigned NewFPReg,
> +                               unsigned NewSPReg,
>                                int64_t Offset) {
> -  // TODO: Not implemented
> +  assert(SPOffset == 0 &&
> +         "Current implementation assumes .setfp precedes .pad");
> +
> +  const MCRegisterInfo &MRI = getContext().getRegisterInfo();
> +
> +  uint16_t NewFPRegEncVal = MRI.getEncodingValue(NewFPReg);
> +  uint16_t NewSPRegEncVal = MRI.getEncodingValue(NewSPReg);
> +
> +  assert((NewSPReg == ARM::SP || NewSPRegEncVal == FPReg) &&
> +         "the operand of .setfp directive should be either $sp or $fp");
> +
> +  UsedFP = true;
> +  FPReg = NewFPRegEncVal;
> +  FPOffset = Offset;
> }
>
> void ARMELFStreamer::EmitPad(int64_t Offset) {
> -  // TODO: Not implemented
> +  SPOffset += Offset;
> }
>
> void ARMELFStreamer::EmitRegSave(const SmallVectorImpl<unsigned> &RegList,
>                                  bool IsVector) {
> -  // TODO: Not implemented
> +  const MCRegisterInfo &MRI = getContext().getRegisterInfo();
> +
> +  unsigned Max = IsVector ? 32 : 16;
> +  uint32_t &RegMask = IsVector ? VFPRegSave : RegSave;
> +
> +  for (size_t i = 0; i < RegList.size(); ++i) {
> +    unsigned Reg = MRI.getEncodingValue(RegList[i]);
> +    assert(Reg < Max && "Register encoded value out of range");
> +    RegMask |= 1u << Reg;
> +  }
> }
>
> namespace llvm {
>
> Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h?rev=179591&r1=179590&r2=179591&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h (original)
> +++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h Tue Apr 16
> 07:02:21 2013
> @@ -107,6 +107,19 @@ namespace llvm {
>     UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD_D8 = 0xd0
>   };
>
> +  /// ARM-defined Personality Routine Index
> +  enum ARMPersonalityRoutineIndex {
> +    // To make the exception handling table become more compact, ARM
> defined
> +    // several personality routines in EHABI.  There are 3 different
> +    // personality routines in ARM EHABI currently.  It is possible to
> have 16
> +    // pre-defined personality routines at most.
> +    AEABI_UNWIND_CPP_PR0 = 0,
> +    AEABI_UNWIND_CPP_PR1 = 1,
> +    AEABI_UNWIND_CPP_PR2 = 2,
> +
> +    NUM_PERSONALITY_INDEX
> +  };
> +
> }
>
> #endif // ARM_UNWIND_OP_H
>
> Added: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp?rev=179591&view=auto
>
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp (added)
> +++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp Tue Apr 16
> 07:02:21 2013
> @@ -0,0 +1,198 @@
> +//===-- ARMUnwindOpAsm.cpp - ARM Unwind Opcodes Assembler -------*- C++
> -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +//
> +// This file implements the unwind opcode assmebler for ARM exception
> handling
> +// table.
> +//
>
> +//===----------------------------------------------------------------------===//
> +
> +#include "ARMUnwindOpAsm.h"
> +
> +#include "ARMUnwindOp.h"
> +#include "llvm/Support/ErrorHandling.h"
> +#include "llvm/Support/LEB128.h"
> +
> +using namespace llvm;
> +
> +void UnwindOpcodeAssembler::EmitRegSave(uint32_t RegSave) {
> +  if (RegSave == 0u)
> +    return;
> +
> +  // One byte opcode to save register r14 and r11-r4
> +  if (RegSave & (1u << 4)) {
> +    // The one byte opcode will always save r4, thus we can't use the one
> byte
> +    // opcode when r4 is not in .save directive.
> +
> +    // Compute the consecutive registers from r4 to r11.
> +    uint32_t Range = 0;
> +    uint32_t Mask = (1u << 4);
> +    for (uint32_t Bit = (1u << 5); Bit < (1u << 12); Bit <<= 1) {
> +      if ((RegSave & Bit) == 0u)
> +        break;
> +      ++Range;
> +      Mask |= Bit;
> +    }
> +
> +    // Emit this opcode when the mask covers every registers.
> +    uint32_t UnmaskedReg = RegSave & 0xfff0u & (~Mask);
> +    if (UnmaskedReg == 0u) {
> +      // Pop r[4 : (4 + n)]
> +      Ops.push_back(UNWIND_OPCODE_POP_REG_RANGE_R4 | Range);
> +      RegSave &= 0x000fu;
> +    } else if (UnmaskedReg == (1u << 14)) {
> +      // Pop r[14] + r[4 : (4 + n)]
> +      Ops.push_back(UNWIND_OPCODE_POP_REG_RANGE_R4_R14 | Range);
> +      RegSave &= 0x000fu;
> +    }
> +  }
> +
> +  // Two bytes opcode to save register r15-r4
> +  if ((RegSave & 0xfff0u) != 0) {
> +    uint32_t Op = UNWIND_OPCODE_POP_REG_MASK_R4 | (RegSave >> 4);
> +    Ops.push_back(static_cast<uint8_t>(Op >> 8));
> +    Ops.push_back(static_cast<uint8_t>(Op & 0xff));
> +  }
> +
> +  // Opcode to save register r3-r0
> +  if ((RegSave & 0x000fu) != 0) {
> +    uint32_t Op = UNWIND_OPCODE_POP_REG_MASK | (RegSave & 0x000fu);
> +    Ops.push_back(static_cast<uint8_t>(Op >> 8));
> +    Ops.push_back(static_cast<uint8_t>(Op & 0xff));
> +  }
> +}
> +
> +/// Emit unwind opcodes for .vsave directives
> +void UnwindOpcodeAssembler::EmitVFPRegSave(uint32_t VFPRegSave) {
> +  size_t i = 32;
> +
> +  while (i > 16) {
> +    uint32_t Bit = 1u << (i - 1);
> +    if ((VFPRegSave & Bit) == 0u) {
> +      --i;
> +      continue;
> +    }
> +
> +    uint32_t Range = 0;
> +
> +    --i;
> +    Bit >>= 1;
> +
> +    while (i > 16 && (VFPRegSave & Bit)) {
> +      --i;
> +      ++Range;
> +      Bit >>= 1;
> +    }
> +
> +    uint32_t Op =
> +        UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD_D16 | ((i - 16) << 4) |
> Range;
> +    Ops.push_back(static_cast<uint8_t>(Op >> 8));
> +    Ops.push_back(static_cast<uint8_t>(Op & 0xff));
> +  }
> +
> +  while (i > 0) {
> +    uint32_t Bit = 1u << (i - 1);
> +    if ((VFPRegSave & Bit) == 0u) {
> +      --i;
> +      continue;
> +    }
> +
> +    uint32_t Range = 0;
> +
> +    --i;
> +    Bit >>= 1;
> +
> +    while (i > 0 && (VFPRegSave & Bit)) {
> +      --i;
> +      ++Range;
> +      Bit >>= 1;
> +    }
> +
> +    uint32_t Op = UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD | (i << 4) |
> Range;
> +    Ops.push_back(static_cast<uint8_t>(Op >> 8));
> +    Ops.push_back(static_cast<uint8_t>(Op & 0xff));
> +  }
> +}
> +
> +/// Emit unwind opcodes for .setfp directives
> +void UnwindOpcodeAssembler::EmitSetFP(uint16_t FPReg) {
> +  Ops.push_back(UNWIND_OPCODE_SET_VSP | FPReg);
> +}
> +
> +/// Emit unwind opcodes to update stack pointer
> +void UnwindOpcodeAssembler::EmitSPOffset(int64_t Offset) {
> +  if (Offset > 0x200) {
> +    uint8_t Buff[10];
> +    size_t Size = encodeULEB128((Offset - 0x204) >> 2, Buff);
> +    Ops.push_back(UNWIND_OPCODE_INC_VSP_ULEB128);
> +    Ops.append(Buff, Buff + Size);
> +  } else if (Offset > 0) {
> +    if (Offset > 0x100) {
> +      Ops.push_back(UNWIND_OPCODE_INC_VSP | 0x3fu);
> +      Offset -= 0x100;
> +    }
> +    Ops.push_back(UNWIND_OPCODE_INC_VSP |
> +                  static_cast<uint8_t>((Offset - 4) >> 2));
> +  } else if (Offset < 0) {
> +    while (Offset < -0x100) {
> +      Ops.push_back(UNWIND_OPCODE_DEC_VSP | 0x3fu);
> +      Offset += 0x100;
> +    }
> +    Ops.push_back(UNWIND_OPCODE_DEC_VSP |
> +                  static_cast<uint8_t>(((-Offset) - 4) >> 2));
> +  }
> +}
> +
> +void UnwindOpcodeAssembler::AddOpcodeSizePrefix(size_t Pos) {
> +  size_t SizeInWords = (size() + 3) / 4;
> +  assert(SizeInWords <= 0x100u &&
> +         "Only 256 additional words are allowed for unwind opcodes");
> +  Ops[Pos] = static_cast<uint8_t>(SizeInWords - 1);
> +}
> +
> +void UnwindOpcodeAssembler::AddPersonalityIndexPrefix(size_t Pos,
> unsigned PI) {
> +  assert(PI < NUM_PERSONALITY_INDEX && "Invalid personality prefix");
> +  Ops[Pos] = EHT_COMPACT | PI;
> +}
> +
> +void UnwindOpcodeAssembler::EmitFinishOpcodes() {
> +  for (size_t i = (0x4u - (size() & 0x3u)) & 0x3u; i > 0; --i)
> +    Ops.push_back(UNWIND_OPCODE_FINISH);
> +}
> +
> +void UnwindOpcodeAssembler::Finalize() {
> +  if (HasPersonality) {
> +    // Personality specified by .personality directive
> +    Offset = 1;
> +    AddOpcodeSizePrefix(1);
> +  } else {
> +    if (getOpcodeSize() <= 3) {
> +      // __aeabi_unwind_cpp_pr0: [ 0x80 , OP1 , OP2 , OP3 ]
> +      Offset = 1;
> +      PersonalityIndex = AEABI_UNWIND_CPP_PR0;
> +      AddPersonalityIndexPrefix(Offset, PersonalityIndex);
> +    } else {
> +      // __aeabi_unwind_cpp_pr1: [ 0x81 , SIZE , OP1 , OP2 , ... ]
> +      Offset = 0;
> +      PersonalityIndex = AEABI_UNWIND_CPP_PR1;
> +      AddPersonalityIndexPrefix(Offset, PersonalityIndex);
> +      AddOpcodeSizePrefix(1);
> +    }
> +  }
> +
> +  // Emit the padding finish opcodes if the size() is not multiple of 4.
> +  EmitFinishOpcodes();
> +
> +  // Swap the byte order
> +  uint8_t *Ptr = Ops.begin() + Offset;
> +  assert(size() % 4 == 0 && "Final unwind opcodes should align to 4");
> +  for (size_t i = 0, n = size(); i < n; i += 4) {
> +    std::swap(Ptr[i], Ptr[i + 3]);
> +    std::swap(Ptr[i + 1], Ptr[i + 2]);
> +  }
> +}
>
> Added: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h?rev=179591&view=auto
>
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h (added)
> +++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h Tue Apr 16
> 07:02:21 2013
> @@ -0,0 +1,114 @@
> +//===-- ARMUnwindOpAsm.h - ARM Unwind Opcodes Assembler ---------*- C++
> -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +//
> +// This file declares the unwind opcode assmebler for ARM exception
> handling
> +// table.
> +//
>
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef ARM_UNWIND_OP_ASM_H
> +#define ARM_UNWIND_OP_ASM_H
> +
> +#include "ARMUnwindOp.h"
> +
> +#include "llvm/ADT/SmallVector.h"
> +#include "llvm/ADT/StringRef.h"
> +#include "llvm/Support/DataTypes.h"
> +
> +namespace llvm {
> +
> +class MCSymbol;
> +
> +class UnwindOpcodeAssembler {
> +private:
> +  llvm::SmallVector<uint8_t, 8> Ops;
> +
> +  unsigned Offset;
> +  unsigned PersonalityIndex;
> +  bool HasPersonality;
> +
> +  enum {
> +    // The number of bytes to be preserved for the size and personality
> index
> +    // prefix of unwind opcodes.
> +    NUM_PRESERVED_PREFIX_BUF = 2
> +  };
> +
> +public:
> +  UnwindOpcodeAssembler()
> +      : Ops(NUM_PRESERVED_PREFIX_BUF), Offset(NUM_PRESERVED_PREFIX_BUF),
> +        PersonalityIndex(NUM_PERSONALITY_INDEX), HasPersonality(0) {
> +  }
> +
> +  /// Reset the unwind opcode assembler.
> +  void Reset() {
> +    Ops.resize(NUM_PRESERVED_PREFIX_BUF);
> +    Offset = NUM_PRESERVED_PREFIX_BUF;
> +    PersonalityIndex = NUM_PERSONALITY_INDEX;
> +    HasPersonality = 0;
> +  }
> +
> +  /// Get the size of the payload (including the size byte)
> +  size_t size() const {
> +    return Ops.size() - Offset;
> +  }
> +
> +  /// Get the beginning of the payload
> +  const uint8_t *begin() const {
> +    return Ops.begin() + Offset;
> +  }
> +
> +  /// Get the payload
> +  StringRef data() const {
> +    return StringRef(reinterpret_cast<const char *>(begin()), size());
> +  }
> +
> +  /// Set the personality index
> +  void setPersonality(const MCSymbol *Per) {
> +    HasPersonality = 1;
> +  }
> +
> +  /// Get the personality index
> +  unsigned getPersonalityIndex() const {
> +    return PersonalityIndex;
> +  }
> +
> +  /// Emit unwind opcodes for .save directives
> +  void EmitRegSave(uint32_t RegSave);
> +
> +  /// Emit unwind opcodes for .vsave directives
> +  void EmitVFPRegSave(uint32_t VFPRegSave);
> +
> +  /// Emit unwind opcodes for .setfp directives
> +  void EmitSetFP(uint16_t FPReg);
> +
> +  /// Emit unwind opcodes to update stack pointer
> +  void EmitSPOffset(int64_t Offset);
> +
> +  /// Finalize the unwind opcode sequence for EmitBytes()
> +  void Finalize();
> +
> +private:
> +  /// Get the size of the opcodes in bytes.
> +  size_t getOpcodeSize() const {
> +    return Ops.size() - NUM_PRESERVED_PREFIX_BUF;
> +  }
> +
> +  /// Add the length prefix to the payload
> +  void AddOpcodeSizePrefix(size_t Pos);
> +
> +  /// Add personality index prefix in some compact format
> +  void AddPersonalityIndexPrefix(size_t Pos, unsigned PersonalityIndex);
> +
> +  /// Fill the words with finish opcode if it is not aligned
> +  void EmitFinishOpcodes();
> +};
> +
> +} // namespace llvm
> +
> +#endif // ARM_UNWIND_OP_ASM_H
>
> Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/CMakeLists.txt?rev=179591&r1=179590&r2=179591&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/MCTargetDesc/CMakeLists.txt (original)
> +++ llvm/trunk/lib/Target/ARM/MCTargetDesc/CMakeLists.txt Tue Apr 16
> 07:02:21 2013
> @@ -8,6 +8,7 @@ add_llvm_library(LLVMARMDesc
>   ARMMCTargetDesc.cpp
>   ARMMachObjectWriter.cpp
>   ARMELFObjectWriter.cpp
> +  ARMUnwindOpAsm.cpp
>   )
> add_dependencies(LLVMARMDesc ARMCommonTableGen)
>
>
> Added: llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr0.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr0.ll?rev=179591&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr0.ll (added)
> +++ llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr0.ll Tue Apr 16
> 07:02:21 2013
> @@ -0,0 +1,49 @@
> +; RUN: llc -mtriple armv7-unknown-linux-gnueabi \
> +; RUN:     -arm-enable-ehabi -arm-enable-ehabi-descriptors \
> +; RUN:     -disable-fp-elim -filetype=obj -o - %s \
> +; RUN:   | llvm-objdump -s - \
> +; RUN:   | FileCheck %s --check-prefix=CHECK
> +
> +; RUN: llc -mtriple armv7-unknown-linux-gnueabi \
> +; RUN:     -arm-enable-ehabi -arm-enable-ehabi-descriptors \
> +; RUN:     -filetype=obj -o - %s \
> +; RUN:   | llvm-objdump -s - \
> +; RUN:   | FileCheck %s --check-prefix=CHECK-FP-ELIM
> +
> +; RUN: llc -mtriple armv7-unknown-linux-gnueabi \
> +; RUN:     -arm-enable-ehabi -arm-enable-ehabi-descriptors \
> +; RUN:     -disable-fp-elim -filetype=obj -o - %s \
> +; RUN:   | llvm-objdump -r - \
> +; RUN:   | FileCheck %s --check-prefix=CHECK-RELOC
> +
> +; RUN: llc -mtriple armv7-unknown-linux-gnueabi \
> +; RUN:     -arm-enable-ehabi -arm-enable-ehabi-descriptors \
> +; RUN:     -filetype=obj -o - %s \
> +; RUN:   | llvm-objdump -r - \
> +; RUN:   | FileCheck %s --check-prefix=CHECK-RELOC
> +
> +define void @_Z4testv() {
> +entry:
> +  tail call void @_Z15throw_exceptionv()
> +  ret void
> +}
> +
> +declare void @_Z15throw_exceptionv()
> +
> +; CHECK-NOT: section .ARM.extab
> +; CHECK: section .text
> +; CHECK-NOT: section .ARM.extab
> +; CHECK: section .ARM.exidx
> +; CHECK-NEXT: 0000 00000000 80849b80
> +; CHECK-NOT: section .ARM.extab
> +
> +; CHECK-FP-ELIM-NOT: section .ARM.extab
> +; CHECK-FP-ELIM: section .text
> +; CHECK-FP-ELIM-NOT: section .ARM.extab
> +; CHECK-FP-ELIM: section .ARM.exidx
> +; CHECK-FP-ELIM-NEXT: 0000 00000000 b0808480
> +; CHECK-FP-ELIM-NOT: section .ARM.extab
> +
> +; CHECK-RELOC: RELOCATION RECORDS FOR [.ARM.exidx]
> +; CHECK-RELOC-NEXT: 0 R_ARM_PREL31 .text
> +; CHECK-RELOC-NEXT: 0 R_ARM_NONE __aeabi_unwind_cpp_pr0
>
> Added: llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr1.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr1.ll?rev=179591&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr1.ll (added)
> +++ llvm/trunk/test/CodeGen/ARM/ehabi-mc-compact-pr1.ll Tue Apr 16
> 07:02:21 2013
> @@ -0,0 +1,62 @@
> +; RUN: llc -mtriple armv7-unknown-linux-gnueabi \
> +; RUN:     -arm-enable-ehabi -arm-enable-ehabi-descriptors \
> +; RUN:     -disable-fp-elim -filetype=obj -o - %s \
> +; RUN:   | llvm-objdump -s - \
> +; RUN:   | FileCheck %s --check-prefix=CHECK
> +
> +; RUN: llc -mtriple armv7-unknown-linux-gnueabi \
> +; RUN:     -arm-enable-ehabi -arm-enable-ehabi-descriptors \
> +; RUN:     -filetype=obj -o - %s \
> +; RUN:   | llvm-objdump -s - \
> +; RUN:   | FileCheck %s --check-prefix=CHECK-FP-ELIM
> +
> +; RUN: llc -mtriple armv7-unknown-linux-gnueabi \
> +; RUN:     -arm-enable-ehabi -arm-enable-ehabi-descriptors \
> +; RUN:     -disable-fp-elim -filetype=obj -o - %s \
> +; RUN:   | llvm-objdump -r - \
> +; RUN:   | FileCheck %s --check-prefix=CHECK-RELOC
> +
> +; RUN: llc -mtriple armv7-unknown-linux-gnueabi \
> +; RUN:     -arm-enable-ehabi -arm-enable-ehabi-descriptors \
> +; RUN:     -filetype=obj -o - %s \
> +; RUN:   | llvm-objdump -r - \
> +; RUN:   | FileCheck %s --check-prefix=CHECK-FP-ELIM-RELOC
> +
> +define i32 @_Z3addiiiiiiii(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32
> %f, i32 %g, i32 %h) {
> +entry:
> +  %add = add nsw i32 %b, %a
> +  %add1 = add nsw i32 %add, %c
> +  %add2 = add nsw i32 %add1, %d
> +  tail call void @_Z15throw_exceptioni(i32 %add2)
> +  %add3 = add nsw i32 %f, %e
> +  %add4 = add nsw i32 %add3, %g
> +  %add5 = add nsw i32 %add4, %h
> +  tail call void @_Z15throw_exceptioni(i32 %add5)
> +  %add6 = add nsw i32 %add5, %add2
> +  ret i32 %add6
> +}
> +
> +declare void @_Z15throw_exceptioni(i32)
> +
> +; CHECK-NOT: section .ARM.extab
> +; CHECK: section .text
> +; CHECK: section .ARM.extab
> +; CHECK-NEXT: 0000 419b0181 b0b08384
> +; CHECK: section .ARM.exidx
> +; CHECK-NEXT: 0000 00000000 00000000
> +; CHECK-NOT: section .ARM.extab
> +
> +; CHECK-FP-ELIM-NOT: section .ARM.extab
> +; CHECK-FP-ELIM: section .text
> +; CHECK-FP-ELIM-NOT: section .ARM.extab
> +; CHECK-FP-ELIM: section .ARM.exidx
> +; CHECK-FP-ELIM-NEXT: 0000 00000000 b0838480
> +; CHECK-FP-ELIM-NOT: section .ARM.extab
> +
> +; CHECK-RELOC: RELOCATION RECORDS FOR [.ARM.exidx]
> +; CHECK-RELOC-NEXT: 0 R_ARM_PREL31 .text
> +; CHECK-RELOC-NEXT: 0 R_ARM_NONE __aeabi_unwind_cpp_pr1
> +
> +; CHECK-FP-ELIM-RELOC: RELOCATION RECORDS FOR [.ARM.exidx]
> +; CHECK-FP-ELIM-RELOC-NEXT: 0 R_ARM_PREL31 .text
> +; CHECK-FP-ELIM-RELOC-NEXT: 0 R_ARM_NONE __aeabi_unwind_cpp_pr0
>
> Modified: llvm/trunk/test/CodeGen/ARM/ehabi-mc-section-group.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/ehabi-mc-section-group.ll?rev=179591&r1=179590&r2=179591&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/ARM/ehabi-mc-section-group.ll (original)
> +++ llvm/trunk/test/CodeGen/ARM/ehabi-mc-section-group.ll Tue Apr 16
> 07:02:21 2013
> @@ -72,17 +72,17 @@ declare void @_ZSt9terminatev()
> ; CHECK:          Index: 1
> ; CHECK-NEXT:     Name: .group (47)
> ; CHECK:          SectionData (
> -; CHECK-NEXT:       0000: 01000000 0A000000 0C000000 0E000000
> +; CHECK-NEXT:       0000: 01000000 09000000 0B000000 0D000000
> ; CHECK-NEXT:     )
>
> ; CHECK:        Section {
> -; CHECK:          Index: 10
> -; CHECK-NEXT:     Name: .text._Z4testIidEvT_S0_S0_S0_S0_T0_S1_S1_S1_S1_
> (225)
> +; CHECK:          Index: 9
> +; CHECK-NEXT:     Name: .text._Z4testIidEvT_S0_S0_S0_S0_T0_S1_S1_S1_S1_
> (214)
>
> ; CHECK:        Section {
> -; CHECK:          Index: 12
> -; CHECK-NEXT:     Name:
> .ARM.extab.text._Z4testIidEvT_S0_S0_S0_S0_T0_S1_S1_S1_S1_ (215)
> +; CHECK:          Index: 11
> +; CHECK-NEXT:     Name:
> .ARM.extab.text._Z4testIidEvT_S0_S0_S0_S0_T0_S1_S1_S1_S1_ (204)
>
> ; CHECK:        Section {
> -; CHECK:          Index: 14
> -; CHECK-NEXT:     Name:
> .ARM.exidx.text._Z4testIidEvT_S0_S0_S0_S0_T0_S1_S1_S1_S1_ (101)
> +; CHECK:          Index: 13
> +; CHECK-NEXT:     Name:
> .ARM.exidx.text._Z4testIidEvT_S0_S0_S0_S0_T0_S1_S1_S1_S1_ (90)
>
> Modified: llvm/trunk/test/CodeGen/ARM/ehabi-mc-section.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/ehabi-mc-section.ll?rev=179591&r1=179590&r2=179591&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/ARM/ehabi-mc-section.ll (original)
> +++ llvm/trunk/test/CodeGen/ARM/ehabi-mc-section.ll Tue Apr 16 07:02:21
> 2013
> @@ -1,8 +1,14 @@
> -; RUN: llc -mtriple arm-unknown-linux-gnueabi \
> +; RUN: llc -mtriple armv7-unknown-linux-gnueabi \
> +; RUN:     -arm-enable-ehabi -arm-enable-ehabi-descriptors \
> +; RUN:     -disable-fp-elim -filetype=obj -o - %s \
> +; RUN:   | llvm-objdump -s - \
> +; RUN:   | FileCheck %s --check-prefix=CHECK
> +
> +; RUN: llc -mtriple armv7-unknown-linux-gnueabi \
> ; RUN:     -arm-enable-ehabi -arm-enable-ehabi-descriptors \
> ; RUN:     -filetype=obj -o - %s \
> ; RUN:   | llvm-objdump -s - \
> -; RUN:   | FileCheck %s
> +; RUN:   | FileCheck %s --check-prefix=CHECK-FP-ELIM
>
> define void @_Z4testiiiiiddddd(i32 %u1, i32 %u2, i32 %u3, i32 %u4, i32
> %u5, double %v1, double %v2, double %v3, double %v4, double %v5) section
> ".test_section" {
> entry:
> @@ -54,6 +60,12 @@ declare void @_ZSt9terminatev()
>
> ; CHECK: section .test_section
> ; CHECK: section .ARM.extab.test_section
> -; CHECK-NEXT: 0000 00000000 b0b0b000
> +; CHECK-NEXT: 0000 00000000 c9409b01 b0818484
> ; CHECK: section .ARM.exidx.test_section
> ; CHECK-NEXT: 0000 00000000 00000000
> +
> +; CHECK-FP-ELIM: section .test_section
> +; CHECK-FP-ELIM: section .ARM.extab.test_section
> +; CHECK-FP-ELIM-NEXT: 0000 00000000 84c90501 b0b0b0a8
> +; CHECK-FP-ELIM: section .ARM.exidx.test_section
> +; CHECK-FP-ELIM-NEXT: 0000 00000000 00000000
>
> Modified: llvm/trunk/test/CodeGen/ARM/ehabi-mc.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/ehabi-mc.ll?rev=179591&r1=179590&r2=179591&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/ARM/ehabi-mc.ll (original)
> +++ llvm/trunk/test/CodeGen/ARM/ehabi-mc.ll Tue Apr 16 07:02:21 2013
> @@ -1,8 +1,14 @@
> -; RUN: llc -mtriple arm-unknown-linux-gnueabi \
> +; RUN: llc -mtriple armv7-unknown-linux-gnueabi \
> +; RUN:     -arm-enable-ehabi -arm-enable-ehabi-descriptors \
> +; RUN:     -disable-fp-elim -filetype=obj -o - %s \
> +; RUN:   | llvm-objdump -s - \
> +; RUN:   | FileCheck %s --check-prefix=CHECK
> +
> +; RUN: llc -mtriple armv7-unknown-linux-gnueabi \
> ; RUN:     -arm-enable-ehabi -arm-enable-ehabi-descriptors \
> ; RUN:     -filetype=obj -o - %s \
> ; RUN:   | llvm-objdump -s - \
> -; RUN:   | FileCheck %s
> +; RUN:   | FileCheck %s --check-prefix=CHECK-FP-ELIM
>
> define void @_Z4testiiiiiddddd(i32 %u1, i32 %u2, i32 %u3, i32 %u4, i32
> %u5, double %v1, double %v2, double %v3, double %v4, double %v5) {
> entry:
> @@ -54,6 +60,12 @@ declare void @_ZSt9terminatev()
>
> ; CHECK: section .text
> ; CHECK: section .ARM.extab
> -; CHECK-NEXT: 0000 00000000 b0b0b000
> +; CHECK-NEXT: 0000 00000000 c9409b01 b0818484
> ; CHECK: section .ARM.exidx
> ; CHECK-NEXT: 0000 00000000 00000000
> +
> +; CHECK-FP-ELIM: section .text
> +; CHECK-FP-ELIM: section .ARM.extab
> +; CHECK-FP-ELIM-NEXT: 0000 00000000 84c90501 b0b0b0a8
> +; CHECK-FP-ELIM: section .ARM.exidx
> +; CHECK-FP-ELIM-NEXT: 0000 00000000 00000000
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130417/8c16644e/attachment.html>


More information about the llvm-commits mailing list