]> granicus.if.org Git - llvm/commitdiff
[RISCV] Don't evaluatePCRelLo if a relocation will be forced (e.g. due to linker...
authorAlex Bradbury <asb@lowrisc.org>
Mon, 1 Apr 2019 02:38:27 +0000 (02:38 +0000)
committerAlex Bradbury <asb@lowrisc.org>
Mon, 1 Apr 2019 02:38:27 +0000 (02:38 +0000)
A pcrel_lo will point to the associated pcrel_hi fixup which in turn points to
the real target. RISCVMCExpr::evaluatePCRelLo will work around this
indirection in order to allow the fixup to be evaluate properly. However, if
relocations are forced (e.g. due to linker relaxation is enabled) then its
evaluation is undesired and will result in a relocation with the wrong target.

This patch modifies evaluatePCRelLo so it will not try to evaluate if the
fixup will be forced as a relocation. A new helper method is added to
RISCVAsmBackend to query this.

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@357374 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
test/MC/RISCV/linker-relaxation.s
test/MC/RISCV/option-relax.s

index 248ef20f927e992cb4a9f9311b93b74fa584671a..246f13f7b796a21c2c157d95336d08ebc22907b1 100644 (file)
@@ -42,11 +42,18 @@ public:
 
   void setForceRelocs() { ForceRelocs = true; }
 
+  // Returns true if relocations will be forced for shouldForceRelocation by
+  // default. This will be true if relaxation is enabled or had previously
+  // been enabled.
+  bool willForceRelocations() const {
+    return ForceRelocs || STI.getFeatureBits()[RISCV::FeatureRelax];
+  }
+
   // Generate diff expression relocations if the relax feature is enabled or had
   // previously been enabled, otherwise it is safe for the assembler to
   // calculate these internally.
   bool requiresDiffExpressionRelocations() const override {
-    return STI.getFeatureBits()[RISCV::FeatureRelax] || ForceRelocs;
+    return willForceRelocations();
   }
 
   // Return Size with extra Nop Bytes for alignment directive in code section.
index c0ca634969bdac13319d2daf8ac8721da6ecf308..b6d2fa070545c2b5ea7d385bd2b3f4b876b5c76d 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
-#include "RISCV.h"
 #include "RISCVMCExpr.h"
+#include "MCTargetDesc/RISCVAsmBackend.h"
+#include "RISCV.h"
 #include "RISCVFixupKinds.h"
+#include "llvm/MC/MCAsmLayout.h"
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCStreamer.h"
@@ -87,6 +89,16 @@ bool RISCVMCExpr::evaluatePCRelLo(MCValue &Res, const MCAsmLayout *Layout,
   // (<real target> + <offset from this fixup to the auipc fixup>).  The Fixup
   // is pcrel relative to the VK_RISCV_PCREL_LO fixup, so we need to add the
   // offset to the VK_RISCV_PCREL_HI Fixup from VK_RISCV_PCREL_LO to correct.
+
+  // Don't try to evaluate if the fixup will be forced as a relocation (e.g.
+  // as linker relaxation is enabled). If we evaluated pcrel_lo in this case,
+  // the modified fixup will be converted into a relocation that no longer
+  // points to the pcrel_hi as the linker requires.
+  auto &RAB =
+      static_cast<RISCVAsmBackend &>(Layout->getAssembler().getBackend());
+  if (RAB.willForceRelocations())
+    return false;
+
   MCValue AUIPCLoc;
   if (!getSubExpr()->evaluateAsValue(AUIPCLoc, *Layout))
     return false;
index 0d50b0ac174f404db6ae7cfec2c9630d2437d498..bc8a90ab2a4db9acabe4b2788e5be0e1f376176c 100644 (file)
@@ -121,14 +121,10 @@ auipc t1, %pcrel_hi(bar)
 # RELAX-FIXUP: fixup A - offset: 0, value: %pcrel_hi(bar), kind: fixup_riscv_pcrel_hi20
 # RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax
 
-# TODO/FIXME: The generated PCREL_LO relocations are incorrect.
-# RISCVMCExpr::evaluatePCRelLo should not be evaluating the fixup when linker
-# relaxation is enabled.
-
 addi t1, t1, %pcrel_lo(2b)
 # NORELAX-RELOC-NOT: R_RISCV_PCREL_LO12_I
 # NORELAX-RELOC-NOT: R_RISCV_RELAX
-# RELAX-RELOC: R_RISCV_PCREL_LO12_I bar 0x4
+# RELAX-RELOC: R_RISCV_PCREL_LO12_I .Ltmp1 0x0
 # RELAX-RELOC: R_RISCV_RELAX - 0x0
 # RELAX-FIXUP: fixup A - offset: 0, value: %pcrel_lo(.Ltmp1), kind: fixup_riscv_pcrel_lo12_i
 # RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax
@@ -136,7 +132,7 @@ addi t1, t1, %pcrel_lo(2b)
 sb t1, %pcrel_lo(2b)(a2)
 # NORELAX-RELOC-NOT: R_RISCV_PCREL_LO12_S
 # NORELAX-RELOC-NOT: R_RISCV_RELAX
-# RELAX-RELOC: R_RISCV_PCREL_LO12_S bar 0x8
+# RELAX-RELOC: R_RISCV_PCREL_LO12_S .Ltmp1 0x0
 # RELAX-RELOC: R_RISCV_RELAX - 0x0
 # RELAX-FIXUP: fixup A - offset: 0, value: %pcrel_lo(.Ltmp1), kind: fixup_riscv_pcrel_lo12_s
 # RELAX-FIXUP: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax
index d5768941af0c4216e39046cb603e4d1709417b63..1ee567a27820dd171d1eed52f6472edb9ba29559 100644 (file)
@@ -64,3 +64,9 @@ call baz
 jal zero, .L1
 # CHECK-RELOC-NEXT: R_RISCV_BRANCH
 beq s1, s1, .L1
+
+1:
+# CHECK-RELOC-NEXT: R_RISCV_PCREL_HI20 .L1
+auipc t1, %pcrel_hi(.L1)
+# CHECK-RELOC-NEXT: R_RISCV_PCREL_LO12_I .Ltmp0
+addi t1, t1, %pcrel_lo(1b)