[PATCH] D34035: [LLD][ELF] Introduce Thunk reuse compatibility

Rafael Avila de Espindola via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 4 08:27:12 PDT 2017


LGTM

Peter Smith via Phabricator <reviews at reviews.llvm.org> writes:

> peter.smith created this revision.
> Herald added subscribers: kristof.beyls, emaste, aemerson.
>
> On ARM the interworking thunks are only produced for branch instructions that can't be changed into a blx instruction so only Thumb callers would call Thumb thunks and only ARM callers would call ARM thunks. With range extension thunks branch and link instructions may need a Thunk. These instructions can be rewritten as a blx and can use either ARM or Thumb thunks.
>
>       
>
> We introduce a compatibleWith() function so that a caller can check if an existing Thunk is compatible before reusing it. With the currently supported interworking thunks all the thunks are reusable by construction so there will be no impact on the tests.
>
>
> https://reviews.llvm.org/D34035
>
> Files:
>   ELF/Relocations.cpp
>   ELF/Thunks.cpp
>   ELF/Thunks.h
>
> Index: ELF/Thunks.h
> ===================================================================
> --- ELF/Thunks.h
> +++ ELF/Thunks.h
> @@ -41,6 +41,10 @@
>    // a branch and fall through to the first Symbol in the Target.
>    virtual InputSection *getTargetInputSection() const { return nullptr; }
>  
> +  // To reuse a Thunk the caller as identified by the RelocType must be
> +  // compatible with it.
> +  virtual bool compatibleWith(uint32_t RelocType) const { return true; }
> +
>    // The alignment requirement for this Thunk, defaults to the size of the
>    // typical code section alignment.
>    const SymbolBody &Destination;
> Index: ELF/Thunks.cpp
> ===================================================================
> --- ELF/Thunks.cpp
> +++ ELF/Thunks.cpp
> @@ -57,6 +57,7 @@
>    uint32_t size() const override { return 12; }
>    void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
>    void addSymbols(ThunkSection &IS) override;
> +  bool compatibleWith(uint32_t RelocType) const override;
>  };
>  
>  class ARMV7PILongThunk final : public Thunk {
> @@ -66,6 +67,7 @@
>    uint32_t size() const override { return 16; }
>    void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
>    void addSymbols(ThunkSection &IS) override;
> +  bool compatibleWith(uint32_t RelocType) const override;
>  };
>  
>  class ThumbV7ABSLongThunk final : public Thunk {
> @@ -77,6 +79,7 @@
>    uint32_t size() const override { return 10; }
>    void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
>    void addSymbols(ThunkSection &IS) override;
> +  bool compatibleWith(uint32_t RelocType) const override;
>  };
>  
>  class ThumbV7PILongThunk final : public Thunk {
> @@ -88,6 +91,7 @@
>    uint32_t size() const override { return 12; }
>    void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
>    void addSymbols(ThunkSection &IS) override;
> +  bool compatibleWith(uint32_t RelocType) const override;
>  };
>  
>  // MIPS LA25 thunk
> @@ -128,6 +132,11 @@
>    addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, &IS);
>  }
>  
> +bool ARMV7ABSLongThunk::compatibleWith(uint32_t RelocType) const {
> +  // Thumb branch relocations can't use BLX
> +  return RelocType != R_ARM_THM_JUMP19 && RelocType != R_ARM_THM_JUMP24;
> +}
> +
>  void ThumbV7ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
>    const uint8_t Data[] = {
>        0x40, 0xf2, 0x00, 0x0c, // movw         ip, :lower16:S
> @@ -147,6 +156,12 @@
>    addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, &IS);
>  }
>  
> +bool ThumbV7ABSLongThunk::compatibleWith(uint32_t RelocType) const {
> +  // ARM branch relocations can't use BLX
> +  return RelocType != R_ARM_JUMP24 && RelocType != R_ARM_PC24 &&
> +         RelocType != R_ARM_PLT32;
> +}
> +
>  void ARMV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
>    const uint8_t Data[] = {
>        0xf0, 0xcf, 0x0f, 0xe3, // P:  movw ip,:lower16:S - (P + (L1-P) +8)
> @@ -168,6 +183,11 @@
>    addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, &IS);
>  }
>  
> +bool ARMV7PILongThunk::compatibleWith(uint32_t RelocType) const {
> +  // Thumb branch relocations can't use BLX
> +  return RelocType != R_ARM_THM_JUMP19 && RelocType != R_ARM_THM_JUMP24;
> +}
> +
>  void ThumbV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
>    const uint8_t Data[] = {
>        0x4f, 0xf6, 0xf4, 0x7c, // P:  movw ip,:lower16:S - (P + (L1-P) + 4)
> @@ -189,6 +209,12 @@
>    addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, &IS);
>  }
>  
> +bool ThumbV7PILongThunk::compatibleWith(uint32_t RelocType) const {
> +  // ARM branch relocations can't use BLX
> +  return RelocType != R_ARM_JUMP24 && RelocType != R_ARM_PC24 &&
> +         RelocType != R_ARM_PLT32;
> +}
> +
>  // Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
>  void MipsThunk::writeTo(uint8_t *Buf, ThunkSection &) const {
>    uint64_t S = this->Destination.getVA();
> Index: ELF/Relocations.cpp
> ===================================================================
> --- ELF/Relocations.cpp
> +++ ELF/Relocations.cpp
> @@ -1051,7 +1051,7 @@
>  std::pair<Thunk *, bool> ThunkCreator::getThunk(SymbolBody &Body,
>                                                  uint32_t Type) {
>    auto res = ThunkedSymbols.insert({&Body, nullptr});
> -  if (res.second)
> +  if (res.second || !res.first->second->compatibleWith(Type))
>      res.first->second = addThunk(Type, Body);
>    return std::make_pair(res.first->second, res.second);
>  }


More information about the llvm-commits mailing list