[llvm] MC: Centralize X86 PC-relative fixup adjustment in MCAssembler (PR #147113)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 8 00:42:43 PDT 2025


================
@@ -683,6 +683,35 @@ static unsigned getFixupKindSize(unsigned Kind) {
   }
 }
 
+// Adjust PC-relative fixup offsets, which are calculated from the start of the
+// next instruction.
+std::optional<bool> X86AsmBackend::evaluateFixup(const MCFragment &,
+                                                 MCFixup &Fixup,
+                                                 MCValue &Target, uint64_t &) {
+  if (Fixup.isPCRel()) {
+    switch (Fixup.getTargetKind()) {
+    case FK_Data_1:
+      Target.setConstant(Target.getConstant() - 1);
+      break;
+    case FK_Data_2:
+      Target.setConstant(Target.getConstant() - 2);
+      break;
+    default: {
+      Target.setConstant(Target.getConstant() - 4);
+      auto *Add = Target.getAddSym();
+      // If this is a pc-relative load off _GLOBAL_OFFSET_TABLE_:
+      // leaq _GLOBAL_OFFSET_TABLE_(%rip), %r15
+      // this needs to be a GOTPC32 relocation.
+      if (Add && Add->getName() == "_GLOBAL_OFFSET_TABLE_")
----------------
MaskRay wrote:

In 2020, I implemented this code path for all PC-relative fixups in https://reviews.llvm.org/D47507 (I overlooked adding corresponding mov tests).

The current implementation is guarded by `if (Fixup.isPCRel()) {`, reflecting the original intention. I think testing the magic symbol during the relocation decision phase (https://maskray.me/blog/2025-03-16-relocation-generation-in-assemblers#relocation-decision-phase) is the correct approach.  Transitioning another `startsWithGlobalOffsetTable` caller in X86MCCodeEmitter.cpp to use X86MCAsmBackend.cpp would be ideal, but that falls outside this change’s scope. X86MCCodeEmitter.cpp has quite a lot of tech debt.

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


More information about the llvm-commits mailing list