[llvm] r306831 - [MIPS] Handle PIC load address macro instructions in N64.

Simon Dardis via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 30 08:44:28 PDT 2017


Author: sdardis
Date: Fri Jun 30 08:44:27 2017
New Revision: 306831

URL: http://llvm.org/viewvc/llvm-project?rev=306831&view=rev
Log:
[MIPS] Handle PIC load address macro instructions in N64.

In particular, use CALL16 (similar to O32) for address loads into T9 for certain
cases.  Otherwise use a %got_disp relocation to load the address of a symbol.
Small offsets (small enough to fit in a 16-bit signed immediate) can be used and
are added to the symbol address after it is loaded from the GOT.  Larger offsets
are currently unsupported and result in an error from the assembler.

Reviewers: sdardis

Reviewed By: sdardis

Patch by: John Baldwin

Subscribers: llvm-commits, seanbruno, arichardson, emaste, dim

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

Added:
    llvm/trunk/test/MC/Mips/macro-dla-bad.s
    llvm/trunk/test/MC/Mips/macro-dla-pic.s
Modified:
    llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp

Modified: llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp?rev=306831&r1=306830&r2=306831&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp Fri Jun 30 08:44:27 2017
@@ -2789,6 +2789,7 @@ bool MipsAsmParser::loadAndAddSymbolAddr
                                             bool Is32BitSym, SMLoc IDLoc,
                                             MCStreamer &Out,
                                             const MCSubtargetInfo *STI) {
+  // FIXME: These expansions do not respect -mxgot.
   MipsTargetStreamer &TOut = getTargetStreamer();
   bool UseSrcReg = SrcReg != Mips::NoRegister;
   warnIfNoMacro(IDLoc);
@@ -2868,6 +2869,85 @@ bool MipsAsmParser::loadAndAddSymbolAddr
 
     return false;
   }
+
+  if (inPicMode() && ABI.ArePtrs64bit()) {
+    MCValue Res;
+    if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
+      Error(IDLoc, "expected relocatable expression");
+      return true;
+    }
+    if (Res.getSymB() != nullptr) {
+      Error(IDLoc, "expected relocatable expression with only one symbol");
+      return true;
+    }
+
+    // The case where the result register is $25 is somewhat special. If the
+    // symbol in the final relocation is external and not modified with a
+    // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
+    if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
+        Res.getConstant() == 0 &&
+        !(Res.getSymA()->getSymbol().isInSection() ||
+          Res.getSymA()->getSymbol().isTemporary() ||
+          (Res.getSymA()->getSymbol().isELF() &&
+           cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
+               ELF::STB_LOCAL))) {
+      const MCExpr *CallExpr =
+          MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
+      TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
+                   MCOperand::createExpr(CallExpr), IDLoc, STI);
+      return false;
+    }
+
+    // The remaining cases are:
+    //   Small offset: ld $tmp, %got_disp(symbol)($gp)
+    //                >daddiu $tmp, $tmp, offset
+    //                >daddu $rd, $tmp, $rs
+    // The daddiu's marked with a '>' may be omitted if they are redundant. If
+    // this happens then the last instruction must use $rd as the result
+    // register.
+    const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
+                                                   Res.getSymA(),
+                                                   getContext());
+    const MCExpr *LoExpr = nullptr;
+    if (Res.getConstant() != 0) {
+      // Symbols fully resolve with just the %got_disp(symbol) but we
+      // must still account for any offset to the symbol for
+      // expressions like symbol+8.
+      LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
+
+      // FIXME: Offsets greater than 16 bits are not yet implemented.
+      // FIXME: The correct range is a 32-bit sign-extended number.
+      if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
+        Error(IDLoc, "macro instruction uses large offset, which is not "
+                     "currently supported");
+        return true;
+      }
+    }
+
+    unsigned TmpReg = DstReg;
+    if (UseSrcReg &&
+        getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
+                                                               SrcReg)) {
+      // If $rs is the same as $rd, we need to use AT.
+      // If it is not available we exit.
+      unsigned ATReg = getATReg(IDLoc);
+      if (!ATReg)
+        return true;
+      TmpReg = ATReg;
+    }
+
+    TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
+                 MCOperand::createExpr(GotExpr), IDLoc, STI);
+
+    if (LoExpr)
+      TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
+                   IDLoc, STI);
+
+    if (UseSrcReg)
+      TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
+
+    return false;
+  }
 
   const MipsMCExpr *HiExpr =
       MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());

Added: llvm/trunk/test/MC/Mips/macro-dla-bad.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/macro-dla-bad.s?rev=306831&view=auto
==============================================================================
--- llvm/trunk/test/MC/Mips/macro-dla-bad.s (added)
+++ llvm/trunk/test/MC/Mips/macro-dla-bad.s Fri Jun 30 08:44:27 2017
@@ -0,0 +1,21 @@
+# RUN: not llvm-mc %s -arch=mips64 -mcpu=mips3 -target-abi n64 2>&1 | \
+# RUN:   FileCheck %s
+
+  .text
+  .option pic2
+  dla $5, symbol+0x8000
+  # CHECK: :[[@LINE-1]]:3: error: macro instruction uses large offset, which is not currently supported
+  dla $5, symbol-0x8001
+  # CHECK: :[[@LINE-1]]:3: error: macro instruction uses large offset, which is not currently supported
+  dla $5, symbol+0x8000($6)
+  # CHECK: :[[@LINE-1]]:3: error: macro instruction uses large offset, which is not currently supported
+  dla $5, symbol-0x8001($6)
+  # CHECK: :[[@LINE-1]]:3: error: macro instruction uses large offset, which is not currently supported
+  dla $25, symbol+0x8000
+  # CHECK: :[[@LINE-1]]:3: error: macro instruction uses large offset, which is not currently supported
+  dla $25, symbol-0x8001
+  # CHECK: :[[@LINE-1]]:3: error: macro instruction uses large offset, which is not currently supported
+  dla $25, symbol+0x8000($6)
+  # CHECK: :[[@LINE-1]]:3: error: macro instruction uses large offset, which is not currently supported
+  dla $25, symbol-0x8001($6)
+  # CHECK: :[[@LINE-1]]:3: error: macro instruction uses large offset, which is not currently supported

