[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