-
Notifications
You must be signed in to change notification settings - Fork 14.7k
MC: Refine ALIGN relocation conditions #150816
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,11 @@ static cl::opt<bool> ULEB128Reloc( | |
"riscv-uleb128-reloc", cl::init(true), cl::Hidden, | ||
cl::desc("Emit R_RISCV_SET_ULEB128/E_RISCV_SUB_ULEB128 if appropriate")); | ||
|
||
static cl::opt<bool> | ||
AlignRvc("riscv-align-rvc", cl::init(true), cl::Hidden, | ||
cl::desc("When generating R_RISCV_ALIGN, insert $alignment-2 " | ||
"bytes of NOPs even in norvc code")); | ||
Comment on lines
+35
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the intention to get rid of this once all the tests can be updated? I don't mind either way, it's just good to know for future reference. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, we can get rid of them after all the tests are updated. This might also be useful to restore the old behavior for debugging before toolchain's R_RISCV_ALIGN becomes more stable. This should hopefully be removed in one year or two. |
||
|
||
RISCVAsmBackend::RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, | ||
bool Is64Bit, const MCTargetOptions &Options) | ||
: MCAsmBackend(llvm::endianness::little), STI(STI), OSABI(OSABI), | ||
|
@@ -306,12 +311,21 @@ 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 after a linker-relaxable | ||
// instruction require a relocation, even if the STI specifies norelax. | ||
// | ||
// 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; | ||
unsigned MinNopLen = STI->hasFeature(RISCV::FeatureStdExtZca) ? 2 : 4; | ||
|
||
// Use default handling unless the alignment is larger than the nop size. | ||
const MCSubtargetInfo *STI = F.getSubtargetInfo(); | ||
unsigned MinNopLen = | ||
AlignRvc || STI->hasFeature(RISCV::FeatureStdExtZca) ? 2 : 4; | ||
if (F.getAlignment() <= MinNopLen) | ||
return false; | ||
|
||
|
@@ -321,7 +335,6 @@ bool RISCVAsmBackend::relaxAlign(MCFragment &F, unsigned &Size) { | |
MCFixup::create(0, Expr, FirstLiteralRelocationKind + ELF::R_RISCV_ALIGN); | ||
F.setVarFixups({Fixup}); | ||
F.setLinkerRelaxable(); | ||
F.getParent()->setLinkerRelaxable(); | ||
return true; | ||
} | ||
|
||
|
@@ -474,8 +487,9 @@ bool RISCVAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, | |
// TODO: emit a mapping symbol right here | ||
|
||
if (Count % 4 == 2) { | ||
// The canonical nop with Zca is c.nop. | ||
OS.write(STI->hasFeature(RISCV::FeatureStdExtZca) ? "\x01\0" : "\0\0", 2); | ||
// The canonical nop with Zca is c.nop. For .balign 4, we generate a 2-byte | ||
// c.nop even in a norvc region. | ||
OS.write("\x01\0", 2); | ||
Count -= 2; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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: 4: 00 00 01 00 .word 0x00010000 | ||
# CHECK-EMPTY: | ||
# CHECK: 8: 78 56 34 12 .word 0x12345678 | ||
# CHECK-NEXT: c: 00 00 00 00 .word 0x00000000 | ||
# CHECK: 10: auipc ra, 0x0 | ||
# CHECK-NEXT: R_RISCV_CALL_PLT foo | ||
# CHECK-NEXT: R_RISCV_RELAX *ABS* | ||
# CHECK: 18: c.nop | ||
# CHECK-NEXT: R_RISCV_ALIGN *ABS*+0x6 | ||
|
||
## Alignment directives in a lower-numbered subsection may be conservatively treated as linker-relaxable. | ||
# CHECK0: 4: 00 00 01 00 .word 0x00010000 | ||
# CHECK0-NEXT: 000000006: R_RISCV_ALIGN *ABS*+0x6 | ||
# CHECK0-NEXT: 8: 13 00 00 00 .word 0x00000013 | ||
# CHECK0: 14: auipc ra, 0x0 | ||
# CHECK0: 1c: c.nop | ||
# CHECK0-NEXT: R_RISCV_ALIGN *ABS*+0x6 | ||
|
||
.text 2 | ||
.option push | ||
.option norelax | ||
## R_RISCV_ALIGN is required even if norelax, because it is after a linker-relaxable instruction. | ||
.balign 8 | ||
l2: | ||
.word 0x12345678 | ||
.option pop | ||
|
||
.text 1 | ||
.org .+1 | ||
.org .+3 | ||
.ifdef LATE | ||
.org .+0 | ||
.endif | ||
call foo | ||
|
||
.text 0 | ||
_start: | ||
.space 6 | ||
.option push | ||
.option norelax | ||
.balign 8 | ||
l0: | ||
.word 0x12345678 | ||
.option pop |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
## To ensure ALIGN relocations in norvc code can adapt to shrinking of preceding rvc code, | ||
## we generate $alignment-2 bytes of NOPs regardless of rvc. | ||
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax %s -o %t | ||
# RUN: llvm-objdump -dr -M no-aliases %t | FileCheck %s | ||
|
||
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -riscv-align-rvc=0 %s -o %t0 | ||
# RUN: llvm-objdump -dr -M no-aliases %t0 | FileCheck %s --check-prefix=CHECK0 | ||
|
||
# CHECK: 00000000: R_RISCV_RELAX *ABS* | ||
# CHECK-NEXT: 4: 0001 <unknown> | ||
# CHECK-NEXT: 00000004: R_RISCV_ALIGN *ABS*+0x6 | ||
# CHECK-NEXT: 6: 00000013 addi zero, zero, 0x0 | ||
# CHECK-NEXT: a: 00000537 lui a0, 0x0 | ||
|
||
# CHECK0: 00000000: R_RISCV_RELAX *ABS* | ||
# CHECK0-NEXT: 4: 00000013 addi zero, zero, 0x0 | ||
# CHECK0-NEXT: 00000004: R_RISCV_ALIGN *ABS*+0x4 | ||
# CHECK0-NEXT: 8: 00000537 lui a0, 0x0 | ||
|
||
lui a0, %hi(foo) | ||
.option norvc | ||
.balign 8 | ||
lui a0, %hi(foo) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: I made minimum changes to keep LoongArch tests passing but I do not intend to apply the ALIGN optimization (first behavior in the description).
Up to a LoongArch contributor to replace
if (!F.getSubtargetInfo()->hasFeature(LoongArch::FeatureRelax))
withif (F.getLayoutOrder() <= Sec->firstLinkerRelaxable())
and a few tests @SixWeining @MQ-mengqingNote: The RISC-V alignment tests are poorly organized, so please avoid following their example. You can create a more effective structure within the LoongArch/Relocations directory.