Added: llvm/trunk/test/MC/Mips/macro-dla-pic.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/macro-dla-pic.s?rev=306831&view=auto
==============================================================================
--- llvm/trunk/test/MC/Mips/macro-dla-pic.s (added)
+++ llvm/trunk/test/MC/Mips/macro-dla-pic.s Fri Jun 30 08:44:27 2017
@@ -0,0 +1,50 @@
+# RUN: llvm-mc %s -triple=mips64-unknown-linux -show-encoding -mcpu=mips3 | \
+# RUN:   FileCheck %s
+
+.option pic2
+dla $5, symbol        # CHECK: ld $5, %got_disp(symbol)($gp)   # encoding: [0xdf,0x85,A,A]
+                      # CHECK:                                 #   fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP
+dla $5, symbol($6)    # CHECK: ld $5, %got_disp(symbol)($gp)   # encoding: [0xdf,0x85,A,A]
+                      # CHECK:                                 #   fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP
+                      # CHECK: daddu $5, $5, $6                # encoding: [0x00,0xa6,0x28,0x2d]
+dla $6, symbol($6)    # CHECK: ld $1, %got_disp(symbol)($gp)   # encoding: [0xdf,0x81,A,A]
+                      # CHECK:                                 #   fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP
+                      # CHECK: daddu $6, $1, $6                # encoding: [0x00,0x26,0x30,0x2d]
+dla $5, symbol+8      # CHECK: ld $5, %got_disp(symbol)($gp)   # encoding: [0xdf,0x85,A,A]
+                      # CHECK:                                 #   fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP
+                      # CHECK: daddiu $5, $5, 8                # encoding: [0x64,0xa5,0x00,0x08]
+dla $5, symbol+8($6)  # CHECK: ld $5, %got_disp(symbol)($gp)   # encoding: [0xdf,0x85,A,A]
+                      # CHECK:                                 #   fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP
+                      # CHECK: daddiu $5, $5, 8                # encoding: [0x64,0xa5,0x00,0x08]
+                      # CHECK: daddu $5, $5, $6                # encoding: [0x00,0xa6,0x28,0x2d]
+dla $6, symbol+8($6)  # CHECK: ld $1, %got_disp(symbol)($gp)   # encoding: [0xdf,0x81,A,A]
+                      # CHECK:                                 #   fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP
+                      # CHECK: daddiu $1, $1, 8                # encoding: [0x64,0x21,0x00,0x08]
+                      # CHECK: daddu $6, $1, $6                # encoding: [0x00,0x26,0x30,0x2d]
+dla $5, 1f            # CHECK: ld $5, %got_disp(.Ltmp0)($gp)   # encoding: [0xdf,0x85,A,A]
+                      # CHECK:                                 #   fixup A - offset: 0, value: %got_disp(.Ltmp0), kind: fixup_Mips_GOT_DISP
+1:
+
+# PIC expansions involving $25 are special.
+dla $25, symbol       # CHECK: ld $25, %call16(symbol)($gp)     # encoding: [0xdf,0x99,A,A]
+                      # CHECK:                                  #   fixup A - offset: 0, value: %call16(symbol), kind: fixup_Mips_CALL16
+dla $25, symbol($6)   # CHECK: ld $25, %got_disp(symbol)($gp)   # encoding: [0xdf,0x99,A,A]
+                      # CHECK:                                  #   fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP
+                      # CHECK: daddu $25, $25, $6               # encoding: [0x03,0x26,0xc8,0x2d]
+dla $25, symbol($25)  # CHECK: ld $1, %got_disp(symbol)($gp)    # encoding: [0xdf,0x81,A,A]
+                      # CHECK:                                  #   fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP
+                      # CHECK: daddu $25, $1, $25               # encoding: [0x00,0x39,0xc8,0x2d]
+dla $25, symbol+8     # CHECK: ld $25, %got_disp(symbol)($gp)   # encoding: [0xdf,0x99,A,A]
+                      # CHECK:                                  #   fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP
+                      # CHECK: daddiu $25, $25, 8               # encoding: [0x67,0x39,0x00,0x08]
+dla $25, symbol+8($6) # CHECK: ld $25, %got_disp(symbol)($gp)   # encoding: [0xdf,0x99,A,A]
+                      # CHECK:                                  #   fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP
+                      # CHECK: daddiu $25, $25, 8               # encoding: [0x67,0x39,0x00,0x08]
+                      # CHECK: daddu $25, $25, $6               # encoding: [0x03,0x26,0xc8,0x2d]
+dla $25, symbol+8($25)# CHECK: ld $1, %got_disp(symbol)($gp)    # encoding: [0xdf,0x81,A,A]
+                      # CHECK:                                  #   fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP
+                      # CHECK: daddiu $1, $1, 8                 # encoding: [0x64,0x21,0x00,0x08]
+                      # CHECK: daddu $25, $1, $25               # encoding: [0x00,0x39,0xc8,0x2d]
+dla $25, 1f           # CHECK: ld $25, %got_disp(.Ltmp1)($gp)    # encoding: [0xdf,0x99,A,A]
+                      # CHECK:                                  #   fixup A - offset: 0, value: %got_disp(.Ltmp1), kind: fixup_Mips_GOT_DISP
+1:




More information about the llvm-commits mailing list