From d72a7d64b139dfd6d58bcc9de580e761f822107e Mon Sep 17 00:00:00 2001 From: Ami-zhang Date: Sat, 16 Mar 2024 17:34:32 +0800 Subject: [PATCH] [Backport][LoongArch] Support `relax` feature (cherry picked from commit 8cf6fb10e49140722443997596f2ae55bec9d525) --- ...d-relax-feature-and-keep-relocations.patch | 178 +++++ ...yed-decision-for-ADD-SUB-relocations.patch | 299 +++++++++ ...ELAX-when-expanding-some-LoadAddress.patch | 364 ++++++++++ ...s-available-and-not-need-insert-nops.patch | 123 ++++ ...-SUB-_ULEB128-for-uleb128-directives.patch | 633 ++++++++++++++++++ ...-the-mutable-label-diff-in-dwarfinfo.patch | 376 +++++++++++ ...eloc-when-handle-alignment-directive.patch | 362 ++++++++++ ...est-Update-dwarf-loongarch-relocs.ll.patch | 86 +++ ...ls-in-.uleb128-for-label-differences.patch | 53 ++ ...ence-revert-isMicroMips-special-case.patch | 135 ++++ llvm.spec | 17 +- 11 files changed, 2625 insertions(+), 1 deletion(-) create mode 100644 0001-Backport-LoongArch-Add-relax-feature-and-keep-relocations.patch create mode 100644 0002-Backport-LoongArch-Allow-delayed-decision-for-ADD-SUB-relocations.patch create mode 100644 0003-Backport-LoongArch-Emit-R_LARCH_RELAX-when-expanding-some-LoadAddress.patch create mode 100644 0004-Backport-MC-LoongArch-Add-AlignFragment-size-if-layout-is-available-and-not-need-insert-nops.patch create mode 100644 0005-Backport-LoongArch-RISCV-Support-R_LARCH_-ADD-SUB-_ULEB128-R_RISCV_-SET-SUB-_ULEB128-for-uleb128-directives.patch create mode 100644 0006-Backport-LoongArch-Add-relaxDwarfLineAddr-and-relaxDwarfCFA-to-handle-the-mutable-label-diff-in-dwarfinfo.patch create mode 100644 0007-Backport-LoongArch-Insert-nops-and-emit-align-reloc-when-handle-alignment-directive.patch create mode 100644 0008-Backport-test-Update-dwarf-loongarch-relocs.ll.patch create mode 100644 0009-Backport-MC-test-Change-ELF-uleb-ehtable.s-Mach-O-to-use-private-symbols-in-.uleb128-for-label-differences.patch create mode 100644 0010-Backport-Mips-MC-AttemptToFoldSymbolOffsetDifference-revert-isMicroMips-special-case.patch diff --git a/0001-Backport-LoongArch-Add-relax-feature-and-keep-relocations.patch b/0001-Backport-LoongArch-Add-relax-feature-and-keep-relocations.patch new file mode 100644 index 0000000..9602f6c --- /dev/null +++ b/0001-Backport-LoongArch-Add-relax-feature-and-keep-relocations.patch @@ -0,0 +1,178 @@ +From 6f135b13769c64a6942b4b232a350b6a6207f2b2 Mon Sep 17 00:00:00 2001 +From: Jinyang He +Date: Thu, 16 Nov 2023 11:01:26 +0800 +Subject: [PATCH 02/14] [LoongArch] Add relax feature and keep relocations + (#72191) + +Add relax feature. To support linker relocation, we should make +relocation with a symbol rather than section plus offset, and keep all +relocations with non-abs symbol. + +(cherry picked from commit f5bfc833fcbf17a5876911783d1adaca7028d20c) +Change-Id: Ief38b480016175f2cc9939b74a84d9444559ffd6 +--- + llvm/lib/Target/LoongArch/LoongArch.td | 4 +++ + .../lib/Target/LoongArch/LoongArchSubtarget.h | 2 ++ + .../MCTargetDesc/LoongArchAsmBackend.cpp | 5 +-- + .../MCTargetDesc/LoongArchELFObjectWriter.cpp | 18 ++++++++--- + .../MCTargetDesc/LoongArchMCTargetDesc.h | 2 +- + .../MC/LoongArch/Relocations/relax-attr.s | 32 +++++++++++++++++++ + 6 files changed, 55 insertions(+), 8 deletions(-) + create mode 100644 llvm/test/MC/LoongArch/Relocations/relax-attr.s + +diff --git a/llvm/lib/Target/LoongArch/LoongArch.td b/llvm/lib/Target/LoongArch/LoongArch.td +index 0675caa3b601..75b65fe69f26 100644 +--- a/llvm/lib/Target/LoongArch/LoongArch.td ++++ b/llvm/lib/Target/LoongArch/LoongArch.td +@@ -102,6 +102,10 @@ def FeatureUAL + : SubtargetFeature<"ual", "HasUAL", "true", + "Allow memory accesses to be unaligned">; + ++def FeatureRelax ++ : SubtargetFeature<"relax", "HasLinkerRelax", "true", ++ "Enable Linker relaxation">; ++ + //===----------------------------------------------------------------------===// + // Registers, instruction descriptions ... + //===----------------------------------------------------------------------===// +diff --git a/llvm/lib/Target/LoongArch/LoongArchSubtarget.h b/llvm/lib/Target/LoongArch/LoongArchSubtarget.h +index 0fbe23f2f62d..5c173675cca4 100644 +--- a/llvm/lib/Target/LoongArch/LoongArchSubtarget.h ++++ b/llvm/lib/Target/LoongArch/LoongArchSubtarget.h +@@ -43,6 +43,7 @@ class LoongArchSubtarget : public LoongArchGenSubtargetInfo { + bool HasLaGlobalWithAbs = false; + bool HasLaLocalWithAbs = false; + bool HasUAL = false; ++ bool HasLinkerRelax = false; + unsigned GRLen = 32; + MVT GRLenVT = MVT::i32; + LoongArchABI::ABI TargetABI = LoongArchABI::ABI_Unknown; +@@ -100,6 +101,7 @@ public: + bool hasLaGlobalWithAbs() const { return HasLaGlobalWithAbs; } + bool hasLaLocalWithAbs() const { return HasLaLocalWithAbs; } + bool hasUAL() const { return HasUAL; } ++ bool hasLinkerRelax() const { return HasLinkerRelax; } + MVT getGRLenVT() const { return GRLenVT; } + unsigned getGRLen() const { return GRLen; } + LoongArchABI::ABI getTargetABI() const { return TargetABI; } +diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +index ecb68ff401e9..aae3e544d326 100644 +--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp ++++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +@@ -168,7 +168,7 @@ bool LoongArchAsmBackend::shouldForceRelocation(const MCAssembler &Asm, + return true; + switch (Fixup.getTargetKind()) { + default: +- return false; ++ return STI.hasFeature(LoongArch::FeatureRelax); + case FK_Data_1: + case FK_Data_2: + case FK_Data_4: +@@ -193,7 +193,8 @@ bool LoongArchAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + + std::unique_ptr + LoongArchAsmBackend::createObjectTargetWriter() const { +- return createLoongArchELFObjectWriter(OSABI, Is64Bit); ++ return createLoongArchELFObjectWriter( ++ OSABI, Is64Bit, STI.hasFeature(LoongArch::FeatureRelax)); + } + + MCAsmBackend *llvm::createLoongArchAsmBackend(const Target &T, +diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp +index a6b9c0652639..e60b9c2cfd97 100644 +--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp ++++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp +@@ -20,19 +20,27 @@ using namespace llvm; + namespace { + class LoongArchELFObjectWriter : public MCELFObjectTargetWriter { + public: +- LoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit); ++ LoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit, bool EnableRelax); + + ~LoongArchELFObjectWriter() override; + ++ bool needsRelocateWithSymbol(const MCSymbol &Sym, ++ unsigned Type) const override { ++ return EnableRelax; ++ } ++ + protected: + unsigned getRelocType(MCContext &Ctx, const MCValue &Target, + const MCFixup &Fixup, bool IsPCRel) const override; ++ bool EnableRelax; + }; + } // end namespace + +-LoongArchELFObjectWriter::LoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit) ++LoongArchELFObjectWriter::LoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit, ++ bool EnableRelax) + : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_LOONGARCH, +- /*HasRelocationAddend*/ true) {} ++ /*HasRelocationAddend=*/true), ++ EnableRelax(EnableRelax) {} + + LoongArchELFObjectWriter::~LoongArchELFObjectWriter() {} + +@@ -87,6 +95,6 @@ unsigned LoongArchELFObjectWriter::getRelocType(MCContext &Ctx, + } + + std::unique_ptr +-llvm::createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit) { +- return std::make_unique(OSABI, Is64Bit); ++llvm::createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit, bool Relax) { ++ return std::make_unique(OSABI, Is64Bit, Relax); + } +diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h +index ab35a0096c8a..bb05baa9b717 100644 +--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h ++++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h +@@ -36,7 +36,7 @@ MCAsmBackend *createLoongArchAsmBackend(const Target &T, + const MCTargetOptions &Options); + + std::unique_ptr +-createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit); ++createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit, bool Relax); + + } // end namespace llvm + +diff --git a/llvm/test/MC/LoongArch/Relocations/relax-attr.s b/llvm/test/MC/LoongArch/Relocations/relax-attr.s +new file mode 100644 +index 000000000000..b1e648d850bb +--- /dev/null ++++ b/llvm/test/MC/LoongArch/Relocations/relax-attr.s +@@ -0,0 +1,32 @@ ++# RUN: llvm-mc --filetype=obj --triple=loongarch64 %s -o %t ++# RUN: llvm-readobj -r %t | FileCheck %s ++# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax %s -o %t ++# RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=CHECKR ++ ++# CHECK: Relocations [ ++# CHECK-NEXT: Section ({{.*}}) .rela.data { ++# CHECK-NEXT: 0x0 R_LARCH_64 .text 0x4 ++# CHECK-NEXT: } ++# CHECK-NEXT: ] ++ ++# CHECKR: Relocations [ ++# CHECKR-NEXT: Section ({{.*}}) .rela.text { ++# CHECKR-NEXT: 0x8 R_LARCH_B21 .L1 0x0 ++# CHECKR-NEXT: 0xC R_LARCH_B16 .L1 0x0 ++# CHECKR-NEXT: 0x10 R_LARCH_B26 .L1 0x0 ++# CHECKR-NEXT: } ++# CHECKR-NEXT: Section ({{.*}}) .rela.data { ++# CHECKR-NEXT: 0x0 R_LARCH_64 .L1 0x0 ++# CHECKR-NEXT: } ++# CHECKR-NEXT: ] ++ ++.text ++ nop ++.L1: ++ nop ++ beqz $a0, .L1 ++ blt $a0, $a1, .L1 ++ b .L1 ++ ++.data ++.dword .L1 +-- +2.20.1 + diff --git a/0002-Backport-LoongArch-Allow-delayed-decision-for-ADD-SUB-relocations.patch b/0002-Backport-LoongArch-Allow-delayed-decision-for-ADD-SUB-relocations.patch new file mode 100644 index 0000000..496e268 --- /dev/null +++ b/0002-Backport-LoongArch-Allow-delayed-decision-for-ADD-SUB-relocations.patch @@ -0,0 +1,299 @@ +From 77d74b8fa071fa2695c9782e2e63e7b930895b1b Mon Sep 17 00:00:00 2001 +From: Jinyang He +Date: Wed, 20 Dec 2023 10:54:51 +0800 +Subject: [PATCH 03/14] [LoongArch] Allow delayed decision for ADD/SUB + relocations (#72960) + +Refer to RISCV [1], LoongArch also need delayed decision for ADD/SUB +relocations. In handleAddSubRelocations, just return directly if SecA != +SecB, handleFixup usually will finish the the rest of creating PCRel +relocations works. Otherwise we emit relocs depends on whether +relaxation is enabled. If not, we return true and avoid record ADD/SUB +relocations. +Now the two symbols separated by alignment directive will return without +folding symbol offset in AttemptToFoldSymbolOffsetDifference, which has +the same effect when relaxation is enabled. + +[1] https://reviews.llvm.org/D155357 + +(cherry picked from commit a8081ed8ff0fd11fb8d5f4c83df49da909e49612) +Change-Id: Ic4c6a3eb11b576cb0c6ed0eba02150ad67c33cf2 +--- + llvm/lib/MC/MCExpr.cpp | 3 +- + .../MCTargetDesc/LoongArchAsmBackend.cpp | 78 +++++++++++++++++++ + .../MCTargetDesc/LoongArchAsmBackend.h | 9 ++- + .../MCTargetDesc/LoongArchFixupKinds.h | 4 +- + llvm/test/MC/LoongArch/Misc/subsection.s | 38 +++++++++ + .../MC/LoongArch/Relocations/relax-addsub.s | 68 ++++++++++++++++ + 6 files changed, 196 insertions(+), 4 deletions(-) + create mode 100644 llvm/test/MC/LoongArch/Misc/subsection.s + create mode 100644 llvm/test/MC/LoongArch/Relocations/relax-addsub.s + +diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp +index a7b980553af0..5a6596f93824 100644 +--- a/llvm/lib/MC/MCExpr.cpp ++++ b/llvm/lib/MC/MCExpr.cpp +@@ -635,7 +635,8 @@ static void AttemptToFoldSymbolOffsetDifference( + // instructions and InSet is false (not expressions in directive like + // .size/.fill), disable the fast path. + if (Layout && (InSet || !SecA.hasInstructions() || +- !Asm->getContext().getTargetTriple().isRISCV())) { ++ !(Asm->getContext().getTargetTriple().isRISCV() || ++ Asm->getContext().getTargetTriple().isLoongArch()))) { + // If both symbols are in the same fragment, return the difference of their + // offsets. canGetFragmentOffset(FA) may be false. + if (FA == FB && !SA.isVariable() && !SB.isVariable()) { +diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +index aae3e544d326..1ed047a8e632 100644 +--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp ++++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +@@ -177,6 +177,34 @@ bool LoongArchAsmBackend::shouldForceRelocation(const MCAssembler &Asm, + } + } + ++static inline std::pair ++getRelocPairForSize(unsigned Size) { ++ switch (Size) { ++ default: ++ llvm_unreachable("unsupported fixup size"); ++ case 6: ++ return std::make_pair( ++ MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_ADD6), ++ MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_SUB6)); ++ case 8: ++ return std::make_pair( ++ MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_ADD8), ++ MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_SUB8)); ++ case 16: ++ return std::make_pair( ++ MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_ADD16), ++ MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_SUB16)); ++ case 32: ++ return std::make_pair( ++ MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_ADD32), ++ MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_SUB32)); ++ case 64: ++ return std::make_pair( ++ MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_ADD64), ++ MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_SUB64)); ++ } ++} ++ + bool LoongArchAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { + // We mostly follow binutils' convention here: align to 4-byte boundary with a +@@ -191,6 +219,56 @@ bool LoongArchAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + return true; + } + ++bool LoongArchAsmBackend::handleAddSubRelocations(const MCAsmLayout &Layout, ++ const MCFragment &F, ++ const MCFixup &Fixup, ++ const MCValue &Target, ++ uint64_t &FixedValue) const { ++ std::pair FK; ++ uint64_t FixedValueA, FixedValueB; ++ const MCSection &SecA = Target.getSymA()->getSymbol().getSection(); ++ const MCSection &SecB = Target.getSymB()->getSymbol().getSection(); ++ ++ // We need record relocation if SecA != SecB. Usually SecB is same as the ++ // section of Fixup, which will be record the relocation as PCRel. If SecB ++ // is not same as the section of Fixup, it will report error. Just return ++ // false and then this work can be finished by handleFixup. ++ if (&SecA != &SecB) ++ return false; ++ ++ // In SecA == SecB case. If the linker relaxation is enabled, we need record ++ // the ADD, SUB relocations. Otherwise the FixedValue has already been ++ // calculated out in evaluateFixup, return true and avoid record relocations. ++ if (!STI.hasFeature(LoongArch::FeatureRelax)) ++ return true; ++ ++ switch (Fixup.getKind()) { ++ case llvm::FK_Data_1: ++ FK = getRelocPairForSize(8); ++ break; ++ case llvm::FK_Data_2: ++ FK = getRelocPairForSize(16); ++ break; ++ case llvm::FK_Data_4: ++ FK = getRelocPairForSize(32); ++ break; ++ case llvm::FK_Data_8: ++ FK = getRelocPairForSize(64); ++ break; ++ default: ++ llvm_unreachable("unsupported fixup size"); ++ } ++ MCValue A = MCValue::get(Target.getSymA(), nullptr, Target.getConstant()); ++ MCValue B = MCValue::get(Target.getSymB()); ++ auto FA = MCFixup::create(Fixup.getOffset(), nullptr, std::get<0>(FK)); ++ auto FB = MCFixup::create(Fixup.getOffset(), nullptr, std::get<1>(FK)); ++ auto &Asm = Layout.getAssembler(); ++ Asm.getWriter().recordRelocation(Asm, Layout, &F, FA, A, FixedValueA); ++ Asm.getWriter().recordRelocation(Asm, Layout, &F, FB, B, FixedValueB); ++ FixedValue = FixedValueA - FixedValueB; ++ return true; ++} ++ + std::unique_ptr + LoongArchAsmBackend::createObjectTargetWriter() const { + return createLoongArchELFObjectWriter( +diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h +index ae9bb8af0419..20f25b5cf53b 100644 +--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h ++++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h +@@ -31,10 +31,15 @@ class LoongArchAsmBackend : public MCAsmBackend { + public: + LoongArchAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit, + const MCTargetOptions &Options) +- : MCAsmBackend(support::little), STI(STI), OSABI(OSABI), Is64Bit(Is64Bit), +- TargetOptions(Options) {} ++ : MCAsmBackend(support::little, ++ LoongArch::fixup_loongarch_relax), ++ STI(STI), OSABI(OSABI), Is64Bit(Is64Bit), TargetOptions(Options) {} + ~LoongArchAsmBackend() override {} + ++ bool handleAddSubRelocations(const MCAsmLayout &Layout, const MCFragment &F, ++ const MCFixup &Fixup, const MCValue &Target, ++ uint64_t &FixedValue) const override; ++ + void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target, MutableArrayRef Data, + uint64_t Value, bool IsResolved, +diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h +index ba2d6718cdf9..178fa6e5262b 100644 +--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h ++++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h +@@ -106,7 +106,9 @@ enum Fixups { + // 20-bit fixup corresponding to %gd_pc_hi20(foo) for instruction pcalau12i. + fixup_loongarch_tls_gd_pc_hi20, + // 20-bit fixup corresponding to %gd_hi20(foo) for instruction lu12i.w. +- fixup_loongarch_tls_gd_hi20 ++ fixup_loongarch_tls_gd_hi20, ++ // Generate an R_LARCH_RELAX which indicates the linker may relax here. ++ fixup_loongarch_relax = FirstLiteralRelocationKind + ELF::R_LARCH_RELAX + }; + } // end namespace LoongArch + } // end namespace llvm +diff --git a/llvm/test/MC/LoongArch/Misc/subsection.s b/llvm/test/MC/LoongArch/Misc/subsection.s +new file mode 100644 +index 000000000000..0bd22b474536 +--- /dev/null ++++ b/llvm/test/MC/LoongArch/Misc/subsection.s +@@ -0,0 +1,38 @@ ++# RUN: not llvm-mc --filetype=obj --triple=loongarch64 --mattr=-relax %s -o /dev/null 2>&1 | FileCheck %s --check-prefixes=ERR,NORELAX --implicit-check-not=error: ++## TODO: not llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o /dev/null 2>&1 | FileCheck %s --check-prefixes=ERR,RELAX --implicit-check-not=error: ++ ++a: ++ nop ++b: ++ la.pcrel $t0, a ++c: ++ nop ++d: ++ ++.data ++## Positive subsection numbers ++## With relaxation, report an error as c-b is not an assemble-time constant. ++# RELAX: :[[#@LINE+1]]:14: error: cannot evaluate subsection number ++.subsection c-b ++# RELAX: :[[#@LINE+1]]:14: error: cannot evaluate subsection number ++.subsection d-b ++# RELAX: :[[#@LINE+1]]:14: error: cannot evaluate subsection number ++.subsection c-a ++ ++.subsection b-a ++.subsection d-c ++ ++## Negative subsection numbers ++# NORELAX: :[[#@LINE+2]]:14: error: subsection number -8 is not within [0,2147483647] ++# RELAX: :[[#@LINE+1]]:14: error: cannot evaluate subsection number ++.subsection b-c ++# NORELAX: :[[#@LINE+2]]:14: error: subsection number -12 is not within [0,2147483647] ++# RELAX: :[[#@LINE+1]]:14: error: cannot evaluate subsection number ++.subsection b-d ++# NORELAX: :[[#@LINE+2]]:14: error: subsection number -12 is not within [0,2147483647] ++# RELAX: :[[#@LINE+1]]:14: error: cannot evaluate subsection number ++.subsection a-c ++# ERR: :[[#@LINE+1]]:14: error: subsection number -4 is not within [0,2147483647] ++.subsection a-b ++# ERR: :[[#@LINE+1]]:14: error: subsection number -4 is not within [0,2147483647] ++.subsection c-d +diff --git a/llvm/test/MC/LoongArch/Relocations/relax-addsub.s b/llvm/test/MC/LoongArch/Relocations/relax-addsub.s +new file mode 100644 +index 000000000000..532eb4e0561a +--- /dev/null ++++ b/llvm/test/MC/LoongArch/Relocations/relax-addsub.s +@@ -0,0 +1,68 @@ ++# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=-relax %s \ ++# RUN: | llvm-readobj -r -x .data - | FileCheck %s --check-prefix=NORELAX ++# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s \ ++# RUN: | llvm-readobj -r -x .data - | FileCheck %s --check-prefix=RELAX ++ ++# NORELAX: Relocations [ ++# NORELAX-NEXT: Section ({{.*}}) .rela.text { ++# NORELAX-NEXT: 0x10 R_LARCH_PCALA_HI20 .text 0x0 ++# NORELAX-NEXT: 0x14 R_LARCH_PCALA_LO12 .text 0x0 ++# NORELAX-NEXT: } ++# NORELAX-NEXT: ] ++ ++# NORELAX: Hex dump of section '.data': ++# NORELAX-NEXT: 0x00000000 04040004 00000004 00000000 0000000c ++# NORELAX-NEXT: 0x00000010 0c000c00 00000c00 00000000 00000808 ++# NORELAX-NEXT: 0x00000020 00080000 00080000 00000000 00 ++ ++# RELAX: Relocations [ ++# RELAX-NEXT: Section ({{.*}}) .rela.text { ++# RELAX-NEXT: 0x10 R_LARCH_PCALA_HI20 .L1 0x0 ++# RELAX-NEXT: 0x14 R_LARCH_PCALA_LO12 .L1 0x0 ++# RELAX-NEXT: } ++# RELAX-NEXT: Section ({{.*}}) .rela.data { ++# RELAX-NEXT: 0xF R_LARCH_ADD8 .L3 0x0 ++# RELAX-NEXT: 0xF R_LARCH_SUB8 .L2 0x0 ++# RELAX-NEXT: 0x10 R_LARCH_ADD16 .L3 0x0 ++# RELAX-NEXT: 0x10 R_LARCH_SUB16 .L2 0x0 ++# RELAX-NEXT: 0x12 R_LARCH_ADD32 .L3 0x0 ++# RELAX-NEXT: 0x12 R_LARCH_SUB32 .L2 0x0 ++# RELAX-NEXT: 0x16 R_LARCH_ADD64 .L3 0x0 ++# RELAX-NEXT: 0x16 R_LARCH_SUB64 .L2 0x0 ++# RELAX-NEXT: } ++# RELAX-NEXT: ] ++ ++# RELAX: Hex dump of section '.data': ++# RELAX-NEXT: 0x00000000 04040004 00000004 00000000 00000000 ++# RELAX-NEXT: 0x00000010 00000000 00000000 00000000 00000808 ++# RELAX-NEXT: 0x00000020 00080000 00080000 00000000 00 ++ ++.text ++.L1: ++ nop ++.L2: ++ .align 4 ++.L3: ++ la.pcrel $t0, .L1 ++.L4: ++ ret ++ ++.data ++## Not emit relocs ++.byte .L2 - .L1 ++.short .L2 - .L1 ++.word .L2 - .L1 ++.dword .L2 - .L1 ++## With relaxation, emit relocs because of the .align making the diff variable. ++## TODO Handle alignment directive. Why they emit relocs now? They returns ++## without folding symbols offset in AttemptToFoldSymbolOffsetDifference(). ++.byte .L3 - .L2 ++.short .L3 - .L2 ++.word .L3 - .L2 ++.dword .L3 - .L2 ++## TODO ++## With relaxation, emit relocs because la.pcrel is a linker-relaxable inst. ++.byte .L4 - .L3 ++.short .L4 - .L3 ++.word .L4 - .L3 ++.dword .L4 - .L3 +-- +2.20.1 + diff --git a/0003-Backport-LoongArch-Emit-R_LARCH_RELAX-when-expanding-some-LoadAddress.patch b/0003-Backport-LoongArch-Emit-R_LARCH_RELAX-when-expanding-some-LoadAddress.patch new file mode 100644 index 0000000..93a2174 --- /dev/null +++ b/0003-Backport-LoongArch-Emit-R_LARCH_RELAX-when-expanding-some-LoadAddress.patch @@ -0,0 +1,364 @@ +From f2495d7efb79fdc82af6147f7201d9cf3c91beba Mon Sep 17 00:00:00 2001 +From: Jinyang He +Date: Wed, 27 Dec 2023 08:51:48 +0800 +Subject: [PATCH 04/14] [LoongArch] Emit R_LARCH_RELAX when expanding some + LoadAddress (#72961) + +Emit relax relocs when expand non-large la.pcrel and non-large la.got on +llvm-mc stage, which like what does on GAS. +1, la.pcrel -> PCALA_HI20 + RELAX + PCALA_LO12 + RELAX +2, la.got -> GOT_PC_HI20 + RELAX + GOT_PC_LO12 + RELAX + +(cherry picked from commit b3ef8dce9811b2725639b0d4fac3f85c7e112817) +Change-Id: I222daf60b36ee70e23c76b753e1d2a3b8148f44b +--- + .../AsmParser/LoongArchAsmParser.cpp | 12 +-- + .../MCTargetDesc/LoongArchMCCodeEmitter.cpp | 13 +++ + .../MCTargetDesc/LoongArchMCExpr.cpp | 7 +- + .../LoongArch/MCTargetDesc/LoongArchMCExpr.h | 8 +- + llvm/test/MC/LoongArch/Macros/macros-la.s | 84 ++++++++++++++++--- + llvm/test/MC/LoongArch/Misc/subsection.s | 2 +- + .../MC/LoongArch/Relocations/relax-addsub.s | 16 +++- + 7 files changed, 115 insertions(+), 27 deletions(-) + +diff --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp +index 94d530306536..a132e645c864 100644 +--- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp ++++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp +@@ -86,7 +86,7 @@ class LoongArchAsmParser : public MCTargetAsmParser { + // "emitLoadAddress*" functions. + void emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg, + const MCExpr *Symbol, SmallVectorImpl &Insts, +- SMLoc IDLoc, MCStreamer &Out); ++ SMLoc IDLoc, MCStreamer &Out, bool RelaxHint = false); + + // Helper to emit pseudo instruction "la.abs $rd, sym". + void emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); +@@ -749,12 +749,14 @@ bool LoongArchAsmParser::ParseInstruction(ParseInstructionInfo &Info, + void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg, + const MCExpr *Symbol, + SmallVectorImpl &Insts, +- SMLoc IDLoc, MCStreamer &Out) { ++ SMLoc IDLoc, MCStreamer &Out, ++ bool RelaxHint) { + MCContext &Ctx = getContext(); + for (LoongArchAsmParser::Inst &Inst : Insts) { + unsigned Opc = Inst.Opc; + LoongArchMCExpr::VariantKind VK = Inst.VK; +- const LoongArchMCExpr *LE = LoongArchMCExpr::create(Symbol, VK, Ctx); ++ const LoongArchMCExpr *LE = ++ LoongArchMCExpr::create(Symbol, VK, Ctx, RelaxHint); + switch (Opc) { + default: + llvm_unreachable("unexpected opcode"); +@@ -855,7 +857,7 @@ void LoongArchAsmParser::emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, + Insts.push_back( + LoongArchAsmParser::Inst(ADDI, LoongArchMCExpr::VK_LoongArch_PCALA_LO12)); + +- emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); ++ emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true); + } + + void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, +@@ -901,7 +903,7 @@ void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, + Insts.push_back( + LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12)); + +- emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out); ++ emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out, true); + } + + void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, +diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp +index 03fb9e008ae9..08c0820cb862 100644 +--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp ++++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp +@@ -19,6 +19,7 @@ + #include "llvm/MC/MCInstBuilder.h" + #include "llvm/MC/MCInstrInfo.h" + #include "llvm/MC/MCRegisterInfo.h" ++#include "llvm/MC/MCSubtargetInfo.h" + #include "llvm/Support/Casting.h" + #include "llvm/Support/EndianStream.h" + +@@ -120,12 +121,15 @@ LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + assert(MO.isExpr() && "getExprOpValue expects only expressions"); ++ bool RelaxCandidate = false; ++ bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax); + const MCExpr *Expr = MO.getExpr(); + MCExpr::ExprKind Kind = Expr->getKind(); + LoongArch::Fixups FixupKind = LoongArch::fixup_loongarch_invalid; + if (Kind == MCExpr::Target) { + const LoongArchMCExpr *LAExpr = cast(Expr); + ++ RelaxCandidate = LAExpr->getRelaxHint(); + switch (LAExpr->getKind()) { + case LoongArchMCExpr::VK_LoongArch_None: + case LoongArchMCExpr::VK_LoongArch_Invalid: +@@ -269,6 +273,15 @@ LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO, + + Fixups.push_back( + MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc())); ++ ++ // Emit an R_LARCH_RELAX if linker relaxation is enabled and LAExpr has relax ++ // hint. ++ if (EnableRelax && RelaxCandidate) { ++ const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx); ++ Fixups.push_back(MCFixup::create( ++ 0, Dummy, MCFixupKind(LoongArch::fixup_loongarch_relax), MI.getLoc())); ++ } ++ + return 0; + } + +diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp +index 993111552a31..82c992b1cc8c 100644 +--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp ++++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp +@@ -25,9 +25,10 @@ using namespace llvm; + + #define DEBUG_TYPE "loongarch-mcexpr" + +-const LoongArchMCExpr * +-LoongArchMCExpr::create(const MCExpr *Expr, VariantKind Kind, MCContext &Ctx) { +- return new (Ctx) LoongArchMCExpr(Expr, Kind); ++const LoongArchMCExpr *LoongArchMCExpr::create(const MCExpr *Expr, ++ VariantKind Kind, MCContext &Ctx, ++ bool Hint) { ++ return new (Ctx) LoongArchMCExpr(Expr, Kind, Hint); + } + + void LoongArchMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { +diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h +index 0945cf82db86..93251f824103 100644 +--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h ++++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h +@@ -67,16 +67,18 @@ public: + private: + const MCExpr *Expr; + const VariantKind Kind; ++ const bool RelaxHint; + +- explicit LoongArchMCExpr(const MCExpr *Expr, VariantKind Kind) +- : Expr(Expr), Kind(Kind) {} ++ explicit LoongArchMCExpr(const MCExpr *Expr, VariantKind Kind, bool Hint) ++ : Expr(Expr), Kind(Kind), RelaxHint(Hint) {} + + public: + static const LoongArchMCExpr *create(const MCExpr *Expr, VariantKind Kind, +- MCContext &Ctx); ++ MCContext &Ctx, bool Hint = false); + + VariantKind getKind() const { return Kind; } + const MCExpr *getSubExpr() const { return Expr; } ++ bool getRelaxHint() const { return RelaxHint; } + + void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override; + bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, +diff --git a/llvm/test/MC/LoongArch/Macros/macros-la.s b/llvm/test/MC/LoongArch/Macros/macros-la.s +index 924e4326b8e5..1a1d12d7d7df 100644 +--- a/llvm/test/MC/LoongArch/Macros/macros-la.s ++++ b/llvm/test/MC/LoongArch/Macros/macros-la.s +@@ -1,66 +1,128 @@ + # RUN: llvm-mc --triple=loongarch64 %s | FileCheck %s ++# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=-relax %s -o %t ++# RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=RELOC ++# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.relax ++# RUN: llvm-readobj -r %t.relax | FileCheck %s --check-prefixes=RELOC,RELAX ++ ++# RELOC: Relocations [ ++# RELOC-NEXT: Section ({{.*}}) .rela.text { + + la.abs $a0, sym_abs + # CHECK: lu12i.w $a0, %abs_hi20(sym_abs) + # CHECK-NEXT: ori $a0, $a0, %abs_lo12(sym_abs) + # CHECK-NEXT: lu32i.d $a0, %abs64_lo20(sym_abs) + # CHECK-NEXT: lu52i.d $a0, $a0, %abs64_hi12(sym_abs) ++# CHECK-EMPTY: ++# RELOC-NEXT: R_LARCH_ABS_HI20 sym_abs 0x0 ++# RELOC-NEXT: R_LARCH_ABS_LO12 sym_abs 0x0 ++# RELOC-NEXT: R_LARCH_ABS64_LO20 sym_abs 0x0 ++# RELOC-NEXT: R_LARCH_ABS64_HI12 sym_abs 0x0 + + la.pcrel $a0, sym_pcrel +-# CHECK: pcalau12i $a0, %pc_hi20(sym_pcrel) ++# CHECK-NEXT: pcalau12i $a0, %pc_hi20(sym_pcrel) + # CHECK-NEXT: addi.d $a0, $a0, %pc_lo12(sym_pcrel) ++# CHECK-EMPTY: ++# RELOC-NEXT: R_LARCH_PCALA_HI20 sym_pcrel 0x0 ++# RELAX-NEXT: R_LARCH_RELAX - 0x0 ++# RELOC-NEXT: R_LARCH_PCALA_LO12 sym_pcrel 0x0 ++# RELAX-NEXT: R_LARCH_RELAX - 0x0 + + la.pcrel $a0, $a1, sym_pcrel_large +-# CHECK: pcalau12i $a0, %pc_hi20(sym_pcrel_large) ++# CHECK-NEXT: pcalau12i $a0, %pc_hi20(sym_pcrel_large) + # CHECK-NEXT: addi.d $a1, $zero, %pc_lo12(sym_pcrel_large) + # CHECK-NEXT: lu32i.d $a1, %pc64_lo20(sym_pcrel_large) + # CHECK-NEXT: lu52i.d $a1, $a1, %pc64_hi12(sym_pcrel_large) + # CHECK-NEXT: add.d $a0, $a0, $a1 ++# CHECK-EMPTY: ++# RELOC-NEXT: R_LARCH_PCALA_HI20 sym_pcrel_large 0x0 ++# RELOC-NEXT: R_LARCH_PCALA_LO12 sym_pcrel_large 0x0 ++# RELOC-NEXT: R_LARCH_PCALA64_LO20 sym_pcrel_large 0x0 ++# RELOC-NEXT: R_LARCH_PCALA64_HI12 sym_pcrel_large 0x0 + + la.got $a0, sym_got +-# CHECK: pcalau12i $a0, %got_pc_hi20(sym_got) ++# CHECK-NEXT: pcalau12i $a0, %got_pc_hi20(sym_got) + # CHECK-NEXT: ld.d $a0, $a0, %got_pc_lo12(sym_got) ++# CHECK-EMPTY: ++# RELOC-NEXT: R_LARCH_GOT_PC_HI20 sym_got 0x0 ++# RELAX-NEXT: R_LARCH_RELAX - 0x0 ++# RELOC-NEXT: R_LARCH_GOT_PC_LO12 sym_got 0x0 ++# RELAX-NEXT: R_LARCH_RELAX - 0x0 + + la.got $a0, $a1, sym_got_large +-# CHECK: pcalau12i $a0, %got_pc_hi20(sym_got_large) ++# CHECK-NEXT: pcalau12i $a0, %got_pc_hi20(sym_got_large) + # CHECK-NEXT: addi.d $a1, $zero, %got_pc_lo12(sym_got_large) + # CHECK-NEXT: lu32i.d $a1, %got64_pc_lo20(sym_got_large) + # CHECK-NEXT: lu52i.d $a1, $a1, %got64_pc_hi12(sym_got_large) + # CHECK-NEXT: ldx.d $a0, $a0, $a1 ++# CHECK-EMPTY: ++# RELOC-NEXT: R_LARCH_GOT_PC_HI20 sym_got_large 0x0 ++# RELOC-NEXT: R_LARCH_GOT_PC_LO12 sym_got_large 0x0 ++# RELOC-NEXT: R_LARCH_GOT64_PC_LO20 sym_got_large 0x0 ++# RELOC-NEXT: R_LARCH_GOT64_PC_HI12 sym_got_large 0x0 + + la.tls.le $a0, sym_le +-# CHECK: lu12i.w $a0, %le_hi20(sym_le) ++# CHECK-NEXT: lu12i.w $a0, %le_hi20(sym_le) + # CHECK-NEXT: ori $a0, $a0, %le_lo12(sym_le) ++# CHECK-EMPTY: ++# RELOC-NEXT: R_LARCH_TLS_LE_HI20 sym_le 0x0 ++# RELOC-NEXT: R_LARCH_TLS_LE_LO12 sym_le 0x0 + + la.tls.ie $a0, sym_ie +-# CHECK: pcalau12i $a0, %ie_pc_hi20(sym_ie) ++# CHECK-NEXT: pcalau12i $a0, %ie_pc_hi20(sym_ie) + # CHECK-NEXT: ld.d $a0, $a0, %ie_pc_lo12(sym_ie) ++# CHECK-EMPTY: ++# RELOC-NEXT: R_LARCH_TLS_IE_PC_HI20 sym_ie 0x0 ++# RELOC-NEXT: R_LARCH_TLS_IE_PC_LO12 sym_ie 0x0 + + la.tls.ie $a0, $a1, sym_ie_large +-# CHECK: pcalau12i $a0, %ie_pc_hi20(sym_ie_large) ++# CHECK-NEXT: pcalau12i $a0, %ie_pc_hi20(sym_ie_large) + # CHECK-NEXT: addi.d $a1, $zero, %ie_pc_lo12(sym_ie_large) + # CHECK-NEXT: lu32i.d $a1, %ie64_pc_lo20(sym_ie_large) + # CHECK-NEXT: lu52i.d $a1, $a1, %ie64_pc_hi12(sym_ie_large) + # CHECK-NEXT: ldx.d $a0, $a0, $a1 ++# CHECK-EMPTY: ++# RELOC-NEXT: R_LARCH_TLS_IE_PC_HI20 sym_ie_large 0x0 ++# RELOC-NEXT: R_LARCH_TLS_IE_PC_LO12 sym_ie_large 0x0 ++# RELOC-NEXT: R_LARCH_TLS_IE64_PC_LO20 sym_ie_large 0x0 ++# RELOC-NEXT: R_LARCH_TLS_IE64_PC_HI12 sym_ie_large 0x0 + + la.tls.ld $a0, sym_ld +-# CHECK: pcalau12i $a0, %ld_pc_hi20(sym_ld) ++# CHECK-NEXT: pcalau12i $a0, %ld_pc_hi20(sym_ld) + # CHECK-NEXT: addi.d $a0, $a0, %got_pc_lo12(sym_ld) ++# CHECK-EMPTY: ++# RELOC-NEXT: R_LARCH_TLS_LD_PC_HI20 sym_ld 0x0 ++# RELOC-NEXT: R_LARCH_GOT_PC_LO12 sym_ld 0x0 + + la.tls.ld $a0, $a1, sym_ld_large +-# CHECK: pcalau12i $a0, %ld_pc_hi20(sym_ld_large) ++# CHECK-NEXT: pcalau12i $a0, %ld_pc_hi20(sym_ld_large) + # CHECK-NEXT: addi.d $a1, $zero, %got_pc_lo12(sym_ld_large) + # CHECK-NEXT: lu32i.d $a1, %got64_pc_lo20(sym_ld_large) + # CHECK-NEXT: lu52i.d $a1, $a1, %got64_pc_hi12(sym_ld_large) + # CHECK-NEXT: add.d $a0, $a0, $a1 ++# CHECK-EMPTY: ++# RELOC-NEXT: R_LARCH_TLS_LD_PC_HI20 sym_ld_large 0x0 ++# RELOC-NEXT: R_LARCH_GOT_PC_LO12 sym_ld_large 0x0 ++# RELOC-NEXT: R_LARCH_GOT64_PC_LO20 sym_ld_large 0x0 ++# RELOC-NEXT: R_LARCH_GOT64_PC_HI12 sym_ld_large 0x0 + + la.tls.gd $a0, sym_gd +-# CHECK: pcalau12i $a0, %gd_pc_hi20(sym_gd) ++# CHECK-NEXT: pcalau12i $a0, %gd_pc_hi20(sym_gd) + # CHECK-NEXT: addi.d $a0, $a0, %got_pc_lo12(sym_gd) ++# CHECK-EMPTY: ++# RELOC-NEXT: R_LARCH_TLS_GD_PC_HI20 sym_gd 0x0 ++# RELOC-NEXT: R_LARCH_GOT_PC_LO12 sym_gd 0x0 + + la.tls.gd $a0, $a1, sym_gd_large +-# CHECK: pcalau12i $a0, %gd_pc_hi20(sym_gd_large) ++# CHECK-NEXT: pcalau12i $a0, %gd_pc_hi20(sym_gd_large) + # CHECK-NEXT: addi.d $a1, $zero, %got_pc_lo12(sym_gd_large) + # CHECK-NEXT: lu32i.d $a1, %got64_pc_lo20(sym_gd_large) + # CHECK-NEXT: lu52i.d $a1, $a1, %got64_pc_hi12(sym_gd_large) + # CHECK-NEXT: add.d $a0, $a0, $a1 ++# CHECK-EMPTY: ++# RELOC-NEXT: R_LARCH_TLS_GD_PC_HI20 sym_gd_large 0x0 ++# RELOC-NEXT: R_LARCH_GOT_PC_LO12 sym_gd_large 0x0 ++# RELOC-NEXT: R_LARCH_GOT64_PC_LO20 sym_gd_large 0x0 ++# RELOC-NEXT: R_LARCH_GOT64_PC_HI12 sym_gd_large 0x0 ++ ++# RELOC-NEXT: } ++# RELOC-NEXT: ] +diff --git a/llvm/test/MC/LoongArch/Misc/subsection.s b/llvm/test/MC/LoongArch/Misc/subsection.s +index 0bd22b474536..566a2408d691 100644 +--- a/llvm/test/MC/LoongArch/Misc/subsection.s ++++ b/llvm/test/MC/LoongArch/Misc/subsection.s +@@ -1,5 +1,5 @@ + # RUN: not llvm-mc --filetype=obj --triple=loongarch64 --mattr=-relax %s -o /dev/null 2>&1 | FileCheck %s --check-prefixes=ERR,NORELAX --implicit-check-not=error: +-## TODO: not llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o /dev/null 2>&1 | FileCheck %s --check-prefixes=ERR,RELAX --implicit-check-not=error: ++# RUN: not llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o /dev/null 2>&1 | FileCheck %s --check-prefixes=ERR,RELAX --implicit-check-not=error: + + a: + nop +diff --git a/llvm/test/MC/LoongArch/Relocations/relax-addsub.s b/llvm/test/MC/LoongArch/Relocations/relax-addsub.s +index 532eb4e0561a..c4454f5bb98d 100644 +--- a/llvm/test/MC/LoongArch/Relocations/relax-addsub.s ++++ b/llvm/test/MC/LoongArch/Relocations/relax-addsub.s +@@ -18,7 +18,9 @@ + # RELAX: Relocations [ + # RELAX-NEXT: Section ({{.*}}) .rela.text { + # RELAX-NEXT: 0x10 R_LARCH_PCALA_HI20 .L1 0x0 ++# RELAX-NEXT: 0x10 R_LARCH_RELAX - 0x0 + # RELAX-NEXT: 0x14 R_LARCH_PCALA_LO12 .L1 0x0 ++# RELAX-NEXT: 0x14 R_LARCH_RELAX - 0x0 + # RELAX-NEXT: } + # RELAX-NEXT: Section ({{.*}}) .rela.data { + # RELAX-NEXT: 0xF R_LARCH_ADD8 .L3 0x0 +@@ -29,13 +31,21 @@ + # RELAX-NEXT: 0x12 R_LARCH_SUB32 .L2 0x0 + # RELAX-NEXT: 0x16 R_LARCH_ADD64 .L3 0x0 + # RELAX-NEXT: 0x16 R_LARCH_SUB64 .L2 0x0 ++# RELAX-NEXT: 0x1E R_LARCH_ADD8 .L4 0x0 ++# RELAX-NEXT: 0x1E R_LARCH_SUB8 .L3 0x0 ++# RELAX-NEXT: 0x1F R_LARCH_ADD16 .L4 0x0 ++# RELAX-NEXT: 0x1F R_LARCH_SUB16 .L3 0x0 ++# RELAX-NEXT: 0x21 R_LARCH_ADD32 .L4 0x0 ++# RELAX-NEXT: 0x21 R_LARCH_SUB32 .L3 0x0 ++# RELAX-NEXT: 0x25 R_LARCH_ADD64 .L4 0x0 ++# RELAX-NEXT: 0x25 R_LARCH_SUB64 .L3 0x0 + # RELAX-NEXT: } + # RELAX-NEXT: ] + + # RELAX: Hex dump of section '.data': + # RELAX-NEXT: 0x00000000 04040004 00000004 00000000 00000000 +-# RELAX-NEXT: 0x00000010 00000000 00000000 00000000 00000808 +-# RELAX-NEXT: 0x00000020 00080000 00080000 00000000 00 ++# RELAX-NEXT: 0x00000010 00000000 00000000 00000000 00000000 ++# RELAX-NEXT: 0x00000020 00000000 00000000 00000000 00 + + .text + .L1: +@@ -60,8 +70,6 @@ + .short .L3 - .L2 + .word .L3 - .L2 + .dword .L3 - .L2 +-## TODO +-## With relaxation, emit relocs because la.pcrel is a linker-relaxable inst. + .byte .L4 - .L3 + .short .L4 - .L3 + .word .L4 - .L3 +-- +2.20.1 + diff --git a/0004-Backport-MC-LoongArch-Add-AlignFragment-size-if-layout-is-available-and-not-need-insert-nops.patch b/0004-Backport-MC-LoongArch-Add-AlignFragment-size-if-layout-is-available-and-not-need-insert-nops.patch new file mode 100644 index 0000000..72b7924 --- /dev/null +++ b/0004-Backport-MC-LoongArch-Add-AlignFragment-size-if-layout-is-available-and-not-need-insert-nops.patch @@ -0,0 +1,123 @@ +From be6e5c566f49bee5efe3d710bdd321e15d8d95ea Mon Sep 17 00:00:00 2001 +From: Jinyang He +Date: Thu, 14 Mar 2024 12:10:50 +0800 +Subject: [PATCH 05/14] [MC][LoongArch] Add AlignFragment size if layout is + available and not need insert nops (#76552) + +Due to delayed decision for ADD/SUB relocations, RISCV and LoongArch may +go slow fragment walk path with available layout. When RISCV (or +LoongArch in the future) don't need insert nops, that means relax is +disabled. With available layout and not needing insert nops, the size of +AlignFragment should be a constant. So we can add it to Displacement for +folding A-B. + +(cherry picked from commit 0731567a31e4ade97c27801045156a88c4589704) +Change-Id: I554d6766bd7f688204e956e4a6431574b4c511c9 +--- + llvm/lib/MC/MCExpr.cpp | 6 +++++ + llvm/test/MC/LoongArch/Misc/cfi-advance.s | 27 +++++++++++++++++++ + .../MC/LoongArch/Relocations/relax-addsub.s | 17 +++--------- + 3 files changed, 37 insertions(+), 13 deletions(-) + create mode 100644 llvm/test/MC/LoongArch/Misc/cfi-advance.s + +diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp +index 5a6596f93824..a561fed11179 100644 +--- a/llvm/lib/MC/MCExpr.cpp ++++ b/llvm/lib/MC/MCExpr.cpp +@@ -707,8 +707,14 @@ static void AttemptToFoldSymbolOffsetDifference( + } + + int64_t Num; ++ unsigned Count; + if (DF) { + Displacement += DF->getContents().size(); ++ } else if (auto *AF = dyn_cast(FI); ++ AF && Layout && ++ !Asm->getBackend().shouldInsertExtraNopBytesForCodeAlign( ++ *AF, Count)) { ++ Displacement += Asm->computeFragmentSize(*Layout, *AF); + } else if (auto *FF = dyn_cast(FI); + FF && FF->getNumValues().evaluateAsAbsolute(Num)) { + Displacement += Num * FF->getValueSize(); +diff --git a/llvm/test/MC/LoongArch/Misc/cfi-advance.s b/llvm/test/MC/LoongArch/Misc/cfi-advance.s +new file mode 100644 +index 000000000000..662c43e6bcea +--- /dev/null ++++ b/llvm/test/MC/LoongArch/Misc/cfi-advance.s +@@ -0,0 +1,27 @@ ++# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=-relax %s -o %t.o ++# RUN: llvm-readobj -r %t.o | FileCheck --check-prefix=RELOC %s ++# RUN: llvm-dwarfdump --debug-frame %t.o | FileCheck --check-prefix=DWARFDUMP %s ++ ++# RELOC: Relocations [ ++# RELOC-NEXT: .rela.eh_frame { ++# RELOC-NEXT: 0x1C R_LARCH_32_PCREL .text 0x0 ++# RELOC-NEXT: } ++# RELOC-NEXT: ] ++# DWARFDUMP: DW_CFA_advance_loc: 4 ++# DWARFDUMP-NEXT: DW_CFA_def_cfa_offset: +8 ++# DWARFDUMP-NEXT: DW_CFA_advance_loc: 8 ++# DWARFDUMP-NEXT: DW_CFA_def_cfa_offset: +8 ++ ++ .text ++ .globl test ++ .p2align 2 ++ .type test,@function ++test: ++ .cfi_startproc ++ nop ++ .cfi_def_cfa_offset 8 ++ .p2align 3 ++ nop ++ .cfi_def_cfa_offset 8 ++ nop ++ .cfi_endproc +diff --git a/llvm/test/MC/LoongArch/Relocations/relax-addsub.s b/llvm/test/MC/LoongArch/Relocations/relax-addsub.s +index c4454f5bb98d..14922657ae89 100644 +--- a/llvm/test/MC/LoongArch/Relocations/relax-addsub.s ++++ b/llvm/test/MC/LoongArch/Relocations/relax-addsub.s +@@ -23,14 +23,6 @@ + # RELAX-NEXT: 0x14 R_LARCH_RELAX - 0x0 + # RELAX-NEXT: } + # RELAX-NEXT: Section ({{.*}}) .rela.data { +-# RELAX-NEXT: 0xF R_LARCH_ADD8 .L3 0x0 +-# RELAX-NEXT: 0xF R_LARCH_SUB8 .L2 0x0 +-# RELAX-NEXT: 0x10 R_LARCH_ADD16 .L3 0x0 +-# RELAX-NEXT: 0x10 R_LARCH_SUB16 .L2 0x0 +-# RELAX-NEXT: 0x12 R_LARCH_ADD32 .L3 0x0 +-# RELAX-NEXT: 0x12 R_LARCH_SUB32 .L2 0x0 +-# RELAX-NEXT: 0x16 R_LARCH_ADD64 .L3 0x0 +-# RELAX-NEXT: 0x16 R_LARCH_SUB64 .L2 0x0 + # RELAX-NEXT: 0x1E R_LARCH_ADD8 .L4 0x0 + # RELAX-NEXT: 0x1E R_LARCH_SUB8 .L3 0x0 + # RELAX-NEXT: 0x1F R_LARCH_ADD16 .L4 0x0 +@@ -43,8 +35,8 @@ + # RELAX-NEXT: ] + + # RELAX: Hex dump of section '.data': +-# RELAX-NEXT: 0x00000000 04040004 00000004 00000000 00000000 +-# RELAX-NEXT: 0x00000010 00000000 00000000 00000000 00000000 ++# RELAX-NEXT: 0x00000000 04040004 00000004 00000000 0000000c ++# RELAX-NEXT: 0x00000010 0c000c00 00000c00 00000000 00000000 + # RELAX-NEXT: 0x00000020 00000000 00000000 00000000 00 + + .text +@@ -63,13 +55,12 @@ + .short .L2 - .L1 + .word .L2 - .L1 + .dword .L2 - .L1 +-## With relaxation, emit relocs because of the .align making the diff variable. +-## TODO Handle alignment directive. Why they emit relocs now? They returns +-## without folding symbols offset in AttemptToFoldSymbolOffsetDifference(). ++## TODO Handle alignment directive. + .byte .L3 - .L2 + .short .L3 - .L2 + .word .L3 - .L2 + .dword .L3 - .L2 ++## With relaxation, emit relocs because the la.pcrel makes the diff variable. + .byte .L4 - .L3 + .short .L4 - .L3 + .word .L4 - .L3 +-- +2.20.1 + diff --git a/0005-Backport-LoongArch-RISCV-Support-R_LARCH_-ADD-SUB-_ULEB128-R_RISCV_-SET-SUB-_ULEB128-for-uleb128-directives.patch b/0005-Backport-LoongArch-RISCV-Support-R_LARCH_-ADD-SUB-_ULEB128-R_RISCV_-SET-SUB-_ULEB128-for-uleb128-directives.patch new file mode 100644 index 0000000..c1c4f9f --- /dev/null +++ b/0005-Backport-LoongArch-RISCV-Support-R_LARCH_-ADD-SUB-_ULEB128-R_RISCV_-SET-SUB-_ULEB128-for-uleb128-directives.patch @@ -0,0 +1,633 @@ +From 8d7b71890179d32474b3a1a1c627481bd5a2327d Mon Sep 17 00:00:00 2001 +From: zhanglimin +Date: Fri, 15 Mar 2024 14:39:48 +0800 +Subject: [PATCH 06/14] [LoongArch][RISCV] Support + R_LARCH_{ADD,SUB}_ULEB128/R_RISCV_{SET,SUB}_ULEB128 for .uleb128 directives + +This patch is originally from three upstream commits: +1, R_LARCH_{ADD,SUB}_ULEB128 are originally landed from b57159cb(#76433). +2, R_RISCV_{SET,SUB}_ULEB128 are originally supported from 1df5ea29. Among it, we change +the default behaviour of `-riscv-uleb128-reloc` to not produce uleb128 reloc, in order +to avoid any other side-effects due to the updated implementation of `MCAssembler::relaxLEB()` +function. And at the same time, we ensure that this patch can't introduce new default traits +(such as the generation for uleb128 reloc) on RISCV in this version. +3, Fix invalid-sleb.s in original commit d7398a35. + +Change-Id: Ie687b7d8483c76cf647141162641db1a9d819a04 +--- + .../llvm/BinaryFormat/ELFRelocs/RISCV.def | 2 + + llvm/include/llvm/MC/MCAsmBackend.h | 8 +++ + llvm/include/llvm/MC/MCFixup.h | 1 + + llvm/include/llvm/MC/MCFragment.h | 9 ++- + llvm/lib/MC/MCAsmBackend.cpp | 1 + + llvm/lib/MC/MCAssembler.cpp | 39 ++++++++-- + .../MCTargetDesc/LoongArchAsmBackend.cpp | 69 ++++++++++++++---- + .../MCTargetDesc/LoongArchAsmBackend.h | 3 + + .../RISCV/MCTargetDesc/RISCVAsmBackend.cpp | 27 +++++++ + .../RISCV/MCTargetDesc/RISCVAsmBackend.h | 2 + + llvm/test/MC/ELF/RISCV/gen-dwarf.s | 5 +- + llvm/test/MC/LoongArch/Relocations/leb128.s | 72 +++++++++++++++++++ + .../MC/LoongArch/Relocations/relax-addsub.s | 57 +++++++++++---- + llvm/test/MC/X86/invalid-sleb.s | 5 -- + 14 files changed, 252 insertions(+), 48 deletions(-) + create mode 100644 llvm/test/MC/LoongArch/Relocations/leb128.s + delete mode 100644 llvm/test/MC/X86/invalid-sleb.s + +diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def +index 9a126df01531..c7fd6490041c 100644 +--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def ++++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def +@@ -55,3 +55,5 @@ ELF_RELOC(R_RISCV_SET32, 56) + ELF_RELOC(R_RISCV_32_PCREL, 57) + ELF_RELOC(R_RISCV_IRELATIVE, 58) + ELF_RELOC(R_RISCV_PLT32, 59) ++ELF_RELOC(R_RISCV_SET_ULEB128, 60) ++ELF_RELOC(R_RISCV_SUB_ULEB128, 61) +diff --git a/llvm/include/llvm/MC/MCAsmBackend.h b/llvm/include/llvm/MC/MCAsmBackend.h +index 5e08fb41679b..968a767b17f8 100644 +--- a/llvm/include/llvm/MC/MCAsmBackend.h ++++ b/llvm/include/llvm/MC/MCAsmBackend.h +@@ -21,6 +21,7 @@ class MCAlignFragment; + class MCDwarfCallFrameFragment; + class MCDwarfLineAddrFragment; + class MCFragment; ++class MCLEBFragment; + class MCRelaxableFragment; + class MCSymbol; + class MCAsmLayout; +@@ -194,6 +195,13 @@ public: + return false; + } + ++ // Defined by linker relaxation targets to possibly emit LEB128 relocations ++ // and set Value at the relocated location. ++ virtual std::pair ++ relaxLEB128(MCLEBFragment &LF, MCAsmLayout &Layout, int64_t &Value) const { ++ return std::make_pair(false, false); ++ } ++ + /// @} + + /// Returns the minimum size of a nop in bytes on this target. The assembler +diff --git a/llvm/include/llvm/MC/MCFixup.h b/llvm/include/llvm/MC/MCFixup.h +index 069ca058310f..7f48a90cb1ec 100644 +--- a/llvm/include/llvm/MC/MCFixup.h ++++ b/llvm/include/llvm/MC/MCFixup.h +@@ -25,6 +25,7 @@ enum MCFixupKind { + FK_Data_4, ///< A four-byte fixup. + FK_Data_8, ///< A eight-byte fixup. + FK_Data_6b, ///< A six-bits fixup. ++ FK_Data_leb128, ///< A leb128 fixup. + FK_PCRel_1, ///< A one-byte pc relative fixup. + FK_PCRel_2, ///< A two-byte pc relative fixup. + FK_PCRel_4, ///< A four-byte pc relative fixup. +diff --git a/llvm/include/llvm/MC/MCFragment.h b/llvm/include/llvm/MC/MCFragment.h +index 7be4792a4521..e965732010fe 100644 +--- a/llvm/include/llvm/MC/MCFragment.h ++++ b/llvm/include/llvm/MC/MCFragment.h +@@ -428,7 +428,7 @@ public: + } + }; + +-class MCLEBFragment : public MCFragment { ++class MCLEBFragment final : public MCEncodedFragmentWithFixups<10, 1> { + /// True if this is a sleb128, false if uleb128. + bool IsSigned; + +@@ -439,17 +439,16 @@ class MCLEBFragment : public MCFragment { + + public: + MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr) +- : MCFragment(FT_LEB, false, Sec), IsSigned(IsSigned_), Value(&Value_) { ++ : MCEncodedFragmentWithFixups<10, 1>(FT_LEB, false, Sec), ++ IsSigned(IsSigned_), Value(&Value_) { + Contents.push_back(0); + } + + const MCExpr &getValue() const { return *Value; } ++ void setValue(const MCExpr *Expr) { Value = Expr; } + + bool isSigned() const { return IsSigned; } + +- SmallString<8> &getContents() { return Contents; } +- const SmallString<8> &getContents() const { return Contents; } +- + /// @} + + static bool classof(const MCFragment *F) { +diff --git a/llvm/lib/MC/MCAsmBackend.cpp b/llvm/lib/MC/MCAsmBackend.cpp +index 64bbc63719c7..2eef7d363fe7 100644 +--- a/llvm/lib/MC/MCAsmBackend.cpp ++++ b/llvm/lib/MC/MCAsmBackend.cpp +@@ -89,6 +89,7 @@ const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { + {"FK_Data_4", 0, 32, 0}, + {"FK_Data_8", 0, 64, 0}, + {"FK_Data_6b", 0, 6, 0}, ++ {"FK_Data_leb128", 0, 0, 0}, + {"FK_PCRel_1", 0, 8, MCFixupKindInfo::FKF_IsPCRel}, + {"FK_PCRel_2", 0, 16, MCFixupKindInfo::FKF_IsPCRel}, + {"FK_PCRel_4", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, +diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp +index 55ed1a285cd7..86c798ec9e27 100644 +--- a/llvm/lib/MC/MCAssembler.cpp ++++ b/llvm/lib/MC/MCAssembler.cpp +@@ -918,6 +918,12 @@ void MCAssembler::layout(MCAsmLayout &Layout) { + Contents = DF.getContents(); + break; + } ++ case MCFragment::FT_LEB: { ++ auto &LF = cast(Frag); ++ Fixups = LF.getFixups(); ++ Contents = LF.getContents(); ++ break; ++ } + case MCFragment::FT_PseudoProbe: { + MCPseudoProbeAddrFragment &PF = cast(Frag); + Fixups = PF.getFixups(); +@@ -1006,12 +1012,31 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout, + } + + bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) { +- uint64_t OldSize = LF.getContents().size(); ++ const unsigned OldSize = static_cast(LF.getContents().size()); ++ unsigned PadTo = OldSize; + int64_t Value; +- bool Abs = LF.getValue().evaluateKnownAbsolute(Value, Layout); +- if (!Abs) +- report_fatal_error("sleb128 and uleb128 expressions must be absolute"); +- SmallString<8> &Data = LF.getContents(); ++ SmallVectorImpl &Data = LF.getContents(); ++ LF.getFixups().clear(); ++ // Use evaluateKnownAbsolute for Mach-O as a hack: .subsections_via_symbols ++ // requires that .uleb128 A-B is foldable where A and B reside in different ++ // fragments. This is used by __gcc_except_table. ++ bool Abs = getSubsectionsViaSymbols() ++ ? LF.getValue().evaluateKnownAbsolute(Value, Layout) ++ : LF.getValue().evaluateAsAbsolute(Value, Layout); ++ if (!Abs) { ++ bool Relaxed, UseZeroPad; ++ std::tie(Relaxed, UseZeroPad) = getBackend().relaxLEB128(LF, Layout, Value); ++ if (!Relaxed) { ++ getContext().reportError(LF.getValue().getLoc(), ++ Twine(LF.isSigned() ? ".s" : ".u") + ++ "leb128 expression is not absolute"); ++ LF.setValue(MCConstantExpr::create(0, Context)); ++ } ++ uint8_t Tmp[10]; // maximum size: ceil(64/7) ++ PadTo = std::max(PadTo, encodeULEB128(uint64_t(Value), Tmp)); ++ if (UseZeroPad) ++ Value = 0; ++ } + Data.clear(); + raw_svector_ostream OSE(Data); + // The compiler can generate EH table assembly that is impossible to assemble +@@ -1019,9 +1044,9 @@ bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) { + // to a later alignment fragment. To accommodate such tables, relaxation can + // only increase an LEB fragment size here, not decrease it. See PR35809. + if (LF.isSigned()) +- encodeSLEB128(Value, OSE, OldSize); ++ encodeSLEB128(Value, OSE, PadTo); + else +- encodeULEB128(Value, OSE, OldSize); ++ encodeULEB128(Value, OSE, PadTo); + return OldSize != LF.getContents().size(); + } + +diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +index 1ed047a8e632..9227d4d6afed 100644 +--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp ++++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +@@ -92,6 +92,7 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, + case FK_Data_2: + case FK_Data_4: + case FK_Data_8: ++ case FK_Data_leb128: + return Value; + case LoongArch::fixup_loongarch_b16: { + if (!isInt<18>(Value)) +@@ -129,6 +130,15 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, + } + } + ++static void fixupLeb128(MCContext &Ctx, const MCFixup &Fixup, ++ MutableArrayRef Data, uint64_t Value) { ++ unsigned I; ++ for (I = 0; I != Data.size() && Value; ++I, Value >>= 7) ++ Data[I] |= uint8_t(Value & 0x7f); ++ if (Value) ++ Ctx.reportError(Fixup.getLoc(), "Invalid uleb128 value!"); ++} ++ + void LoongArchAsmBackend::applyFixup(const MCAssembler &Asm, + const MCFixup &Fixup, + const MCValue &Target, +@@ -144,6 +154,10 @@ void LoongArchAsmBackend::applyFixup(const MCAssembler &Asm, + MCFixupKindInfo Info = getFixupKindInfo(Kind); + MCContext &Ctx = Asm.getContext(); + ++ // Fixup leb128 separately. ++ if (Fixup.getTargetKind() == FK_Data_leb128) ++ return fixupLeb128(Ctx, Fixup, Data, Value); ++ + // Apply any target-specific value adjustments. + Value = adjustFixupValue(Fixup, Value, Ctx); + +@@ -173,6 +187,7 @@ bool LoongArchAsmBackend::shouldForceRelocation(const MCAssembler &Asm, + case FK_Data_2: + case FK_Data_4: + case FK_Data_8: ++ case FK_Data_leb128: + return !Target.isAbsolute(); + } + } +@@ -202,9 +217,24 @@ getRelocPairForSize(unsigned Size) { + return std::make_pair( + MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_ADD64), + MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_SUB64)); ++ case 128: ++ return std::make_pair( ++ MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_ADD_ULEB128), ++ MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_SUB_ULEB128)); + } + } + ++std::pair LoongArchAsmBackend::relaxLEB128(MCLEBFragment &LF, ++ MCAsmLayout &Layout, ++ int64_t &Value) const { ++ const MCExpr &Expr = LF.getValue(); ++ if (LF.isSigned() || !Expr.evaluateKnownAbsolute(Value, Layout)) ++ return std::make_pair(false, false); ++ LF.getFixups().push_back( ++ MCFixup::create(0, &Expr, FK_Data_leb128, Expr.getLoc())); ++ return std::make_pair(true, true); ++} ++ + bool LoongArchAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { + // We mostly follow binutils' convention here: align to 4-byte boundary with a +@@ -226,21 +256,27 @@ bool LoongArchAsmBackend::handleAddSubRelocations(const MCAsmLayout &Layout, + uint64_t &FixedValue) const { + std::pair FK; + uint64_t FixedValueA, FixedValueB; +- const MCSection &SecA = Target.getSymA()->getSymbol().getSection(); +- const MCSection &SecB = Target.getSymB()->getSymbol().getSection(); +- +- // We need record relocation if SecA != SecB. Usually SecB is same as the +- // section of Fixup, which will be record the relocation as PCRel. If SecB +- // is not same as the section of Fixup, it will report error. Just return +- // false and then this work can be finished by handleFixup. +- if (&SecA != &SecB) +- return false; +- +- // In SecA == SecB case. If the linker relaxation is enabled, we need record +- // the ADD, SUB relocations. Otherwise the FixedValue has already been +- // calculated out in evaluateFixup, return true and avoid record relocations. +- if (!STI.hasFeature(LoongArch::FeatureRelax)) +- return true; ++ const MCSymbol &SA = Target.getSymA()->getSymbol(); ++ const MCSymbol &SB = Target.getSymB()->getSymbol(); ++ ++ bool force = !SA.isInSection() || !SB.isInSection(); ++ if (!force) { ++ const MCSection &SecA = SA.getSection(); ++ const MCSection &SecB = SB.getSection(); ++ ++ // We need record relocation if SecA != SecB. Usually SecB is same as the ++ // section of Fixup, which will be record the relocation as PCRel. If SecB ++ // is not same as the section of Fixup, it will report error. Just return ++ // false and then this work can be finished by handleFixup. ++ if (&SecA != &SecB) ++ return false; ++ ++ // In SecA == SecB case. If the linker relaxation is enabled, we need record ++ // the ADD, SUB relocations. Otherwise the FixedValue has already been calc- ++ // ulated out in evaluateFixup, return true and avoid record relocations. ++ if (!STI.hasFeature(LoongArch::FeatureRelax)) ++ return true; ++ } + + switch (Fixup.getKind()) { + case llvm::FK_Data_1: +@@ -255,6 +291,9 @@ bool LoongArchAsmBackend::handleAddSubRelocations(const MCAsmLayout &Layout, + case llvm::FK_Data_8: + FK = getRelocPairForSize(64); + break; ++ case llvm::FK_Data_leb128: ++ FK = getRelocPairForSize(128); ++ break; + default: + llvm_unreachable("unsupported fixup size"); + } +diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h +index 20f25b5cf53b..49801e4fd81a 100644 +--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h ++++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h +@@ -65,6 +65,9 @@ public: + void relaxInstruction(MCInst &Inst, + const MCSubtargetInfo &STI) const override {} + ++ std::pair relaxLEB128(MCLEBFragment &LF, MCAsmLayout &Layout, ++ int64_t &Value) const override; ++ + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; + +diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +index 1b890fbe041a..5c651aa93225 100644 +--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp ++++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +@@ -19,6 +19,7 @@ + #include "llvm/MC/MCObjectWriter.h" + #include "llvm/MC/MCSymbol.h" + #include "llvm/MC/MCValue.h" ++#include "llvm/Support/CommandLine.h" + #include "llvm/Support/Endian.h" + #include "llvm/Support/EndianStream.h" + #include "llvm/Support/ErrorHandling.h" +@@ -27,6 +28,13 @@ + + using namespace llvm; + ++// Temporary workaround for old linkers that do not support ULEB128 relocations, ++// which are abused by DWARF v5 DW_LLE_offset_pair/DW_RLE_offset_pair ++// implemented in Clang/LLVM. ++static cl::opt ULEB128Reloc( ++ "riscv-uleb128-reloc", cl::init(false), cl::Hidden, ++ cl::desc("Emit R_RISCV_SET_ULEB128/E_RISCV_SUB_ULEB128 if appropriate")); ++ + std::optional RISCVAsmBackend::getFixupKind(StringRef Name) const { + if (STI.getTargetTriple().isOSBinFormatELF()) { + unsigned Type; +@@ -126,6 +134,7 @@ bool RISCVAsmBackend::shouldForceRelocation(const MCAssembler &Asm, + case FK_Data_2: + case FK_Data_4: + case FK_Data_8: ++ case FK_Data_leb128: + if (Target.isAbsolute()) + return false; + break; +@@ -330,6 +339,19 @@ bool RISCVAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, + return true; + } + ++std::pair RISCVAsmBackend::relaxLEB128(MCLEBFragment &LF, ++ MCAsmLayout &Layout, ++ int64_t &Value) const { ++ if (LF.isSigned()) ++ return std::make_pair(false, false); ++ const MCExpr &Expr = LF.getValue(); ++ if (ULEB128Reloc) { ++ LF.getFixups().push_back( ++ MCFixup::create(0, &Expr, FK_Data_leb128, Expr.getLoc())); ++ } ++ return std::make_pair(Expr.evaluateKnownAbsolute(Value, Layout), false); ++} ++ + // Given a compressed control flow instruction this function returns + // the expanded instruction. + unsigned RISCVAsmBackend::getRelaxedOpcode(unsigned Op) const { +@@ -416,6 +438,7 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, + case FK_Data_4: + case FK_Data_8: + case FK_Data_6b: ++ case FK_Data_leb128: + return Value; + case RISCV::fixup_riscv_set_6b: + return Value & 0x03; +@@ -596,6 +619,10 @@ bool RISCVAsmBackend::handleAddSubRelocations(const MCAsmLayout &Layout, + TA = ELF::R_RISCV_ADD64; + TB = ELF::R_RISCV_SUB64; + break; ++ case llvm::FK_Data_leb128: ++ TA = ELF::R_RISCV_SET_ULEB128; ++ TB = ELF::R_RISCV_SUB_ULEB128; ++ break; + default: + llvm_unreachable("unsupported fixup size"); + } +diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h +index 0ea1f32e8296..edefb171bcdc 100644 +--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h ++++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h +@@ -99,6 +99,8 @@ public: + bool &WasRelaxed) const override; + bool relaxDwarfCFA(MCDwarfCallFrameFragment &DF, MCAsmLayout &Layout, + bool &WasRelaxed) const override; ++ std::pair relaxLEB128(MCLEBFragment &LF, MCAsmLayout &Layout, ++ int64_t &Value) const override; + + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; +diff --git a/llvm/test/MC/ELF/RISCV/gen-dwarf.s b/llvm/test/MC/ELF/RISCV/gen-dwarf.s +index 2235559d5f35..2a7dc777e70c 100644 +--- a/llvm/test/MC/ELF/RISCV/gen-dwarf.s ++++ b/llvm/test/MC/ELF/RISCV/gen-dwarf.s +@@ -9,7 +9,7 @@ + ## emit special opcodes to make .debug_line smaller, but we don't do this for + ## consistency. + +-# RUN: llvm-mc -filetype=obj -triple=riscv64 -g -dwarf-version=5 -mattr=+relax < %s -o %t ++# RUN: llvm-mc -filetype=obj -triple=riscv64 -g -dwarf-version=5 -mattr=+relax -riscv-uleb128-reloc=1 < %s -o %t + # RUN: llvm-dwarfdump -eh-frame -debug-line -debug-rnglists -v %t | FileCheck %s + # RUN: llvm-readobj -r -x .eh_frame %t | FileCheck %s --check-prefix=RELOC + +@@ -48,9 +48,10 @@ + # RELOC-NEXT: 0x34 R_RISCV_32_PCREL 0x0 + # RELOC-NEXT: } + +-## TODO A section needs two relocations. + # RELOC: Section ([[#]]) .rela.debug_rnglists { + # RELOC-NEXT: 0xD R_RISCV_64 .text.foo 0x0 ++# RELOC-NEXT: 0x15 R_RISCV_SET_ULEB128 0x0 ++# RELOC-NEXT: 0x15 R_RISCV_SUB_ULEB128 .text.foo 0x0 + # RELOC-NEXT: 0x17 R_RISCV_64 .text.bar 0x0 + # RELOC-NEXT: } + +diff --git a/llvm/test/MC/LoongArch/Relocations/leb128.s b/llvm/test/MC/LoongArch/Relocations/leb128.s +new file mode 100644 +index 000000000000..7a96ec551b76 +--- /dev/null ++++ b/llvm/test/MC/LoongArch/Relocations/leb128.s +@@ -0,0 +1,72 @@ ++# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=-relax %s -o %t ++# RUN: llvm-readobj -r -x .alloc_w %t | FileCheck --check-prefixes=CHECK,NORELAX %s ++# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.relax ++# RUN: llvm-readobj -r -x .alloc_w %t.relax | FileCheck --check-prefixes=CHECK,RELAX %s ++ ++# RUN: not llvm-mc --filetype=obj --triple=loongarch64 --mattr=-relax --defsym ERR=1 %s -o /dev/null 2>&1 | \ ++# RUN: FileCheck %s --check-prefix=ERR ++# RUN: not llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax --defsym ERR=1 %s -o /dev/null 2>&1 | \ ++# RUN: FileCheck %s --check-prefix=ERR ++ ++# CHECK: Relocations [ ++# CHECK-NEXT: .rela.alloc_w { ++# RELAX-NEXT: 0x0 R_LARCH_ADD_ULEB128 w1 0x0 ++# RELAX-NEXT: 0x0 R_LARCH_SUB_ULEB128 w 0x0 ++# RELAX-NEXT: 0x1 R_LARCH_ADD_ULEB128 w2 0x0 ++# RELAX-NEXT: 0x1 R_LARCH_SUB_ULEB128 w1 0x0 ++# CHECK-NEXT: 0x2 R_LARCH_PCALA_HI20 foo 0x0 ++# RELAX-NEXT: 0x2 R_LARCH_RELAX - 0x0 ++# CHECK-NEXT: 0x6 R_LARCH_PCALA_LO12 foo 0x0 ++# RELAX-NEXT: 0x6 R_LARCH_RELAX - 0x0 ++# RELAX-NEXT: 0xA R_LARCH_ADD_ULEB128 w2 0x0 ++# RELAX-NEXT: 0xA R_LARCH_SUB_ULEB128 w1 0x0 ++# RELAX-NEXT: 0xB R_LARCH_ADD_ULEB128 w2 0x78 ++# RELAX-NEXT: 0xB R_LARCH_SUB_ULEB128 w1 0x0 ++# RELAX-NEXT: 0xD R_LARCH_ADD_ULEB128 w1 0x0 ++# RELAX-NEXT: 0xD R_LARCH_SUB_ULEB128 w2 0x0 ++# RELAX-NEXT: 0x17 R_LARCH_ADD_ULEB128 w3 0x6F ++# RELAX-NEXT: 0x17 R_LARCH_SUB_ULEB128 w2 0x0 ++# RELAX-NEXT: 0x18 R_LARCH_ADD_ULEB128 w3 0x71 ++# RELAX-NEXT: 0x18 R_LARCH_SUB_ULEB128 w2 0x0 ++# CHECK-NEXT: } ++# CHECK-NEXT: ] ++ ++# CHECK: Hex dump of section '.alloc_w': ++# NORELAX-NEXT: 0x00000000 02080c00 001a8c01 c0020880 01f8ffff ++# NORELAX-NEXT: 0x00000010 ffffffff ffff017f 8101 ++# RELAX-NEXT: 0x00000000 00000c00 001a8c01 c0020080 00808080 ++# RELAX-NEXT: 0x00000010 80808080 80800000 8000 ++ ++.section .alloc_w,"ax",@progbits; w: ++.uleb128 w1-w # w1 is later defined in the same section ++.uleb128 w2-w1 # w1 and w2 are separated by a linker relaxable instruction ++w1: ++ la.pcrel $t0, foo ++w2: ++.uleb128 w2-w1 # 0x08 ++.uleb128 w2-w1+120 # 0x0180 ++.uleb128 -(w2-w1) # 0x01fffffffffffffffff8 ++.uleb128 w3-w2+111 # 0x7f ++.uleb128 w3-w2+113 # 0x0181 ++w3: ++ ++.ifdef ERR ++# ERR: :[[#@LINE+1]]:16: error: .uleb128 expression is not absolute ++.uleb128 extern-w # extern is undefined ++# ERR: :[[#@LINE+1]]:11: error: .uleb128 expression is not absolute ++.uleb128 w-extern ++# ERR: :[[#@LINE+1]]:11: error: .uleb128 expression is not absolute ++.uleb128 x-w # x is later defined in another section ++ ++.section .alloc_x,"aw",@progbits; x: ++# ERR: :[[#@LINE+1]]:11: error: .uleb128 expression is not absolute ++.uleb128 y-x ++.section .alloc_y,"aw",@progbits; y: ++# ERR: :[[#@LINE+1]]:11: error: .uleb128 expression is not absolute ++.uleb128 x-y ++ ++# ERR: :[[#@LINE+1]]:10: error: .uleb128 expression is not absolute ++.uleb128 extern ++# ERR: :[[#@LINE+1]]:10: error: .uleb128 expression is not absolute ++.uleb128 y ++.endif +diff --git a/llvm/test/MC/LoongArch/Relocations/relax-addsub.s b/llvm/test/MC/LoongArch/Relocations/relax-addsub.s +index 14922657ae89..cd01332afd0b 100644 +--- a/llvm/test/MC/LoongArch/Relocations/relax-addsub.s ++++ b/llvm/test/MC/LoongArch/Relocations/relax-addsub.s +@@ -8,12 +8,23 @@ + # NORELAX-NEXT: 0x10 R_LARCH_PCALA_HI20 .text 0x0 + # NORELAX-NEXT: 0x14 R_LARCH_PCALA_LO12 .text 0x0 + # NORELAX-NEXT: } ++# NORELAX-NEXT: Section ({{.*}}) .rela.data { ++# NORELAX-NEXT: 0x30 R_LARCH_ADD8 foo 0x0 ++# NORELAX-NEXT: 0x30 R_LARCH_SUB8 .text 0x10 ++# NORELAX-NEXT: 0x31 R_LARCH_ADD16 foo 0x0 ++# NORELAX-NEXT: 0x31 R_LARCH_SUB16 .text 0x10 ++# NORELAX-NEXT: 0x33 R_LARCH_ADD32 foo 0x0 ++# NORELAX-NEXT: 0x33 R_LARCH_SUB32 .text 0x10 ++# NORELAX-NEXT: 0x37 R_LARCH_ADD64 foo 0x0 ++# NORELAX-NEXT: 0x37 R_LARCH_SUB64 .text 0x10 ++# NORELAX-NEXT: } + # NORELAX-NEXT: ] + + # NORELAX: Hex dump of section '.data': +-# NORELAX-NEXT: 0x00000000 04040004 00000004 00000000 0000000c +-# NORELAX-NEXT: 0x00000010 0c000c00 00000c00 00000000 00000808 +-# NORELAX-NEXT: 0x00000020 00080000 00080000 00000000 00 ++# NORELAX-NEXT: 0x00000000 04040004 00000004 00000000 00000004 ++# NORELAX-NEXT: 0x00000010 0c0c000c 0000000c 00000000 0000000c ++# NORELAX-NEXT: 0x00000020 08080008 00000008 00000000 00000008 ++# NORELAX-NEXT: 0x00000030 00000000 00000000 00000000 000000 + + # RELAX: Relocations [ + # RELAX-NEXT: Section ({{.*}}) .rela.text { +@@ -23,21 +34,32 @@ + # RELAX-NEXT: 0x14 R_LARCH_RELAX - 0x0 + # RELAX-NEXT: } + # RELAX-NEXT: Section ({{.*}}) .rela.data { +-# RELAX-NEXT: 0x1E R_LARCH_ADD8 .L4 0x0 +-# RELAX-NEXT: 0x1E R_LARCH_SUB8 .L3 0x0 +-# RELAX-NEXT: 0x1F R_LARCH_ADD16 .L4 0x0 +-# RELAX-NEXT: 0x1F R_LARCH_SUB16 .L3 0x0 +-# RELAX-NEXT: 0x21 R_LARCH_ADD32 .L4 0x0 +-# RELAX-NEXT: 0x21 R_LARCH_SUB32 .L3 0x0 +-# RELAX-NEXT: 0x25 R_LARCH_ADD64 .L4 0x0 +-# RELAX-NEXT: 0x25 R_LARCH_SUB64 .L3 0x0 ++# RELAX-NEXT: 0x20 R_LARCH_ADD8 .L4 0x0 ++# RELAX-NEXT: 0x20 R_LARCH_SUB8 .L3 0x0 ++# RELAX-NEXT: 0x21 R_LARCH_ADD16 .L4 0x0 ++# RELAX-NEXT: 0x21 R_LARCH_SUB16 .L3 0x0 ++# RELAX-NEXT: 0x23 R_LARCH_ADD32 .L4 0x0 ++# RELAX-NEXT: 0x23 R_LARCH_SUB32 .L3 0x0 ++# RELAX-NEXT: 0x27 R_LARCH_ADD64 .L4 0x0 ++# RELAX-NEXT: 0x27 R_LARCH_SUB64 .L3 0x0 ++# RELAX-NEXT: 0x2F R_LARCH_ADD_ULEB128 .L4 0x0 ++# RELAX-NEXT: 0x2F R_LARCH_SUB_ULEB128 .L3 0x0 ++# RELAX-NEXT: 0x30 R_LARCH_ADD8 foo 0x0 ++# RELAX-NEXT: 0x30 R_LARCH_SUB8 .L3 0x0 ++# RELAX-NEXT: 0x31 R_LARCH_ADD16 foo 0x0 ++# RELAX-NEXT: 0x31 R_LARCH_SUB16 .L3 0x0 ++# RELAX-NEXT: 0x33 R_LARCH_ADD32 foo 0x0 ++# RELAX-NEXT: 0x33 R_LARCH_SUB32 .L3 0x0 ++# RELAX-NEXT: 0x37 R_LARCH_ADD64 foo 0x0 ++# RELAX-NEXT: 0x37 R_LARCH_SUB64 .L3 0x0 + # RELAX-NEXT: } + # RELAX-NEXT: ] + + # RELAX: Hex dump of section '.data': +-# RELAX-NEXT: 0x00000000 04040004 00000004 00000000 0000000c +-# RELAX-NEXT: 0x00000010 0c000c00 00000c00 00000000 00000000 +-# RELAX-NEXT: 0x00000020 00000000 00000000 00000000 00 ++# RELAX-NEXT: 0x00000000 04040004 00000004 00000000 00000004 ++# RELAX-NEXT: 0x00000010 0c0c000c 0000000c 00000000 0000000c ++# RELAX-NEXT: 0x00000020 00000000 00000000 00000000 00000000 ++# RELAX-NEXT: 0x00000030 00000000 00000000 00000000 000000 + + .text + .L1: +@@ -55,13 +77,20 @@ + .short .L2 - .L1 + .word .L2 - .L1 + .dword .L2 - .L1 ++.uleb128 .L2 - .L1 + ## TODO Handle alignment directive. + .byte .L3 - .L2 + .short .L3 - .L2 + .word .L3 - .L2 + .dword .L3 - .L2 ++.uleb128 .L3 - .L2 + ## With relaxation, emit relocs because the la.pcrel makes the diff variable. + .byte .L4 - .L3 + .short .L4 - .L3 + .word .L4 - .L3 + .dword .L4 - .L3 ++.uleb128 .L4 - .L3 ++.byte foo - .L3 ++.short foo - .L3 ++.word foo - .L3 ++.dword foo - .L3 +diff --git a/llvm/test/MC/X86/invalid-sleb.s b/llvm/test/MC/X86/invalid-sleb.s +deleted file mode 100644 +index 7d7df351ce4e..000000000000 +--- a/llvm/test/MC/X86/invalid-sleb.s ++++ /dev/null +@@ -1,5 +0,0 @@ +-// RUN: not --crash llvm-mc -filetype=obj -triple x86_64-pc-linux %s -o %t 2>&1 | FileCheck %s +- +-// CHECK: sleb128 and uleb128 expressions must be absolute +- +- .sleb128 undefined +-- +2.20.1 + diff --git a/0006-Backport-LoongArch-Add-relaxDwarfLineAddr-and-relaxDwarfCFA-to-handle-the-mutable-label-diff-in-dwarfinfo.patch b/0006-Backport-LoongArch-Add-relaxDwarfLineAddr-and-relaxDwarfCFA-to-handle-the-mutable-label-diff-in-dwarfinfo.patch new file mode 100644 index 0000000..4d19f8c --- /dev/null +++ b/0006-Backport-LoongArch-Add-relaxDwarfLineAddr-and-relaxDwarfCFA-to-handle-the-mutable-label-diff-in-dwarfinfo.patch @@ -0,0 +1,376 @@ +From 286c92a8e78c4b67368c2f47a8e73036fdacbae2 Mon Sep 17 00:00:00 2001 +From: Jinyang He +Date: Tue, 16 Jan 2024 13:20:13 +0800 +Subject: [PATCH 07/14] [LoongArch] Add relaxDwarfLineAddr and relaxDwarfCFA to + handle the mutable label diff in dwarfinfo (#77728) + +When linker-relaxation is enabled, part of the label diff in dwarfinfo +cannot be computed before static link. Refer to RISCV, we add the +relaxDwarfLineAddr and relaxDwarfCFA to add relocations for these label +diffs. Calculate whether the label diff is mutable. For immutable label +diff, return false and do the other works by its parent function. + +(cherry picked from commit ed7f4edc19ada006789318a0929b57d1b5a761bd) +Change-Id: Iae5bad958c6d1a71dac1672f5f03991eaeea6d22 +--- + llvm/lib/Object/RelocationResolver.cpp | 12 +- + .../MCTargetDesc/LoongArchAsmBackend.cpp | 129 ++++++++++++++++++ + .../MCTargetDesc/LoongArchAsmBackend.h | 5 + + .../LoongArch/dwarf-loongarch-relocs.ll | 128 +++++++++++++++++ + llvm/test/DebugInfo/LoongArch/lit.local.cfg | 2 + + 5 files changed, 274 insertions(+), 2 deletions(-) + create mode 100644 llvm/test/DebugInfo/LoongArch/dwarf-loongarch-relocs.ll + create mode 100644 llvm/test/DebugInfo/LoongArch/lit.local.cfg + +diff --git a/llvm/lib/Object/RelocationResolver.cpp b/llvm/lib/Object/RelocationResolver.cpp +index 03ac59289528..0e5036d7dfcc 100644 +--- a/llvm/lib/Object/RelocationResolver.cpp ++++ b/llvm/lib/Object/RelocationResolver.cpp +@@ -539,6 +539,8 @@ static bool supportsLoongArch(uint64_t Type) { + case ELF::R_LARCH_32: + case ELF::R_LARCH_32_PCREL: + case ELF::R_LARCH_64: ++ case ELF::R_LARCH_ADD6: ++ case ELF::R_LARCH_SUB6: + case ELF::R_LARCH_ADD8: + case ELF::R_LARCH_SUB8: + case ELF::R_LARCH_ADD16: +@@ -564,6 +566,10 @@ static uint64_t resolveLoongArch(uint64_t Type, uint64_t Offset, uint64_t S, + return (S + Addend - Offset) & 0xFFFFFFFF; + case ELF::R_LARCH_64: + return S + Addend; ++ case ELF::R_LARCH_ADD6: ++ return (LocData & 0xC0) | ((LocData + S + Addend) & 0x3F); ++ case ELF::R_LARCH_SUB6: ++ return (LocData & 0xC0) | ((LocData - (S + Addend)) & 0x3F); + case ELF::R_LARCH_ADD8: + return (LocData + (S + Addend)) & 0xFF; + case ELF::R_LARCH_SUB8: +@@ -880,8 +886,10 @@ uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R, + + if (GetRelSectionType() == ELF::SHT_RELA) { + Addend = getELFAddend(R); +- // RISCV relocations use both LocData and Addend. +- if (Obj->getArch() != Triple::riscv32 && ++ // LoongArch and RISCV relocations use both LocData and Addend. ++ if (Obj->getArch() != Triple::loongarch32 && ++ Obj->getArch() != Triple::loongarch64 && ++ Obj->getArch() != Triple::riscv32 && + Obj->getArch() != Triple::riscv64) + LocData = 0; + } +diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +index 9227d4d6afed..8d82327b2e2b 100644 +--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp ++++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +@@ -12,6 +12,7 @@ + + #include "LoongArchAsmBackend.h" + #include "LoongArchFixupKinds.h" ++#include "llvm/MC/MCAsmInfo.h" + #include "llvm/MC/MCAsmLayout.h" + #include "llvm/MC/MCAssembler.h" + #include "llvm/MC/MCContext.h" +@@ -19,6 +20,7 @@ + #include "llvm/MC/MCValue.h" + #include "llvm/Support/Endian.h" + #include "llvm/Support/EndianStream.h" ++#include "llvm/Support/LEB128.h" + + #define DEBUG_TYPE "loongarch-asmbackend" + +@@ -235,6 +237,133 @@ std::pair LoongArchAsmBackend::relaxLEB128(MCLEBFragment &LF, + return std::make_pair(true, true); + } + ++bool LoongArchAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, ++ MCAsmLayout &Layout, ++ bool &WasRelaxed) const { ++ MCContext &C = Layout.getAssembler().getContext(); ++ ++ int64_t LineDelta = DF.getLineDelta(); ++ const MCExpr &AddrDelta = DF.getAddrDelta(); ++ SmallVectorImpl &Data = DF.getContents(); ++ SmallVectorImpl &Fixups = DF.getFixups(); ++ size_t OldSize = Data.size(); ++ ++ int64_t Value; ++ if (AddrDelta.evaluateAsAbsolute(Value, Layout)) ++ return false; ++ bool IsAbsolute = AddrDelta.evaluateKnownAbsolute(Value, Layout); ++ assert(IsAbsolute && "CFA with invalid expression"); ++ (void)IsAbsolute; ++ ++ Data.clear(); ++ Fixups.clear(); ++ raw_svector_ostream OS(Data); ++ ++ // INT64_MAX is a signal that this is actually a DW_LNE_end_sequence. ++ if (LineDelta != INT64_MAX) { ++ OS << uint8_t(dwarf::DW_LNS_advance_line); ++ encodeSLEB128(LineDelta, OS); ++ } ++ ++ unsigned Offset; ++ std::pair FK; ++ ++ // According to the DWARF specification, the `DW_LNS_fixed_advance_pc` opcode ++ // takes a single unsigned half (unencoded) operand. The maximum encodable ++ // value is therefore 65535. Set a conservative upper bound for relaxation. ++ if (Value > 60000) { ++ unsigned PtrSize = C.getAsmInfo()->getCodePointerSize(); ++ ++ OS << uint8_t(dwarf::DW_LNS_extended_op); ++ encodeULEB128(PtrSize + 1, OS); ++ ++ OS << uint8_t(dwarf::DW_LNE_set_address); ++ Offset = OS.tell(); ++ assert((PtrSize == 4 || PtrSize == 8) && "Unexpected pointer size"); ++ FK = getRelocPairForSize(PtrSize == 4 ? 32 : 64); ++ OS.write_zeros(PtrSize); ++ } else { ++ OS << uint8_t(dwarf::DW_LNS_fixed_advance_pc); ++ Offset = OS.tell(); ++ FK = getRelocPairForSize(16); ++ support::endian::write(OS, 0, support::little); ++ } ++ ++ const MCBinaryExpr &MBE = cast(AddrDelta); ++ Fixups.push_back(MCFixup::create(Offset, MBE.getLHS(), std::get<0>(FK))); ++ Fixups.push_back(MCFixup::create(Offset, MBE.getRHS(), std::get<1>(FK))); ++ ++ if (LineDelta == INT64_MAX) { ++ OS << uint8_t(dwarf::DW_LNS_extended_op); ++ OS << uint8_t(1); ++ OS << uint8_t(dwarf::DW_LNE_end_sequence); ++ } else { ++ OS << uint8_t(dwarf::DW_LNS_copy); ++ } ++ ++ WasRelaxed = OldSize != Data.size(); ++ return true; ++} ++ ++bool LoongArchAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, ++ MCAsmLayout &Layout, ++ bool &WasRelaxed) const { ++ const MCExpr &AddrDelta = DF.getAddrDelta(); ++ SmallVectorImpl &Data = DF.getContents(); ++ SmallVectorImpl &Fixups = DF.getFixups(); ++ size_t OldSize = Data.size(); ++ ++ int64_t Value; ++ if (AddrDelta.evaluateAsAbsolute(Value, Layout)) ++ return false; ++ bool IsAbsolute = AddrDelta.evaluateKnownAbsolute(Value, Layout); ++ assert(IsAbsolute && "CFA with invalid expression"); ++ (void)IsAbsolute; ++ ++ Data.clear(); ++ Fixups.clear(); ++ raw_svector_ostream OS(Data); ++ ++ assert( ++ Layout.getAssembler().getContext().getAsmInfo()->getMinInstAlignment() == ++ 1 && ++ "expected 1-byte alignment"); ++ if (Value == 0) { ++ WasRelaxed = OldSize != Data.size(); ++ return true; ++ } ++ ++ auto AddFixups = [&Fixups, ++ &AddrDelta](unsigned Offset, ++ std::pair FK) { ++ const MCBinaryExpr &MBE = cast(AddrDelta); ++ Fixups.push_back(MCFixup::create(Offset, MBE.getLHS(), std::get<0>(FK))); ++ Fixups.push_back(MCFixup::create(Offset, MBE.getRHS(), std::get<1>(FK))); ++ }; ++ ++ if (isUIntN(6, Value)) { ++ OS << uint8_t(dwarf::DW_CFA_advance_loc); ++ AddFixups(0, getRelocPairForSize(6)); ++ } else if (isUInt<8>(Value)) { ++ OS << uint8_t(dwarf::DW_CFA_advance_loc1); ++ support::endian::write(OS, 0, support::little); ++ AddFixups(1, getRelocPairForSize(8)); ++ } else if (isUInt<16>(Value)) { ++ OS << uint8_t(dwarf::DW_CFA_advance_loc2); ++ support::endian::write(OS, 0, support::little); ++ AddFixups(1, getRelocPairForSize(16)); ++ } else if (isUInt<32>(Value)) { ++ OS << uint8_t(dwarf::DW_CFA_advance_loc4); ++ support::endian::write(OS, 0, support::little); ++ AddFixups(1, getRelocPairForSize(32)); ++ } else { ++ llvm_unreachable("unsupported CFA encoding"); ++ } ++ ++ WasRelaxed = OldSize != Data.size(); ++ return true; ++} ++ + bool LoongArchAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const { + // We mostly follow binutils' convention here: align to 4-byte boundary with a +diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h +index 49801e4fd81a..657f5ca5e731 100644 +--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h ++++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h +@@ -68,6 +68,11 @@ public: + std::pair relaxLEB128(MCLEBFragment &LF, MCAsmLayout &Layout, + int64_t &Value) const override; + ++ bool relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, MCAsmLayout &Layout, ++ bool &WasRelaxed) const override; ++ bool relaxDwarfCFA(MCDwarfCallFrameFragment &DF, MCAsmLayout &Layout, ++ bool &WasRelaxed) const override; ++ + bool writeNopData(raw_ostream &OS, uint64_t Count, + const MCSubtargetInfo *STI) const override; + +diff --git a/llvm/test/DebugInfo/LoongArch/dwarf-loongarch-relocs.ll b/llvm/test/DebugInfo/LoongArch/dwarf-loongarch-relocs.ll +new file mode 100644 +index 000000000000..e03b4c1d34de +--- /dev/null ++++ b/llvm/test/DebugInfo/LoongArch/dwarf-loongarch-relocs.ll +@@ -0,0 +1,128 @@ ++; RUN: llc --filetype=obj --mtriple=loongarch64 --mattr=-relax %s -o %t.o ++; RUN: llvm-readobj -r %t.o | FileCheck --check-prefixes=RELOCS-BOTH,RELOCS-NORL %s ++; RUN: llvm-objdump --source %t.o | FileCheck --check-prefix=SOURCE %s ++; RUN: llvm-dwarfdump --debug-info --debug-line %t.o | FileCheck --check-prefix=DWARF %s ++ ++; RUN: llc --filetype=obj --mtriple=loongarch64 --mattr=+relax %s -o %t.r.o ++; RUN: llvm-readobj -r %t.r.o | FileCheck --check-prefixes=RELOCS-BOTH,RELOCS-ENRL %s ++; RUN: llvm-objdump --source %t.r.o | FileCheck --check-prefix=SOURCE %s ++; RUN: llvm-dwarfdump --debug-info --debug-line %t.r.o | FileCheck --check-prefix=DWARF %s ++ ++; RELOCS-BOTH: Relocations [ ++; RELOCS-BOTH-NEXT: Section ({{.*}}) .rela.text { ++; RELOCS-BOTH-NEXT: 0x14 R_LARCH_PCALA_HI20 sym 0x0 ++; RELOCS-ENRL-NEXT: 0x14 R_LARCH_RELAX - 0x0 ++; RELOCS-BOTH-NEXT: 0x18 R_LARCH_PCALA_LO12 sym 0x0 ++; RELOCS-ENRL-NEXT: 0x18 R_LARCH_RELAX - 0x0 ++; RELOCS-BOTH-NEXT: } ++; RELOCS-BOTH: Section ({{.*}}) .rela.debug_frame { ++; RELOCS-NORL-NEXT: 0x1C R_LARCH_32 .debug_frame 0x0 ++; RELOCS-NORL-NEXT: 0x20 R_LARCH_64 .text 0x0 ++; RELOCS-ENRL-NEXT: 0x1C R_LARCH_32 0x0 ++; RELOCS-ENRL-NEXT: 0x20 R_LARCH_64 0x0 ++; RELOCS-ENRL-NEXT: 0x28 R_LARCH_ADD64 0x0 ++; RELOCS-ENRL-NEXT: 0x28 R_LARCH_SUB64 0x0 ++; RELOCS-ENRL-NEXT: 0x3F R_LARCH_ADD6 0x0 ++; RELOCS-ENRL-NEXT: 0x3F R_LARCH_SUB6 0x0 ++; RELOCS-BOTH-NEXT: } ++; RELOCS-BOTH: Section ({{.*}}) .rela.debug_line { ++; RELOCS-BOTH-NEXT: 0x22 R_LARCH_32 .debug_line_str 0x0 ++; RELOCS-BOTH-NEXT: 0x31 R_LARCH_32 .debug_line_str 0x2 ++; RELOCS-BOTH-NEXT: 0x46 R_LARCH_32 .debug_line_str 0x1B ++; RELOCS-NORL-NEXT: 0x4F R_LARCH_64 .text 0x0 ++; RELOCS-ENRL-NEXT: 0x4F R_LARCH_64 0x0 ++; RELOCS-ENRL-NEXT: 0x5F R_LARCH_ADD16 0x0 ++; RELOCS-ENRL-NEXT: 0x5F R_LARCH_SUB16 0x0 ++; RELOCS-BOTH-NEXT: } ++; RELOCS-BOTH-NEXT: ] ++ ++; SOURCE: 0000000000000000 : ++; SOURCE: ; { ++; SOURCE: ; asm volatile( ++; SOURCE: ; return 0; ++ ++; DWARF: DW_AT_producer ("clang") ++; DWARF: DW_AT_name ("dwarf-loongarch-relocs.c") ++; DWARF: DW_AT_comp_dir (".") ++; DWARF: DW_AT_name ("foo") ++; DWARF-NEXT: DW_AT_decl_file ("{{.*}}dwarf-loongarch-relocs.c") ++; DWARF-NEXT: DW_AT_decl_line (1) ++; DWARF-NEXT: DW_AT_type (0x00000032 "int") ++; DWARF: DW_AT_name ("int") ++; DWARF-NEXT: DW_AT_encoding (DW_ATE_signed) ++; DWARF-NEXT: DW_AT_byte_size (0x04) ++; DWARF: .debug_line contents: ++; DWARF-NEXT: debug_line[0x00000000] ++; DWARF-NEXT: Line table prologue: ++; DWARF-NEXT: total_length: {{.*}} ++; DWARF-NEXT: format: DWARF32 ++; DWARF-NEXT: version: 5 ++; DWARF-NEXT: address_size: 8 ++; DWARF-NEXT: seg_select_size: 0 ++; DWARF-NEXT: prologue_length: 0x0000003e ++; DWARF-NEXT: min_inst_length: 1 ++; DWARF-NEXT: max_ops_per_inst: 1 ++; DWARF-NEXT: default_is_stmt: 1 ++; DWARF-NEXT: line_base: -5 ++; DWARF-NEXT: line_range: 14 ++; DWARF-NEXT: opcode_base: 13 ++; DWARF-NEXT: standard_opcode_lengths[DW_LNS_copy] = 0 ++; DWARF-NEXT: standard_opcode_lengths[DW_LNS_advance_pc] = 1 ++; DWARF-NEXT: standard_opcode_lengths[DW_LNS_advance_line] = 1 ++; DWARF-NEXT: standard_opcode_lengths[DW_LNS_set_file] = 1 ++; DWARF-NEXT: standard_opcode_lengths[DW_LNS_set_column] = 1 ++; DWARF-NEXT: standard_opcode_lengths[DW_LNS_negate_stmt] = 0 ++; DWARF-NEXT: standard_opcode_lengths[DW_LNS_set_basic_block] = 0 ++; DWARF-NEXT: standard_opcode_lengths[DW_LNS_const_add_pc] = 0 ++; DWARF-NEXT: standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1 ++; DWARF-NEXT: standard_opcode_lengths[DW_LNS_set_prologue_end] = 0 ++; DWARF-NEXT: standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0 ++; DWARF-NEXT: standard_opcode_lengths[DW_LNS_set_isa] = 1 ++; DWARF-NEXT: include_directories[ 0] = "." ++; DWARF-NEXT: file_names[ 0]: ++; DWARF-NEXT: name: "dwarf-loongarch-relocs.c" ++; DWARF-NEXT: dir_index: 0 ++; DWARF-NEXT: md5_checksum: f44d6d71bc4da58b4abe338ca507c007 ++; DWARF-NEXT: source: "{{.*}}" ++; DWARF-EMPTY: ++; DWARF-NEXT: Address Line Column File ISA Discriminator OpIndex Flags ++; DWARF-NEXT: ------------------ ------ ------ ------ --- ------------- ------- ------------- ++; DWARF-NEXT: 0x0000000000000000 2 0 0 0 0 0 is_stmt ++; DWARF-NEXT: 0x0000000000000010 3 3 0 0 0 0 is_stmt prologue_end ++; DWARF-NEXT: 0x0000000000000020 10 3 0 0 0 0 is_stmt ++; DWARF-NEXT: 0x000000000000002c 10 3 0 0 0 0 epilogue_begin ++; DWARF-NEXT: 0x0000000000000034 10 3 0 0 0 0 end_sequence ++ ++; ModuleID = 'dwarf-loongarch-relocs.c' ++source_filename = "dwarf-loongarch-relocs.c" ++target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128" ++target triple = "loongarch64" ++ ++; Function Attrs: noinline nounwind optnone ++define dso_local signext i32 @foo() #0 !dbg !8 { ++ call void asm sideeffect ".cfi_remember_state\0A\09.cfi_adjust_cfa_offset 16\0A\09nop\0A\09la.pcrel $$t0, sym\0A\09nop\0A\09.cfi_restore_state\0A\09", ""() #1, !dbg !12, !srcloc !13 ++ ret i32 0, !dbg !14 ++} ++ ++attributes #0 = { noinline nounwind optnone "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="loongarch64" "target-features"="+64bit,+d,+f,+ual" } ++attributes #1 = { nounwind } ++ ++!llvm.dbg.cu = !{!0} ++!llvm.module.flags = !{!2, !3, !4, !5, !6} ++!llvm.ident = !{!7} ++ ++!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) ++!1 = !DIFile(filename: "dwarf-loongarch-relocs.c", directory: ".", checksumkind: CSK_MD5, checksum: "f44d6d71bc4da58b4abe338ca507c007", source: "int foo()\0A{\0A asm volatile(\0A \22.cfi_remember_state\\n\\t\22\0A \22.cfi_adjust_cfa_offset 16\\n\\t\22\0A \22nop\\n\\t\22\0A \22la.pcrel $t0, sym\\n\\t\22\0A \22nop\\n\\t\22\0A \22.cfi_restore_state\\n\\t\22);\0A return 0;\0A}\0A") ++!2 = !{i32 7, !"Dwarf Version", i32 5} ++!3 = !{i32 2, !"Debug Info Version", i32 3} ++!4 = !{i32 1, !"wchar_size", i32 4} ++!5 = !{i32 7, !"direct-access-external-data", i32 0} ++!6 = !{i32 7, !"frame-pointer", i32 2} ++!7 = !{!"clang"} ++!8 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !9, scopeLine: 2, spFlags: DISPFlagDefinition, unit: !0) ++!9 = !DISubroutineType(types: !10) ++!10 = !{!11} ++!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ++!12 = !DILocation(line: 3, column: 3, scope: !8) ++!13 = !{i64 34, i64 56, i64 92, i64 106, i64 134, i64 148, i64 177} ++!14 = !DILocation(line: 10, column: 3, scope: !8) +diff --git a/llvm/test/DebugInfo/LoongArch/lit.local.cfg b/llvm/test/DebugInfo/LoongArch/lit.local.cfg +new file mode 100644 +index 000000000000..77becb8eee90 +--- /dev/null ++++ b/llvm/test/DebugInfo/LoongArch/lit.local.cfg +@@ -0,0 +1,2 @@ ++if "LoongArch" not in config.root.targets: ++ config.unsupported = True +-- +2.20.1 + diff --git a/0007-Backport-LoongArch-Insert-nops-and-emit-align-reloc-when-handle-alignment-directive.patch b/0007-Backport-LoongArch-Insert-nops-and-emit-align-reloc-when-handle-alignment-directive.patch new file mode 100644 index 0000000..9d027af --- /dev/null +++ b/0007-Backport-LoongArch-Insert-nops-and-emit-align-reloc-when-handle-alignment-directive.patch @@ -0,0 +1,362 @@ +From 87f6adc2acf635a0a4c294217fb54c55eee3a06c Mon Sep 17 00:00:00 2001 +From: Jinyang He +Date: Wed, 24 Jan 2024 09:17:49 +0800 +Subject: [PATCH 08/14] [LoongArch] Insert nops and emit align reloc when + handle alignment directive (#72962) + +Refer to RISCV, we will fix up the alignment if linker relaxation +changes code size and breaks alignment. Insert enough Nops and emit +R_LARCH_ALIGN relocation type so that linker could satisfy the alignment +by removing Nops. +It does so only in sections with the SHF_EXECINSTR flag. + +In LoongArch psABI v2.30, R_LARCH_ALIGN requires symbol index. The +lowest 8 bits of addend represent alignment and the other bits of addend +represent the maximum number of bytes to emit. + +(cherry picked from commit c51ab483e6c2d991a01179584705b83fbea1940d) +Change-Id: Iba30702c9dda378acfae0b1f1134926fa838a368 +--- + llvm/lib/MC/MCExpr.cpp | 2 +- + .../MCTargetDesc/LoongArchAsmBackend.cpp | 67 ++++++++++++++++ + .../MCTargetDesc/LoongArchAsmBackend.h | 15 ++++ + .../MCTargetDesc/LoongArchFixupKinds.h | 4 +- + .../Relocations/align-non-executable.s | 27 +++++++ + .../MC/LoongArch/Relocations/relax-addsub.s | 15 +++- + .../MC/LoongArch/Relocations/relax-align.s | 79 +++++++++++++++++++ + 7 files changed, 205 insertions(+), 4 deletions(-) + create mode 100644 llvm/test/MC/LoongArch/Relocations/align-non-executable.s + create mode 100644 llvm/test/MC/LoongArch/Relocations/relax-align.s + +diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp +index a561fed11179..79808a58d81c 100644 +--- a/llvm/lib/MC/MCExpr.cpp ++++ b/llvm/lib/MC/MCExpr.cpp +@@ -711,7 +711,7 @@ static void AttemptToFoldSymbolOffsetDifference( + if (DF) { + Displacement += DF->getContents().size(); + } else if (auto *AF = dyn_cast(FI); +- AF && Layout && ++ AF && Layout && AF->hasEmitNops() && + !Asm->getBackend().shouldInsertExtraNopBytesForCodeAlign( + *AF, Count)) { + Displacement += Asm->computeFragmentSize(*Layout, *AF); +diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +index 8d82327b2e2b..8c482356402f 100644 +--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp ++++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +@@ -17,10 +17,13 @@ + #include "llvm/MC/MCAssembler.h" + #include "llvm/MC/MCContext.h" + #include "llvm/MC/MCELFObjectWriter.h" ++#include "llvm/MC/MCExpr.h" ++#include "llvm/MC/MCSection.h" + #include "llvm/MC/MCValue.h" + #include "llvm/Support/Endian.h" + #include "llvm/Support/EndianStream.h" + #include "llvm/Support/LEB128.h" ++#include "llvm/Support/MathExtras.h" + + #define DEBUG_TYPE "loongarch-asmbackend" + +@@ -177,6 +180,70 @@ void LoongArchAsmBackend::applyFixup(const MCAssembler &Asm, + } + } + ++// Linker relaxation may change code size. We have to insert Nops ++// for .align directive when linker relaxation enabled. So then Linker ++// could satisfy alignment by removing Nops. ++// The function returns the total Nops Size we need to insert. ++bool LoongArchAsmBackend::shouldInsertExtraNopBytesForCodeAlign( ++ const MCAlignFragment &AF, unsigned &Size) { ++ // Calculate Nops Size only when linker relaxation enabled. ++ if (!AF.getSubtargetInfo()->hasFeature(LoongArch::FeatureRelax)) ++ return false; ++ ++ // Ignore alignment if MaxBytesToEmit is less than the minimum Nop size. ++ const unsigned MinNopLen = 4; ++ if (AF.getMaxBytesToEmit() < MinNopLen) ++ return false; ++ Size = AF.getAlignment().value() - MinNopLen; ++ return AF.getAlignment() > MinNopLen; ++} ++ ++// We need to insert R_LARCH_ALIGN relocation type to indicate the ++// position of Nops and the total bytes of the Nops have been inserted ++// when linker relaxation enabled. ++// The function inserts fixup_loongarch_align fixup which eventually will ++// transfer to R_LARCH_ALIGN relocation type. ++// The improved R_LARCH_ALIGN requires symbol index. The lowest 8 bits of ++// addend represent alignment and the other bits of addend represent the ++// maximum number of bytes to emit. The maximum number of bytes is zero ++// means ignore the emit limit. ++bool LoongArchAsmBackend::shouldInsertFixupForCodeAlign( ++ MCAssembler &Asm, const MCAsmLayout &Layout, MCAlignFragment &AF) { ++ // Insert the fixup only when linker relaxation enabled. ++ if (!AF.getSubtargetInfo()->hasFeature(LoongArch::FeatureRelax)) ++ return false; ++ ++ // Calculate total Nops we need to insert. If there are none to insert ++ // then simply return. ++ unsigned Count; ++ if (!shouldInsertExtraNopBytesForCodeAlign(AF, Count)) ++ return false; ++ ++ MCSection *Sec = AF.getParent(); ++ MCContext &Ctx = Asm.getContext(); ++ const MCExpr *Dummy = MCConstantExpr::create(0, Ctx); ++ // Create fixup_loongarch_align fixup. ++ MCFixup Fixup = ++ MCFixup::create(0, Dummy, MCFixupKind(LoongArch::fixup_loongarch_align)); ++ const MCSymbolRefExpr *MCSym = getSecToAlignSym()[Sec]; ++ if (MCSym == nullptr) { ++ // Create a symbol and make the value of symbol is zero. ++ MCSymbol *Sym = Ctx.createNamedTempSymbol("la-relax-align"); ++ Sym->setFragment(&*Sec->getBeginSymbol()->getFragment()); ++ Asm.registerSymbol(*Sym); ++ MCSym = MCSymbolRefExpr::create(Sym, Ctx); ++ getSecToAlignSym()[Sec] = MCSym; ++ } ++ ++ uint64_t FixedValue = 0; ++ unsigned Lo = Log2_64(Count) + 1; ++ unsigned Hi = AF.getMaxBytesToEmit() >= Count ? 0 : AF.getMaxBytesToEmit(); ++ MCValue Value = MCValue::get(MCSym, nullptr, Hi << 8 | Lo); ++ Asm.getWriter().recordRelocation(Asm, Layout, &AF, Fixup, Value, FixedValue); ++ ++ return true; ++} ++ + bool LoongArchAsmBackend::shouldForceRelocation(const MCAssembler &Asm, + const MCFixup &Fixup, + const MCValue &Target) { +diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h +index 657f5ca5e731..71bbd003888a 100644 +--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h ++++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h +@@ -17,7 +17,9 @@ + #include "MCTargetDesc/LoongArchFixupKinds.h" + #include "MCTargetDesc/LoongArchMCTargetDesc.h" + #include "llvm/MC/MCAsmBackend.h" ++#include "llvm/MC/MCExpr.h" + #include "llvm/MC/MCFixupKindInfo.h" ++#include "llvm/MC/MCSection.h" + #include "llvm/MC/MCSubtargetInfo.h" + + namespace llvm { +@@ -27,6 +29,7 @@ class LoongArchAsmBackend : public MCAsmBackend { + uint8_t OSABI; + bool Is64Bit; + const MCTargetOptions &TargetOptions; ++ DenseMap SecToAlignSym; + + public: + LoongArchAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit, +@@ -45,6 +48,15 @@ public: + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override; + ++ // Return Size with extra Nop Bytes for alignment directive in code section. ++ bool shouldInsertExtraNopBytesForCodeAlign(const MCAlignFragment &AF, ++ unsigned &Size) override; ++ ++ // Insert target specific fixup type for alignment directive in code section. ++ bool shouldInsertFixupForCodeAlign(MCAssembler &Asm, ++ const MCAsmLayout &Layout, ++ MCAlignFragment &AF) override; ++ + bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target) override; + +@@ -79,6 +91,9 @@ public: + std::unique_ptr + createObjectTargetWriter() const override; + const MCTargetOptions &getTargetOptions() const { return TargetOptions; } ++ DenseMap &getSecToAlignSym() { ++ return SecToAlignSym; ++ } + }; + } // end namespace llvm + +diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h +index 178fa6e5262b..78414408f21f 100644 +--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h ++++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h +@@ -108,7 +108,9 @@ enum Fixups { + // 20-bit fixup corresponding to %gd_hi20(foo) for instruction lu12i.w. + fixup_loongarch_tls_gd_hi20, + // Generate an R_LARCH_RELAX which indicates the linker may relax here. +- fixup_loongarch_relax = FirstLiteralRelocationKind + ELF::R_LARCH_RELAX ++ fixup_loongarch_relax = FirstLiteralRelocationKind + ELF::R_LARCH_RELAX, ++ // Generate an R_LARCH_ALIGN which indicates the linker may fixup align here. ++ fixup_loongarch_align = FirstLiteralRelocationKind + ELF::R_LARCH_ALIGN, + }; + } // end namespace LoongArch + } // end namespace llvm +diff --git a/llvm/test/MC/LoongArch/Relocations/align-non-executable.s b/llvm/test/MC/LoongArch/Relocations/align-non-executable.s +new file mode 100644 +index 000000000000..47834acd9521 +--- /dev/null ++++ b/llvm/test/MC/LoongArch/Relocations/align-non-executable.s +@@ -0,0 +1,27 @@ ++## A label difference separated by an alignment directive, when the ++## referenced symbols are in a non-executable section with instructions, ++## should generate ADD/SUB relocations. ++## https://github.com/llvm/llvm-project/pull/76552 ++ ++# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s \ ++# RUN: | llvm-readobj -r - | FileCheck --check-prefixes=CHECK,RELAX %s ++# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=-relax %s \ ++# RUN: | llvm-readobj -r - | FileCheck %s ++ ++.section ".dummy", "a" ++.L1: ++ la.pcrel $t0, sym ++.p2align 3 ++.L2: ++.dword .L2 - .L1 ++ ++# CHECK: Relocations [ ++# CHECK-NEXT: Section ({{.*}}) .rela.dummy { ++# CHECK-NEXT: 0x0 R_LARCH_PCALA_HI20 sym 0x0 ++# RELAX-NEXT: 0x0 R_LARCH_RELAX - 0x0 ++# CHECK-NEXT: 0x4 R_LARCH_PCALA_LO12 sym 0x0 ++# RELAX-NEXT: 0x4 R_LARCH_RELAX - 0x0 ++# RELAX-NEXT: 0x8 R_LARCH_ADD64 .L2 0x0 ++# RELAX-NEXT: 0x8 R_LARCH_SUB64 .L1 0x0 ++# CHECK-NEXT: } ++# CHECK-NEXT: ] +diff --git a/llvm/test/MC/LoongArch/Relocations/relax-addsub.s b/llvm/test/MC/LoongArch/Relocations/relax-addsub.s +index cd01332afd0b..18e0ede5e293 100644 +--- a/llvm/test/MC/LoongArch/Relocations/relax-addsub.s ++++ b/llvm/test/MC/LoongArch/Relocations/relax-addsub.s +@@ -28,12 +28,23 @@ + + # RELAX: Relocations [ + # RELAX-NEXT: Section ({{.*}}) .rela.text { ++# RELAX-NEXT: 0x4 R_LARCH_ALIGN {{.*}} 0x4 + # RELAX-NEXT: 0x10 R_LARCH_PCALA_HI20 .L1 0x0 + # RELAX-NEXT: 0x10 R_LARCH_RELAX - 0x0 + # RELAX-NEXT: 0x14 R_LARCH_PCALA_LO12 .L1 0x0 + # RELAX-NEXT: 0x14 R_LARCH_RELAX - 0x0 + # RELAX-NEXT: } + # RELAX-NEXT: Section ({{.*}}) .rela.data { ++# RELAX-NEXT: 0x10 R_LARCH_ADD8 .L3 0x0 ++# RELAX-NEXT: 0x10 R_LARCH_SUB8 .L2 0x0 ++# RELAX-NEXT: 0x11 R_LARCH_ADD16 .L3 0x0 ++# RELAX-NEXT: 0x11 R_LARCH_SUB16 .L2 0x0 ++# RELAX-NEXT: 0x13 R_LARCH_ADD32 .L3 0x0 ++# RELAX-NEXT: 0x13 R_LARCH_SUB32 .L2 0x0 ++# RELAX-NEXT: 0x17 R_LARCH_ADD64 .L3 0x0 ++# RELAX-NEXT: 0x17 R_LARCH_SUB64 .L2 0x0 ++# RELAX-NEXT: 0x1F R_LARCH_ADD_ULEB128 .L3 0x0 ++# RELAX-NEXT: 0x1F R_LARCH_SUB_ULEB128 .L2 0x0 + # RELAX-NEXT: 0x20 R_LARCH_ADD8 .L4 0x0 + # RELAX-NEXT: 0x20 R_LARCH_SUB8 .L3 0x0 + # RELAX-NEXT: 0x21 R_LARCH_ADD16 .L4 0x0 +@@ -57,7 +68,7 @@ + + # RELAX: Hex dump of section '.data': + # RELAX-NEXT: 0x00000000 04040004 00000004 00000000 00000004 +-# RELAX-NEXT: 0x00000010 0c0c000c 0000000c 00000000 0000000c ++# RELAX-NEXT: 0x00000010 00000000 00000000 00000000 00000000 + # RELAX-NEXT: 0x00000020 00000000 00000000 00000000 00000000 + # RELAX-NEXT: 0x00000030 00000000 00000000 00000000 000000 + +@@ -78,7 +89,7 @@ + .word .L2 - .L1 + .dword .L2 - .L1 + .uleb128 .L2 - .L1 +-## TODO Handle alignment directive. ++## With relaxation, emit relocs because the .align makes the diff variable. + .byte .L3 - .L2 + .short .L3 - .L2 + .word .L3 - .L2 +diff --git a/llvm/test/MC/LoongArch/Relocations/relax-align.s b/llvm/test/MC/LoongArch/Relocations/relax-align.s +new file mode 100644 +index 000000000000..294fd9fb916c +--- /dev/null ++++ b/llvm/test/MC/LoongArch/Relocations/relax-align.s +@@ -0,0 +1,79 @@ ++## The file testing Nop insertion with R_LARCH_ALIGN for relaxation. ++ ++# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=-relax %s -o %t ++# RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=INSTR ++# RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=RELOC ++# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.r ++# RUN: llvm-objdump -d %t.r | FileCheck %s --check-prefixes=INSTR,RELAX-INSTR ++# RUN: llvm-readobj -r %t.r | FileCheck %s --check-prefixes=RELOC,RELAX-RELOC ++ ++.text ++break 0 ++# INSTR: break 0 ++ ++## Not emit R_LARCH_ALIGN if alignment directive is less than or equal to ++## minimum code alignment(a.k.a 4). ++.p2align 2 ++.p2align 1 ++.p2align 0 ++ ++## Not emit instructions if max emit bytes less than min nop size. ++.p2align 4, , 2 ++ ++## Not emit R_LARCH_ALIGN if alignment directive with specific padding value. ++## The behavior is the same as GNU assembler. ++break 1 ++.p2align 4, 1 ++# INSTR-NEXT: break 1 ++# INSTR-COUNT-2: 01 01 01 01 ++ ++break 2 ++.p2align 4, 1, 12 ++# INSTR-NEXT: break 2 ++# INSTR-COUNT-3: 01 01 01 01 ++ ++break 3 ++.p2align 4 ++# INSTR-NEXT: break 3 ++# INSTR-COUNT-3: nop ++ ++break 4 ++.p2align 5 ++.p2align 4 ++# INSTR-NEXT: break 4 ++# INSTR-COUNT-3: nop ++# RELAX-INSTR-COUNT-7: nop ++ ++break 5 ++.p2align 4, , 11 ++# INSTR-NEXT: break 5 ++# RELAX-INSTR-COUNT-3: nop ++ ++break 6 ++## Not emit the third parameter. ++.p2align 4, , 12 ++# INSTR-NEXT: break 6 ++# INSTR-NEXT: nop ++# INSTR-NEXT: nop ++# RELAX-INSTR-NEXT: nop ++ ++ret ++# INSNR-NEXT: ret ++ ++## Test the symbol index is different from .text. ++.section .text2, "ax" ++.p2align 4 ++break 7 ++ ++# RELOC: Relocations [ ++# RELAX-RELOC-NEXT: Section ({{.*}}) .rela.text { ++# RELAX-RELOC-NEXT: 0x24 R_LARCH_ALIGN .Lla-relax-align0 0x4 ++# RELAX-RELOC-NEXT: 0x34 R_LARCH_ALIGN .Lla-relax-align0 0x5 ++# RELAX-RELOC-NEXT: 0x50 R_LARCH_ALIGN .Lla-relax-align0 0x4 ++# RELAX-RELOC-NEXT: 0x60 R_LARCH_ALIGN .Lla-relax-align0 0xB04 ++# RELAX-RELOC-NEXT: 0x70 R_LARCH_ALIGN .Lla-relax-align0 0x4 ++# RELAX-RELOC-NEXT: } ++# RELAX-RELOC-NEXT: Section ({{.*}}) .rela.text2 { ++# RELAX-RELOC-NEXT: 0x0 R_LARCH_ALIGN .Lla-relax-align1 0x4 ++# RELAX-RELOC-NEXT: } ++# RELOC-NEXT: ] +-- +2.20.1 + diff --git a/0008-Backport-test-Update-dwarf-loongarch-relocs.ll.patch b/0008-Backport-test-Update-dwarf-loongarch-relocs.ll.patch new file mode 100644 index 0000000..4ed67f0 --- /dev/null +++ b/0008-Backport-test-Update-dwarf-loongarch-relocs.ll.patch @@ -0,0 +1,86 @@ +From f51ee6c3468eacc82d3b3f09fcca381178bdc9e7 Mon Sep 17 00:00:00 2001 +From: Weining Lu +Date: Wed, 24 Jan 2024 11:03:14 +0800 +Subject: [PATCH 11/14] [test] Update dwarf-loongarch-relocs.ll + +Address buildbot faiures: +http://45.33.8.238/macm1/77360/step_11.txt +http://45.33.8.238/linux/128902/step_12.txt + +(cherry picked from commit baba7e4175b6ca21e83b1cf8229f29dbba02e979) +(cherry picked from commit c9e73cdd9a17f15ede120ea57657553f9e105eab) +Change-Id: I00aa1414f556f0ba5ff6bf6a879a6fc1fcfa49e0 +--- + .../LoongArch/dwarf-loongarch-relocs.ll | 37 ++++++++++++------- + 1 file changed, 23 insertions(+), 14 deletions(-) + +diff --git a/llvm/test/DebugInfo/LoongArch/dwarf-loongarch-relocs.ll b/llvm/test/DebugInfo/LoongArch/dwarf-loongarch-relocs.ll +index e03b4c1d34de..07443a62b933 100644 +--- a/llvm/test/DebugInfo/LoongArch/dwarf-loongarch-relocs.ll ++++ b/llvm/test/DebugInfo/LoongArch/dwarf-loongarch-relocs.ll +@@ -1,19 +1,22 @@ + ; RUN: llc --filetype=obj --mtriple=loongarch64 --mattr=-relax %s -o %t.o + ; RUN: llvm-readobj -r %t.o | FileCheck --check-prefixes=RELOCS-BOTH,RELOCS-NORL %s +-; RUN: llvm-objdump --source %t.o | FileCheck --check-prefix=SOURCE %s +-; RUN: llvm-dwarfdump --debug-info --debug-line %t.o | FileCheck --check-prefix=DWARF %s ++; RUN: llvm-objdump --source %t.o | FileCheck --check-prefixes=SOURCE,SOURCE-NORL %s ++; RUN: llvm-dwarfdump --debug-info --debug-line %t.o | FileCheck --check-prefixes=DWARF,DWARF-NORL %s + + ; RUN: llc --filetype=obj --mtriple=loongarch64 --mattr=+relax %s -o %t.r.o + ; RUN: llvm-readobj -r %t.r.o | FileCheck --check-prefixes=RELOCS-BOTH,RELOCS-ENRL %s +-; RUN: llvm-objdump --source %t.r.o | FileCheck --check-prefix=SOURCE %s +-; RUN: llvm-dwarfdump --debug-info --debug-line %t.r.o | FileCheck --check-prefix=DWARF %s ++; RUN: llvm-objdump --source %t.r.o | FileCheck --check-prefixes=SOURCE,SOURCE-ENRL %s ++; RUN: llvm-dwarfdump --debug-info --debug-line %t.r.o | FileCheck --check-prefixes=DWARF,DWARF-ENRL %s + + ; RELOCS-BOTH: Relocations [ + ; RELOCS-BOTH-NEXT: Section ({{.*}}) .rela.text { +-; RELOCS-BOTH-NEXT: 0x14 R_LARCH_PCALA_HI20 sym 0x0 +-; RELOCS-ENRL-NEXT: 0x14 R_LARCH_RELAX - 0x0 +-; RELOCS-BOTH-NEXT: 0x18 R_LARCH_PCALA_LO12 sym 0x0 +-; RELOCS-ENRL-NEXT: 0x18 R_LARCH_RELAX - 0x0 ++; RELOCS-NORL-NEXT: 0x14 R_LARCH_PCALA_HI20 sym 0x0 ++; RELOCS-NORL-NEXT: 0x18 R_LARCH_PCALA_LO12 sym 0x0 ++; RELOCS-ENRL-NEXT: 0x0 R_LARCH_ALIGN .Lla-relax-align0 0x5 ++; RELOCS-ENRL-NEXT: 0x30 R_LARCH_PCALA_HI20 sym 0x0 ++; RELOCS-ENRL-NEXT: 0x30 R_LARCH_RELAX - 0x0 ++; RELOCS-ENRL-NEXT: 0x34 R_LARCH_PCALA_LO12 sym 0x0 ++; RELOCS-ENRL-NEXT: 0x34 R_LARCH_RELAX - 0x0 + ; RELOCS-BOTH-NEXT: } + ; RELOCS-BOTH: Section ({{.*}}) .rela.debug_frame { + ; RELOCS-NORL-NEXT: 0x1C R_LARCH_32 .debug_frame 0x0 +@@ -36,7 +39,8 @@ + ; RELOCS-BOTH-NEXT: } + ; RELOCS-BOTH-NEXT: ] + +-; SOURCE: 0000000000000000 : ++; SOURCE-NORL: 0000000000000000 : ++; SOURCE-ENRL: 000000000000001c : + ; SOURCE: ; { + ; SOURCE: ; asm volatile( + ; SOURCE: ; return 0; +@@ -87,11 +91,16 @@ + ; DWARF-EMPTY: + ; DWARF-NEXT: Address Line Column File ISA Discriminator OpIndex Flags + ; DWARF-NEXT: ------------------ ------ ------ ------ --- ------------- ------- ------------- +-; DWARF-NEXT: 0x0000000000000000 2 0 0 0 0 0 is_stmt +-; DWARF-NEXT: 0x0000000000000010 3 3 0 0 0 0 is_stmt prologue_end +-; DWARF-NEXT: 0x0000000000000020 10 3 0 0 0 0 is_stmt +-; DWARF-NEXT: 0x000000000000002c 10 3 0 0 0 0 epilogue_begin +-; DWARF-NEXT: 0x0000000000000034 10 3 0 0 0 0 end_sequence ++; DWARF-NORL-NEXT: 0x0000000000000000 2 0 0 0 0 0 is_stmt ++; DWARF-NORL-NEXT: 0x0000000000000010 3 3 0 0 0 0 is_stmt prologue_end ++; DWARF-NORL-NEXT: 0x0000000000000020 10 3 0 0 0 0 is_stmt ++; DWARF-NORL-NEXT: 0x000000000000002c 10 3 0 0 0 0 epilogue_begin ++; DWARF-NORL-NEXT: 0x0000000000000034 10 3 0 0 0 0 end_sequence ++; DWARF-ENRL-NEXT: 0x000000000000001c 2 0 0 0 0 0 is_stmt ++; DWARF-ENRL-NEXT: 0x000000000000002c 3 3 0 0 0 0 is_stmt prologue_end ++; DWARF-ENRL-NEXT: 0x000000000000003c 10 3 0 0 0 0 is_stmt ++; DWARF-ENRL-NEXT: 0x0000000000000048 10 3 0 0 0 0 epilogue_begin ++; DWARF-ENRL-NEXT: 0x0000000000000050 10 3 0 0 0 0 end_sequence + + ; ModuleID = 'dwarf-loongarch-relocs.c' + source_filename = "dwarf-loongarch-relocs.c" +-- +2.20.1 + diff --git a/0009-Backport-MC-test-Change-ELF-uleb-ehtable.s-Mach-O-to-use-private-symbols-in-.uleb128-for-label-differences.patch b/0009-Backport-MC-test-Change-ELF-uleb-ehtable.s-Mach-O-to-use-private-symbols-in-.uleb128-for-label-differences.patch new file mode 100644 index 0000000..94bb772 --- /dev/null +++ b/0009-Backport-MC-test-Change-ELF-uleb-ehtable.s-Mach-O-to-use-private-symbols-in-.uleb128-for-label-differences.patch @@ -0,0 +1,53 @@ +From 442b5109ccbabed1110c122c1ca92d4194ba632b Mon Sep 17 00:00:00 2001 +From: Fangrui Song +Date: Wed, 9 Aug 2023 21:42:18 -0700 +Subject: [PATCH 13/14] [MC][test] Change ELF/uleb-ehtable.s Mach-O to use + private symbols in .uleb128 for label differences + +On Mach-O, `.uleb128 A-B` where A and B are separated by a non-private symbol is invalid +(see D153167). + +(cherry picked from commit 0a89bda4a8b756a00985e0965f7686b5ceb43295) +Change-Id: I92ed11d6913b8c781e29be6e8c642cf0a371910d +--- + llvm/test/MC/ELF/uleb-ehtable.s | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/llvm/test/MC/ELF/uleb-ehtable.s b/llvm/test/MC/ELF/uleb-ehtable.s +index ca3f9e97bffc..6407223f36e7 100644 +--- a/llvm/test/MC/ELF/uleb-ehtable.s ++++ b/llvm/test/MC/ELF/uleb-ehtable.s +@@ -1,7 +1,7 @@ + // RUN: llvm-mc -filetype=obj -triple i686-pc-linux-gnu %s -o - | llvm-readobj -S --sd - | FileCheck %s -check-prefix=CHECK -check-prefix=ELF + // RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | llvm-readobj -S --sd - | FileCheck %s -check-prefix=CHECK -check-prefix=ELF +-// RUN: llvm-mc -filetype=obj -triple i386-apple-darwin9 %s -o - | llvm-readobj -S --sd - | FileCheck %s -check-prefix=CHECK -check-prefix=MACHO +-// RUN: llvm-mc -filetype=obj -triple x86_64-apple-darwin9 %s -o - | llvm-readobj -S --sd - | FileCheck %s -check-prefix=CHECK -check-prefix=MACHO ++// RUN: llvm-mc -filetype=obj -triple i386-apple-darwin9 --defsym MACHO=1 %s -o - | llvm-readobj -S --sd - | FileCheck %s -check-prefix=CHECK -check-prefix=MACHO ++// RUN: llvm-mc -filetype=obj -triple x86_64-apple-darwin9 --defsym MACHO=1 %s -o - | llvm-readobj -S --sd - | FileCheck %s -check-prefix=CHECK -check-prefix=MACHO + + // Test that we can assemble a GCC-like EH table that has 16381-16383 bytes of + // non-padding data between .ttbaseref and .ttbase. The assembler must insert +@@ -13,11 +13,20 @@ + foo: + .byte 0xff // LPStart omitted + .byte 0x1 // TType encoding (uleb128) ++.ifdef MACHO ++ .uleb128 Lttbase-Lttbaseref ++Lttbaseref: ++.else + .uleb128 .ttbase-.ttbaseref + .ttbaseref: ++.endif + .fill 128*128-1, 1, 0xcd // call site and actions tables + .balign 4 ++.ifdef MACHO ++Lttbase: ++.else + .ttbase: ++.endif + .byte 1, 2, 3, 4 + + // ELF: Name: .data +-- +2.20.1 + diff --git a/0010-Backport-Mips-MC-AttemptToFoldSymbolOffsetDifference-revert-isMicroMips-special-case.patch b/0010-Backport-Mips-MC-AttemptToFoldSymbolOffsetDifference-revert-isMicroMips-special-case.patch new file mode 100644 index 0000000..1d370ee --- /dev/null +++ b/0010-Backport-Mips-MC-AttemptToFoldSymbolOffsetDifference-revert-isMicroMips-special-case.patch @@ -0,0 +1,135 @@ +From 3b777f98a3997f338919af7ff1ef8a6fd07f76a0 Mon Sep 17 00:00:00 2001 +From: Fangrui Song +Date: Wed, 16 Aug 2023 23:11:59 -0700 +Subject: [PATCH 14/14] [Mips][MC] AttemptToFoldSymbolOffsetDifference: revert + isMicroMips special case + +D52985/D57677 added a .gcc_except_table workaround, but the new behavior +doesn't match GNU assembler. +``` +void foo(); +int bar() { + foo(); + try { throw 1; } + catch (int) { return 1; } + return 0; +} + +clang --target=mipsel-linux-gnu -mmicromips -S a.cc +mipsel-linux-gnu-gcc -mmicromips -c a.s -o gnu.o + +.uleb128 ($cst_end0)-($cst_begin0) // bit 0 is not forced to 1 +.uleb128 ($func_begin0)-($func_begin0) // bit 0 is not forced to 1 +``` + +I have inspected `.gcc_except_table` output by `mipsel-linux-gnu-gcc -mmicromips -c a.cc`. +The `.uleb128` values are not forced to set the least significant bit. + +In addition, D57677's adjustment (even->odd) to CodeGen/Mips/micromips-b-range.ll is wrong. +PC-relative `.long func - .` values will differ from GNU assembler as well. + +The original intention of D52985 seems unclear to me. I think whatever +goal it wants to achieve should be moved to an upper layer. + +This isMicroMips special case has caused problems to fix MCAssembler::relaxLEB to use evaluateAsAbsolute instead of evaluateKnownAbsolute, +which is needed to proper support R_RISCV_SET_ULEB128/R_RISCV_SUB_ULEB128. + +Differential Revision: https://reviews.llvm.org/D157655 + +(cherry picked from commit 4c89277095ee7cda3d20e0f5f18b384212069778) +Change-Id: Iedd73e0c61856c30fde442309fc16d4327829f1a +--- + llvm/lib/MC/MCExpr.cpp | 5 ----- + llvm/test/CodeGen/Mips/micromips-b-range.ll | 8 ++++---- + llvm/test/CodeGen/Mips/micromips-gcc-except-table.ll | 2 +- + llvm/test/DebugInfo/Mips/eh_frame.ll | 4 ++-- + 4 files changed, 7 insertions(+), 12 deletions(-) + +diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp +index 79808a58d81c..c9ff1865cf91 100644 +--- a/llvm/lib/MC/MCExpr.cpp ++++ b/llvm/lib/MC/MCExpr.cpp +@@ -611,11 +611,6 @@ static void AttemptToFoldSymbolOffsetDifference( + if (Asm->isThumbFunc(&SA)) + Addend |= 1; + +- // If symbol is labeled as micromips, we set low-bit to ensure +- // correct offset in .gcc_except_table +- if (Asm->getBackend().isMicroMips(&SA)) +- Addend |= 1; +- + // Clear the symbol expr pointers to indicate we have folded these + // operands. + A = B = nullptr; +diff --git a/llvm/test/CodeGen/Mips/micromips-b-range.ll b/llvm/test/CodeGen/Mips/micromips-b-range.ll +index 064afff3da0e..81d1c04208cc 100644 +--- a/llvm/test/CodeGen/Mips/micromips-b-range.ll ++++ b/llvm/test/CodeGen/Mips/micromips-b-range.ll +@@ -13,7 +13,7 @@ + ; CHECK-NEXT: 1e: fb fd 00 00 sw $ra, 0($sp) + ; CHECK-NEXT: 22: 41 a1 00 01 lui $1, 1 + ; CHECK-NEXT: 26: 40 60 00 02 bal 0x2e +-; CHECK-NEXT: 2a: 30 21 04 69 addiu $1, $1, 1129 ++; CHECK-NEXT: 2a: 30 21 04 68 addiu $1, $1, 1128 + ; CHECK-NEXT: 2e: 00 3f 09 50 addu $1, $ra, $1 + ; CHECK-NEXT: 32: ff fd 00 00 lw $ra, 0($sp) + ; CHECK-NEXT: 36: 00 01 0f 3c jr $1 +@@ -27,7 +27,7 @@ + ; CHECK-NEXT: 56: fb fd 00 00 sw $ra, 0($sp) + ; CHECK-NEXT: 5a: 41 a1 00 01 lui $1, 1 + ; CHECK-NEXT: 5e: 40 60 00 02 bal 0x66 +-; CHECK-NEXT: 62: 30 21 04 5d addiu $1, $1, 1117 ++; CHECK-NEXT: 62: 30 21 04 5c addiu $1, $1, 1116 + ; CHECK-NEXT: 66: 00 3f 09 50 addu $1, $ra, $1 + ; CHECK-NEXT: 6a: ff fd 00 00 lw $ra, 0($sp) + ; CHECK-NEXT: 6e: 00 01 0f 3c jr $1 +@@ -39,7 +39,7 @@ + ; CHECK-NEXT: 86: fb fd 00 00 sw $ra, 0($sp) + ; CHECK-NEXT: 8a: 41 a1 00 01 lui $1, 1 + ; CHECK-NEXT: 8e: 40 60 00 02 bal 0x96 +-; CHECK-NEXT: 92: 30 21 04 2d addiu $1, $1, 1069 ++; CHECK-NEXT: 92: 30 21 04 2c addiu $1, $1, 1068 + ; CHECK-NEXT: 96: 00 3f 09 50 addu $1, $ra, $1 + ; CHECK-NEXT: 9a: ff fd 00 00 lw $ra, 0($sp) + ; CHECK-NEXT: 9e: 00 01 0f 3c jr $1 +@@ -51,7 +51,7 @@ + ; CHECK-NEXT: 10476: fb fd 00 00 sw $ra, 0($sp) + ; CHECK-NEXT: 1047a: 41 a1 00 01 lui $1, 1 + ; CHECK-NEXT: 1047e: 40 60 00 02 bal 0x10486 +-; CHECK-NEXT: 10482: 30 21 04 01 addiu $1, $1, 1025 ++; CHECK-NEXT: 10482: 30 21 04 00 addiu $1, $1, 1024 + ; CHECK-NEXT: 10486: 00 3f 09 50 addu $1, $ra, $1 + ; CHECK-NEXT: 1048a: ff fd 00 00 lw $ra, 0($sp) + ; CHECK-NEXT: 1048e: 00 01 0f 3c jr $1 +diff --git a/llvm/test/CodeGen/Mips/micromips-gcc-except-table.ll b/llvm/test/CodeGen/Mips/micromips-gcc-except-table.ll +index 2b63aff01574..20d64fc216b7 100644 +--- a/llvm/test/CodeGen/Mips/micromips-gcc-except-table.ll ++++ b/llvm/test/CodeGen/Mips/micromips-gcc-except-table.ll +@@ -1,7 +1,7 @@ + ; RUN: llc -mtriple=mips-linux-gnu -mcpu=mips32r2 -mattr=+micromips -O3 -filetype=obj < %s | llvm-objdump -s -j .gcc_except_table - | FileCheck %s + + ; CHECK: Contents of section .gcc_except_table: +-; CHECK-NEXT: 0000 ff9b1501 0c011100 00110e1f 011f1800 ++; CHECK-NEXT: 0000 ff9b1501 0c001000 00100e1e 011e1800 + ; CHECK-NEXT: 0010 00010000 00000000 + + @_ZTIi = external constant ptr +diff --git a/llvm/test/DebugInfo/Mips/eh_frame.ll b/llvm/test/DebugInfo/Mips/eh_frame.ll +index 506e5b87892b..60d4dc76777e 100644 +--- a/llvm/test/DebugInfo/Mips/eh_frame.ll ++++ b/llvm/test/DebugInfo/Mips/eh_frame.ll +@@ -26,9 +26,9 @@ + ; CHECK-READELF-PIC-NEXT: R_MIPS_PC32 + ; CHECK-READELF-NEXT: .gcc_except_table + +-; EXCEPT-TABLE-STATIC: 0000 ff9b1501 0c011500 00150e23 01231e00 ...........#.#.. ++; EXCEPT-TABLE-STATIC: 0000 ff9b1501 0c001400 00140e22 01221e00 ...........".".. + ; EXCEPT-TABLE-STATIC: 0010 00010000 00000000 +-; EXCEPT-TABLE-PIC: 0000 ff9b1501 0c012d00 002d133f 013f2a00 ......-..-.?.?*. ++; EXCEPT-TABLE-PIC: 0000 ff9b1501 0c002c00 002c123e 013e2a00 ......,..,.>.>*. + ; EXCEPT-TABLE-PIC: 0010 00010000 00000000 ........ + + @_ZTIi = external constant ptr +-- +2.20.1 + diff --git a/llvm.spec b/llvm.spec index 7eb8cd1..452d614 100644 --- a/llvm.spec +++ b/llvm.spec @@ -37,7 +37,7 @@ Name: %{pkg_name} Version: %{maj_ver}.%{min_ver}.%{patch_ver} -Release: 1 +Release: 2 Summary: The Low Level Virtual Machine License: NCSA @@ -46,6 +46,18 @@ Source0: https://github.com/llvm/llvm-project/releases/download/llvmorg-%{versio Source1: https://github.com/llvm/llvm-project/releases/download/llvmorg-%{version}/cmake-%{version}.src.tar.xz Source2: https://github.com/llvm/llvm-project/releases/download/llvmorg-%{version}/third-party-%{version}.src.tar.xz +# Patch{1-10} for supporting `relax` feture on LoongArch, which is consistent with !47 in openEuler repos +Patch1: 0001-Backport-LoongArch-Add-relax-feature-and-keep-relocations.patch +Patch2: 0002-Backport-LoongArch-Allow-delayed-decision-for-ADD-SUB-relocations.patch +Patch3: 0003-Backport-LoongArch-Emit-R_LARCH_RELAX-when-expanding-some-LoadAddress.patch +Patch4: 0004-Backport-MC-LoongArch-Add-AlignFragment-size-if-layout-is-available-and-not-need-insert-nops.patch +Patch5: 0005-Backport-LoongArch-RISCV-Support-R_LARCH_-ADD-SUB-_ULEB128-R_RISCV_-SET-SUB-_ULEB128-for-uleb128-directives.patch +Patch6: 0006-Backport-LoongArch-Add-relaxDwarfLineAddr-and-relaxDwarfCFA-to-handle-the-mutable-label-diff-in-dwarfinfo.patch +Patch7: 0007-Backport-LoongArch-Insert-nops-and-emit-align-reloc-when-handle-alignment-directive.patch +Patch8: 0008-Backport-test-Update-dwarf-loongarch-relocs.ll.patch +Patch9: 0009-Backport-MC-test-Change-ELF-uleb-ehtable.s-Mach-O-to-use-private-symbols-in-.uleb128-for-label-differences.patch +Patch10: 0010-Backport-Mips-MC-AttemptToFoldSymbolOffsetDifference-revert-isMicroMips-special-case.patch + BuildRequires: binutils-devel BuildRequires: cmake BuildRequires: gcc @@ -327,6 +339,9 @@ LD_LIBRARY_PATH=%{buildroot}/%{install_libdir} %{__ninja} check-all -C ./_build %{install_includedir}/llvm-gmock %changelog +* Sat Mar 16 2024 zhanglimin - 17.0.6-2 +- Supoort `relax` feature on LoongArch + * Thu Nov 30 2023 zhoujing - 17.0.6-1 - Update to 17.0.6 -- Gitee