Index: lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ } 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 @@ 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 @@ 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); + CollectUnwindOpcodes(); - // 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; - - 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 @@ 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 @@ 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 &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 { Index: lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h +++ lib/Target/ARM/MCTargetDesc/ARMUnwindOp.h @@ -107,6 +107,19 @@ 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 Index: lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h +++ lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h @@ -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 Ops; + + unsigned Offset: 2; + unsigned HasPersonality: 1; + unsigned PersonalityIndex: 5; + + 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), + HasPersonality(0), PersonalityIndex(NUM_PERSONALITY_INDEX) { + } + + /// Reset the unwind opcode assembler. + void Reset() { + Ops.resize(NUM_PRESERVED_PREFIX_BUF); + Offset = NUM_PRESERVED_PREFIX_BUF; + HasPersonality = 0; + PersonalityIndex = NUM_PERSONALITY_INDEX; + } + + /// 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(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 Index: lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp +++ lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp @@ -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(Op >> 8)); + Ops.push_back(static_cast(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(Op >> 8)); + Ops.push_back(static_cast(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(Op >> 8)); + Ops.push_back(static_cast(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(Op >> 8)); + Ops.push_back(static_cast(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((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(((-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(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]); + } +} Index: lib/Target/ARM/MCTargetDesc/CMakeLists.txt =================================================================== --- lib/Target/ARM/MCTargetDesc/CMakeLists.txt +++ lib/Target/ARM/MCTargetDesc/CMakeLists.txt @@ -8,6 +8,7 @@ ARMMCTargetDesc.cpp ARMMachObjectWriter.cpp ARMELFObjectWriter.cpp + ARMUnwindOpAsm.cpp ) add_dependencies(LLVMARMDesc ARMCommonTableGen) Index: test/CodeGen/ARM/ehabi-mc-compact-pr0.ll =================================================================== --- test/CodeGen/ARM/ehabi-mc-compact-pr0.ll +++ test/CodeGen/ARM/ehabi-mc-compact-pr0.ll @@ -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 Index: test/CodeGen/ARM/ehabi-mc-compact-pr1.ll =================================================================== --- test/CodeGen/ARM/ehabi-mc-compact-pr1.ll +++ test/CodeGen/ARM/ehabi-mc-compact-pr1.ll @@ -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 Index: test/CodeGen/ARM/ehabi-mc-section-group.ll =================================================================== --- test/CodeGen/ARM/ehabi-mc-section-group.ll +++ test/CodeGen/ARM/ehabi-mc-section-group.ll @@ -72,17 +72,17 @@ ; 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) Index: test/CodeGen/ARM/ehabi-mc-section.ll =================================================================== --- test/CodeGen/ARM/ehabi-mc-section.ll +++ test/CodeGen/ARM/ehabi-mc-section.ll @@ -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 @@ ; 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 Index: test/CodeGen/ARM/ehabi-mc.ll =================================================================== --- test/CodeGen/ARM/ehabi-mc.ll +++ test/CodeGen/ARM/ehabi-mc.ll @@ -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 @@ ; 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