llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lld @llvm/pr-subscribers-lld-elf Author: None (llvmbot) <details> <summary>Changes</summary> Backport b42f96bc057fd9e31572069b241ba130c21144e5 Requested by: @<!-- -->androm3da --- Patch is 27.54 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/149723.diff 9 Files Affected: - (modified) lld/ELF/Arch/Hexagon.cpp (+47) - (modified) lld/ELF/Relocations.cpp (+40-13) - (modified) lld/ELF/Thunks.cpp (+71-1) - (removed) lld/test/ELF/hexagon-jump-error.s (-32) - (added) lld/test/ELF/hexagon-thunk-range-b22rel.s (+115) - (added) lld/test/ELF/hexagon-thunk-range-gdplt.s (+95) - (added) lld/test/ELF/hexagon-thunk-range-plt.s (+75) - (added) lld/test/ELF/hexagon-thunks-packets.s (+122) - (added) lld/test/ELF/hexagon-thunks.s (+53) ``````````diff diff --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp index 479131a24dcfc..9b33e78731c97 100644 --- a/lld/ELF/Arch/Hexagon.cpp +++ b/lld/ELF/Arch/Hexagon.cpp @@ -11,6 +11,7 @@ #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" +#include "Thunks.h" #include "lld/Common/ErrorHandler.h" #include "llvm/ADT/SmallVector.h" #include "llvm/BinaryFormat/ELF.h" @@ -36,6 +37,10 @@ class Hexagon final : public TargetInfo { const uint8_t *loc) const override; RelType getDynRel(RelType type) const override; int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override; + bool needsThunk(RelExpr expr, RelType type, const InputFile *file, + uint64_t branchAddr, const Symbol &s, + int64_t a) const override; + bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override; void relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const override; void writePltHeader(uint8_t *buf) const override; @@ -63,6 +68,8 @@ Hexagon::Hexagon(Ctx &ctx) : TargetInfo(ctx) { tlsGotRel = R_HEX_TPREL_32; tlsModuleIndexRel = R_HEX_DTPMOD_32; tlsOffsetRel = R_HEX_DTPREL_32; + + needsThunks = true; } uint32_t Hexagon::calcEFlags() const { @@ -258,6 +265,46 @@ static uint32_t findMaskR16(Ctx &ctx, uint32_t insn) { static void or32le(uint8_t *p, int32_t v) { write32le(p, read32le(p) | v); } +bool Hexagon::inBranchRange(RelType type, uint64_t src, uint64_t dst) const { + int64_t offset = dst - src; + switch (type) { + case llvm::ELF::R_HEX_B22_PCREL: + case llvm::ELF::R_HEX_PLT_B22_PCREL: + case llvm::ELF::R_HEX_GD_PLT_B22_PCREL: + case llvm::ELF::R_HEX_LD_PLT_B22_PCREL: + return llvm::isInt<22>(offset >> 2); + case llvm::ELF::R_HEX_B15_PCREL: + return llvm::isInt<15>(offset >> 2); + break; + case llvm::ELF::R_HEX_B13_PCREL: + return llvm::isInt<13>(offset >> 2); + break; + case llvm::ELF::R_HEX_B9_PCREL: + return llvm::isInt<9>(offset >> 2); + default: + return true; + } + llvm_unreachable("unsupported relocation"); +} + +bool Hexagon::needsThunk(RelExpr expr, RelType type, const InputFile *file, + uint64_t branchAddr, const Symbol &s, + int64_t a) const { + // Only check branch range for supported branch relocation types + switch (type) { + case R_HEX_B22_PCREL: + case R_HEX_PLT_B22_PCREL: + case R_HEX_GD_PLT_B22_PCREL: + case R_HEX_LD_PLT_B22_PCREL: + case R_HEX_B15_PCREL: + case R_HEX_B13_PCREL: + case R_HEX_B9_PCREL: + return !ctx.target->inBranchRange(type, branchAddr, s.getVA(ctx, a)); + default: + return false; + } +} + void Hexagon::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { switch (rel.type) { diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index cebd564036b2c..41f153e97de77 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -2139,17 +2139,44 @@ void ThunkCreator::mergeThunks(ArrayRef<OutputSection *> outputSections) { }); } -static int64_t getPCBias(Ctx &ctx, RelType type) { - if (ctx.arg.emachine != EM_ARM) - return 0; - switch (type) { - case R_ARM_THM_JUMP19: - case R_ARM_THM_JUMP24: - case R_ARM_THM_CALL: - return 4; - default: - return 8; +constexpr uint32_t HEXAGON_MASK_END_PACKET = 3 << 14; +constexpr uint32_t HEXAGON_END_OF_PACKET = 3 << 14; +constexpr uint32_t HEXAGON_END_OF_DUPLEX = 0 << 14; + +// Return the distance between the packet start and the instruction in the +// relocation. +static int getHexagonPacketOffset(const InputSection &isec, + const Relocation &rel) { + const ArrayRef<uint8_t> data = isec.content(); + + // Search back as many as 3 instructions. + for (unsigned i = 0;; i++) { + if (i == 3 || rel.offset < (i + 1) * 4) + return i * 4; + uint32_t instWord = 0; + const ArrayRef<uint8_t> instWordContents = + data.drop_front(rel.offset - (i + 1) * 4); + memcpy(&instWord, instWordContents.data(), sizeof(instWord)); + if (((instWord & HEXAGON_MASK_END_PACKET) == HEXAGON_END_OF_PACKET) || + ((instWord & HEXAGON_MASK_END_PACKET) == HEXAGON_END_OF_DUPLEX)) + return i * 4; + } +} +static int64_t getPCBias(Ctx &ctx, const InputSection &isec, + const Relocation &rel) { + if (ctx.arg.emachine == EM_ARM) { + switch (rel.type) { + case R_ARM_THM_JUMP19: + case R_ARM_THM_JUMP24: + case R_ARM_THM_CALL: + return 4; + default: + return 8; + } } + if (ctx.arg.emachine == EM_HEXAGON) + return -getHexagonPacketOffset(isec, rel); + return 0; } // Find or create a ThunkSection within the InputSectionDescription (ISD) that @@ -2161,7 +2188,7 @@ ThunkSection *ThunkCreator::getISDThunkSec(OutputSection *os, const Relocation &rel, uint64_t src) { // See the comment in getThunk for -pcBias below. - const int64_t pcBias = getPCBias(ctx, rel.type); + const int64_t pcBias = getPCBias(ctx, *isec, rel); for (std::pair<ThunkSection *, uint32_t> tp : isd->thunkSections) { ThunkSection *ts = tp.first; uint64_t tsBase = os->addr + ts->outSecOff - pcBias; @@ -2322,7 +2349,7 @@ std::pair<Thunk *, bool> ThunkCreator::getThunk(InputSection *isec, // out in the relocation addend. We compensate for the PC bias so that // an Arm and Thumb relocation to the same destination get the same keyAddend, // which is usually 0. - const int64_t pcBias = getPCBias(ctx, rel.type); + const int64_t pcBias = getPCBias(ctx, *isec, rel); const int64_t keyAddend = rel.addend + pcBias; // We use a ((section, offset), addend) pair to find the thunk position if @@ -2481,7 +2508,7 @@ bool ThunkCreator::createThunks(uint32_t pass, // STT_SECTION + non-zero addend, clear the addend after // redirection. if (ctx.arg.emachine != EM_MIPS) - rel.addend = -getPCBias(ctx, rel.type); + rel.addend = -getPCBias(ctx, *isec, rel); } for (auto &p : isd->thunkSections) diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp index c26ba76bccb7e..65d0f094c43c3 100644 --- a/lld/ELF/Thunks.cpp +++ b/lld/ELF/Thunks.cpp @@ -415,6 +415,22 @@ class AVRThunk : public Thunk { void addSymbols(ThunkSection &isec) override; }; +// Hexagon CPUs need thunks for R_HEX_B{9,1{3,5},22}_PCREL, +// R_HEX_{,GD_}PLT_B22_PCREL when their destination is out of +// range. +class HexagonThunk : public Thunk { +public: + HexagonThunk(Ctx &ctx, const InputSection &isec, Relocation &rel, + Symbol &dest) + : Thunk(ctx, dest, 0), relOffset(rel.offset) { + alignment = 4; + } + uint32_t relOffset; + uint32_t size() override { return ctx.arg.isPic ? 12 : 8; } + void writeTo(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; +}; + // MIPS LA25 thunk class MipsThunk final : public Thunk { public: @@ -1519,6 +1535,39 @@ bool PPC64LongBranchThunk::isCompatibleWith(const InputSection &isec, return rel.type == R_PPC64_REL24 || rel.type == R_PPC64_REL14; } +// Hexagon Target Thunks +static uint64_t getHexagonThunkDestVA(Ctx &ctx, const Symbol &s, int64_t a) { + uint64_t v = s.isInPlt(ctx) ? s.getPltVA(ctx) : s.getVA(ctx, a); + return SignExtend64<32>(v); +} + +void HexagonThunk::writeTo(uint8_t *buf) { + uint64_t s = getHexagonThunkDestVA(ctx, destination, addend); + uint64_t p = getThunkTargetSym()->getVA(ctx); + + if (ctx.arg.isPic) { + write32(ctx, buf + 0, 0x00004000); // { immext(#0) + ctx.target->relocateNoSym(buf, R_HEX_B32_PCREL_X, s - p); + write32(ctx, buf + 4, 0x6a49c00e); // r14 = add(pc,##0) } + ctx.target->relocateNoSym(buf + 4, R_HEX_6_PCREL_X, s - p); + + write32(ctx, buf + 8, 0x528ec000); // { jumpr r14 } + } else { + write32(ctx, buf + 0, 0x00004000); // { immext + ctx.target->relocateNoSym(buf, R_HEX_B32_PCREL_X, s - p); + write32(ctx, buf + 4, 0x5800c000); // jump <> } + ctx.target->relocateNoSym(buf + 4, R_HEX_B22_PCREL_X, s - p); + } +} +void HexagonThunk::addSymbols(ThunkSection &isec) { + Symbol *enclosing = isec.getEnclosingSymbol(relOffset); + StringRef src = enclosing ? enclosing->getName() : isec.name; + + addSymbol( + saver().save("__hexagon_thunk_" + destination.getName() + "_from_" + src), + STT_FUNC, 0, isec); +} + Thunk::Thunk(Ctx &ctx, Symbol &d, int64_t a) : ctx(ctx), destination(d), addend(a), offset(0) { destination.thunkAccessed = true; @@ -1692,6 +1741,24 @@ static std::unique_ptr<Thunk> addThunkAVR(Ctx &ctx, RelType type, Symbol &s, } } +static std::unique_ptr<Thunk> addThunkHexagon(Ctx &ctx, + const InputSection &isec, + Relocation &rel, Symbol &s) { + switch (rel.type) { + case R_HEX_B9_PCREL: + case R_HEX_B13_PCREL: + case R_HEX_B15_PCREL: + case R_HEX_B22_PCREL: + case R_HEX_PLT_B22_PCREL: + case R_HEX_GD_PLT_B22_PCREL: + return std::make_unique<HexagonThunk>(ctx, isec, rel, s); + default: + Fatal(ctx) << "unrecognized relocation " << rel.type << " to " << &s + << " for hexagon target"; + llvm_unreachable(""); + } +} + static std::unique_ptr<Thunk> addThunkMips(Ctx &ctx, RelType type, Symbol &s) { if ((s.stOther & STO_MIPS_MICROMIPS) && isMipsR6(ctx)) return std::make_unique<MicroMipsR6Thunk>(ctx, s); @@ -1761,8 +1828,11 @@ std::unique_ptr<Thunk> elf::addThunk(Ctx &ctx, const InputSection &isec, return addThunkPPC32(ctx, isec, rel, s); case EM_PPC64: return addThunkPPC64(ctx, rel.type, s, a); + case EM_HEXAGON: + return addThunkHexagon(ctx, isec, rel, s); default: - llvm_unreachable("add Thunk only supported for ARM, AVR, Mips and PowerPC"); + llvm_unreachable( + "add Thunk only supported for ARM, AVR, Hexagon, Mips and PowerPC"); } } diff --git a/lld/test/ELF/hexagon-jump-error.s b/lld/test/ELF/hexagon-jump-error.s deleted file mode 100644 index 53860b5daf2b1..0000000000000 --- a/lld/test/ELF/hexagon-jump-error.s +++ /dev/null @@ -1,32 +0,0 @@ -# REQUIRES: hexagon -# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf %s -o %t.o -## Use --threads=1 to keep emitted warnings across sections sequential. -# RUN: not ld.lld %t.o -o /dev/null --threads=1 2>&1 | FileCheck --implicit-check-not "out of range" %s - - .globl _start - .type _start, @function -_start: - -# CHECK: relocation R_HEX_B9_PCREL out of range: 1028 is not in [-1024, 1023] -{r0 = #0; jump #1f} -.space (1<<10) -.section b9, "ax" -1: - -# CHECK: relocation R_HEX_B13_PCREL out of range: 16388 is not in [-16384, 16383] -if (r0==#0) jump:t #1f -.space (1<<14) -.section b13, "ax" -1: - -# CHECK: relocation R_HEX_B15_PCREL out of range: 65540 is not in [-65536, 65535] -if (p0) jump #1f -.space (1<<16) -.section b15, "ax" -1: - -# CHECK: relocation R_HEX_B22_PCREL out of range: 8388612 is not in [-8388608, 8388607] -jump #1f -.space (1<<23) -.section b22, "ax" -1: diff --git a/lld/test/ELF/hexagon-thunk-range-b22rel.s b/lld/test/ELF/hexagon-thunk-range-b22rel.s new file mode 100644 index 0000000000000..08e37bf0a5552 --- /dev/null +++ b/lld/test/ELF/hexagon-thunk-range-b22rel.s @@ -0,0 +1,115 @@ +# REQUIRES: hexagon +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf main.s -o main.o +# RUN: ld.lld main.o -o test +# RUN: llvm-objdump -d --no-show-raw-insn test | FileCheck %s + +## Test thunk range scenarios for Hexagon R_HEX_B22_PCREL relocations. +## R_HEX_B22_PCREL has a range of +/- 8MB (0x800000 bytes). + +#--- main.s +.globl _start +.type _start, %function +_start: + call target_within_range_max + call target_beyond_range + call target_within_range_min + call target_beyond_range_min + call target_multiple_calls + call target_multiple_calls + call target_close + jumpr r31 + +target_close: + jumpr r31 + +## Target at maximum positive range (8MB - 4 bytes from _start) +## We need to account for the instructions above: 7 calls + 1 jumpr = 8 * 4 = 32 bytes +.skip 0X7fffbc +.globl target_within_range_max +.type target_within_range_max, %function +target_within_range_max: + jumpr r31 + +## Target just beyond maximum positive range (needs thunk) +.skip 8 +.globl target_beyond_range +.type target_beyond_range, %function +target_beyond_range: + call target_within_range_max + jumpr r31 + +## Target for multiple calls test +.skip 0x100000 +.globl target_multiple_calls +.type target_multiple_calls, %function +target_multiple_calls: + jumpr r31 + +## Now place targets at maximum negative range +## We'll put these before _start in memory layout +.section .text_negative, "ax", %progbits + +## Target at maximum negative range (-8MB + 4 bytes from _start) +.globl target_within_range_min +.type target_within_range_min, %function +target_within_range_min: + call target_close + jumpr r31 + +.skip 0X7ffff4 + +## Target beyond maximum negative range (needs thunk) +.globl target_beyond_range_min +.type target_beyond_range_min, %function +target_beyond_range_min: + jumpr r31 + +## Verify thunk generation for targets beyond B22_PCREL range +# CHECK: <__hexagon_thunk_target_within_range_min_from_.text.thunk>: +# CHECK-NEXT: 200b4: { immext(#0x900000) +# CHECK-NEXT: jump 0x9200cc <target_within_range_min> } + +# CHECK: <__hexagon_thunk_target_beyond_range_min_from_.text.thunk>: +# CHECK-NEXT: 200bc: { immext(#0x1100000) +# CHECK-NEXT: jump 0x11200c8 <target_beyond_range_min> } + +# CHECK: <__hexagon_thunk_target_multiple_calls_from_.text.thunk>: +# CHECK-NEXT: 200c4: { immext(#0x8fffc0) +# CHECK-NEXT: jump 0x9200c0 <target_multiple_calls> } + +## Verify _start calls - some direct, some via thunks +# CHECK: <_start>: +# CHECK-NEXT: 200cc: { call 0x8200ac <target_within_range_max> } +# CHECK-NEXT: { call 0x8200b8 <target_beyond_range> } +# CHECK-NEXT: { call 0x200b4 <__hexagon_thunk_target_within_range_min_from_.text.thunk> } +# CHECK-NEXT: { call 0x200bc <__hexagon_thunk_target_beyond_range_min_from_.text.thunk> } +# CHECK-NEXT: { call 0x200c4 <__hexagon_thunk_target_multiple_calls_from_.text.thunk> } +# CHECK-NEXT: { call 0x200c4 <__hexagon_thunk_target_multiple_calls_from_.text.thunk> } +# CHECK-NEXT: { call 0x200ec <target_close> } + +# CHECK: <target_close>: +# CHECK-NEXT: 200ec: { jumpr r31 } + +## Verify targets at maximum positive range (direct calls, no thunks needed) +# CHECK: <target_within_range_max>: +# CHECK-NEXT: 8200ac: { jumpr r31 } + +# CHECK: <target_beyond_range>: +# CHECK-NEXT: 8200b8: { call 0x8200ac <target_within_range_max> } +# CHECK-NEXT: { jumpr r31 } + +# CHECK: <target_multiple_calls>: +# CHECK-NEXT: 9200c0: { jumpr r31 } + +## Verify targets in negative section and thunk for calling back to main section +# CHECK: <__hexagon_thunk__from_.text.thunk>: +# CHECK-NEXT: 9200c4: { immext(#0xff700000) +# CHECK-NEXT: jump 0x200cc <_start> } + +# CHECK: <target_within_range_min>: +# CHECK-NEXT: 9200cc: { call 0x9200c4 <__hexagon_thunk__from_.text.thunk> } +# CHECK-NEXT: { jumpr r31 } + +# CHECK: <target_beyond_range_min>: +# CHECK-NEXT: 11200c8: { jumpr r31 } diff --git a/lld/test/ELF/hexagon-thunk-range-gdplt.s b/lld/test/ELF/hexagon-thunk-range-gdplt.s new file mode 100644 index 0000000000000..77fd0e5754568 --- /dev/null +++ b/lld/test/ELF/hexagon-thunk-range-gdplt.s @@ -0,0 +1,95 @@ +# REQUIRES: hexagon +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf main.s -o main.o +# RUN: ld.lld -shared main.o -o test.so +# RUN: llvm-objdump -d --no-show-raw-insn test.so | FileCheck %s + +## Test thunk range scenarios for Hexagon R_HEX_GD_PLT_B22_PCREL relocations. +## Same ±8MB range as regular calls. + +#--- main.s +.globl _start +.type _start, @function +_start: + ## Setup for TLS Global Dynamic calls + r2 = add(pc,##_GLOBAL_OFFSET_TABLE_@PCREL) + + ## Test TLS GD PLT calls + r0 = add(r2,##tls_var_close@GDGOT) + call tls_var_close@GDPLT + + r0 = add(r2,##tls_var_far@GDGOT) + call tls_var_far@GDPLT + + jumpr r31 + +.skip 0x400000 + +more_code: + r0 = add(r2,##tls_var_distant@GDGOT) + call tls_var_distant@GDPLT + jumpr r31 + +## TLS variables in .tdata section +.section .tdata,"awT",@progbits +.globl tls_var_close, tls_var_far, tls_var_distant +.type tls_var_close, @object +.type tls_var_far, @object +.type tls_var_distant, @object + +tls_var_close: + .word 0x1234 + +tls_var_far: + .word 0x5678 + +tls_var_distant: + .word 0x9abc + +# CHECK: Disassembly of section .text: +# CHECK: <_start>: +# CHECK-NEXT: 102d4: { immext(#0x420100) +# CHECK-NEXT: r2 = add(pc,##0x420130) } +# CHECK-NEXT: { immext(#0xfffeffc0) +# CHECK-NEXT: r0 = add(r2,##-0x10018) } +# CHECK-NEXT: { call 0x410360 <__tls_get_addr@plt> } +# CHECK-NEXT: { immext(#0xfffeffc0) +# CHECK-NEXT: r0 = add(r2,##-0x10010) } +# CHECK-NEXT: { call 0x410360 <__tls_get_addr@plt> } +# CHECK-NEXT: { jumpr r31 } + +# CHECK: <more_code>: +# CHECK-NEXT: 4102f8: { immext(#0xfffeffc0) +# CHECK-NEXT: r0 = add(r2,##-0x10008) } +# CHECK-NEXT: { call 0x410360 <__tls_get_addr@plt> } +# CHECK-NEXT: { jumpr r31 } + +## Verify PLT entries are created for TLS +# CHECK: Disassembly of section .plt: +# CHECK: <.plt>: +# CHECK-NEXT: 410310: { immext(#0x200c0) +# CHECK-NEXT: r28 = add(pc,##0x200f4) } +# CHECK-NEXT: { r14 -= add(r28,#0x10) +# CHECK-NEXT: r15 = memw(r28+#0x8) +# CHECK-NEXT: r28 = memw(r28+#0x4) } +# CHECK-NEXT: { r14 = asr(r14,#0x2) +# CHECK-NEXT: jumpr r28 } +# CHECK-NEXT: { trap0(#0xdb) } + +# CHECK: <tls_var_far@plt>: +# CHECK-NEXT: 410340: { immext(#0x200c0) +# CHECK-NEXT: r14 = add(pc,##0x200d8) } +# CHECK-NEXT: { r28 = memw(r14+#0x0) } +# CHECK-NEXT: { jumpr r28 } + +# CHECK: <tls_var_distant@plt>: +# CHECK-NEXT: 410350: { immext(#0x200c0) +# CHECK-NEXT: r14 = add(pc,##0x200cc) } +# CHECK-NEXT: { r28 = memw(r14+#0x0) } +# CHECK-NEXT: { jumpr r28 } + +# CHECK: <__tls_get_addr@plt>: +# CHECK-NEXT: 410360: { immext(#0x200c0) +# CHECK-NEXT: r14 = add(pc,##0x200c0) } +# CHECK-NEXT: { r28 = memw(r14+#0x0) } +# CHECK-NEXT: { jumpr r28 } diff --git a/lld/test/ELF/hexagon-thunk-range-plt.s b/lld/test/ELF/hexagon-thunk-range-plt.s new file mode 100644 index 0000000000000..3a8f50b681d81 --- /dev/null +++ b/lld/test/ELF/hexagon-thunk-range-plt.s @@ -0,0 +1,75 @@ +# REQUIRES: hexagon +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf external.s -o external.o +# RUN: ld.lld -shared external.o -soname external.so -o external.so +# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf main.s -o main.o +# RUN: ld.lld main.o external.so -o test +# RUN: llvm-objdump -d --no-show-raw-insn test | FileCheck %s + +## Test thunk range scenarios for Hexagon R_HEX_PLT_B22_PCREL relocations. +## PLT calls use the same ±8MB range as regular calls but go through PLT entries. +## This test verifies thunk generation for PLT calls at range boundaries. + +#--- external.s +.globl extern_within_range, extern_beyond_range, extern_close +.type extern_within_range, @function +.type extern_beyond_range, @function +.type extern_close, @function + +extern_within_range: + jumpr r31 + +extern_beyond_range: + jumpr r31 + +extern_close: + jumpr r31 + +#--- main.s +.globl _start +.type _start, @function +_start: + ## Test PLT calls to external functions at various ranges + call extern_within_range@PLT + call extern_beyond_range@PLT + call extern_close@PLT + jumpr r31 + +.skip 0x200000 + +# CHECK: Disassembly of section .text: +# CHECK: <_start>: +# CHECK-NEXT: 2021c: { call 0x220250 <extern_within_range@plt> } +# CHECK-NEXT: { call 0x220260 <extern_beyond_range@plt> } +# CHECK-NEXT: { call 0x220270 <extern_close@plt> } +# CHECK-NEXT: { jumpr r31 } + +## Verify PLT header and entries are created with exact addresses +# CHECK: Disassembly of section .plt: +# CHECK: <.plt>: +# CHECK-NEXT: 220230: { immext(#0x20080) +# CHECK-NEXT: ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/149723 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits