[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