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 < 16 && "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,17 @@ 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); +} + void ARMELFStreamer::EmitFnStart() { assert(FnStart == 0); FnStart = getContext().CreateTempSymbol(); @@ -296,33 +333,30 @@ // 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); + if (UnwindOpAsm.getOpcodeSize() <= 3) { + PersonalityIndex = 0; + UnwindOpAsm.Finalize(PersonalityIndex); + } else { + PersonalityIndex = 1; + UnwindOpAsm.Finalize(PersonalityIndex); - PersonalityIndex = 1; + // For __aeabi_unwind_cpp_pr1, we have to emit opcodes in .ARM.extab. + SwitchToExTabSection(*FnStart); - 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); + // Create temporary label for reference + 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"); + if (PersonalityIndex == 0 || PersonalityIndex == 1) + EmitPersonalityFixup(GetAEABIUnwindPersonalityName(PersonalityIndex)); const MCSymbolRefExpr *FnStartRef = MCSymbolRefExpr::Create(FnStart, @@ -333,12 +367,16 @@ if (CantUnwind) { EmitIntValue(EXIDX_CANTUNWIND, 4, 0); - } else { + } else if (ExTab) { const MCSymbolRefExpr *ExTabEntryRef = MCSymbolRefExpr::Create(ExTab, MCSymbolRefExpr::VK_ARM_PREL31, getContext()); EmitValue(ExTabEntryRef, 4, 0); + } else { + 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 +406,51 @@ EmitValue(PersonalityRef, 4, 0); // Emit unwind opcodes - uint32_t Entry = 0; - uint32_t NumExtraEntryWords = 0; + CollectUnwindOpcodes(); + UnwindOpAsm.Finalize(-1); - // 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); + EmitBytes(UnwindOpAsm.data(), 0); } void ARMELFStreamer::EmitPersonality(const MCSymbol *Per) { Personality = 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/ARMUnwindOpAsm.h =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h +++ lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h @@ -0,0 +1,96 @@ +//===-- 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 "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class UnwindOpcodeAssembler { +private: + size_t Offset; + llvm::SmallVector Ops; + +public: + UnwindOpcodeAssembler(): Offset(2) { + // Note: These are placeholders for possible additional prefix for unwind + // opcodes. Read Finalize() for more details. + Ops.push_back(0x00); + Ops.push_back(0x00); + } + + /// Reset the unwind opcode assembler. + void Reset() { + Ops.resize(0); + + // Note: These are placeholders for possible additional prefix for unwind + // opcodes. Read Finalize() for more details. + Ops.push_back(0x00); + Ops.push_back(0x00); + Offset = 2; + } + + /// Get the size of the opcodes in bytes. + size_t getOpcodeSize() const { + return Ops.size() - 2; + } + + /// 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()); + } + + /// 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(int PersonalityIndex); + +private: + /// 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, int 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,194 @@ +//===-- 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 bytes opcode to save register r14 and r11-r4 + if (RegSave & 0x0010u) { + uint32_t Range = 0; + uint32_t Mask = 0x0010; + for (uint32_t Bit = (1u << 5); Bit < (1u << 12); Bit <<= 1) { + if ((RegSave & Bit) == 0u) + break; + ++Range; + Mask |= Bit; + } + + if (RegSave & 0x4000u) { + if (((RegSave & 0xbff0u) & (~Mask)) == 0u) { + // Pop r[14] + r[4 : (4 + n)] + Ops.push_back(UNWIND_OPCODE_POP_REG_RANGE_R4_R14 | Range); + RegSave &= 0x000fu; + } + } else { + if (((RegSave & 0xfff0u) & (~Mask)) == 0u) { + // Pop r[4 : (4 + n)] + Ops.push_back(UNWIND_OPCODE_POP_REG_RANGE_R4 | Range); + RegSave &= 0x000fu; + } + } + } + + // Two bytes opcode to save register r15-r4 + if ((RegSave & 0xfff0u) != 0) { + uint32_t Op = 0x8000u | (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; + } + + Ops.push_back(0xc8u); + Ops.push_back(((i - 16) << 4) | Range); + } + + 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; + } + + Ops.push_back(0xc9u); + Ops.push_back((i << 4) | Range); + } +} + +/// 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, + int PersonalityIndex) { + Ops[Pos] = EHT_COMPACT | PersonalityIndex; +} + +void UnwindOpcodeAssembler::EmitFinishOpcodes() { + for (size_t i = (0x4u - (size() & 0x3u)) & 0x3u; i > 0; --i) + Ops.push_back(UNWIND_OPCODE_FINISH); +} + +void UnwindOpcodeAssembler::Finalize(int PersonalityIndex) { + // Add the prefix properly + if (PersonalityIndex == 0) { + // __aeabi_unwind_cpp_pr0: [ 0x80 , OP1 , OP2 , OP3 ] + assert(getOpcodeSize() <= 3 && + "too many opcodes for __aeabi_unwind_cpp_pr0"); + Offset = 1; + AddPersonalityIndexPrefix(1, PersonalityIndex); + + } else if (PersonalityIndex == 1) { + // __aeabi_unwind_cpp_pr1: [ 0x81 , SIZE , OP1 , OP2 , ... ] + Offset = 0; + AddPersonalityIndexPrefix(0, PersonalityIndex); + AddOpcodeSizePrefix(1); + + } else if (PersonalityIndex == -1) { + // Personality specified by .personality directive + Offset = 1; + 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 @@ -70,10 +70,10 @@ ; CHECK: # Section 1 ; CHECK-NEXT: (('sh_name', 0x0000002f) # '.group' -; CHECK: ('_section_data', '01000000 0a000000 0c000000 0e000000') -; CHECK: # Section 10 -; CHECK-NEXT: (('sh_name', 0x000000e1) # '.text._Z4testIidEvT_S0_S0_S0_S0_T0_S1_S1_S1_S1_' -; CHECK: # Section 12 -; CHECK-NEXT: (('sh_name', 0x000000d7) # '.ARM.extab.text._Z4testIidEvT_S0_S0_S0_S0_T0_S1_S1_S1_S1_' -; CHECK: # Section 14 -; CHECK-NEXT: (('sh_name', 0x00000065) # '.ARM.exidx.text._Z4testIidEvT_S0_S0_S0_S0_T0_S1_S1_S1_S1_' +; CHECK: ('_section_data', '01000000 09000000 0b000000 0d000000') +; CHECK: # Section 9 +; CHECK-NEXT: (('sh_name', 0x000000d6) # '.text._Z4testIidEvT_S0_S0_S0_S0_T0_S1_S1_S1_S1_' +; CHECK: # Section 11 +; CHECK-NEXT: (('sh_name', 0x000000cc) # '.ARM.extab.text._Z4testIidEvT_S0_S0_S0_S0_T0_S1_S1_ +; CHECK: # Section 13 +; CHECK-NEXT: (('sh_name', 0x0000005a) # '.ARM.exidx.text._Z4testIidEvT_S0_S0_S0_S0_T0_S1_S1_S1_S1_' 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