[lld] r314797 - [MIPS] Generate thunks for microMIPS code

Simon Atanasyan via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 3 06:30:02 PDT 2017


Author: atanasyan
Date: Tue Oct  3 06:30:02 2017
New Revision: 314797

URL: http://llvm.org/viewvc/llvm-project?rev=314797&view=rev
Log:
[MIPS] Generate thunks for microMIPS code

If symbol has the STO_MIPS_MICROMIPS flag and requires a thunk to perform
call PIC from non-PIC functions, we need to generate a thunk with microMIPS
code.

Added:
    lld/trunk/test/ELF/mips-micro-thunks.s
Modified:
    lld/trunk/ELF/Arch/Mips.cpp
    lld/trunk/ELF/Arch/MipsArchTree.cpp
    lld/trunk/ELF/Thunks.cpp
    lld/trunk/ELF/Writer.h

Modified: lld/trunk/ELF/Arch/Mips.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/Mips.cpp?rev=314797&r1=314796&r2=314797&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/Mips.cpp (original)
+++ lld/trunk/ELF/Arch/Mips.cpp Tue Oct  3 06:30:02 2017
@@ -240,11 +240,6 @@ static void writeMicroRelocation16(uint8
 
 static bool isMicroMips() { return Config->MipsEFlags & EF_MIPS_MICROMIPS; }
 
-static bool isMipsR6() {
-  uint32_t Arch = Config->MipsEFlags & EF_MIPS_ARCH;
-  return Arch == EF_MIPS_ARCH_32R6 || Arch == EF_MIPS_ARCH_64R6;
-}
-
 template <class ELFT> void MIPS<ELFT>::writePltHeader(uint8_t *Buf) const {
   const endianness E = ELFT::TargetEndianness;
   if (isMicroMips()) {

Modified: lld/trunk/ELF/Arch/MipsArchTree.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/MipsArchTree.cpp?rev=314797&r1=314796&r2=314797&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/MipsArchTree.cpp (original)
+++ lld/trunk/ELF/Arch/MipsArchTree.cpp Tue Oct  3 06:30:02 2017
@@ -364,6 +364,11 @@ bool elf::isMipsN32Abi(const InputFile *
   }
 }
 
+bool elf::isMipsR6() {
+  uint32_t Arch = Config->MipsEFlags & EF_MIPS_ARCH;
+  return Arch == EF_MIPS_ARCH_32R6 || Arch == EF_MIPS_ARCH_64R6;
+}
+
 template uint32_t elf::calcMipsEFlags<ELF32LE>();
 template uint32_t elf::calcMipsEFlags<ELF32BE>();
 template uint32_t elf::calcMipsEFlags<ELF64LE>();

Modified: lld/trunk/ELF/Thunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Thunks.cpp?rev=314797&r1=314796&r2=314797&view=diff
==============================================================================
--- lld/trunk/ELF/Thunks.cpp (original)
+++ lld/trunk/ELF/Thunks.cpp Tue Oct  3 06:30:02 2017
@@ -101,6 +101,28 @@ public:
   InputSection *getTargetInputSection() const override;
 };
 
+// microMIPS R2-R5 LA25 thunk
+class MicroMipsThunk final : public Thunk {
+public:
+  MicroMipsThunk(const SymbolBody &Dest) : Thunk(Dest) {}
+
+  uint32_t size() const override { return 14; }
+  void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+  void addSymbols(ThunkSection &IS) override;
+  InputSection *getTargetInputSection() const override;
+};
+
+// microMIPS R6 LA25 thunk
+class MicroMipsR6Thunk final : public Thunk {
+public:
+  MicroMipsR6Thunk(const SymbolBody &Dest) : Thunk(Dest) {}
+
+  uint32_t size() const override { return 12; }
+  void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
+  void addSymbols(ThunkSection &IS) override;
+  InputSection *getTargetInputSection() const override;
+};
+
 } // end anonymous namespace
 
 // ARM Target Thunks
@@ -235,6 +257,56 @@ InputSection *MipsThunk::getTargetInputS
   return dyn_cast<InputSection>(DR->Section);
 }
 
+// Write microMIPS R2-R5 LA25 thunk code
+// to call PIC function from the non-PIC one.
+void MicroMipsThunk::writeTo(uint8_t *Buf, ThunkSection &) const {
+  uint64_t S = Destination.getVA();
+  write16(Buf, 0x41b9, Config->Endianness);       // lui   $25, %hi(func)
+  write16(Buf + 4, 0xd400, Config->Endianness);   // j     func
+  write16(Buf + 8, 0x3339, Config->Endianness);   // addiu $25, $25, %lo(func)
+  write16(Buf + 12, 0x0c00, Config->Endianness);  // nop
+  Target->relocateOne(Buf, R_MICROMIPS_HI16, S);
+  Target->relocateOne(Buf + 4, R_MICROMIPS_26_S1, S);
+  Target->relocateOne(Buf + 8, R_MICROMIPS_LO16, S);
+}
+
+void MicroMipsThunk::addSymbols(ThunkSection &IS) {
+  ThunkSym =
+      addSyntheticLocal(Saver.save("__microLA25Thunk_" + Destination.getName()),
+                        STT_FUNC, Offset, size(), &IS);
+  ThunkSym->StOther |= STO_MIPS_MICROMIPS;
+}
+
+InputSection *MicroMipsThunk::getTargetInputSection() const {
+  auto *DR = dyn_cast<DefinedRegular>(&Destination);
+  return dyn_cast<InputSection>(DR->Section);
+}
+
+// Write microMIPS R6 LA25 thunk code
+// to call PIC function from the non-PIC one.
+void MicroMipsR6Thunk::writeTo(uint8_t *Buf, ThunkSection &) const {
+  uint64_t S = Destination.getVA();
+  uint64_t P = ThunkSym->getVA();
+  write16(Buf, 0x1320, Config->Endianness);       // lui   $25, %hi(func)
+  write16(Buf + 4, 0x3339, Config->Endianness);   // addiu $25, $25, %lo(func)
+  write16(Buf + 8, 0x9400, Config->Endianness);   // bc    func
+  Target->relocateOne(Buf, R_MICROMIPS_HI16, S);
+  Target->relocateOne(Buf + 4, R_MICROMIPS_LO16, S);
+  Target->relocateOne(Buf + 8, R_MICROMIPS_PC26_S1, S - P - 12);
+}
+
+void MicroMipsR6Thunk::addSymbols(ThunkSection &IS) {
+  ThunkSym =
+      addSyntheticLocal(Saver.save("__microLA25Thunk_" + Destination.getName()),
+                        STT_FUNC, Offset, size(), &IS);
+  ThunkSym->StOther |= STO_MIPS_MICROMIPS;
+}
+
+InputSection *MicroMipsR6Thunk::getTargetInputSection() const {
+  auto *DR = dyn_cast<DefinedRegular>(&Destination);
+  return dyn_cast<InputSection>(DR->Section);
+}
+
 Thunk::Thunk(const SymbolBody &D) : Destination(D), Offset(0) {}
 
 Thunk::~Thunk() = default;
