!84 [Backport][LoongArch] Support relax feature on LoongArch in llvm17

From: @ami-zhang 
Reviewed-by: @cf-zhao 
Signed-off-by: @cf-zhao
This commit is contained in:
openeuler-ci-bot 2024-03-25 01:47:32 +00:00 committed by Gitee
commit 78bd6c8c44
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
11 changed files with 2625 additions and 1 deletions

View File

@ -0,0 +1,178 @@
From 6f135b13769c64a6942b4b232a350b6a6207f2b2 Mon Sep 17 00:00:00 2001
From: Jinyang He <hejinyang@loongson.cn>
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<MCObjectTargetWriter>
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<MCObjectTargetWriter>
-llvm::createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit) {
- return std::make_unique<LoongArchELFObjectWriter>(OSABI, Is64Bit);
+llvm::createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit, bool Relax) {
+ return std::make_unique<LoongArchELFObjectWriter>(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<MCObjectTargetWriter>
-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

View File

@ -0,0 +1,299 @@
From 77d74b8fa071fa2695c9782e2e63e7b930895b1b Mon Sep 17 00:00:00 2001
From: Jinyang He <hejinyang@loongson.cn>
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<MCFixupKind, MCFixupKind>
+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<MCFixupKind, MCFixupKind> 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<MCObjectTargetWriter>
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<char> 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

View File

@ -0,0 +1,364 @@
From f2495d7efb79fdc82af6147f7201d9cf3c91beba Mon Sep 17 00:00:00 2001
From: Jinyang He <hejinyang@loongson.cn>
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<Inst> &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<Inst> &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<MCFixup> &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<LoongArchMCExpr>(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

View File

@ -0,0 +1,123 @@
From be6e5c566f49bee5efe3d710bdd321e15d8d95ea Mon Sep 17 00:00:00 2001
From: Jinyang He <hejinyang@loongson.cn>
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<MCAlignFragment>(FI);
+ AF && Layout &&
+ !Asm->getBackend().shouldInsertExtraNopBytesForCodeAlign(
+ *AF, Count)) {
+ Displacement += Asm->computeFragmentSize(*Layout, *AF);
} else if (auto *FF = dyn_cast<MCFillFragment>(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

View File

@ -0,0 +1,633 @@
From 8d7b71890179d32474b3a1a1c627481bd5a2327d Mon Sep 17 00:00:00 2001
From: zhanglimin <zhanglimin@loongson.cn>
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<bool, bool>
+ 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<MCLEBFragment>(Frag);
+ Fixups = LF.getFixups();
+ Contents = LF.getContents();
+ break;
+ }
case MCFragment::FT_PseudoProbe: {
MCPseudoProbeAddrFragment &PF = cast<MCPseudoProbeAddrFragment>(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<unsigned>(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<char> &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<char> 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<bool, bool> 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<MCFixupKind, MCFixupKind> 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<bool, bool> 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<bool> ULEB128Reloc(
+ "riscv-uleb128-reloc", cl::init(false), cl::Hidden,
+ cl::desc("Emit R_RISCV_SET_ULEB128/E_RISCV_SUB_ULEB128 if appropriate"));
+
std::optional<MCFixupKind> 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<bool, bool> 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<bool, bool> 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 <null> 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 <null> 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

View File

@ -0,0 +1,376 @@
From 286c92a8e78c4b67368c2f47a8e73036fdacbae2 Mon Sep 17 00:00:00 2001
From: Jinyang He <hejinyang@loongson.cn>
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<bool, bool> 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<char> &Data = DF.getContents();
+ SmallVectorImpl<MCFixup> &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<MCFixupKind, MCFixupKind> 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<uint16_t>(OS, 0, support::little);
+ }
+
+ const MCBinaryExpr &MBE = cast<MCBinaryExpr>(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<char> &Data = DF.getContents();
+ SmallVectorImpl<MCFixup> &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<MCFixupKind, MCFixupKind> FK) {
+ const MCBinaryExpr &MBE = cast<MCBinaryExpr>(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<uint8_t>(OS, 0, support::little);
+ AddFixups(1, getRelocPairForSize(8));
+ } else if (isUInt<16>(Value)) {
+ OS << uint8_t(dwarf::DW_CFA_advance_loc2);
+ support::endian::write<uint16_t>(OS, 0, support::little);
+ AddFixups(1, getRelocPairForSize(16));
+ } else if (isUInt<32>(Value)) {
+ OS << uint8_t(dwarf::DW_CFA_advance_loc4);
+ support::endian::write<uint32_t>(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<bool, bool> 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 <null> 0x0
+; RELOCS-ENRL-NEXT: 0x20 R_LARCH_64 <null> 0x0
+; RELOCS-ENRL-NEXT: 0x28 R_LARCH_ADD64 <null> 0x0
+; RELOCS-ENRL-NEXT: 0x28 R_LARCH_SUB64 <null> 0x0
+; RELOCS-ENRL-NEXT: 0x3F R_LARCH_ADD6 <null> 0x0
+; RELOCS-ENRL-NEXT: 0x3F R_LARCH_SUB6 <null> 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 <null> 0x0
+; RELOCS-ENRL-NEXT: 0x5F R_LARCH_ADD16 <null> 0x0
+; RELOCS-ENRL-NEXT: 0x5F R_LARCH_SUB16 <null> 0x0
+; RELOCS-BOTH-NEXT: }
+; RELOCS-BOTH-NEXT: ]
+
+; SOURCE: 0000000000000000 <foo>:
+; 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

View File

@ -0,0 +1,362 @@
From 87f6adc2acf635a0a4c294217fb54c55eee3a06c Mon Sep 17 00:00:00 2001
From: Jinyang He <hejinyang@loongson.cn>
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<MCAlignFragment>(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<MCSection *, const MCSymbolRefExpr *> 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<MCObjectTargetWriter>
createObjectTargetWriter() const override;
const MCTargetOptions &getTargetOptions() const { return TargetOptions; }
+ DenseMap<MCSection *, const MCSymbolRefExpr *> &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

View File

@ -0,0 +1,86 @@
From f51ee6c3468eacc82d3b3f09fcca381178bdc9e7 Mon Sep 17 00:00:00 2001
From: Weining Lu <luweining@loongson.cn>
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 <foo>:
+; SOURCE-NORL: 0000000000000000 <foo>:
+; SOURCE-ENRL: 000000000000001c <foo>:
; 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

View File

@ -0,0 +1,53 @@
From 442b5109ccbabed1110c122c1ca92d4194ba632b Mon Sep 17 00:00:00 2001
From: Fangrui Song <i@maskray.me>
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

View File

@ -0,0 +1,135 @@
From 3b777f98a3997f338919af7ff1ef8a6fd07f76a0 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i@maskray.me>
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 <foo+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 <foo+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 <foo+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 <foo+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

View File

@ -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 <zhanglimin@loongson.cn> - 17.0.6-2
- Supoort `relax` feature on LoongArch
* Thu Nov 30 2023 zhoujing <zhoujing106@huawei.com> - 17.0.6-1
- Update to 17.0.6