From c7177e17f6a52336fa4d77dd3919465c3dc7b6e2 Mon Sep 17 00:00:00 2001 From: chenli Date: Wed, 20 Aug 2025 14:35:49 +0800 Subject: [PATCH] LoongArch: Add support for RuntimeDyld --- 0022-RuntimeDyld-Add-LoongArch-support.patch | 457 ++++++++++++++++++ ...gArch-Support-large-code-model-14858.patch | 169 +++++++ llvm.spec | 8 +- 3 files changed, 633 insertions(+), 1 deletion(-) create mode 100644 0022-RuntimeDyld-Add-LoongArch-support.patch create mode 100644 0023-RuntimeDyld-LoongArch-Support-large-code-model-14858.patch diff --git a/0022-RuntimeDyld-Add-LoongArch-support.patch b/0022-RuntimeDyld-Add-LoongArch-support.patch new file mode 100644 index 0000000..7f1adda --- /dev/null +++ b/0022-RuntimeDyld-Add-LoongArch-support.patch @@ -0,0 +1,457 @@ +From 23779f75196b633b09c3880cc7a2ce3501f7100c Mon Sep 17 00:00:00 2001 +From: wanglei +Date: Fri, 8 Nov 2024 10:42:31 +0800 +Subject: [PATCH 1/2] [RuntimeDyld] Add LoongArch support + +This is necessary for supporting function calls in LLDB expressions for +LoongArch. +This patch is inspired by #99336 and simply extracts the parts related +to RuntimeDyld. + +Reviewed By: lhames + +Pull Request: https://github.com/llvm/llvm-project/pull/114741 + +(cherry picked from commit 4e668d5b27a339918bee4d994fca31d962519e80) +--- + .../RuntimeDyld/RuntimeDyld.cpp | 12 + + .../RuntimeDyld/RuntimeDyldELF.cpp | 219 ++++++++++++++++++ + .../RuntimeDyld/RuntimeDyldELF.h | 14 ++ + .../LoongArch/ELF_LoongArch_relocations.s | 102 ++++++++ + .../RuntimeDyld/LoongArch/lit.local.cfg | 2 + + 5 files changed, 349 insertions(+) + create mode 100644 llvm/test/ExecutionEngine/RuntimeDyld/LoongArch/ELF_LoongArch_relocations.s + create mode 100644 llvm/test/ExecutionEngine/RuntimeDyld/LoongArch/lit.local.cfg + +diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +index a9aaff42433f..b154ea287e3c 100644 +--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp ++++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +@@ -987,6 +987,18 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr, + // and stubs for branches Thumb - ARM and ARM - Thumb. + writeBytesUnaligned(0xe51ff004, Addr, 4); // ldr pc, [pc, #-4] + return Addr + 4; ++ } else if (Arch == Triple::loongarch64) { ++ // lu12i.w $t0, %abs_hi20(addr) ++ // ori $t0, $t0, %abs_lo12(addr) ++ // lu32i.d $t0, %abs64_lo20(addr) ++ // lu52i.d $t0, $t0, %abs64_lo12(addr) ++ // jr $t0 ++ writeBytesUnaligned(0x1400000c, Addr, 4); ++ writeBytesUnaligned(0x0380018c, Addr + 4, 4); ++ writeBytesUnaligned(0x1600000c, Addr + 8, 4); ++ writeBytesUnaligned(0x0300018c, Addr + 12, 4); ++ writeBytesUnaligned(0x4c000180, Addr + 16, 4); ++ return Addr; + } else if (IsMipsO32ABI || IsMipsN32ABI) { + // 0: 3c190000 lui t9,%hi(addr). + // 4: 27390000 addiu t9,t9,%lo(addr). +diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +index d439b1b4ebfb..35d1c90cc606 100644 +--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp ++++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +@@ -645,6 +645,206 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, + } + } + ++bool RuntimeDyldELF::resolveLoongArch64ShortBranch( ++ unsigned SectionID, relocation_iterator RelI, ++ const RelocationValueRef &Value) { ++ uint64_t Address; ++ if (Value.SymbolName) { ++ auto Loc = GlobalSymbolTable.find(Value.SymbolName); ++ // Don't create direct branch for external symbols. ++ if (Loc == GlobalSymbolTable.end()) ++ return false; ++ const auto &SymInfo = Loc->second; ++ Address = ++ uint64_t(Sections[SymInfo.getSectionID()].getLoadAddressWithOffset( ++ SymInfo.getOffset())); ++ } else { ++ Address = uint64_t(Sections[Value.SectionID].getLoadAddress()); ++ } ++ uint64_t Offset = RelI->getOffset(); ++ uint64_t SourceAddress = Sections[SectionID].getLoadAddressWithOffset(Offset); ++ if (!isInt<28>(Address + Value.Addend - SourceAddress)) ++ return false; ++ resolveRelocation(Sections[SectionID], Offset, Address, RelI->getType(), ++ Value.Addend); ++ return true; ++} ++ ++void RuntimeDyldELF::resolveLoongArch64Branch(unsigned SectionID, ++ const RelocationValueRef &Value, ++ relocation_iterator RelI, ++ StubMap &Stubs) { ++ LLVM_DEBUG(dbgs() << "\t\tThis is an LoongArch64 branch relocation.\n"); ++ ++ if (resolveLoongArch64ShortBranch(SectionID, RelI, Value)) ++ return; ++ ++ SectionEntry &Section = Sections[SectionID]; ++ uint64_t Offset = RelI->getOffset(); ++ unsigned RelType = RelI->getType(); ++ // Look for an existing stub. ++ StubMap::const_iterator i = Stubs.find(Value); ++ if (i != Stubs.end()) { ++ resolveRelocation(Section, Offset, ++ (uint64_t)Section.getAddressWithOffset(i->second), ++ RelType, 0); ++ LLVM_DEBUG(dbgs() << " Stub function found\n"); ++ return; ++ } ++ // Create a new stub function. ++ LLVM_DEBUG(dbgs() << " Create a new stub function\n"); ++ Stubs[Value] = Section.getStubOffset(); ++ uint8_t *StubTargetAddr = ++ createStubFunction(Section.getAddressWithOffset(Section.getStubOffset())); ++ RelocationEntry LU12I_W(SectionID, StubTargetAddr - Section.getAddress(), ++ ELF::R_LARCH_ABS_HI20, Value.Addend); ++ RelocationEntry ORI(SectionID, StubTargetAddr - Section.getAddress() + 4, ++ ELF::R_LARCH_ABS_LO12, Value.Addend); ++ RelocationEntry LU32I_D(SectionID, StubTargetAddr - Section.getAddress() + 8, ++ ELF::R_LARCH_ABS64_LO20, Value.Addend); ++ RelocationEntry LU52I_D(SectionID, StubTargetAddr - Section.getAddress() + 12, ++ ELF::R_LARCH_ABS64_HI12, Value.Addend); ++ if (Value.SymbolName) { ++ addRelocationForSymbol(LU12I_W, Value.SymbolName); ++ addRelocationForSymbol(ORI, Value.SymbolName); ++ addRelocationForSymbol(LU32I_D, Value.SymbolName); ++ addRelocationForSymbol(LU52I_D, Value.SymbolName); ++ } else { ++ addRelocationForSection(LU12I_W, Value.SectionID); ++ addRelocationForSection(ORI, Value.SectionID); ++ addRelocationForSection(LU32I_D, Value.SectionID); ++ ++ addRelocationForSection(LU52I_D, Value.SectionID); ++ } ++ resolveRelocation(Section, Offset, ++ reinterpret_cast( ++ Section.getAddressWithOffset(Section.getStubOffset())), ++ RelType, 0); ++ Section.advanceStubOffset(getMaxStubSize()); ++} ++ ++// Returns extract bits Val[Hi:Lo]. ++static inline uint32_t extractBits(uint64_t Val, uint32_t Hi, uint32_t Lo) { ++ return Hi == 63 ? Val >> Lo : (Val & (((1ULL << (Hi + 1)) - 1))) >> Lo; ++} ++ ++void RuntimeDyldELF::resolveLoongArch64Relocation(const SectionEntry &Section, ++ uint64_t Offset, ++ uint64_t Value, uint32_t Type, ++ int64_t Addend) { ++ auto *TargetPtr = Section.getAddressWithOffset(Offset); ++ uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); ++ ++ LLVM_DEBUG(dbgs() << "resolveLoongArch64Relocation, LocalAddress: 0x" ++ << format("%llx", Section.getAddressWithOffset(Offset)) ++ << " FinalAddress: 0x" << format("%llx", FinalAddress) ++ << " Value: 0x" << format("%llx", Value) << " Type: 0x" ++ << format("%x", Type) << " Addend: 0x" ++ << format("%llx", Addend) << "\n"); ++ ++ switch (Type) { ++ default: ++ report_fatal_error("Relocation type not implemented yet!"); ++ break; ++ case ELF::R_LARCH_32: ++ support::ulittle32_t::ref{TargetPtr} = ++ static_cast(Value + Addend); ++ break; ++ case ELF::R_LARCH_64: ++ support::ulittle64_t::ref{TargetPtr} = Value + Addend; ++ break; ++ case ELF::R_LARCH_32_PCREL: ++ support::ulittle32_t::ref{TargetPtr} = ++ static_cast(Value + Addend - FinalAddress); ++ break; ++ case ELF::R_LARCH_B26: { ++ uint64_t B26 = (Value + Addend - FinalAddress) >> 2; ++ auto Instr = support::ulittle32_t::ref(TargetPtr); ++ uint32_t Imm15_0 = extractBits(B26, /*Hi=*/15, /*Lo=*/0) << 10; ++ uint32_t Imm25_16 = extractBits(B26, /*Hi=*/25, /*Lo=*/16); ++ Instr = (Instr & 0xfc000000) | Imm15_0 | Imm25_16; ++ break; ++ } ++ case ELF::R_LARCH_CALL36: { ++ uint64_t Call36 = (Value + Addend - FinalAddress) >> 2; ++ auto Pcaddu18i = support::ulittle32_t::ref(TargetPtr); ++ uint32_t Imm35_16 = ++ extractBits((Call36 + (1UL << 15)), /*Hi=*/35, /*Lo=*/16) << 5; ++ Pcaddu18i = (Pcaddu18i & 0xfe00001f) | Imm35_16; ++ auto Jirl = support::ulittle32_t::ref(TargetPtr + 4); ++ uint32_t Imm15_0 = extractBits(Call36, /*Hi=*/15, /*Lo=*/0) << 10; ++ Jirl = (Jirl & 0xfc0003ff) | Imm15_0; ++ break; ++ } ++ case ELF::R_LARCH_GOT_PC_HI20: ++ case ELF::R_LARCH_PCALA_HI20: { ++ uint64_t Target = Value + Addend; ++ uint64_t TargetPage = ++ (Target + (Target & 0x800)) & ~static_cast(0xfff); ++ uint64_t PCPage = FinalAddress & ~static_cast(0xfff); ++ int64_t PageDelta = TargetPage - PCPage; ++ auto Instr = support::ulittle32_t::ref(TargetPtr); ++ uint32_t Imm31_12 = extractBits(PageDelta, /*Hi=*/31, /*Lo=*/12) << 5; ++ Instr = (Instr & 0xfe00001f) | Imm31_12; ++ break; ++ } ++ case ELF::R_LARCH_GOT_PC_LO12: ++ case ELF::R_LARCH_PCALA_LO12: { ++ uint64_t TargetOffset = (Value + Addend) & 0xfff; ++ auto Instr = support::ulittle32_t::ref(TargetPtr); ++ uint32_t Imm11_0 = TargetOffset << 10; ++ Instr = (Instr & 0xffc003ff) | Imm11_0; ++ break; ++ } ++ case ELF::R_LARCH_ABS_HI20: { ++ uint64_t Target = Value + Addend; ++ auto Instr = support::ulittle32_t::ref(TargetPtr); ++ uint32_t Imm31_12 = extractBits(Target, /*Hi=*/31, /*Lo=*/12) << 5; ++ Instr = (Instr & 0xfe00001f) | Imm31_12; ++ break; ++ } ++ case ELF::R_LARCH_ABS_LO12: { ++ uint64_t Target = Value + Addend; ++ auto Instr = support::ulittle32_t::ref(TargetPtr); ++ uint32_t Imm11_0 = extractBits(Target, /*Hi=*/11, /*Lo=*/0) << 10; ++ Instr = (Instr & 0xffc003ff) | Imm11_0; ++ break; ++ } ++ case ELF::R_LARCH_ABS64_LO20: { ++ uint64_t Target = Value + Addend; ++ auto Instr = support::ulittle32_t::ref(TargetPtr); ++ uint32_t Imm51_32 = extractBits(Target, /*Hi=*/51, /*Lo=*/32) << 5; ++ Instr = (Instr & 0xfe00001f) | Imm51_32; ++ break; ++ } ++ case ELF::R_LARCH_ABS64_HI12: { ++ uint64_t Target = Value + Addend; ++ auto Instr = support::ulittle32_t::ref(TargetPtr); ++ uint32_t Imm63_52 = extractBits(Target, /*Hi=*/63, /*Lo=*/52) << 10; ++ Instr = (Instr & 0xffc003ff) | Imm63_52; ++ break; ++ } ++ case ELF::R_LARCH_ADD32: ++ support::ulittle32_t::ref{TargetPtr} = ++ (support::ulittle32_t::ref{TargetPtr} + ++ static_cast(Value + Addend)); ++ break; ++ case ELF::R_LARCH_SUB32: ++ support::ulittle32_t::ref{TargetPtr} = ++ (support::ulittle32_t::ref{TargetPtr} - ++ static_cast(Value + Addend)); ++ break; ++ case ELF::R_LARCH_ADD64: ++ support::ulittle64_t::ref{TargetPtr} = ++ (support::ulittle64_t::ref{TargetPtr} + Value + Addend); ++ break; ++ case ELF::R_LARCH_SUB64: ++ support::ulittle64_t::ref{TargetPtr} = ++ (support::ulittle64_t::ref{TargetPtr} - Value - Addend); ++ break; ++ } ++} ++ + void RuntimeDyldELF::setMipsABI(const ObjectFile &Obj) { + if (Arch == Triple::UnknownArch || + !StringRef(Triple::getArchTypePrefix(Arch)).equals("mips")) { +@@ -1061,6 +1261,9 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section, + resolveARMRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type, + (uint32_t)(Addend & 0xffffffffL)); + break; ++ case Triple::loongarch64: ++ resolveLoongArch64Relocation(Section, Offset, Value, Type, Addend); ++ break; + case Triple::ppc: // Fall through. + case Triple::ppcle: + resolvePPC32Relocation(Section, Offset, Value, Type, Addend); +@@ -1374,6 +1577,17 @@ RuntimeDyldELF::processRelocationRef( + } + processSimpleRelocation(SectionID, Offset, RelType, Value); + } ++ } else if (Arch == Triple::loongarch64) { ++ if (RelType == ELF::R_LARCH_B26 && MemMgr.allowStubAllocation()) { ++ resolveLoongArch64Branch(SectionID, Value, RelI, Stubs); ++ } else if (RelType == ELF::R_LARCH_GOT_PC_HI20 || ++ RelType == ELF::R_LARCH_GOT_PC_LO12) { ++ uint64_t GOTOffset = findOrAllocGOTEntry(Value, ELF::R_LARCH_64); ++ resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend, ++ RelType); ++ } else { ++ processSimpleRelocation(SectionID, Offset, RelType, Value); ++ } + } else if (IsMipsO32ABI) { + uint8_t *Placeholder = reinterpret_cast( + computePlaceholderAddress(SectionID, Offset)); +@@ -2219,6 +2433,7 @@ size_t RuntimeDyldELF::getGOTEntrySize() { + case Triple::x86_64: + case Triple::aarch64: + case Triple::aarch64_be: ++ case Triple::loongarch64: + case Triple::ppc64: + case Triple::ppc64le: + case Triple::systemz: +@@ -2531,6 +2746,10 @@ bool RuntimeDyldELF::relocationNeedsGot(const RelocationRef &R) const { + return RelTy == ELF::R_AARCH64_ADR_GOT_PAGE || + RelTy == ELF::R_AARCH64_LD64_GOT_LO12_NC; + ++ if (Arch == Triple::loongarch64) ++ return RelTy == ELF::R_LARCH_GOT_PC_HI20 || ++ RelTy == ELF::R_LARCH_GOT_PC_LO12; ++ + if (Arch == Triple::x86_64) + return RelTy == ELF::R_X86_64_GOTPCREL || + RelTy == ELF::R_X86_64_GOTPCRELX || +diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +index dfdd98cb3a34..2c930219c0ff 100644 +--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h ++++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +@@ -48,6 +48,18 @@ class RuntimeDyldELF : public RuntimeDyldImpl { + void resolveARMRelocation(const SectionEntry &Section, uint64_t Offset, + uint32_t Value, uint32_t Type, int32_t Addend); + ++ void resolveLoongArch64Relocation(const SectionEntry &Section, ++ uint64_t Offset, uint64_t Value, ++ uint32_t Type, int64_t Addend); ++ ++ bool resolveLoongArch64ShortBranch(unsigned SectionID, ++ relocation_iterator RelI, ++ const RelocationValueRef &Value); ++ ++ void resolveLoongArch64Branch(unsigned SectionID, ++ const RelocationValueRef &Value, ++ relocation_iterator RelI, StubMap &Stubs); ++ + void resolvePPC32Relocation(const SectionEntry &Section, uint64_t Offset, + uint64_t Value, uint32_t Type, int64_t Addend); + +@@ -69,6 +81,8 @@ class RuntimeDyldELF : public RuntimeDyldImpl { + return 16; + else if (IsMipsN64ABI) + return 32; ++ if (Arch == Triple::loongarch64) ++ return 20; // lu12i.w; ori; lu32i.d; lu52i.d; jr + else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) + return 44; + else if (Arch == Triple::x86_64) +diff --git a/llvm/test/ExecutionEngine/RuntimeDyld/LoongArch/ELF_LoongArch_relocations.s b/llvm/test/ExecutionEngine/RuntimeDyld/LoongArch/ELF_LoongArch_relocations.s +new file mode 100644 +index 000000000000..0fca88b6e9ba +--- /dev/null ++++ b/llvm/test/ExecutionEngine/RuntimeDyld/LoongArch/ELF_LoongArch_relocations.s +@@ -0,0 +1,102 @@ ++# RUN: rm -rf %t && mkdir -p %t ++# RUN: llvm-mc --triple=loongarch64 --filetype=obj -o %t/reloc.o %s ++# RUN: llvm-rtdyld --triple=loongarch64 --verify --check=%s %t/reloc.o \ ++# RUN: --map-section reloc.o,.got=0x21f00 \ ++# RUN: --dummy-extern abs=0x0123456789abcdef \ ++# RUN: --dummy-extern external_data=0x1234 ++ ++ .text ++ .globl main ++ .p2align 2 ++ .type main,@function ++main: ++## Check R_LARCH_ABS_HI20 ++# rtdyld-check: *{4}(main) = 0x1513578c ++ lu12i.w $t0, %abs_hi20(abs) ++## Check R_LARCH_ABS_LO12 ++# rtdyld-check: *{4}(main + 4) = 0x03b7bd8c ++ ori $t0, $t0, %abs_lo12(abs) ++## Check R_LARCH_ABS64_LO20 ++# rtdyld-check: *{4}(main + 8) = 0x1668acec ++ lu32i.d $t0, %abs64_lo20(abs) ++## Check R_LARCH_ABS64_HI12 ++# rtdyld-check: *{4}(main + 12) = 0x0300498c ++ lu52i.d $t0, $t0, %abs64_hi12(abs) ++ ret ++ .size main, .-main ++ ++ .globl local_func ++ .p2align 2 ++ .type local_func,@function ++local_func: ++ ret ++ .size local_func, .-local_func ++ ++ .globl local_func_call26 ++ .p2align 2 ++local_func_call26: ++## Check R_LARCH_B26 ++# rtdyld-check: decode_operand(local_func_call26, 0)[27:0] = \ ++# rtdyld-check: (local_func - local_func_call26)[27:0] ++ bl local_func ++ .size local_func_call26, .-local_func_call26 ++ ++ .globl local_func_call36 ++ .p2align 2 ++local_func_call36: ++## Check R_LARCH_CALL36 ++# rtdyld-check: decode_operand(local_func_call36, 1)[19:0] = \ ++# rtdyld-check: ((local_func - local_func_call36) + \ ++# rtdyld-check: (((local_func - local_func_call36)[17:17]) << 17))[37:18] ++# rtdyld-check: decode_operand(local_func_call36 + 4, 2)[17:0] = \ ++# rtdyld-check: (local_func - local_func_call36)[17:0] ++ pcaddu18i $ra, %call36(local_func) ++ jirl $ra, $ra, 0 ++ .size local_func_call36, .-local_func_call36 ++ ++ .globl test_pc_hi20 ++ .p2align 2 ++test_pc_hi20: ++## Check R_LARCH_PCALA_HI20 ++# rtdyld-check: decode_operand(test_pc_hi20, 1)[19:0] = \ ++# rtdyld-check: (named_data - test_pc_hi20)[31:12] + \ ++# rtdyld-check: named_data[11:11] ++ pcalau12i $a0, %pc_hi20(named_data) ++ .size test_pc_hi20, .-test_pc_hi20 ++ ++ .globl test_pc_lo12 ++ .p2align 2 ++test_pc_lo12: ++## Check R_LARCH_PCALA_LO12 ++# rtdyld-check: decode_operand(test_pc_lo12, 2)[11:0] = \ ++# rtdyld-check: (named_data)[11:0] ++ addi.d $a0, $a0, %pc_lo12(named_data) ++ .size test_pc_lo12, .-test_pc_lo12 ++ ++ .globl test_got_pc_hi20 ++ .p2align 2 ++test_got_pc_hi20: ++## Check R_LARCH_GOT_PC_HI20 ++# rtdyld-check: decode_operand(test_got_pc_hi20, 1)[19:0] = \ ++# rtdyld-check: (section_addr(reloc.o, .got)[31:12] - \ ++# rtdyld-check: test_got_pc_hi20[31:12] + \ ++# rtdyld-check: section_addr(reloc.o, .got)[11:11]) ++ pcalau12i $a0, %got_pc_hi20(external_data) ++ .size test_got_pc_hi20, .-test_got_pc_hi20 ++ ++ .globl test_got_pc_lo12 ++ .p2align 2 ++test_got_pc_lo12: ++## Check R_LARCH_GOT_PC_LO12 ++# rtdyld-check: decode_operand(test_got_pc_lo12, 2)[11:0] = \ ++# rtdyld-check: (section_addr(reloc.o, .got)[11:0]) ++ ld.d $a0, $a0, %got_pc_lo12(external_data) ++ .size test_gotoffset12_external, .-test_gotoffset12_external ++ ++ .globl named_data ++ .p2align 4 ++ .type named_data,@object ++named_data: ++ .quad 0x2222222222222222 ++ .quad 0x3333333333333333 ++ .size named_data, .-named_data +diff --git a/llvm/test/ExecutionEngine/RuntimeDyld/LoongArch/lit.local.cfg b/llvm/test/ExecutionEngine/RuntimeDyld/LoongArch/lit.local.cfg +new file mode 100644 +index 000000000000..cc24278acbb4 +--- /dev/null ++++ b/llvm/test/ExecutionEngine/RuntimeDyld/LoongArch/lit.local.cfg +@@ -0,0 +1,2 @@ ++if not "LoongArch" in config.root.targets: ++ config.unsupported = True +-- +2.20.1 + diff --git a/0023-RuntimeDyld-LoongArch-Support-large-code-model-14858.patch b/0023-RuntimeDyld-LoongArch-Support-large-code-model-14858.patch new file mode 100644 index 0000000..bdc5f63 --- /dev/null +++ b/0023-RuntimeDyld-LoongArch-Support-large-code-model-14858.patch @@ -0,0 +1,169 @@ +From bb0073689acc41301aab19451d79643b9f4c28dc Mon Sep 17 00:00:00 2001 +From: Ami-zhang +Date: Mon, 21 Jul 2025 09:28:24 +0800 +Subject: [PATCH 2/2] [RuntimeDyld][LoongArch] Support large code model + (#148584) + +Co-authored-by: Weining Lu +(cherry picked from commit 4e35ae10c4d7bc840ad6b6a9b13e465bfaaf3768) +--- + .../RuntimeDyld/RuntimeDyldELF.cpp | 57 +++++++++++++++++-- + .../LoongArch/ELF_LoongArch_relocations.s | 42 ++++++++++++++ + 2 files changed, 93 insertions(+), 6 deletions(-) + +diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +index 35d1c90cc606..5aa67142afa3 100644 +--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp ++++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +@@ -728,6 +728,32 @@ static inline uint32_t extractBits(uint64_t Val, uint32_t Hi, uint32_t Lo) { + return Hi == 63 ? Val >> Lo : (Val & (((1ULL << (Hi + 1)) - 1))) >> Lo; + } + ++// Calculate the adjusted page delta between dest and PC. The code is copied ++// from lld and see comments there for more details. ++static uint64_t getLoongArchPageDelta(uint64_t dest, uint64_t pc, ++ uint32_t type) { ++ uint64_t pcalau12i_pc; ++ switch (type) { ++ case ELF::R_LARCH_PCALA64_LO20: ++ case ELF::R_LARCH_GOT64_PC_LO20: ++ pcalau12i_pc = pc - 8; ++ break; ++ case ELF::R_LARCH_PCALA64_HI12: ++ case ELF::R_LARCH_GOT64_PC_HI12: ++ pcalau12i_pc = pc - 12; ++ break; ++ default: ++ pcalau12i_pc = pc; ++ break; ++ } ++ uint64_t result = (dest & ~0xfffULL) - (pcalau12i_pc & ~0xfffULL); ++ if (dest & 0x800) ++ result += 0x1000 - 0x1'0000'0000; ++ if (result & 0x8000'0000) ++ result += 0x1'0000'0000; ++ return result; ++} ++ + void RuntimeDyldELF::resolveLoongArch64Relocation(const SectionEntry &Section, + uint64_t Offset, + uint64_t Value, uint32_t Type, +@@ -779,10 +805,7 @@ void RuntimeDyldELF::resolveLoongArch64Relocation(const SectionEntry &Section, + case ELF::R_LARCH_GOT_PC_HI20: + case ELF::R_LARCH_PCALA_HI20: { + uint64_t Target = Value + Addend; +- uint64_t TargetPage = +- (Target + (Target & 0x800)) & ~static_cast(0xfff); +- uint64_t PCPage = FinalAddress & ~static_cast(0xfff); +- int64_t PageDelta = TargetPage - PCPage; ++ int64_t PageDelta = getLoongArchPageDelta(Target, FinalAddress, Type); + auto Instr = support::ulittle32_t::ref(TargetPtr); + uint32_t Imm31_12 = extractBits(PageDelta, /*Hi=*/31, /*Lo=*/12) << 5; + Instr = (Instr & 0xfe00001f) | Imm31_12; +@@ -796,6 +819,24 @@ void RuntimeDyldELF::resolveLoongArch64Relocation(const SectionEntry &Section, + Instr = (Instr & 0xffc003ff) | Imm11_0; + break; + } ++ case ELF::R_LARCH_GOT64_PC_LO20: ++ case ELF::R_LARCH_PCALA64_LO20: { ++ uint64_t Target = Value + Addend; ++ int64_t PageDelta = getLoongArchPageDelta(Target, FinalAddress, Type); ++ auto Instr = support::ulittle32_t::ref(TargetPtr); ++ uint32_t Imm51_32 = extractBits(PageDelta, /*Hi=*/51, /*Lo=*/32) << 5; ++ Instr = (Instr & 0xfe00001f) | Imm51_32; ++ break; ++ } ++ case ELF::R_LARCH_GOT64_PC_HI12: ++ case ELF::R_LARCH_PCALA64_HI12: { ++ uint64_t Target = Value + Addend; ++ int64_t PageDelta = getLoongArchPageDelta(Target, FinalAddress, Type); ++ auto Instr = support::ulittle32_t::ref(TargetPtr); ++ uint32_t Imm63_52 = extractBits(PageDelta, /*Hi=*/63, /*Lo=*/52) << 10; ++ Instr = (Instr & 0xffc003ff) | Imm63_52; ++ break; ++ } + case ELF::R_LARCH_ABS_HI20: { + uint64_t Target = Value + Addend; + auto Instr = support::ulittle32_t::ref(TargetPtr); +@@ -1581,7 +1622,9 @@ RuntimeDyldELF::processRelocationRef( + if (RelType == ELF::R_LARCH_B26 && MemMgr.allowStubAllocation()) { + resolveLoongArch64Branch(SectionID, Value, RelI, Stubs); + } else if (RelType == ELF::R_LARCH_GOT_PC_HI20 || +- RelType == ELF::R_LARCH_GOT_PC_LO12) { ++ RelType == ELF::R_LARCH_GOT_PC_LO12 || ++ RelType == ELF::R_LARCH_GOT64_PC_HI12 || ++ RelType == ELF::R_LARCH_GOT64_PC_LO20) { + uint64_t GOTOffset = findOrAllocGOTEntry(Value, ELF::R_LARCH_64); + resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend, + RelType); +@@ -2748,7 +2791,9 @@ bool RuntimeDyldELF::relocationNeedsGot(const RelocationRef &R) const { + + if (Arch == Triple::loongarch64) + return RelTy == ELF::R_LARCH_GOT_PC_HI20 || +- RelTy == ELF::R_LARCH_GOT_PC_LO12; ++ RelTy == ELF::R_LARCH_GOT_PC_LO12 || ++ RelTy == ELF::R_LARCH_GOT64_PC_HI12 || ++ RelTy == ELF::R_LARCH_GOT64_PC_LO20; + + if (Arch == Triple::x86_64) + return RelTy == ELF::R_X86_64_GOTPCREL || +diff --git a/llvm/test/ExecutionEngine/RuntimeDyld/LoongArch/ELF_LoongArch_relocations.s b/llvm/test/ExecutionEngine/RuntimeDyld/LoongArch/ELF_LoongArch_relocations.s +index 0fca88b6e9ba..ddbf02c1869f 100644 +--- a/llvm/test/ExecutionEngine/RuntimeDyld/LoongArch/ELF_LoongArch_relocations.s ++++ b/llvm/test/ExecutionEngine/RuntimeDyld/LoongArch/ELF_LoongArch_relocations.s +@@ -2,6 +2,9 @@ + # RUN: llvm-mc --triple=loongarch64 --filetype=obj -o %t/reloc.o %s + # RUN: llvm-rtdyld --triple=loongarch64 --verify --check=%s %t/reloc.o \ + # RUN: --map-section reloc.o,.got=0x21f00 \ ++# RUN: --map-section reloc.o,.sec.large.pc=0x0000000012345000 \ ++# RUN: --map-section reloc.o,.sec.large.got=0x44433333abcde000 \ ++# RUN: --map-section reloc.o,.sec.dummy=0x4443333334567111 \ + # RUN: --dummy-extern abs=0x0123456789abcdef \ + # RUN: --dummy-extern external_data=0x1234 + +@@ -100,3 +103,42 @@ named_data: + .quad 0x2222222222222222 + .quad 0x3333333333333333 + .size named_data, .-named_data ++ ++ .section .sec.large.pc,"ax" ++ .globl test_large_pc ++test_large_pc: ++## Code after link should be: ++## 1a44444d pcalau12i $t1, 139810 ++## 02c4440c addi.d $t0, $zero, 273 ++## 1666666c lu32i.d $t0, 209715 ++## 0311118c lu52i.d $t0, $t0, 1092 ++ ++# rtdyld-check: *{4}(test_large_pc) = 0x1a44444d ++ pcalau12i $t1, %pc_hi20(.sec.dummy) ++# rtdyld-check: *{4}(test_large_pc + 4) = 0x02c4440c ++ addi.d $t0, $zero, %pc_lo12(.sec.dummy) ++# rtdyld-check: *{4}(test_large_pc + 8) = 0x1666666c ++ lu32i.d $t0, %pc64_lo20(.sec.dummy) ++# rtdyld-check: *{4}(test_large_pc + 12) = 0x0311118c ++ lu52i.d $t0, $t0, %pc64_hi12(.sec.dummy) ++ ++ .section .sec.large.got,"ax" ++ .globl test_large_got ++test_large_got: ++## Code after link should be: ++## 1aa8688d pcalau12i $t1, 344900 ++## 02fc000c addi.d $t0, $zero, -256 ++## 1799996c lu32i.d $t0, -209717 ++## 032eed8c lu52i.d $t0, $t0, -1093 ++ ++# rtdyld-check: *{4}(test_large_got) = 0x1aa8688d ++ pcalau12i $t1, %got_pc_hi20(external_data) ++# rtdyld-check: *{4}(test_large_got + 4) = 0x02fc000c ++ addi.d $t0, $zero, %got_pc_lo12(external_data) ++# rtdyld-check: *{4}(test_large_got + 8) = 0x1799996c ++ lu32i.d $t0, %got64_pc_lo20(external_data) ++# rtdyld-check: *{4}(test_large_got + 12) = 0x032eed8c ++ lu52i.d $t0, $t0, %got64_pc_hi12(external_data) ++ ++ .section .sec.dummy,"a" ++ .word 0 +-- +2.20.1 + diff --git a/llvm.spec b/llvm.spec index 1efef88..a045abc 100644 --- a/llvm.spec +++ b/llvm.spec @@ -2,7 +2,7 @@ Name: llvm Version: 17.0.6 -Release: 11%{?dist} +Release: 12%{?dist} Summary: Low Level Virtual Machine, modular and reusable compiler and toolchain License: Apache License v2.0 with LLVM Exceptions URL: http://llvm.org @@ -34,6 +34,8 @@ Patch0018: 0017-LoongArch-Fix-test-cases-after-2dd8460d8a36.patch Patch0019: 0019-BinaryFormat-LoongArch-Define-psABI-v2.30-relocs-770.patch Patch0020: 0020-LoongArch-Pre-commit-test-for-fixing-xvshuf-instruct.patch Patch0021: 0021-LoongArch-Fix-xvshuf-instructions-lowering-145868.patch +Patch0022: 0022-RuntimeDyld-Add-LoongArch-support.patch +Patch0023: 0023-RuntimeDyld-LoongArch-Support-large-code-model-14858.patch Patch3000: deprecated-recommonmark.patch Patch3001: 0001-Clear-instructions-not-recorded-in-ErasedInstrs.patch @@ -257,6 +259,10 @@ LD_LIBRARY_PATH=%{buildroot}/%{_libdir} %{__ninja} check-all -C %{_vpath_buildd %{_includedir}/llvm-gmock %changelog +* Wed Aug 20 2025 chenli - 17.0.6-12 +- [Type] bugfix +- [DESC] Add support for RuntimeDyld on loongarch64 + * Thu Jul 10 2025 chenli - 17.0.6-11 - LoongArch Backport: Define psABI v2.30 relocs - LoongArch Backport: Fix xvshuf instructions lowering -- Gitee