[llvm] MC: Refine ALIGN relocation conditions (PR #150816)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 1 23:34:39 PDT 2025
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/150816
>From 774df86e74ec6b4379c5431b5b19c8b084d86e73 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sat, 26 Jul 2025 23:00:59 -0700
Subject: [PATCH 1/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?=
=?UTF-8?q?itial=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.5-bogner
---
llvm/include/llvm/MC/MCSection.h | 13 ++---
llvm/lib/MC/MCObjectStreamer.cpp | 4 +-
llvm/lib/MC/MCSection.cpp | 2 +-
.../MCTargetDesc/LoongArchAsmBackend.cpp | 3 +-
.../RISCV/MCTargetDesc/RISCVAsmBackend.cpp | 19 +++++--
.../MC/RISCV/Relocations/align-after-relax.s | 50 +++++++++++++++++++
llvm/test/MC/RISCV/align-option-relax.s | 23 +++++++--
llvm/test/MC/RISCV/align.s | 35 +++++--------
llvm/test/MC/RISCV/cfi-advance.s | 28 ++++++-----
llvm/test/MC/RISCV/nop-slide.s | 19 +++----
10 files changed, 129 insertions(+), 67 deletions(-)
create mode 100644 llvm/test/MC/RISCV/Relocations/align-after-relax.s
diff --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h
index 7989310e5a8f2..f70ed4ade23f2 100644
--- a/llvm/include/llvm/MC/MCSection.h
+++ b/llvm/include/llvm/MC/MCSection.h
@@ -567,6 +567,10 @@ class LLVM_ABI MCSection {
Align Alignment;
/// The section index in the assemblers section list.
unsigned Ordinal = 0;
+ // If not -1u, the first linker-relaxable fragment's order within the
+ // subsection. When present, the offset between two locations crossing this
+ // fragment may not be fully resolved.
+ unsigned FirstLinkerRelaxable = -1u;
/// Whether this section has had instructions emitted into it.
bool HasInstructions : 1;
@@ -576,10 +580,6 @@ class LLVM_ABI MCSection {
bool IsText : 1;
bool IsBss : 1;
- /// Whether the section contains linker-relaxable fragments. If true, the
- /// offset between two locations may not be fully resolved.
- bool LinkerRelaxable : 1;
-
MCFragment DummyFragment;
// Mapping from subsection number to fragment list. At layout time, the
@@ -634,8 +634,9 @@ class LLVM_ABI MCSection {
bool isRegistered() const { return IsRegistered; }
void setIsRegistered(bool Value) { IsRegistered = Value; }
- bool isLinkerRelaxable() const { return LinkerRelaxable; }
- void setLinkerRelaxable() { LinkerRelaxable = true; }
+ unsigned firstLinkerRelaxable() const { return FirstLinkerRelaxable; }
+ bool isLinkerRelaxable() const { return FirstLinkerRelaxable != -1u; }
+ void setFirstLinkerRelaxable(unsigned Order) { FirstLinkerRelaxable = Order; }
MCFragment &getDummyFragment() { return DummyFragment; }
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index f0465521c1433..6c66031e7dfb3 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -361,7 +361,9 @@ void MCObjectStreamer::emitInstToData(const MCInst &Inst,
// instruction cannot be resolved at assemble-time.
if (!MarkedLinkerRelaxable) {
MarkedLinkerRelaxable = true;
- getCurrentSectionOnly()->setLinkerRelaxable();
+ auto *Sec = getCurrentSectionOnly();
+ if (!Sec->isLinkerRelaxable())
+ Sec->setFirstLinkerRelaxable(F->getLayoutOrder());
newFragment();
}
}
diff --git a/llvm/lib/MC/MCSection.cpp b/llvm/lib/MC/MCSection.cpp
index 4f282672afbbf..eafd59a2478e9 100644
--- a/llvm/lib/MC/MCSection.cpp
+++ b/llvm/lib/MC/MCSection.cpp
@@ -20,7 +20,7 @@ using namespace llvm;
MCSection::MCSection(StringRef Name, bool IsText, bool IsBss, MCSymbol *Begin)
: Begin(Begin), HasInstructions(false), IsRegistered(false), IsText(IsText),
- IsBss(IsBss), LinkerRelaxable(false), Name(Name) {
+ IsBss(IsBss), Name(Name) {
DummyFragment.setParent(this);
}
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
index d9ea88cdeaf24..6110920b3760e 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
@@ -255,7 +255,8 @@ bool LoongArchAsmBackend::relaxAlign(MCFragment &F, unsigned &Size) {
MCFixup::create(0, Expr, FirstLiteralRelocationKind + ELF::R_LARCH_ALIGN);
F.setVarFixups({Fixup});
F.setLinkerRelaxable();
- F.getParent()->setLinkerRelaxable();
+ if (!F.getParent()->isLinkerRelaxable())
+ F.getParent()->setFirstLinkerRelaxable(F.getLayoutOrder());
return true;
}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index 82e3b5ceb4ef6..2d9ffc69ccc2f 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -306,11 +306,19 @@ void RISCVAsmBackend::relaxInstruction(MCInst &Inst,
// If conditions are met, compute the padding size and create a fixup encoding
// the padding size in the addend.
bool RISCVAsmBackend::relaxAlign(MCFragment &F, unsigned &Size) {
- // Use default handling unless linker relaxation is enabled and the alignment
- // is larger than the nop size.
- const MCSubtargetInfo *STI = F.getSubtargetInfo();
- if (!STI->hasFeature(RISCV::FeatureRelax))
+ // Alignments before the first linker-relaxable instruction have fixed sizes
+ // and do not require relocations. Alignments following a linker-relaxable
+ // instruction require a relocation, even if the STI specifies norelax.
+ //
+ // firstLinkerRelaxable represents the layout order within the subsection,
+ // which may be smaller than the section's order. Therefore, alignments in
+ // an earlier subsection may be unnecessarily treated as linker-relaxable.
+ auto *Sec = F.getParent();
+ if (F.getLayoutOrder() <= Sec->firstLinkerRelaxable())
return false;
+
+ // Use default handling unless the alignment is larger than the nop size.
+ const MCSubtargetInfo *STI = F.getSubtargetInfo();
unsigned MinNopLen = STI->hasFeature(RISCV::FeatureStdExtZca) ? 2 : 4;
if (F.getAlignment() <= MinNopLen)
return false;
@@ -321,7 +329,8 @@ bool RISCVAsmBackend::relaxAlign(MCFragment &F, unsigned &Size) {
MCFixup::create(0, Expr, FirstLiteralRelocationKind + ELF::R_RISCV_ALIGN);
F.setVarFixups({Fixup});
F.setLinkerRelaxable();
- F.getParent()->setLinkerRelaxable();
+ if (!Sec->isLinkerRelaxable())
+ Sec->setFirstLinkerRelaxable(F.getLayoutOrder());
return true;
}
diff --git a/llvm/test/MC/RISCV/Relocations/align-after-relax.s b/llvm/test/MC/RISCV/Relocations/align-after-relax.s
new file mode 100644
index 0000000000000..cb22e0245e286
--- /dev/null
+++ b/llvm/test/MC/RISCV/Relocations/align-after-relax.s
@@ -0,0 +1,50 @@
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+c,+relax %s --defsym LATE=1 -o %t1
+# RUN: llvm-objdump -dr --no-show-raw-insn -M no-aliases %t1 | FileCheck %s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+c,+relax %s -o %t0
+# RUN: llvm-objdump -dr --no-show-raw-insn -M no-aliases %t0 | FileCheck %s --check-prefix=CHECK0
+
+# CHECK: 6: c.nop
+# CHECK-EMPTY:
+# CHECK: 10: auipc ra, 0x0
+# CHECK-NEXT: R_RISCV_CALL_PLT foo
+# CHECK-NEXT: R_RISCV_RELAX *ABS*
+# CHECK: 20: c.nop
+# CHECK-NEXT: R_RISCV_ALIGN *ABS*+0x6
+
+## Alignment directives in a smaller-number subsection might be conservatively treated as linker-relaxable.
+# CHECK0: 6: c.nop
+# CHECK0-NEXT: R_RISCV_ALIGN *ABS*+0x6
+# CHECK0: 20: c.nop
+# CHECK0-NEXT: R_RISCV_ALIGN *ABS*+0x6
+
+.text 2
+.option push
+.option norelax
+## R_RISCV_ALIGN is required even if norelax, because there is a preceding linker-relaxable instruction.
+.balign 8
+l2:
+ .word 0x12345678
+.option pop
+
+.text 1
+ .space 4
+.ifdef LATE
+ .space 0
+.endif
+ call foo
+.ifdef LATE
+ .space 8
+.else
+ .space 4
+.endif
+
+.text 0
+_start:
+ .space 6
+.option push
+.option norelax
+.balign 8
+l0:
+ .word 0x12345678
+.option pop
diff --git a/llvm/test/MC/RISCV/align-option-relax.s b/llvm/test/MC/RISCV/align-option-relax.s
index 890e1e72d7706..60cd55f5a8b4d 100644
--- a/llvm/test/MC/RISCV/align-option-relax.s
+++ b/llvm/test/MC/RISCV/align-option-relax.s
@@ -1,8 +1,21 @@
# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=-relax < %s \
# RUN: | llvm-readobj -r - | FileCheck %s
-# Check that .option relax overrides -mno-relax and enables R_RISCV_ALIGN
-# relocations.
-# CHECK: R_RISCV_ALIGN
- .option relax
- .align 4
+## .option relax overrides -mno-relax and enables R_RISCV_ALIGN/R_RISCV_RELAX relocations.
+# CHECK: .rela.text
+# CHECK: R_RISCV_CALL_PLT
+# CHECK-NEXT: R_RISCV_RELAX
+# CHECK-NEXT: R_RISCV_ALIGN
+.option relax
+call foo
+.align 4
+
+## Alignments before the first linker-relaxable instruction do not need relocations.
+# CHECK-NOT: .rela.text1
+.section .text1,"ax"
+.align 4
+nop
+
+# CHECK: .rela.text2
+.section .text2,"ax"
+call foo
diff --git a/llvm/test/MC/RISCV/align.s b/llvm/test/MC/RISCV/align.s
index da3b1aa9b637a..ab317f079dbcd 100644
--- a/llvm/test/MC/RISCV/align.s
+++ b/llvm/test/MC/RISCV/align.s
@@ -46,16 +46,17 @@
# type for .align N directive when linker relaxation enabled.
# Linker could satisfy alignment by removing NOPs after linker relaxation.
-# The first R_RISCV_ALIGN come from
-# MCELFStreamer::InitSections() emitCodeAlignment(getTextSectionAligntment()).
-# C-OR-ZCA-EXT-RELAX-RELOC: R_RISCV_ALIGN - 0x2
-# C-OR-ZCA-EXT-RELAX-INST: c.nop
test:
+## Start with a linker-relaxable instruction so that the following alignment can be relaxable.
+ call foo
+# NORELAX-RELOC: R_RISCV_CALL_PLT
+# C-OR-ZCA-EXT-NORELAX-RELOC: R_RISCV_CALL_PLT
+
.p2align 2
# If the +c extension is enabled, the text section will be 2-byte aligned, so
# one c.nop instruction is sufficient.
-# C-OR-ZCA-EXT-RELAX-RELOC-NOT: R_RISCV_ALIGN - 0x2
-# C-OR-ZCA-EXT-RELAX-INST-NOT: c.nop
+# C-OR-ZCA-EXT-RELAX-RELOC: R_RISCV_ALIGN - 0x2
+# C-OR-ZCA-EXT-RELAX-INST: c.nop
bne zero, a0, .LBB0_2
mv a0, zero
.p2align 3
@@ -136,16 +137,8 @@ data2:
add a0, a0, a1
## Branches crossing the linker-relaxable R_RISCV_ALIGN need relocations.
-# RELAX-RELOC: .rela.text3 {
-# RELAX-RELOC-NEXT: 0x4 R_RISCV_BRANCH .Ltmp[[#]] 0x0
-# RELAX-RELOC-NEXT: 0x8 R_RISCV_ALIGN - 0x4
-# RELAX-RELOC-NEXT: 0xC R_RISCV_BRANCH .Ltmp[[#]] 0x0
-# RELAX-RELOC-NEXT: }
-# C-OR-ZCA-EXT-RELAX-RELOC: .rela.text3 {
-# C-OR-ZCA-EXT-RELAX-RELOC-NEXT: 0x4 R_RISCV_BRANCH .Ltmp[[#]] 0x0
-# C-OR-ZCA-EXT-RELAX-RELOC-NEXT: 0x8 R_RISCV_ALIGN - 0x4
-# C-OR-ZCA-EXT-RELAX-RELOC-NEXT: 0xC R_RISCV_BRANCH .Ltmp[[#]] 0x0
-# C-OR-ZCA-EXT-RELAX-RELOC-NEXT: }
+# RELAX-RELOC-NOT: .rela.text3 {
+# C-OR-ZCA-EXT-RELAX-RELOC-NOT: .rela.text3 {
.section .text3, "ax"
bnez t1, 1f
bnez t2, 2f
@@ -157,7 +150,6 @@ data2:
## .text3 with a call at the start
# NORELAX-RELOC: .rela.text3a
-# C-OR-ZCA-EXT-NORELAX-RELOC: .rela.text3a
# RELAX-RELOC: .rela.text3a {
# RELAX-RELOC-NEXT: 0x0 R_RISCV_CALL_PLT foo 0x0
# RELAX-RELOC-NEXT: 0x0 R_RISCV_RELAX - 0x0
@@ -165,6 +157,8 @@ data2:
# RELAX-RELOC-NEXT: 0x10 R_RISCV_ALIGN - 0x4
# RELAX-RELOC-NEXT: 0x14 R_RISCV_BRANCH .Ltmp[[#]] 0x0
# RELAX-RELOC-NEXT: }
+# C-OR-ZCA-EXT-NORELAX-RELOC: .rela.text3a
+# C-OR-ZCA-EXT-RELAX-RELOC: .rela.text3a
.section .text3a, "ax"
call foo
bnez t1, 1f
@@ -177,11 +171,8 @@ bnez t1, 2b
## .text3 with a call at the end
# RELAX-RELOC: .rela.text3b {
-# RELAX-RELOC-NEXT: 0x4 R_RISCV_BRANCH .Ltmp[[#]] 0x0
-# RELAX-RELOC-NEXT: 0x8 R_RISCV_ALIGN - 0x4
-# RELAX-RELOC-NEXT: 0xC R_RISCV_BRANCH .Ltmp[[#]] 0x0
-# RELAX-RELOC-NEXT: 0x14 R_RISCV_CALL_PLT foo 0x0
-# RELAX-RELOC-NEXT: 0x14 R_RISCV_RELAX - 0x0
+# RELAX-RELOC-NEXT: 0x10 R_RISCV_CALL_PLT foo 0x0
+# RELAX-RELOC-NEXT: 0x10 R_RISCV_RELAX - 0x0
# RELAX-RELOC-NEXT: }
.section .text3b, "ax"
bnez t1, 1f
diff --git a/llvm/test/MC/RISCV/cfi-advance.s b/llvm/test/MC/RISCV/cfi-advance.s
index f3f8530c419f0..bad2ef07235e5 100644
--- a/llvm/test/MC/RISCV/cfi-advance.s
+++ b/llvm/test/MC/RISCV/cfi-advance.s
@@ -7,7 +7,7 @@
# NORELAX: Relocation section '.rela.text1' at offset {{.*}} contains 1 entries:
# NORELAX-NEXT: Offset Info Type Sym. Value Symbol's Name + Addend
-# NORELAX-NEXT: 00000000 00000313 R_RISCV_CALL_PLT 00000004 .L0 + 0
+# NORELAX-NEXT: 00000000 00000313 R_RISCV_CALL_PLT 00000008 .L0 + 0
# NORELAX-EMPTY:
# RELAX: Relocation section '.rela.text1' at offset {{.*}} contains 2 entries:
# RELAX: R_RISCV_CALL_PLT
@@ -16,23 +16,25 @@
# NORELAX-NEXT: Relocation section '.rela.eh_frame' at offset {{.*}} contains 1 entries:
# NORELAX: Offset Info Type Sym. Value Symbol's Name + Addend
# NORELAX-NEXT: 0000001c 00000139 R_RISCV_32_PCREL 00000000 .L0 + 0
-# RELAX-NEXT: Relocation section '.rela.eh_frame' at offset {{.*}} contains 5 entries:
+# RELAX-NEXT: Relocation section '.rela.eh_frame' at offset {{.*}} contains 7 entries:
# RELAX: Offset Info Type Sym. Value Symbol's Name + Addend
# RELAX-NEXT: 0000001c 00000139 R_RISCV_32_PCREL 00000000 .L0 + 0
-# RELAX-NEXT: 00000020 00000c23 R_RISCV_ADD32 0001017a .L0 + 0
+# RELAX-NEXT: 00000020 00000d23 R_RISCV_ADD32 0001017a .L0 + 0
# RELAX-NEXT: 00000020 00000127 R_RISCV_SUB32 00000000 .L0 + 0
-# RELAX-NEXT: 00000035 00000b35 R_RISCV_SET6 00010176 .L0 + 0
-# RELAX-NEXT: 00000035 00000934 R_RISCV_SUB6 0001016e .L0 + 0
+# RELAX-NEXT: 00000026 00000536 R_RISCV_SET8 00000068 .L0 + 0
+# RELAX-NEXT: 00000026 00000125 R_RISCV_SUB8 00000000 .L0 + 0
+# RELAX-NEXT: 00000035 00000c35 R_RISCV_SET6 00010176 .L0 + 0
+# RELAX-NEXT: 00000035 00000a34 R_RISCV_SUB6 0001016e .L0 + 0
# CHECK-EMPTY:
-# NORELAX: Symbol table '.symtab' contains 13 entries:
-# RELAX: Symbol table '.symtab' contains 16 entries:
+# NORELAX: Symbol table '.symtab' contains 14 entries:
+# RELAX: Symbol table '.symtab' contains 18 entries:
# RELAX-NEXT: Num: Value Size Type Bind Vis Ndx Name
# RELAX-NEXT: 0: 00000000 0 NOTYPE LOCAL DEFAULT UND
# RELAX-NEXT: 1: 00000000 0 NOTYPE LOCAL DEFAULT 2 .L0 {{$}}
-# RELAX: 3: 00000004 0 NOTYPE LOCAL DEFAULT 2 .L0{{$}}
-# RELAX: 9: 0001016e 0 NOTYPE LOCAL DEFAULT 2 .L0 {{$}}
-# RELAX: 11: 00010176 0 NOTYPE LOCAL DEFAULT 2 .L0 {{$}}
-# RELAX: 12: 0001017a 0 NOTYPE LOCAL DEFAULT 2 .L0 {{$}}
+# RELAX: 3: 00000008 0 NOTYPE LOCAL DEFAULT 2 .L0{{$}}
+# RELAX: 10: 0001016e 0 NOTYPE LOCAL DEFAULT 2 .L0 {{$}}
+# RELAX: 12: 00010176 0 NOTYPE LOCAL DEFAULT 2 .L0 {{$}}
+# RELAX: 13: 0001017a 0 NOTYPE LOCAL DEFAULT 2 .L0 {{$}}
# CHECK-DWARFDUMP: DW_CFA_advance_loc1: 104
# CHECK-DWARFDUMP-NEXT: DW_CFA_def_cfa_offset: +8
@@ -48,11 +50,11 @@
.type test, at function
test:
.cfi_startproc
- nop
+ call foo
## This looks similar to fake label names ".L0 ". Even if this is ".L0 ",
## the assembler will not conflate it with fake labels.
.L0:
- .zero 100, 0x90
+ .zero 96, 0x90
.cfi_def_cfa_offset 8
nop
.zero 255, 0x90
diff --git a/llvm/test/MC/RISCV/nop-slide.s b/llvm/test/MC/RISCV/nop-slide.s
index 4dc888b3ba777..9ce2e59f31b08 100644
--- a/llvm/test/MC/RISCV/nop-slide.s
+++ b/llvm/test/MC/RISCV/nop-slide.s
@@ -1,5 +1,5 @@
-# RUN: llvm-mc -triple riscv64 -mattr +c,-relax -filetype obj -o - %s | llvm-objdump -d - | FileCheck %s -check-prefix CHECK-RVC-NORELAX
-# RUN: llvm-mc -triple riscv64 -mattr +c,+relax -filetype obj -o - %s | llvm-objdump -d - | FileCheck %s -check-prefix CHECK-RVC-RELAX
+# RUN: llvm-mc -triple riscv64 -mattr +c,-relax -filetype obj -o - %s | llvm-objdump -d - | FileCheck %s -check-prefix CHECK-RVC
+# RUN: llvm-mc -triple riscv64 -mattr +c,+relax -filetype obj -o - %s | llvm-objdump -d - | FileCheck %s -check-prefix CHECK-RVC
# RUN: llvm-mc -triple riscv64 -mattr -c,-relax -filetype obj -o - %s | llvm-objdump -d - | FileCheck %s
# RUN: llvm-mc -triple riscv64 -mattr -c,+relax -filetype obj -o - %s | llvm-objdump -d - | FileCheck %s
@@ -9,17 +9,10 @@
.balign 4
auipc a0, 0
-# CHECK-RVC-NORELAX: 0000000000000000 <.text>:
-# CHECK-RVC-NORELAX-NEXT: 0: 0000 unimp
-# CHECK-RVC-NORELAX-NEXT: 2: 0001 nop
-# CHECK-RVC-NORELAX-NEXT: 4: 00000517 auipc a0, 0x0
-
-# CHECK-RVC-RELAX: 0000000000000000 <.text>:
-# CHECK-RVC-RELAX-NEXT: 0: 0001 nop
-# CHECK-RVC-RELAX-NEXT: 2: 0100 addi s0, sp, 0x80
-# CHECK-RVC-RELAX-NEXT: 4: 1700 addi s0, sp, 0x3a0
-# CHECK-RVC-RELAX-NEXT: 6: 0005 c.nop 0x1
-# CHECK-RVC-RELAX-NEXT: 8: 00 <unknown>
+# CHECK-RVC: 0000000000000000 <.text>:
+# CHECK-RVC-NEXT: 0: 0000 unimp
+# CHECK-RVC-NEXT: 2: 0001 nop
+# CHECK-RVC-NEXT: 4: 00000517 auipc a0, 0x0
# CHECK: 0000000000000000 <.text>:
# CHECK-NEXT: 0: 0000 <unknown>
>From 5572e677c5dcfc3c4a2875ab45979a3582f018b7 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sat, 26 Jul 2025 23:45:07 -0700
Subject: [PATCH 2/2] comments
Created using spr 1.3.5-bogner
---
llvm/lib/MC/MCObjectStreamer.cpp | 26 +++++++++----------
.../RISCV/MCTargetDesc/RISCVAsmBackend.cpp | 10 +++----
.../MC/RISCV/Relocations/align-after-relax.s | 4 +--
3 files changed, 19 insertions(+), 21 deletions(-)
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index 6c66031e7dfb3..d2e37ef766d43 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -340,33 +340,33 @@ void MCObjectStreamer::emitInstToData(const MCInst &Inst,
MCFragment *F = getCurrentFragment();
// Append the instruction to the data fragment.
- size_t FixupStartIndex = F->getFixups().size();
size_t CodeOffset = F->getContents().size();
SmallVector<MCFixup, 1> Fixups;
getAssembler().getEmitter().encodeInstruction(
Inst, F->getContentsForAppending(), Fixups, STI);
F->doneAppending();
- if (!Fixups.empty())
- F->appendFixups(Fixups);
F->setHasInstructions(STI);
+ if (Fixups.empty())
+ return;
bool MarkedLinkerRelaxable = false;
- for (auto &Fixup : MutableArrayRef(F->getFixups()).slice(FixupStartIndex)) {
+ for (auto &Fixup : Fixups) {
Fixup.setOffset(Fixup.getOffset() + CodeOffset);
- if (!Fixup.isLinkerRelaxable())
+ if (!Fixup.isLinkerRelaxable() || MarkedLinkerRelaxable)
continue;
- F->setLinkerRelaxable();
+ MarkedLinkerRelaxable = true;
+ // Set the fragment's order within the subsection for use by
+ // MCAssembler::relaxAlign.
+ auto *Sec = F->getParent();
+ if (!Sec->isLinkerRelaxable())
+ Sec->setFirstLinkerRelaxable(F->getLayoutOrder());
// Do not add data after a linker-relaxable instruction. The difference
// between a new label and a label at or before the linker-relaxable
// instruction cannot be resolved at assemble-time.
- if (!MarkedLinkerRelaxable) {
- MarkedLinkerRelaxable = true;
- auto *Sec = getCurrentSectionOnly();
- if (!Sec->isLinkerRelaxable())
- Sec->setFirstLinkerRelaxable(F->getLayoutOrder());
- newFragment();
- }
+ F->setLinkerRelaxable();
+ newFragment();
}
+ F->appendFixups(Fixups);
}
void MCObjectStreamer::emitInstToFragment(const MCInst &Inst,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index 2d9ffc69ccc2f..c99a9e722473a 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -307,12 +307,12 @@ void RISCVAsmBackend::relaxInstruction(MCInst &Inst,
// the padding size in the addend.
bool RISCVAsmBackend::relaxAlign(MCFragment &F, unsigned &Size) {
// Alignments before the first linker-relaxable instruction have fixed sizes
- // and do not require relocations. Alignments following a linker-relaxable
+ // and do not require relocations. Alignments after a linker-relaxable
// instruction require a relocation, even if the STI specifies norelax.
//
- // firstLinkerRelaxable represents the layout order within the subsection,
- // which may be smaller than the section's order. Therefore, alignments in
- // an earlier subsection may be unnecessarily treated as linker-relaxable.
+ // firstLinkerRelaxable is the layout order within the subsection, which may
+ // be smaller than the section's order. Therefore, alignments in a
+ // lower-numbered subsection may be unnecessarily treated as linker-relaxable.
auto *Sec = F.getParent();
if (F.getLayoutOrder() <= Sec->firstLinkerRelaxable())
return false;
@@ -329,8 +329,6 @@ bool RISCVAsmBackend::relaxAlign(MCFragment &F, unsigned &Size) {
MCFixup::create(0, Expr, FirstLiteralRelocationKind + ELF::R_RISCV_ALIGN);
F.setVarFixups({Fixup});
F.setLinkerRelaxable();
- if (!Sec->isLinkerRelaxable())
- Sec->setFirstLinkerRelaxable(F.getLayoutOrder());
return true;
}
diff --git a/llvm/test/MC/RISCV/Relocations/align-after-relax.s b/llvm/test/MC/RISCV/Relocations/align-after-relax.s
index cb22e0245e286..e21bf02b24e24 100644
--- a/llvm/test/MC/RISCV/Relocations/align-after-relax.s
+++ b/llvm/test/MC/RISCV/Relocations/align-after-relax.s
@@ -12,7 +12,7 @@
# CHECK: 20: c.nop
# CHECK-NEXT: R_RISCV_ALIGN *ABS*+0x6
-## Alignment directives in a smaller-number subsection might be conservatively treated as linker-relaxable.
+## Alignment directives in a lower-numbered subsection may be conservatively treated as linker-relaxable.
# CHECK0: 6: c.nop
# CHECK0-NEXT: R_RISCV_ALIGN *ABS*+0x6
# CHECK0: 20: c.nop
@@ -21,7 +21,7 @@
.text 2
.option push
.option norelax
-## R_RISCV_ALIGN is required even if norelax, because there is a preceding linker-relaxable instruction.
+## R_RISCV_ALIGN is required even if norelax, because it is after a linker-relaxable instruction.
.balign 8
l2:
.word 0x12345678
More information about the llvm-commits
mailing list