[llvm] r271644 - [mips] Implement 'la' macro in PIC mode for O32.

Daniel Sanders via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 3 02:53:06 PDT 2016


Author: dsanders
Date: Fri Jun  3 04:53:06 2016
New Revision: 271644

URL: http://llvm.org/viewvc/llvm-project?rev=271644&view=rev
Log:
[mips] Implement 'la' macro in PIC mode for O32.

Summary:
N32 support will follow in a later patch since the symbol version of 'la'
incorrectly believes N32 to have 64-bit pointers and rejects it early.

This fixes the three incorrectly expanded 'la' macros found in bionic.

Reviewers: sdardis

Subscribers: dsanders, llvm-commits, sdardis

Differential Revision: http://reviews.llvm.org/D20820


Added:
    llvm/trunk/test/MC/Mips/macro-la-pic.s
Modified:
    llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
    llvm/trunk/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp
    llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp
    llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h
    llvm/trunk/test/CodeGen/Mips/hf1_body.ll

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=271644&r1=271643&r2=271644&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp Fri Jun  3 04:53:06 2016
@@ -2376,15 +2376,85 @@ bool MipsAsmParser::loadAndAddSymbolAddr
                                             MCStreamer &Out,
                                             const MCSubtargetInfo *STI) {
   MipsTargetStreamer &TOut = getTargetStreamer();
+  bool UseSrcReg = SrcReg != Mips::NoRegister;
   warnIfNoMacro(IDLoc);
 
-  const MCExpr *Symbol = cast<MCExpr>(SymExpr);
+  if (inPicMode() && ABI.IsO32()) {
+    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_GOT16.
+    if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
+        Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
+        !Res.getSymA()->getSymbol().isTemporary()) {
+      const MCExpr *CallExpr =
+          MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
+      TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
+                   MCOperand::createExpr(CallExpr), IDLoc, STI);
+      return false;
+    }
+
+    // The remaining cases are:
+    //   External GOT: lw $tmp, %got(symbol+offset)($gp)
+    //                >addiu $tmp, $tmp, %lo(offset)
+    //                >addiu $rd, $tmp, $rs
+    //   Local GOT:    lw $tmp, %got(symbol+offset)($gp)
+    //                 addiu $tmp, $tmp, %lo(symbol+offset)($gp)
+    //                >addiu $rd, $tmp, $rs
+    // The addiu'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, SymExpr, getContext());
+    const MCExpr *LoExpr = nullptr;
+    if (Res.getSymA()->getSymbol().isInSection() ||
+        Res.getSymA()->getSymbol().isTemporary())
+      LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
+    else if (Res.getConstant() != 0) {
+      // External symbols fully resolve the symbol with just the %got(symbol)
+      // but we must still account for any offset to the symbol for expressions
+      // like symbol+8.
+      LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
+    }
+
+    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::LW, TmpReg, ABI.GetGlobalPtr(),
+                 MCOperand::createExpr(GotExpr), IDLoc, STI);
+
+    if (LoExpr)
+      TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
+                   IDLoc, STI);
+
+    if (UseSrcReg)
+      TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
+
+    return false;
+  }
+
   const MipsMCExpr *HiExpr =
-      MipsMCExpr::create(MipsMCExpr::MEK_HI, Symbol, getContext());
+      MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
   const MipsMCExpr *LoExpr =
-      MipsMCExpr::create(MipsMCExpr::MEK_LO, Symbol, getContext());
-
-  bool UseSrcReg = SrcReg != Mips::NoRegister;
+      MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
 
   // This is the 64-bit symbol address expansion.
   if (ABI.ArePtrs64bit() && isGP64bit()) {
@@ -2395,9 +2465,9 @@ bool MipsAsmParser::loadAndAddSymbolAddr
       return true;
 
     const MipsMCExpr *HighestExpr =
-        MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, Symbol, getContext());
+        MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
     const MipsMCExpr *HigherExpr =
-        MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, Symbol, getContext());
+        MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
 
     if (UseSrcReg &&
         getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,

Modified: llvm/trunk/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp?rev=271644&r1=271643&r2=271644&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp (original)
+++ llvm/trunk/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp Fri Jun  3 04:53:06 2016
@@ -122,33 +122,6 @@ void MipsInstPrinter::printInst(const MC
   }
 }
 
