[lld] r340832 - [PPC64] Fix DQ-form instruction handling and emit error for misalignment.

Sean Fertile via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 28 08:16:01 PDT 2018


Author: sfertile
Date: Tue Aug 28 08:16:01 2018
New Revision: 340832

URL: http://llvm.org/viewvc/llvm-project?rev=340832&view=rev
Log:
[PPC64] Fix DQ-form instruction handling and emit error for misalignment.

Relanding r340564, original commit message:

Fixes the handling of *_DS relocations used on DQ-form instructions where we
were overwriting some of the extended opcode bits. Also adds an alignment check
so that the user will receive a diagnostic error if the value we are writing
is not properly aligned.

Differential Revision: https://reviews.llvm.org/D51124

Added:
    lld/trunk/test/ELF/ppc64-dq.s
    lld/trunk/test/ELF/ppc64-error-missaligned-dq.s
    lld/trunk/test/ELF/ppc64-error-missaligned-ds.s
Modified:
    lld/trunk/ELF/Arch/PPC64.cpp

Modified: lld/trunk/ELF/Arch/PPC64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/PPC64.cpp?rev=340832&r1=340831&r2=340832&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/PPC64.cpp (original)
+++ lld/trunk/ELF/Arch/PPC64.cpp Tue Aug 28 08:16:01 2018
@@ -98,6 +98,24 @@ static uint16_t highera(uint64_t V) { re
 static uint16_t highest(uint64_t V) { return V >> 48; }
 static uint16_t highesta(uint64_t V) { return (V + 0x8000) >> 48; }
 
+// Extracts the 'PO' field of an instruction encoding.
+static uint8_t getPrimaryOpCode(uint32_t Encoding) { return (Encoding >> 26); }
+
+static bool isDQFormInstruction(uint32_t Encoding) {
+  switch (getPrimaryOpCode(Encoding)) {
+  default:
+    return false;
+  case 56:
+    // The only instruction with a primary opcode of 56 is `lq`.
+    return true;
+  case 61:
+    // There are both DS and DQ instruction forms with this primary opcode.
+    // Namely `lxv` and `stxv` are the DQ-forms that use it.
+    // The DS 'XO' bits being set to 01 is restricted to DQ form.
+    return (Encoding & 3) == 0x1;
+  }
+}
+
 PPC64::PPC64() {
   GotRel = R_PPC64_GLOB_DAT;
   PltRel = R_PPC64_JMP_SLOT;
@@ -298,7 +316,7 @@ void PPC64::relaxTlsIeToLe(uint8_t *Loc,
     break;
   }
   case R_PPC64_TLS: {
-    uint32_t PrimaryOp = (read32(Loc) & 0xFC000000) >> 26; // bits 0-5
+    uint32_t PrimaryOp = getPrimaryOpCode(read32(Loc));
     if (PrimaryOp != 31)
       error("unrecognized instruction for IE to LE R_PPC64_TLS");
     uint32_t SecondaryOp = (read32(Loc) & 0x000007FE) >> 1; // bits 21-30
@@ -506,10 +524,15 @@ void PPC64::relocateOne(uint8_t *Loc, Re
     write16(Loc, Val);
     break;
   case R_PPC64_ADDR16_DS:
-  case R_PPC64_TPREL16_DS:
+  case R_PPC64_TPREL16_DS: {
     checkInt(Loc, Val, 16, Type);
-    write16(Loc, (read16(Loc) & 3) | (Val & ~3));
-    break;
+    // DQ-form instructions use bits 28-31 as part of the instruction encoding
+    // DS-form instructions only use bits 30-31.
+    uint32_t EndianOffset = Config->EKind == ELF64BEKind ? 2U : 0U;
+    uint16_t Mask = isDQFormInstruction(read32(Loc - EndianOffset)) ? 0xF : 0x3;
+    checkAlignment(Loc, lo(Val), Mask + 1, Type);
+    write16(Loc, (read16(Loc) & Mask) | lo(Val));
+  } break;
   case R_PPC64_ADDR16_HA:
   case R_PPC64_REL16_HA:
   case R_PPC64_TPREL16_HA:
@@ -542,9 +565,14 @@ void PPC64::relocateOne(uint8_t *Loc, Re
     write16(Loc, lo(Val));
     break;
   case R_PPC64_ADDR16_LO_DS:
-  case R_PPC64_TPREL16_LO_DS:
-    write16(Loc, (read16(Loc) & 3) | (lo(Val) & ~3));
-    break;
+  case R_PPC64_TPREL16_LO_DS: {
+    // DQ-form instructions use bits 28-31 as part of the instruction encoding
+    // DS-form instructions only use bits 30-31.
+    uint32_t EndianOffset = Config->EKind == ELF64BEKind ? 2U : 0U;
+    uint16_t Mask = isDQFormInstruction(read32(Loc - EndianOffset)) ? 0xF : 0x3;
+    checkAlignment(Loc, lo(Val), Mask + 1, Type);
+    write16(Loc, (read16(Loc) & Mask) | lo(Val));
+  } break;
   case R_PPC64_ADDR32:
   case R_PPC64_REL32:
     checkInt(Loc, Val, 32, Type);

Added: lld/trunk/test/ELF/ppc64-dq.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc64-dq.s?rev=340832&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc64-dq.s (added)
+++ lld/trunk/test/ELF/ppc64-dq.s Tue Aug 28 08:16:01 2018
@@ -0,0 +1,32 @@
+# REQUIRES: ppc
+
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-objdump -D %t | FileCheck %s
+
+# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-objdump -D %t | FileCheck %s
+
+        .global test
+        .p2align        4
+        .type   test, at function
+test:
+.Lgep:
+        addis 2, 12, .TOC.-.Lgep at ha
+        addi  2, 2,  .TOC.-.Lgep at l
+.Llep:
+        .localentry test, .Llep-.Lgep
+        addis 3, 2, qword at toc@ha
+        lxv   3, qword at toc@l(3)
+        addis 3, 2, qword at toc@ha
+        stxv  3, qword at toc@l(3)
+        blr
+
+       .comm qword, 16, 16
+
+# Verify that we don't overwrite any of the extended opcode bits on a DQ form
+# instruction.
+# CHECK-LABEL: test
+# CHECK:         lxv 3, -32768(3)
+# CHECK:         stxv 3, -32768(3)

Added: lld/trunk/test/ELF/ppc64-error-missaligned-dq.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc64-error-missaligned-dq.s?rev=340832&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc64-error-missaligned-dq.s (added)
+++ lld/trunk/test/ELF/ppc64-error-missaligned-dq.s Tue Aug 28 08:16:01 2018
@@ -0,0 +1,26 @@
+# REQUIRES: ppc
+#
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
+# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s
+
+# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
+# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s
+
+# CHECK: improper alignment for relocation R_PPC64_ADDR16_LO_DS: 0x8001 is not aligned to 16 bytes
+
+        .global test
+        .p2align        4
+        .type   test, at function
+test:
+.Lgep:
+        addis 2, 12, .TOC.-.Lgep at ha
+        addi  2, 2,  .TOC.-.Lgep at l
+.Llep:
+        .localentry test, .Llep-.Lgep
+        addis 3, 2, qword at toc@ha
+        lxv   3, qword at toc@l(3)
+        blr
+
+       .comm pad, 1, 1
+       .comm qword, 16, 1
+

Added: lld/trunk/test/ELF/ppc64-error-missaligned-ds.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc64-error-missaligned-ds.s?rev=340832&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc64-error-missaligned-ds.s (added)
+++ lld/trunk/test/ELF/ppc64-error-missaligned-ds.s Tue Aug 28 08:16:01 2018
@@ -0,0 +1,26 @@
+# REQUIRES: ppc
+
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
+# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s
+
+# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
+# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s
+
+# CHECK: improper alignment for relocation R_PPC64_ADDR16_LO_DS: 0x8001 is not aligned to 4 bytes
+
+        .global test
+        .p2align        4
+        .type   test, at function
+test:
+.Lgep:
+        addis 2, 12, .TOC.-.Lgep at ha
+        addi  2, 2,  .TOC.-.Lgep at l
+.Llep:
+        .localentry test, .Llep-.Lgep
+        addis 3, 2, word at toc@ha
+        lwa   3, word at toc@l(3)
+        blr
+
+       .comm pad, 1, 1
+       .comm word, 4, 1
+




More information about the llvm-commits mailing list