From 35e04e84fa8c08705ec0fd88abfe2e8646f79835 Mon Sep 17 00:00:00 2001 From: James Y Knight Date: Fri, 1 May 2015 17:13:02 +0000 Subject: [PATCH] [Sparc] Repair fixups in little endian mode. Differential Revision: http://reviews.llvm.org/D9434 llvm-svn: 236324 --- .../Sparc/MCTargetDesc/SparcAsmBackend.cpp | 69 +++++++++++++++---- llvm/test/MC/Sparc/sparc-little-endian.s | 18 +++++ 2 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 llvm/test/MC/Sparc/sparc-little-endian.s diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp index c9c3f5379962..3792a596a6b8 100644 --- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -98,16 +98,23 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { namespace { class SparcAsmBackend : public MCAsmBackend { + protected: const Target &TheTarget; + bool IsLittleEndian; + bool Is64Bit; + public: - SparcAsmBackend(const Target &T) : MCAsmBackend(), TheTarget(T) {} + SparcAsmBackend(const Target &T) + : MCAsmBackend(), TheTarget(T), + IsLittleEndian(StringRef(TheTarget.getName()) == "sparcel"), + Is64Bit(StringRef(TheTarget.getName()) == "sparcv9") {} unsigned getNumFixupKinds() const override { return Sparc::NumTargetFixupKinds; } const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { - const static MCFixupKindInfo Infos[Sparc::NumTargetFixupKinds] = { + const static MCFixupKindInfo InfosBE[Sparc::NumTargetFixupKinds] = { // name offset bits flags { "fixup_sparc_call30", 2, 30, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_sparc_br22", 10, 22, MCFixupKindInfo::FKF_IsPCRel }, @@ -146,12 +153,54 @@ namespace { { "fixup_sparc_tls_le_lox10", 0, 0, 0 } }; + const static MCFixupKindInfo InfosLE[Sparc::NumTargetFixupKinds] = { + // name offset bits flags + { "fixup_sparc_call30", 0, 30, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_br22", 0, 22, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_br16_2", 20, 2, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_br16_14", 0, 14, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_hi22", 0, 22, 0 }, + { "fixup_sparc_lo10", 0, 10, 0 }, + { "fixup_sparc_h44", 0, 22, 0 }, + { "fixup_sparc_m44", 0, 10, 0 }, + { "fixup_sparc_l44", 0, 12, 0 }, + { "fixup_sparc_hh", 0, 22, 0 }, + { "fixup_sparc_hm", 0, 10, 0 }, + { "fixup_sparc_pc22", 0, 22, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_pc10", 0, 10, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_got22", 0, 22, 0 }, + { "fixup_sparc_got10", 0, 10, 0 }, + { "fixup_sparc_wplt30", 0, 30, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_tls_gd_hi22", 0, 22, 0 }, + { "fixup_sparc_tls_gd_lo10", 0, 10, 0 }, + { "fixup_sparc_tls_gd_add", 0, 0, 0 }, + { "fixup_sparc_tls_gd_call", 0, 0, 0 }, + { "fixup_sparc_tls_ldm_hi22", 0, 22, 0 }, + { "fixup_sparc_tls_ldm_lo10", 0, 10, 0 }, + { "fixup_sparc_tls_ldm_add", 0, 0, 0 }, + { "fixup_sparc_tls_ldm_call", 0, 0, 0 }, + { "fixup_sparc_tls_ldo_hix22", 0, 22, 0 }, + { "fixup_sparc_tls_ldo_lox10", 0, 10, 0 }, + { "fixup_sparc_tls_ldo_add", 0, 0, 0 }, + { "fixup_sparc_tls_ie_hi22", 0, 22, 0 }, + { "fixup_sparc_tls_ie_lo10", 0, 10, 0 }, + { "fixup_sparc_tls_ie_ld", 0, 0, 0 }, + { "fixup_sparc_tls_ie_ldx", 0, 0, 0 }, + { "fixup_sparc_tls_ie_add", 0, 0, 0 }, + { "fixup_sparc_tls_le_hix22", 0, 0, 0 }, + { "fixup_sparc_tls_le_lox10", 0, 0, 0 } + }; + if (Kind < FirstTargetFixupKind) return MCAsmBackend::getFixupKindInfo(Kind); assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && "Invalid kind!"); - return Infos[Kind - FirstTargetFixupKind]; + if (IsLittleEndian) + return InfosLE[Kind - FirstTargetFixupKind]; + + return InfosBE[Kind - FirstTargetFixupKind]; } void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, @@ -215,11 +264,6 @@ namespace { return true; } - - bool is64Bit() const { return StringRef(TheTarget.getName()) == "sparcv9"; } - bool isLittleEndian() const { - return StringRef(TheTarget.getName()) == "sparcel"; - } }; class ELFSparcAsmBackend : public SparcAsmBackend { @@ -239,14 +283,15 @@ namespace { // For each byte of the fragment that the fixup touches, mask in the bits // from the fixup value. The Value has been "split up" into the // appropriate bitfields above. - for (unsigned i = 0; i != 4; ++i) - Data[Offset + i] |= uint8_t((Value >> ((4 - i - 1)*8)) & 0xff); - + for (unsigned i = 0; i != 4; ++i) { + unsigned Idx = IsLittleEndian ? i : 3 - i; + Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff); + } } MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override { uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType); - return createSparcELFObjectWriter(OS, is64Bit(), isLittleEndian(), OSABI); + return createSparcELFObjectWriter(OS, Is64Bit, IsLittleEndian, OSABI); } }; diff --git a/llvm/test/MC/Sparc/sparc-little-endian.s b/llvm/test/MC/Sparc/sparc-little-endian.s new file mode 100644 index 000000000000..18ced35c8883 --- /dev/null +++ b/llvm/test/MC/Sparc/sparc-little-endian.s @@ -0,0 +1,18 @@ +! RUN: llvm-mc %s -arch=sparcel -show-encoding | FileCheck %s +! RUN: llvm-mc -arch=sparcel -filetype=obj < %s | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-OBJ + + ! CHECK-OBJ: .text: + .BB0: + + ! Ensure instructions are emitted in reversed byte order: + + ! CHECK: call %g1 ! encoding: [0x00,0x40,0xc0,0x9f] + ! CHECK-OBJ: 0: 00 40 c0 9f call %g1 + call %g1 + + ! ...and that fixups are applied to the correct bytes. + + ! CHECK: ba .BB0 ! encoding: [A,A,0b10AAAAAA,0x10] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + ! CHECK-OBJ: 4: ff ff bf 10 ba 4194303 + ba .BB0