diff options
author | Stefan Gränitz <stefan.graenitz@gmail.com> | 2024-01-23 02:59:30 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-23 02:59:30 +0100 |
commit | e5ca202ef8870f3b46cc19a7a62624e6908be9a8 (patch) | |
tree | 18e3549fbe72be58917ad63b7be0d68b9ac390dd /llvm/tools/llvm-jitlink/llvm-jitlink.cpp | |
parent | b8e708b9d39862c2b7595c02e7bdc4878a2d7186 (diff) | |
download | llvm-e5ca202ef8870f3b46cc19a7a62624e6908be9a8.zip llvm-e5ca202ef8870f3b46cc19a7a62624e6908be9a8.tar.gz llvm-e5ca202ef8870f3b46cc19a7a62624e6908be9a8.tar.bz2 |
[JITLink][AArch32] Multi-stub support for armv7/thumbv7 (#78371)
We want to emit stubs that match the instruction set state of the
relocation site. This is important for branches that have no built-in
switch for the instruction set state. It's the case for Jump24
relocations. Relocations on instructions that support switching on
the fly will be rewritten in a relaxation step in the future. This
affects Call relocations on `BL`/`BLX` instructions.
In this patch, the StubManager gains a second stub symbol slot for each
target and selects which one to use based on the relocation type. For
testing, we select the appropriate slot with a stub-kind filter, i.e.
`arm` or `thumb`. With that we can implement Armv7 stubs and test
that we can have both kinds of stubs for a single external symbol.
Diffstat (limited to 'llvm/tools/llvm-jitlink/llvm-jitlink.cpp')
-rw-r--r-- | llvm/tools/llvm-jitlink/llvm-jitlink.cpp | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp index 7e21377..b2a1338 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp +++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp @@ -1265,8 +1265,52 @@ Session::findSectionInfo(StringRef FileName, StringRef SectionName) { return SecInfoItr->second; } +class MemoryMatcher { +public: + MemoryMatcher(ArrayRef<char> Content) + : Pos(Content.data()), End(Pos + Content.size()) {} + + template <typename MaskType> bool matchMask(MaskType Mask) { + if (Mask == (Mask & *reinterpret_cast<const MaskType *>(Pos))) { + Pos += sizeof(MaskType); + return true; + } + return false; + } + + template <typename ValueType> bool matchEqual(ValueType Value) { + if (Value == *reinterpret_cast<const ValueType *>(Pos)) { + Pos += sizeof(ValueType); + return true; + } + return false; + } + + bool done() const { return Pos == End; } + +private: + const char *Pos; + const char *End; +}; + static StringRef detectStubKind(const Session::MemoryRegionInfo &Stub) { - // Implement acutal stub kind detection + constexpr uint32_t Armv7MovWTle = 0xe300c000; + constexpr uint32_t Armv7BxR12le = 0xe12fff1c; + constexpr uint32_t Thumbv7MovWTle = 0x0c00f240; + constexpr uint16_t Thumbv7BxR12le = 0x4760; + + MemoryMatcher M(Stub.getContent()); + if (M.matchMask(Thumbv7MovWTle)) { + if (M.matchMask(Thumbv7MovWTle)) + if (M.matchEqual(Thumbv7BxR12le)) + if (M.done()) + return "thumbv7_abs_le"; + } else if (M.matchMask(Armv7MovWTle)) { + if (M.matchMask(Armv7MovWTle)) + if (M.matchEqual(Armv7BxR12le)) + if (M.done()) + return "armv7_abs_le"; + } return ""; } |