[lld] [lld][ELF] Support relax R_LARCH_{ALIGN, PCALA_{HI20,LO12}, GOT_PC_{HI20,LO12}} (PR #78692)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 30 00:11:43 PST 2024


================
@@ -659,6 +664,253 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
   }
 }
 
+// Relax R_LARCH_PCALA_{HI20,LO12}
+// pcalau12i+addi.{d,w} to pcaddi
+static void relaxPcalaAddi(const InputSection &sec, size_t i, uint64_t loc,
+                           Relocation &r, Relocation &rl, uint32_t &remove) {
+  const Symbol &sym = *r.sym;
+  const uint32_t pca = read64le(sec.content().data() + r.offset);
+  const uint32_t adi = read64le(sec.content().data() + rl.offset);
+  const uint32_t rd = pca & 0x1f;
+  const uint32_t op_addi = config->is64 ? ADDI_D : ADDI_W;
+  const uint64_t dest = sym.getVA() + r.addend;
+  const int64_t displace = dest - loc;
+
+  if (!(dest & 0x3) && isInt<22>(displace) && rd == (adi & 0x1f) &&
+      rd == ((adi >> 5) & 0x1f) && rl.offset == r.offset + 4 &&
+      (adi & 0xffc00000) == op_addi) {
+    sec.relaxAux->relocTypes[i] = R_LARCH_PCREL20_S2;
+    sec.relaxAux->relocTypes[i + 2] = R_LARCH_RELAX;
+    sec.relaxAux->writes.push_back(PCADDI | rd);
+    remove = 4;
+  }
+}
+
+// Relax R_LARCH_GOT_PC_{HI20,LO12}
+// pcalau12i+ld.{d,w} to pcalau12i+addi.{d,w} or pcaddi
+static void relaxPcalaLd(const InputSection &sec, size_t i, uint64_t loc,
+                         Relocation &r, Relocation &rl, uint32_t &remove) {
+  const Symbol &sym = *r.sym;
+  const uint32_t pca = read64le(sec.content().data() + r.offset);
+  const uint32_t ld = read64le(sec.content().data() + rl.offset);
+  const uint32_t rd = pca & 0x1f;
+  const uint32_t op_addi = config->is64 ? ADDI_D : ADDI_W;
+  const uint32_t op_ld = config->is64 ? LD_D : LD_W;
+  const uint64_t dest = sym.getVA() + r.addend;
+  const int64_t displace = dest - loc;
+
+  if (!sym.isLocal())
+    return;
+
+  if (rd != (ld & 0x1f) || rd != ((ld >> 5) & 0x1f) ||
+      rl.offset != r.offset + 4 || (ld & 0xffc00000) != op_ld)
+    return;
+
+  if (!(dest & 0x3) && isInt<22>(displace)) {
+    sec.relaxAux->relocTypes[i] = R_LARCH_PCREL20_S2;
+    sec.relaxAux->relocTypes[i + 2] = R_LARCH_RELAX;
+    sec.relaxAux->writes.push_back(PCADDI | rd);
+    remove = 4;
+  } else {
+    sec.relaxAux->relocTypes[i] = R_LARCH_PCALA_HI20;
+    sec.relaxAux->relocTypes[i + 2] = R_LARCH_PCALA_LO12;
+    sec.relaxAux->writes.push_back(PCALAU12I | rd);
+    sec.relaxAux->writes.push_back(op_addi | (rd << 5) | rd);
+  }
+}
+
+static bool relax(InputSection &sec) {
+  const uint64_t secAddr = sec.getVA();
+  auto &aux = *sec.relaxAux;
+  bool changed = false;
+  ArrayRef<SymbolAnchor> sa = ArrayRef(aux.anchors);
+  uint64_t delta = 0;
+
+  std::fill_n(aux.relocTypes.get(), sec.relocs().size(), R_LARCH_NONE);
+  aux.writes.clear();
----------------
MaskRay wrote:

In RISCV.cpp, I have defined `relocs` as a variable to hold `src.relocs()`

https://github.com/llvm/llvm-project/pull/78692


More information about the llvm-commits mailing list