Skip to content

Commit

Permalink
RISCV: permit unaligned nop-slide padding emission
Browse files Browse the repository at this point in the history
We may be requested to emit an unaligned nop sequence (e.g. 7-bytes or
3-bytes).  These should be 0-filled even though that is not a valid
instruction.  This matches the behaviour on other architectures like
ARM, X86, and MIPS.  When a custom section is emitted, it may be
classified as text even though it may be a data section or we may be
emitting data into a text segment (e.g. a literal pool).  In such cases,
we should be resilient to the emission request.

This was originally identified by the Linux kernel build and reported on
D131270 by Nathan Chancellor.

Differential Revision: https://reviews.llvm.org/D132482
Reviewed By: luismarques
Tested By: Nathan Chancellor
  • Loading branch information
compnerd committed Aug 24, 2022
1 parent 38d58c1 commit 8f45b5a
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 11 deletions.
2 changes: 1 addition & 1 deletion lld/test/ELF/riscv-relax-align-rvc.s
Expand Up @@ -25,10 +25,10 @@
# CHECK-NEXT: c.addi a0, 1
# CHECK-EMPTY:
# CHECK-NEXT: <a>:
# CHECK-NEXT: c.nop
# CHECK-NEXT: addi zero, zero, 0
# CHECK-NEXT: addi zero, zero, 0
# CHECK-NEXT: addi zero, zero, 0
# CHECK-NEXT: c.nop
# CHECK-EMPTY:
# CHECK-NEXT: <b>:
# CHECK-NEXT: 10010: c.addi a0, 2
Expand Down
24 changes: 16 additions & 8 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
Expand Up @@ -354,20 +354,28 @@ bool RISCVAsmBackend::mayNeedRelaxation(const MCInst &Inst,

bool RISCVAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
const MCSubtargetInfo *STI) const {
bool HasStdExtC = STI->getFeatureBits()[RISCV::FeatureStdExtC];
unsigned MinNopLen = HasStdExtC ? 2 : 4;
// We mostly follow binutils' convention here: align to even boundary with a
// 0-fill padding. We emit up to 1 2-byte nop, though we use c.nop if RVC is
// enabled or 0-fill otherwise. The remainder is now padded with 4-byte nops.

// Instructions always are at even addresses. We must be in a data area or
// be unaligned due to some other reason.
if (Count % 2) {
OS.write("\0", 1);
Count -= 1;
}

if ((Count % MinNopLen) != 0)
return false;
// The canonical nop on RVC is c.nop.
if (Count % 4 == 2) {
OS.write(STI->getFeatureBits()[RISCV::FeatureStdExtC] ? "\x01\0" : "\0\0",
2);
Count -= 2;
}

// The canonical nop on RISC-V is addi x0, x0, 0.
for (; Count >= 4; Count -= 4)
OS.write("\x13\0\0\0", 4);

// The canonical nop on RVC is c.nop.
if (Count && HasStdExtC)
OS.write("\x01\0", 2);

return true;
}

Expand Down
4 changes: 2 additions & 2 deletions llvm/test/MC/RISCV/align.s
Expand Up @@ -48,8 +48,8 @@ test:
# RELAX-RELOC: R_RISCV_ALIGN - 0x4
# RELAX-INST: addi zero, zero, 0
# C-EXT-RELAX-RELOC: R_RISCV_ALIGN - 0x6
# C-EXT-RELAX-INST: addi zero, zero, 0
# C-EXT-RELAX-INST: c.nop
# C-EXT-RELAX-INST: addi zero, zero, 0
# C-EXT-NORELAX-INST: addi zero, zero, 0
add a0, a0, a1
.align 4
Expand All @@ -75,7 +75,7 @@ test:
# NORELAX-INST: addi zero, zero, 0
# C-EXT-RELAX-RELOC: R_RISCV_ALIGN - 0x6
# C-EXT-RELAX-INST: addi zero, zero, 0
# C-EXT-RELAX-INST: c.nop
# C-EXT-RELAX-INST-NOT: c.nop
# C-EXT-INST: addi zero, zero, 0
# C-EXT-INST: c.nop
add a0, a0, a1
Expand Down
27 changes: 27 additions & 0 deletions llvm/test/MC/RISCV/nop-slide.s
@@ -0,0 +1,27 @@
# 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
# RUN: llvm-mc -triple riscv64 -mattr -c,+relax -filetype obj -o - %s | llvm-objdump -d - | FileCheck %s

.balign 4
.byte 0

.balign 4
auipc a0, 0

# CHECK-RVC-NORELAX: 0000000000000000 <.text>:
# CHECK-RVC-NORELAX-NEXT: 0: 00 00 unimp
# CHECK-RVC-NORELAX-NEXT: 2: 01 00 nop
# CHECK-RVC-NORELAX-NEXT: 4: 17 05 00 00 auipc a0, 0

# CHECK-RVC-RELAX: 0000000000000000 <.text>:
# CHECK-RVC-RELAX-NEXT: 0: 01 00 nop
# CHECK-RVC-RELAX-NEXT: 2: 00 01 addi s0, sp, 128
# CHECK-RVC-RELAX-NEXT: 4: 00 17 addi s0, sp, 928
# CHECK-RVC-RELAX-NEXT: 6: 05 00 c.nop 1
# CHECK-RVC-RELAX-NEXT: 8: 00 <unknown>

# CHECK: 0000000000000000 <.text>:
# CHECK-NEXT: 0: 00 00 <unknown>
# CHECK-NEXT: 2: 00 00 <unknown>
# CHECK-NEXT: 4: 17 05 00 00 auipc a0, 0

0 comments on commit 8f45b5a

Please sign in to comment.