[llvm] r179591 - Implement ARM unwind opcode assembler.

Jim Grosbach grosbach at apple.com
Wed Apr 17 09:54:32 PDT 2013


Hi Logan,

Can we move this test case to check the .s file output instead, then, rather than the .o file? As-is this is not a viable test case and must be fixed. It’s far too fragile, and if/when something changes that causes the test to fail, it’s completely opaque whether the test case just need updated or whether the failure indicates a real problem in the newer code. Worst case, we will need to revert this patch and do the assembly parser work first to enable a better test case. I’d really like to avoid that if possible, obviously. FWIW, in the future this sort of thing tends to be made much easier by doing the assembler support first, then building on that for the compiler.

-Jim

On Apr 17, 2013, at 12:43 AM, Logan Chien <tzuhsiang.chien at gmail.com> wrote:

> 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/aaa32999/attachment.html>


More information about the llvm-commits mailing list