-static void printExpr(const MCExpr *Expr, const MCAsmInfo *MAI,
-                      raw_ostream &OS) {
-  int Offset = 0;
-  const MCSymbolRefExpr *SRE;
-
-  if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
-    SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
-    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(BE->getRHS());
-    assert(SRE && CE && "Binary expression must be sym+const.");
-    Offset = CE->getValue();
-  } else if (const MipsMCExpr *ME = dyn_cast<MipsMCExpr>(Expr)) {
-    ME->print(OS, MAI);
-    return;
-  } else
-    SRE = cast<MCSymbolRefExpr>(Expr);
-
-  assert(SRE->getKind() == MCSymbolRefExpr::VK_None && "Invalid kind!");
-
-  SRE->getSymbol().print(OS, MAI);
-
-  if (Offset) {
-    if (Offset > 0)
-      OS << '+';
-    OS << Offset;
-  }
-}
-
 void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
                                    raw_ostream &O) {
   const MCOperand &Op = MI->getOperand(OpNo);
@@ -163,7 +136,7 @@ void MipsInstPrinter::printOperand(const
   }
 
   assert(Op.isExpr() && "unknown operand kind in printOperand");
-  printExpr(Op.getExpr(), &MAI, O);
+  Op.getExpr()->print(O, &MAI, true);
 }
 
 template <unsigned Bits, unsigned Offset>

Modified: llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp?rev=271644&r1=271643&r2=271644&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp Fri Jun  3 04:53:06 2016
@@ -102,6 +102,10 @@ unsigned MipsABIInfo::GetBasePtr() const
   return ArePtrs64bit() ? Mips::S7_64 : Mips::S7;
 }
 
+unsigned MipsABIInfo::GetGlobalPtr() const {
+  return ArePtrs64bit() ? Mips::GP_64 : Mips::GP;
+}
+
 unsigned MipsABIInfo::GetNullPtr() const {
   return ArePtrs64bit() ? Mips::ZERO_64 : Mips::ZERO;
 }

Modified: llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h?rev=271644&r1=271643&r2=271644&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h (original)
+++ llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h Fri Jun  3 04:53:06 2016
@@ -66,6 +66,7 @@ public:
   unsigned GetStackPtr() const;
   unsigned GetFramePtr() const;
   unsigned GetBasePtr() const;
+  unsigned GetGlobalPtr() const;
   unsigned GetNullPtr() const;
   unsigned GetZeroReg() const;
   unsigned GetPtrAdduOp() const;

Modified: llvm/trunk/test/CodeGen/Mips/hf1_body.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/hf1_body.ll?rev=271644&r1=271643&r2=271644&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/hf1_body.ll (original)
+++ llvm/trunk/test/CodeGen/Mips/hf1_body.ll Fri Jun  3 04:53:06 2016
@@ -23,7 +23,7 @@ entry:
 ; ALL:       .set reorder
 ; ALL:       .reloc 0, R_MIPS_NONE, v_sf
 ; GAS:       la $25, $__fn_local_v_sf
-; IAS:       lui $25, %hi($$__fn_local_v_sf)
+; IAS:       lw $25, %got($$__fn_local_v_sf)($gp)
 ; IAS:       addiu $25, $25, %lo($$__fn_local_v_sf)
 ; ALL:       mfc1 $4, $f12
 ; ALL:       jr $25

