diff options
author | Simon Atanasyan <simon@atanasyan.com> | 2015-07-21 05:54:22 +0000 |
---|---|---|
committer | Simon Atanasyan <simon@atanasyan.com> | 2015-07-21 05:54:22 +0000 |
commit | f9db71eaec623d4e50f0efe6dc327388f70d8de3 (patch) | |
tree | fa7fe76cad917dd08da98bd31aef9acbea9d78d0 | |
parent | 61459cef40cd99fa9fcef7b986eb72b63635e4de (diff) | |
download | bcm5719-llvm-f9db71eaec623d4e50f0efe6dc327388f70d8de3.tar.gz bcm5719-llvm-f9db71eaec623d4e50f0efe6dc327388f70d8de3.zip |
[Mips] Handle R_MIPS_JALR relocation to omptimize jalr/jr instructions
llvm-svn: 242759
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp | 45 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp | 4 | ||||
-rw-r--r-- | lld/test/elf/Mips/jalx-jalr.test | 47 | ||||
-rw-r--r-- | lld/test/elf/Mips/rel-jalr-01.test | 101 | ||||
-rw-r--r-- | lld/test/elf/Mips/rel-jalr-02.test | 68 |
5 files changed, 255 insertions, 10 deletions
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp index 3e9619f9f19..c0feb735960 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp @@ -21,7 +21,8 @@ namespace { enum class CrossJumpMode { None, // Not a jump or non-isa-cross jump ToRegular, // cross isa jump to regular symbol - ToMicro // cross isa jump to microMips symbol + ToMicro, // cross isa jump to microMips symbol + ToMicroJalr// cross isa jump to microMips symbol referenced by R_MIPS_JALR }; typedef std::function<std::error_code(int64_t, bool)> OverflowChecker; @@ -178,7 +179,7 @@ static MipsRelocationParams getRelocationParams(uint32_t rType) { case R_MICROMIPS_GOT_OFST: return {4, 0xffff, 0, true, signedCheck<16>}; case R_MIPS_JALR: - return {4, 0x0, 0, false, dummyCheck}; + return {4, 0xffffffff, 0, false, dummyCheck}; case R_MICROMIPS_JALR: return {4, 0x0, 0, true, dummyCheck}; case R_MIPS_JUMP_SLOT: @@ -200,6 +201,10 @@ static MipsRelocationParams getRelocationParams(uint32_t rType) { } } +template <class ELFT> +static uint64_t relocRead(const MipsRelocationParams ¶ms, + const uint8_t *loc); + static int64_t getHi16(int64_t value) { return ((value + 0x8000) >> 16) & 0xffff; } @@ -299,6 +304,22 @@ static ErrorOr<int64_t> relocPc26(uint64_t P, uint64_t S, int64_t A) { return S + A - P; } +template <class ELFT> +static ErrorOr<int64_t> relocJalr(uint64_t P, uint64_t S, bool isCrossJump, + uint8_t *location) { + uint64_t ins = relocRead<ELFT>(getRelocationParams(R_MIPS_JALR), location); + if (isCrossJump) + return ins; + int64_t off = S - P - 4; + if (!llvm::isInt<18>(off)) + return ins; + if (ins == 0x0320f809) // jalr t9 + return 0x04110000 | ((off >> 2) & 0xffff); + if (ins == 0x03200008) // jr t9 + return 0x10000000 | ((off >> 2) & 0xffff); + return ins; +} + static int64_t relocRel32(int64_t A) { // If output relocation format is REL and the input one is RELA, the only // method to transfer the relocation addend from the input relocation @@ -309,7 +330,7 @@ static int64_t relocRel32(int64_t A) { static std::error_code adjustJumpOpCode(uint64_t &ins, uint64_t tgt, CrossJumpMode mode) { - if (mode == CrossJumpMode::None) + if (mode == CrossJumpMode::None || mode == CrossJumpMode::ToMicroJalr) return std::error_code(); bool toMicro = mode == CrossJumpMode::ToMicro; @@ -345,6 +366,8 @@ static CrossJumpMode getCrossJumpMode(const Reference &ref) { return CrossJumpMode::None; bool isTgtMicro = isMicroMipsAtom(ref.target()); switch (ref.kindValue()) { + case R_MIPS_JALR: + return isTgtMicro ? CrossJumpMode::ToMicroJalr : CrossJumpMode::None; case R_MIPS_26: case LLD_R_MIPS_GLOBAL_26: return isTgtMicro ? CrossJumpMode::ToMicro : CrossJumpMode::None; @@ -356,11 +379,12 @@ static CrossJumpMode getCrossJumpMode(const Reference &ref) { } } -static ErrorOr<int64_t> calculateRelocation(Reference::KindValue kind, - Reference::Addend addend, - uint64_t tgtAddr, uint64_t relAddr, - uint64_t gpAddr, bool isGP, - bool isCrossJump, bool isDynamic) { +template <class ELFT> +static ErrorOr<int64_t> +calculateRelocation(Reference::KindValue kind, Reference::Addend addend, + uint64_t tgtAddr, uint64_t relAddr, uint64_t gpAddr, + bool isGP, bool isCrossJump, bool isDynamic, + uint8_t *location) { switch (kind) { case R_MIPS_NONE: return 0; @@ -461,6 +485,7 @@ static ErrorOr<int64_t> calculateRelocation(Reference::KindValue kind, case R_MICROMIPS_LITERAL: return tgtAddr + addend - gpAddr; case R_MIPS_JALR: + return relocJalr<ELFT>(relAddr, tgtAddr, isCrossJump, location); case R_MICROMIPS_JALR: // We do not do JALR optimization now. return 0; @@ -591,8 +616,8 @@ std::error_code RelocationHandler<ELFT>::applyRelocation( if (kind == R_MIPS_NONE) break; auto params = getRelocationParams(kind); - res = calculateRelocation(kind, *res, sym, relAddr, gpAddr, isGpDisp, - isCrossJump, _ctx.isDynamic()); + res = calculateRelocation<ELFT>(kind, *res, sym, relAddr, gpAddr, isGpDisp, + isCrossJump, _ctx.isDynamic(), location); if (auto ec = res.getError()) return ec; // Check result for the last relocation only. diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp index d9be544b681..99d2ccf9676 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp @@ -771,6 +771,10 @@ void RelocationPass<ELFT>::handleReference(const MipsELFDefinedAtom<ELFT> &atom, ref.setTarget(getTLSGOTEntry(ref.target(), ref.addend())); else if (kind == R_MIPS_GPREL32 || (isLocal(ref.target()) && isGpRelReloc(kind))) ref.setAddend(ref.addend() + atom.file().getGP0()); + else if (kind == R_MIPS_JALR) { + if (_ctx.getOutputELFType() != ET_EXEC || !isLocalCall(ref.target())) + ref.setKindValue(R_MIPS_NONE); + } } template <typename ELFT> diff --git a/lld/test/elf/Mips/jalx-jalr.test b/lld/test/elf/Mips/jalx-jalr.test new file mode 100644 index 00000000000..9b5eff5a6d9 --- /dev/null +++ b/lld/test/elf/Mips/jalx-jalr.test @@ -0,0 +1,47 @@ +# Check that R_MIPS_JALR relocation does not affect code in case of cross jump. + +# RUN: yaml2obj -format=elf %s > %t.o +# RUN: lld -flavor gnu -target mipsel -o %t.exe %t.o +# RUN: llvm-objdump -s %t.exe | FileCheck %s + +# CHECK: Contents of section .text: +# CHECK-NEXT: {{[0-9a-f]+}} 08002003 00000000 + +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, + EF_MIPS_MICROMIPS, EF_MIPS_ARCH_32R2] + +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 16 + Content: "0800200300000000" + + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 4 + Info: .text + Relocations: + - Offset: 0 + Symbol: M1 + Type: R_MIPS_JALR + +Symbols: + Global: + - Name: __start + Type: STT_FUNC + Section: .text + Value: 0 + Size: 4 + - Name: M1 + Type: STT_FUNC + Section: .text + Value: 4 + Size: 4 + Other: [ STO_MIPS_MICROMIPS ] diff --git a/lld/test/elf/Mips/rel-jalr-01.test b/lld/test/elf/Mips/rel-jalr-01.test new file mode 100644 index 00000000000..48f7c44fa18 --- /dev/null +++ b/lld/test/elf/Mips/rel-jalr-01.test @@ -0,0 +1,101 @@ +# REQUIRES: mips + +# Check handling of the R_MIPS_JALR relocation. + +# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o +# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t1.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o +# RUN: lld -flavor gnu -target mipsel -o %t.exe %t2.o %t.so +# RUN: llvm-objdump -d %t.exe | FileCheck %s + +# CHECK: __start: +# CHECK-NEXT: {{[0-9a-f]+}}: 05 00 11 04 bal 24 +# CHECK-NEXT: {{[0-9a-f]+}}: 00 00 00 00 nop +# CHECK-NEXT: {{[0-9a-f]+}}: 04 00 00 10 b 20 +# CHECK-NEXT: {{[0-9a-f]+}}: 00 00 00 00 nop +# CHECK-NEXT: {{[0-9a-f]+}}: 09 f8 20 03 jalr $25 +# CHECK-NEXT: {{[0-9a-f]+}}: 00 00 00 00 nop + +# t1.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32] + +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 16 + Size: 4 + +Symbols: + Global: + - Name: T3 + Type: STT_FUNC + Section: .text + Value: 0 + Size: 4 + +# t2.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32] + +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 16 + Content: "09f8200300000000080020030000000009f82003000000000000000000000000" +# ^ jalr T1 ^ j T2 ^ jalr T3 + + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 4 + Info: .text + Relocations: + - Offset: 0 + Symbol: T1 + Type: R_MIPS_JALR + - Offset: 8 + Symbol: T2 + Type: R_MIPS_JALR + - Offset: 16 + Symbol: T3 + Type: R_MIPS_JALR + + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 16 + Size: 0 + +Symbols: + Local: + - Name: T1 + Type: STT_FUNC + Section: .text + Value: 24 + Size: 4 + Global: + - Name: __start + Type: STT_FUNC + Section: .text + Value: 0 + Size: 24 + - Name: T2 + Type: STT_FUNC + Section: .text + Value: 28 + Size: 4 + - Name: T3 +... diff --git a/lld/test/elf/Mips/rel-jalr-02.test b/lld/test/elf/Mips/rel-jalr-02.test new file mode 100644 index 00000000000..2a4e4df3678 --- /dev/null +++ b/lld/test/elf/Mips/rel-jalr-02.test @@ -0,0 +1,68 @@ +# REQUIRES: mips + +# Check R_MIPS_JALR relocations do not affect the code +# in case of relocatable targets. + +# RUN: yaml2obj -format=elf %s > %t.o +# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t.o +# RUN: llvm-objdump -d %t.so | FileCheck %s + +# CHECK: __start: +# CHECK-NEXT: {{[0-9a-f]+}}: 09 f8 20 03 jalr $25 +# CHECK-NEXT: {{[0-9a-f]+}}: 00 00 00 00 nop +# CHECK-NEXT: {{[0-9a-f]+}}: 08 00 20 03 jr $25 +# CHECK-NEXT: {{[0-9a-f]+}}: 00 00 00 00 nop + +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32] + +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 16 + Content: "09f820030000000008002003000000000000000000000000" +# ^ jalr ^ jr ^ T1 ^ T2 + + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 4 + Info: .text + Relocations: + - Offset: 0 + Symbol: T1 + Type: R_MIPS_JALR + - Offset: 8 + Symbol: T2 + Type: R_MIPS_JALR + + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 16 + Size: 0 + +Symbols: + Global: + - Name: __start + Type: STT_FUNC + Section: .text + Value: 0 + Size: 16 + - Name: T1 + Type: STT_FUNC + Section: .text + Value: 16 + Size: 4 + - Name: T2 + Type: STT_FUNC + Section: .text + Value: 20 + Size: 4 +... |