@@ -260,13 +332,19 @@ static Thunk *addThunkArm(uint32_t Reloc
   fatal("unrecognized relocation type");
 }
 
-static Thunk *addThunkMips(SymbolBody &S) { return make<MipsThunk>(S); }
+static Thunk *addThunkMips(uint32_t Reloc, SymbolBody &S) {
+  if ((S.StOther & STO_MIPS_MICROMIPS) && isMipsR6())
+    return make<MicroMipsR6Thunk>(S);
+  if (S.StOther & STO_MIPS_MICROMIPS)
+    return make<MicroMipsThunk>(S);
+  return make<MipsThunk>(S);
+}
 
 Thunk *addThunk(uint32_t RelocType, SymbolBody &S) {
   if (Config->EMachine == EM_ARM)
     return addThunkArm(RelocType, S);
   else if (Config->EMachine == EM_MIPS)
-    return addThunkMips(S);
+    return addThunkMips(RelocType, S);
   llvm_unreachable("add Thunk only supported for ARM and Mips");
   return nullptr;
 }

Modified: lld/trunk/ELF/Writer.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.h?rev=314797&r1=314796&r2=314797&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.h (original)
+++ lld/trunk/ELF/Writer.h Tue Oct  3 06:30:02 2017
@@ -54,6 +54,7 @@ uint8_t getMipsFpAbiFlag(uint8_t OldFlag
                          llvm::StringRef FileName);
 
 bool isMipsN32Abi(const InputFile *F);
+bool isMipsR6();
 } // namespace elf
 } // namespace lld
 

Added: lld/trunk/test/ELF/mips-micro-thunks.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-micro-thunks.s?rev=314797&view=auto
==============================================================================
--- lld/trunk/test/ELF/mips-micro-thunks.s (added)
+++ lld/trunk/test/ELF/mips-micro-thunks.s Tue Oct  3 06:30:02 2017
@@ -0,0 +1,47 @@
+# Check microMIPS thunk generation.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN:         -mattr=micromips %s -o %t-eb.o
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN:         -position-independent -mattr=micromips \
+# RUN:         %S/Inputs/mips-micro.s -o %t-eb-pic.o
+# RUN: ld.lld -o %t-eb.exe %t-eb.o %t-eb-pic.o
+# RUN: llvm-objdump -d -mattr=+micromips %t-eb.exe \
+# RUN:   | FileCheck --check-prefix=EB %s
+
+# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux \
+# RUN:         -mattr=micromips %s -o %t-el.o
+# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux \
+# RUN:         -position-independent -mattr=micromips \
+# RUN:         %S/Inputs/mips-micro.s -o %t-el-pic.o
+# RUN: ld.lld -o %t-el.exe %t-el.o %t-el-pic.o
+# RUN: llvm-objdump -d -mattr=+micromips %t-el.exe \
+# RUN:   | FileCheck --check-prefix=EL %s
+
+# REQUIRES: mips
+
+# EB: __start:
+# EB-NEXT:    20000:       f4 01 00 04     jal     131080 <__microLA25Thunk_foo>
+# EB-NEXT:    20004:       00 00 00 00     nop
+
+# EB: __microLA25Thunk_foo:
+# EB-NEXT:    20008:       41 b9 00 02     lui     $25, 2
+# EB-NEXT:    2000c:       d4 01 00 10     j       131104
+# EB-NEXT:    20010:       33 39 00 20     addiu   $25, $25, 32
+# EB-NEXT:    20014:       0c 00           nop
+
+# EL: __start:
+# EL-NEXT:    20000:       01 f4 04 00     jal     131080 <__microLA25Thunk_foo>
+# EL-NEXT:    20004:       00 00 00 00     nop
+
+# EL: __microLA25Thunk_foo:
+# EL-NEXT:    20008:       b9 41 02 00     lui     $25, 2
+# EL-NEXT:    2000c:       01 d4 10 00     j       131104
+# EL-NEXT:    20010:       39 33 20 00     addiu   $25, $25, 32
+# EL-NEXT:    20014:       00 0c           nop
+
+  .text
+  .set micromips
+  .global __start
+__start:
+  jal foo




More information about the llvm-commits mailing list