RISCV: permit unaligned nop-slide padding emission
authorSaleem Abdulrasool <compnerd@compnerd.org>
Tue, 23 Aug 2022 15:58:36 +0000 (15:58 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Wed, 24 Aug 2022 20:26:48 +0000 (20:26 +0000)
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

lld/test/ELF/riscv-relax-align-rvc.s
llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
llvm/test/MC/RISCV/align.s
llvm/test/MC/RISCV/nop-slide.s [new file with mode: 0644]

index 37758ed..0134b77 100644 (file)
 # 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
index a494adf..96af23d 100644 (file)
@@ -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;
 }
 
index 75ea8eb..cd9f47a 100644 (file)
@@ -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
@@ -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
diff --git a/llvm/test/MC/RISCV/nop-slide.s b/llvm/test/MC/RISCV/nop-slide.s
new file mode 100644 (file)
index 0000000..353c6f9
--- /dev/null
@@ -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