[lld] r342410 - [PPC64] Helpers for read/write an instr while relocating a half16 type. [NFC]

Sean Fertile via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 17 13:27:00 PDT 2018


Author: sfertile
Date: Mon Sep 17 13:27:00 2018
New Revision: 342410

URL: http://llvm.org/viewvc/llvm-project?rev=342410&view=rev
Log:
[PPC64] Helpers for read/write an instr while relocating a half16 type. [NFC]

There are a growing number of places when we either want to read or write an
instruction when handling a half16 relocation type. On big-endian the buffer
pointer is pointing into the middle of the word we want and on little-endian it
is pointing to the start of the word. These 2 helpers are to simplify reading
and writing in these contexts.

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

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=342410&r1=342409&r2=342410&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/PPC64.cpp (original)
+++ lld/trunk/ELF/Arch/PPC64.cpp Mon Sep 17 13:27:00 2018
@@ -116,6 +116,19 @@ static bool isDQFormInstruction(uint32_t
   }
 }
 
+// There are a number of places when we either want to read or write an
+// instruction when handling a half16 relocation type. On big-endian the buffer
+// pointer is pointing into the middle of the word we want to extract, and on
+// little-endian it is pointing to the start of the word. These 2 helpers are to
+// simplify reading and writing in that context.
+static void writeInstrFromHalf16(uint8_t *Loc, uint32_t Instr) {
+  write32(Loc - (Config->EKind == ELF64BEKind ? 2 : 0), Instr);
+}
+
+static uint32_t readInstrFromHalf16(const uint8_t *Loc) {
+  return read32(Loc - (Config->EKind == ELF64BEKind ? 2 : 0));
+}
+
 PPC64::PPC64() {
   GotRel = R_PPC64_GLOB_DAT;
   PltRel = R_PPC64_JMP_SLOT;
@@ -191,27 +204,28 @@ void PPC64::relaxTlsGdToLe(uint8_t *Loc,
   // bl __tls_get_addr(x at tlsgd)      into      nop
   // nop                             into      addi r3, r3, x at tprel@l
 
-  uint32_t EndianOffset = Config->EKind == ELF64BEKind ? 2U : 0U;
-
   switch (Type) {
   case R_PPC64_GOT_TLSGD16_HA:
-    write32(Loc - EndianOffset, 0x60000000); // nop
+    writeInstrFromHalf16(Loc, 0x60000000); // nop
     break;
   case R_PPC64_GOT_TLSGD16_LO:
-    write32(Loc - EndianOffset, 0x3c6d0000); // addis r3, r13
+    writeInstrFromHalf16(Loc, 0x3c6d0000); // addis r3, r13
     relocateOne(Loc, R_PPC64_TPREL16_HA, Val);
     break;
   case R_PPC64_TLSGD:
     write32(Loc, 0x60000000);     // nop
     write32(Loc + 4, 0x38630000); // addi r3, r3
-    relocateOne(Loc + 4 + EndianOffset, R_PPC64_TPREL16_LO, Val);
+    // Since we are relocating a half16 type relocation and Loc + 4 points to
+    // the start of an instruction we need to advance the buffer by an extra
+    // 2 bytes on BE.
+    relocateOne(Loc + 4 + (Config->EKind == ELF64BEKind ? 2 : 0),
+                R_PPC64_TPREL16_LO, Val);
     break;
   default:
     llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");
   }
 }
 
-
 void PPC64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
   // Reference: 3.7.4.3 of the 64-bit ELF V2 abi supplement.
   // The local dynamic code sequence for a global `x` will look like:
@@ -228,13 +242,12 @@ void PPC64::relaxTlsLdToLe(uint8_t *Loc,
   // bl __tls_get_addr(x at tlsgd)     into      nop
   // nop                            into      addi r3, r3, 4096
 
-  uint32_t EndianOffset = Config->EKind == ELF64BEKind ? 2U : 0U;
   switch (Type) {
   case R_PPC64_GOT_TLSLD16_HA:
-    write32(Loc - EndianOffset, 0x60000000); // nop
+    writeInstrFromHalf16(Loc, 0x60000000); // nop
     break;
   case R_PPC64_GOT_TLSLD16_LO:
-    write32(Loc - EndianOffset, 0x3c6d0000); // addis r3, r13, 0
+    writeInstrFromHalf16(Loc, 0x3c6d0000); // addis r3, r13, 0
     break;
   case R_PPC64_TLSLD:
     write32(Loc, 0x60000000);     // nop
@@ -528,8 +541,7 @@ void PPC64::relocateOne(uint8_t *Loc, Re
     checkInt(Loc, Val, 16, Type);
     // 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;
+    uint16_t Mask = isDQFormInstruction(readInstrFromHalf16(Loc)) ? 0xF : 0x3;
     checkAlignment(Loc, lo(Val), Mask + 1, Type);
     write16(Loc, (read16(Loc) & Mask) | lo(Val));
   } break;
@@ -568,8 +580,7 @@ void PPC64::relocateOne(uint8_t *Loc, Re
   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;
+    uint16_t Mask = isDQFormInstruction(readInstrFromHalf16(Loc)) ? 0xF : 0x3;
     checkAlignment(Loc, lo(Val), Mask + 1, Type);
     write16(Loc, (read16(Loc) & Mask) | lo(Val));
   } break;
@@ -640,9 +651,8 @@ void PPC64::relaxTlsGdToIe(uint8_t *Loc,
   case R_PPC64_GOT_TLSGD16_LO: {
     // Relax from addi  r3, rA, sym at got@tlsgd at l to
     //            ld r3, sym at got@tprel at l(rA)
-    uint32_t EndianOffset = Config->EKind == ELF64BEKind ? 2U : 0U;
-    uint32_t InputRegister = (read32(Loc - EndianOffset) & (0x1f << 16));
-    write32(Loc - EndianOffset, 0xE8600000 | InputRegister);
+    uint32_t InputRegister = (readInstrFromHalf16(Loc) & (0x1f << 16));
+    writeInstrFromHalf16(Loc, 0xE8600000 | InputRegister);
     relocateOne(Loc, R_PPC64_GOT_TPREL16_LO_DS, Val);
     return;
   }




More information about the llvm-commits mailing list