Added: llvm/trunk/test/MC/Mips/macro-la-pic.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/macro-la-pic.s?rev=271644&view=auto
==============================================================================
--- llvm/trunk/test/MC/Mips/macro-la-pic.s (added)
+++ llvm/trunk/test/MC/Mips/macro-la-pic.s Fri Jun  3 04:53:06 2016
@@ -0,0 +1,54 @@
+# RUN: llvm-mc %s -triple=mips-unknown-linux -show-encoding -mcpu=mips32r2 | \
+# RUN:   FileCheck %s
+# RUN: llvm-mc %s -triple=mips-unknown-linux -show-encoding -mcpu=mips32r6 | \
+# RUN:   FileCheck %s
+# N32 should be acceptable too but it currently errors out.
+# N64 should be acceptable too but we cannot convert la to dla yet.
+
+.option pic2
+la $5, symbol         # CHECK: lw $5, %got(symbol)($gp)    # encoding: [0x8f,0x85,A,A]
+                      # CHECK:                             #   fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
+la $5, symbol($6)     # CHECK: lw $5, %got(symbol)($gp)    # encoding: [0x8f,0x85,A,A]
+                      # CHECK:                             #   fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
+                      # CHECK: addu $5, $5, $6             # encoding: [0x00,0xa6,0x28,0x21]
+la $6, symbol($6)     # CHECK: lw $1, %got(symbol)($gp)    # encoding: [0x8f,0x81,A,A]
+                      # CHECK:                             #   fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
+                      # CHECK: addu $6, $1, $6             # encoding: [0x00,0x26,0x30,0x21]
+la $5, symbol+8       # CHECK: lw $5, %got(symbol+8)($gp)  # encoding: [0x8f,0x85,A,A]
+                      # CHECK:                             #   fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
+la $5, symbol+8($6)   # CHECK: lw $5, %got(symbol+8)($gp)  # encoding: [0x8f,0x85,A,A]
+                      # CHECK:                             #   fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
+                      # CHECK: addu $5, $5, $6             # encoding: [0x00,0xa6,0x28,0x21]
+la $6, symbol+8($6)   # CHECK: lw $1, %got(symbol+8)($gp)  # encoding: [0x8f,0x81,A,A]
+                      # CHECK:                             #   fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
+                      # CHECK: addiu $1, $1, 8             # encoding: [0x24,0x21,0x00,0x08]
+                      # CHECK: addu $6, $1, $6             # encoding: [0x00,0x26,0x30,0x21]
+la $5, 1f             # CHECK: lw $5, %got($tmp0)($gp)     # encoding: [0x8f,0x85,A,A]
+                      # CHECK:                             #   fixup A - offset: 0, value: %got($tmp0), kind: fixup_Mips_GOT
+                      # CHECK: addiu $5, $5, %lo($tmp0)    # encoding: [0x24,0xa5,A,A]
+                      # CHECK:                             #   fixup A - offset: 0, value: %lo($tmp0), kind: fixup_Mips_LO16
+1:
+
+# PIC expansions involving $25 are special.
+la $25, symbol        # CHECK: lw $25, %call16(symbol)($gp) # encoding: [0x8f,0x99,A,A]
+                      # CHECK:                              #   fixup A - offset: 0, value: %call16(symbol), kind: fixup_Mips_CALL16
+la $25, symbol($6)    # CHECK: lw $25, %got(symbol)($gp)    # encoding: [0x8f,0x99,A,A]
+                      # CHECK:                              #   fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
+                      # CHECK: addu $25, $25, $6            # encoding: [0x03,0x26,0xc8,0x21]
+la $25, symbol($25)   # CHECK: lw $1, %got(symbol)($gp)     # encoding: [0x8f,0x81,A,A]
+                      # CHECK:                              #   fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
+                      # CHECK: addu $25, $1, $25            # encoding: [0x00,0x39,0xc8,0x21]
+la $25, symbol+8      # CHECK: lw $25, %got(symbol+8)($gp)  # encoding: [0x8f,0x99,A,A]
+                      # CHECK:                              #   fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
+la $25, symbol+8($6)  # CHECK: lw $25, %got(symbol+8)($gp)  # encoding: [0x8f,0x99,A,A]
+                      # CHECK:                              #   fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
+                      # CHECK: addu $25, $25, $6            # encoding: [0x03,0x26,0xc8,0x21]
+la $25, symbol+8($25) # CHECK: lw $1, %got(symbol+8)($gp)   # encoding: [0x8f,0x81,A,A]
+                      # CHECK:                              #   fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
+                      # CHECK: addiu $1, $1, 8              # encoding: [0x24,0x21,0x00,0x08]
+                      # CHECK: addu $25, $1, $25            # encoding: [0x00,0x39,0xc8,0x21]
+la $25, 1f            # CHECK: lw $25, %got($tmp1)($gp)     # encoding: [0x8f,0x99,A,A]
+                      # CHECK:                              #   fixup A - offset: 0, value: %got($tmp1), kind: fixup_Mips_GOT
+                      # CHECK: addiu $25, $25, %lo($tmp1)   # encoding: [0x27,0x39,A,A]
+                      # CHECK:                              #   fixup A - offset: 0, value: %lo($tmp1), kind: fixup_Mips_LO16
+1:




More information about the llvm-commits mailing list