[llvm] r366300 - [mips] Implement .cplocal directive

Simon Atanasyan via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 17 01:11:31 PDT 2019


Author: atanasyan
Date: Wed Jul 17 01:11:31 2019
New Revision: 366300

URL: http://llvm.org/viewvc/llvm-project?rev=366300&view=rev
Log:
[mips] Implement .cplocal directive

This directive forces to use the alternate register for context pointer.
For example, this code:
  .cplocal $4
  jal foo
expands to:
  ld    $25, %call16(foo)($4)
  jalr  $25

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

Added:
    llvm/trunk/test/MC/Mips/cplocal-bad.s
    llvm/trunk/test/MC/Mips/cplocal.s
Modified:
    llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
    llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
    llvm/trunk/lib/Target/Mips/MipsTargetStreamer.h

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=366300&r1=366299&r2=366300&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp Wed Jul 17 01:11:31 2019
@@ -146,6 +146,7 @@ class MipsAsmParser : public MCTargetAsm
   bool IsPicEnabled;
   bool IsCpRestoreSet;
   int CpRestoreOffset;
+  unsigned GPReg;
   unsigned CpSaveLocation;
   /// If true, then CpSaveLocation is a register, otherwise it's an offset.
   bool     CpSaveLocationIsRegister;
@@ -334,6 +335,7 @@ class MipsAsmParser : public MCTargetAsm
   bool parseSetFeature(uint64_t Feature);
   bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
   bool parseDirectiveCpLoad(SMLoc Loc);
+  bool parseDirectiveCpLocal(SMLoc Loc);
   bool parseDirectiveCpRestore(SMLoc Loc);
   bool parseDirectiveCPSetup();
   bool parseDirectiveCPReturn();
@@ -527,6 +529,7 @@ public:
 
     IsCpRestoreSet = false;
     CpRestoreOffset = -1;
+    GPReg = ABI.GetGlobalPtr();
 
     const Triple &TheTriple = sti.getTargetTriple();
     IsLittleEndian = TheTriple.isLittleEndian();
@@ -2040,7 +2043,7 @@ bool MipsAsmParser::processInstruction(M
         const MCExpr *Lo16RelocExpr =
             MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
 
-        TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
+        TOut.emitRRX(Mips::LW, Mips::T9, GPReg,
                      MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
         TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
                      MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
@@ -2054,7 +2057,7 @@ bool MipsAsmParser::processInstruction(M
             MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
 
         TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
-                     Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
+                     GPReg, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
                      STI);
       }
     } else {
@@ -2065,7 +2068,7 @@ bool MipsAsmParser::processInstruction(M
       const MCExpr *Call16RelocExpr =
           MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
 
-      TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
+      TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, GPReg,
                    MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
     }
 
@@ -2893,8 +2896,8 @@ bool MipsAsmParser::loadAndAddSymbolAddr
                ELF::STB_LOCAL))) {
       const MCExpr *CallExpr =
           MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
-      TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
-                   MCOperand::createExpr(CallExpr), IDLoc, STI);
+      TOut.emitRRX(Mips::LW, DstReg, GPReg, MCOperand::createExpr(CallExpr),
+                   IDLoc, STI);
       return false;
     }
 
@@ -2933,8 +2936,8 @@ bool MipsAsmParser::loadAndAddSymbolAddr
       TmpReg = ATReg;
     }
 
-    TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
-                 MCOperand::createExpr(GotExpr), IDLoc, STI);
+    TOut.emitRRX(Mips::LW, TmpReg, GPReg, MCOperand::createExpr(GotExpr), IDLoc,
+                 STI);
 
     if (LoExpr)
       TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
@@ -2969,8 +2972,8 @@ bool MipsAsmParser::loadAndAddSymbolAddr
                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);
+      TOut.emitRRX(Mips::LD, DstReg, GPReg, MCOperand::createExpr(CallExpr),
+                   IDLoc, STI);
       return false;
     }
 
@@ -3012,8 +3015,8 @@ bool MipsAsmParser::loadAndAddSymbolAddr
       TmpReg = ATReg;
     }
 
-    TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
-                 MCOperand::createExpr(GotExpr), IDLoc, STI);
+    TOut.emitRRX(Mips::LD, TmpReg, GPReg, MCOperand::createExpr(GotExpr), IDLoc,
+                 STI);
 
     if (LoExpr)
       TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
@@ -3243,10 +3246,10 @@ bool MipsAsmParser::emitPartialAddress(M
         MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
 
     if(isABI_O32() || isABI_N32()) {
-      TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
+      TOut.emitRRX(Mips::LW, ATReg, GPReg, MCOperand::createExpr(GotExpr),
                    IDLoc, STI);
     } else { //isABI_N64()
-      TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
+      TOut.emitRRX(Mips::LD, ATReg, GPReg, MCOperand::createExpr(GotExpr),
                    IDLoc, STI);
     }
   } else { //!IsPicEnabled
@@ -7241,6 +7244,40 @@ bool MipsAsmParser::parseDirectiveCpLoad
   return false;
 }
 
+bool MipsAsmParser::parseDirectiveCpLocal(SMLoc Loc) {
+  if (!isABI_N32() && !isABI_N64()) {
+    reportParseError(".cplocal is allowed only in N32 or N64 mode");
+    return false;
+  }
+
+  SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
+  OperandMatchResultTy ResTy = parseAnyRegister(Reg);
+  if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
+    reportParseError("expected register containing global pointer");
+    return false;
+  }
+
+  MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
+  if (!RegOpnd.isGPRAsmReg()) {
+    reportParseError(RegOpnd.getStartLoc(), "invalid register");
+    return false;
+  }
+
+  // If this is not the end of the statement, report an error.
+  if (getLexer().isNot(AsmToken::EndOfStatement)) {
+    reportParseError("unexpected token, expected end of statement");
+    return false;
+  }
+  getParser().Lex(); // Consume the EndOfStatement.
+
+  unsigned NewReg = RegOpnd.getGPR32Reg();
+  if (IsPicEnabled)
+    GPReg = NewReg;
+
+  getTargetStreamer().emitDirectiveCpLocal(NewReg);
+  return false;
+}
+
 bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
   MCAsmParser &Parser = getParser();
 
@@ -8091,6 +8128,10 @@ bool MipsAsmParser::ParseDirective(AsmTo
     parseDirectiveCpRestore(DirectiveID.getLoc());
     return false;
   }
+  if (IDVal == ".cplocal") {
+    parseDirectiveCpLocal(DirectiveID.getLoc());
+    return false;
+  }
   if (IDVal == ".ent") {
     StringRef SymbolName;
 

Modified: llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp?rev=366300&r1=366299&r2=366300&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp Wed Jul 17 01:11:31 2019
@@ -35,7 +35,7 @@ static cl::opt<bool> RoundSectionSizes(
 } // end anonymous namespace
 
 MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S)
-    : MCTargetStreamer(S), ModuleDirectiveAllowed(true) {
+    : MCTargetStreamer(S), GPReg(Mips::GP), ModuleDirectiveAllowed(true) {
   GPRInfoSet = FPRInfoSet = FrameInfoSet = false;
 }
 void MipsTargetStreamer::emitDirectiveSetMicroMips() {}
@@ -106,6 +106,23 @@ void MipsTargetStreamer::emitDirectiveSe
 void MipsTargetStreamer::emitDirectiveSetDspr2() { forbidModuleDirective(); }
 void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); }
 void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {}
+void MipsTargetStreamer::emitDirectiveCpLocal(unsigned RegNo) {
+  // .cplocal $reg
+  // This directive forces to use the alternate register for context pointer.
+  // For example
+  //   .cplocal $4
+  //   jal foo
+  // expands to
+  //   ld    $25, %call16(foo)($4)
+  //   jalr  $25
+
+  if (!getABI().IsN32() && !getABI().IsN64())
+    return;
+
+  GPReg = RegNo;
+
+  forbidModuleDirective();
+}
 bool MipsTargetStreamer::emitDirectiveCpRestore(
     int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,
     const MCSubtargetInfo *STI) {
@@ -257,8 +274,7 @@ void MipsTargetStreamer::emitNop(SMLoc I
 /// Emit the $gp restore operation for .cprestore.
 void MipsTargetStreamer::emitGPRestore(int Offset, SMLoc IDLoc,
                                        const MCSubtargetInfo *STI) {
-  emitLoadWithImmOffset(Mips::LW, Mips::GP, Mips::SP, Offset, Mips::GP, IDLoc,
-                        STI);
+  emitLoadWithImmOffset(Mips::LW, GPReg, Mips::SP, Offset, GPReg, IDLoc, STI);
 }
 
 /// Emit a store instruction with an immediate offset.
@@ -665,6 +681,12 @@ void MipsTargetAsmStreamer::emitDirectiv
   forbidModuleDirective();
 }
 
+void MipsTargetAsmStreamer::emitDirectiveCpLocal(unsigned RegNo) {
+  OS << "\t.cplocal\t$"
+     << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n";
+  MipsTargetStreamer::emitDirectiveCpLocal(RegNo);
+}
+
 bool MipsTargetAsmStreamer::emitDirectiveCpRestore(
     int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,
     const MCSubtargetInfo *STI) {
@@ -1135,7 +1157,7 @@ void MipsTargetELFStreamer::emitDirectiv
 
   MCInst TmpInst;
   TmpInst.setOpcode(Mips::LUi);
-  TmpInst.addOperand(MCOperand::createReg(Mips::GP));
+  TmpInst.addOperand(MCOperand::createReg(GPReg));
   const MCExpr *HiSym = MipsMCExpr::create(
       MipsMCExpr::MEK_HI,
       MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None,
@@ -1147,8 +1169,8 @@ void MipsTargetELFStreamer::emitDirectiv
   TmpInst.clear();
 
   TmpInst.setOpcode(Mips::ADDiu);
-  TmpInst.addOperand(MCOperand::createReg(Mips::GP));
-  TmpInst.addOperand(MCOperand::createReg(Mips::GP));
+  TmpInst.addOperand(MCOperand::createReg(GPReg));
+  TmpInst.addOperand(MCOperand::createReg(GPReg));
   const MCExpr *LoSym = MipsMCExpr::create(
       MipsMCExpr::MEK_LO,
       MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None,
@@ -1160,14 +1182,19 @@ void MipsTargetELFStreamer::emitDirectiv
   TmpInst.clear();
 
   TmpInst.setOpcode(Mips::ADDu);
-  TmpInst.addOperand(MCOperand::createReg(Mips::GP));
-  TmpInst.addOperand(MCOperand::createReg(Mips::GP));
+  TmpInst.addOperand(MCOperand::createReg(GPReg));
+  TmpInst.addOperand(MCOperand::createReg(GPReg));
   TmpInst.addOperand(MCOperand::createReg(RegNo));
   getStreamer().EmitInstruction(TmpInst, STI);
 
   forbidModuleDirective();
 }
 
+void MipsTargetELFStreamer::emitDirectiveCpLocal(unsigned RegNo) {
+  if (Pic)
+    MipsTargetStreamer::emitDirectiveCpLocal(RegNo);
+}
+
 bool MipsTargetELFStreamer::emitDirectiveCpRestore(
     int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,
     const MCSubtargetInfo *STI) {
@@ -1184,7 +1211,7 @@ bool MipsTargetELFStreamer::emitDirectiv
     return true;
 
   // Store the $gp on the stack.
-  emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, Offset, GetATReg, IDLoc,
+  emitStoreWithImmOffset(Mips::SW, GPReg, Mips::SP, Offset, GetATReg, IDLoc,
                          STI);
   return true;
 }
@@ -1205,10 +1232,10 @@ void MipsTargetELFStreamer::emitDirectiv
   // Either store the old $gp in a register or on the stack
   if (IsReg) {
     // move $save, $gpreg
-    emitRRR(Mips::OR64, RegOrOffset, Mips::GP, Mips::ZERO, SMLoc(), &STI);
+    emitRRR(Mips::OR64, RegOrOffset, GPReg, Mips::ZERO, SMLoc(), &STI);
   } else {
     // sd $gpreg, offset($sp)
-    emitRRI(Mips::SD, Mips::GP, Mips::SP, RegOrOffset, SMLoc(), &STI);
+    emitRRI(Mips::SD, GPReg, Mips::SP, RegOrOffset, SMLoc(), &STI);
   }
 
   if (getABI().IsN32()) {
@@ -1221,11 +1248,11 @@ void MipsTargetELFStreamer::emitDirectiv
         MCA.getContext());
 
     // lui $gp, %hi(__gnu_local_gp)
-    emitRX(Mips::LUi, Mips::GP, MCOperand::createExpr(HiExpr), SMLoc(), &STI);
+    emitRX(Mips::LUi, GPReg, MCOperand::createExpr(HiExpr), SMLoc(), &STI);
 
     // addiu  $gp, $gp, %lo(__gnu_local_gp)
-    emitRRX(Mips::ADDiu, Mips::GP, Mips::GP, MCOperand::createExpr(LoExpr),
-            SMLoc(), &STI);
+    emitRRX(Mips::ADDiu, GPReg, GPReg, MCOperand::createExpr(LoExpr), SMLoc(),
+            &STI);
 
     return;
   }
@@ -1238,14 +1265,14 @@ void MipsTargetELFStreamer::emitDirectiv
       MCA.getContext());
 
   // lui $gp, %hi(%neg(%gp_rel(funcSym)))
-  emitRX(Mips::LUi, Mips::GP, MCOperand::createExpr(HiExpr), SMLoc(), &STI);
+  emitRX(Mips::LUi, GPReg, MCOperand::createExpr(HiExpr), SMLoc(), &STI);
 
   // addiu  $gp, $gp, %lo(%neg(%gp_rel(funcSym)))
-  emitRRX(Mips::ADDiu, Mips::GP, Mips::GP, MCOperand::createExpr(LoExpr),
-          SMLoc(), &STI);
+  emitRRX(Mips::ADDiu, GPReg, GPReg, MCOperand::createExpr(LoExpr), SMLoc(),
+          &STI);
 
   // daddu  $gp, $gp, $funcreg
-  emitRRR(Mips::DADDu, Mips::GP, Mips::GP, RegNo, SMLoc(), &STI);
+  emitRRR(Mips::DADDu, GPReg, GPReg, RegNo, SMLoc(), &STI);
 }
 
 void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation,
@@ -1258,12 +1285,12 @@ void MipsTargetELFStreamer::emitDirectiv
   // Either restore the old $gp from a register or on the stack
   if (SaveLocationIsRegister) {
     Inst.setOpcode(Mips::OR);
-    Inst.addOperand(MCOperand::createReg(Mips::GP));
+    Inst.addOperand(MCOperand::createReg(GPReg));
     Inst.addOperand(MCOperand::createReg(SaveLocation));
     Inst.addOperand(MCOperand::createReg(Mips::ZERO));
   } else {
     Inst.setOpcode(Mips::LD);
-    Inst.addOperand(MCOperand::createReg(Mips::GP));
+    Inst.addOperand(MCOperand::createReg(GPReg));
     Inst.addOperand(MCOperand::createReg(Mips::SP));
     Inst.addOperand(MCOperand::createImm(SaveLocation));
   }

Modified: llvm/trunk/lib/Target/Mips/MipsTargetStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsTargetStreamer.h?rev=366300&r1=366299&r2=366300&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsTargetStreamer.h (original)
+++ llvm/trunk/lib/Target/Mips/MipsTargetStreamer.h Wed Jul 17 01:11:31 2019
@@ -91,6 +91,7 @@ public:
 
   // PIC support
   virtual void emitDirectiveCpLoad(unsigned RegNo);
+  virtual void emitDirectiveCpLocal(unsigned RegNo);
   virtual bool emitDirectiveCpRestore(int Offset,
                                       function_ref<unsigned()> GetATReg,
                                       SMLoc IDLoc, const MCSubtargetInfo *STI);
@@ -199,6 +200,7 @@ protected:
   bool FrameInfoSet;
   int FrameOffset;
   unsigned FrameReg;
+  unsigned GPReg;
   unsigned ReturnReg;
 
 private:
@@ -274,6 +276,7 @@ public:
 
   // PIC support
   void emitDirectiveCpLoad(unsigned RegNo) override;
+  void emitDirectiveCpLocal(unsigned RegNo) override;
 
   /// Emit a .cprestore directive.  If the offset is out of range then it will
   /// be synthesized using the assembler temporary.
@@ -345,6 +348,7 @@ public:
 
   // PIC support
   void emitDirectiveCpLoad(unsigned RegNo) override;
+  void emitDirectiveCpLocal(unsigned RegNo) override;
   bool emitDirectiveCpRestore(int Offset, function_ref<unsigned()> GetATReg,
                               SMLoc IDLoc, const MCSubtargetInfo *STI) override;
   void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,

Added: llvm/trunk/test/MC/Mips/cplocal-bad.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/cplocal-bad.s?rev=366300&view=auto
==============================================================================
--- llvm/trunk/test/MC/Mips/cplocal-bad.s (added)
+++ llvm/trunk/test/MC/Mips/cplocal-bad.s Wed Jul 17 01:11:31 2019
@@ -0,0 +1,20 @@
+# RUN: not llvm-mc -triple=mips-unknown-linux-gnu %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=O32 %s
+# RUN: not llvm-mc -triple=mips64-unknown-linux-gnuabin32 %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=NABI %s
+# RUN: not llvm-mc -triple=mips64-unknown-linux-gnu %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=NABI %s
+
+  .text
+  .cplocal $32
+# O32:  :[[@LINE-1]]:{{[0-9]+}}: error: .cplocal is allowed only in N32 or N64 mode
+# NABI: :[[@LINE-2]]:{{[0-9]+}}: error: invalid register
+  .cplocal $foo
+# O32:  :[[@LINE-1]]:{{[0-9]+}}: error: .cplocal is allowed only in N32 or N64 mode
+# NABI: :[[@LINE-2]]:{{[0-9]+}}: error: expected register containing global pointer
+  .cplocal bar
+# O32:  :[[@LINE-1]]:{{[0-9]+}}: error: .cplocal is allowed only in N32 or N64 mode
+# NABI: :[[@LINE-2]]:{{[0-9]+}}: error: expected register containing global pointer
+  .cplocal $25 foobar
+# O32:  :[[@LINE-1]]:{{[0-9]+}}: error: .cplocal is allowed only in N32 or N64 mode
+# NABI: :[[@LINE-2]]:{{[0-9]+}}: error: unexpected token, expected end of statement

Added: llvm/trunk/test/MC/Mips/cplocal.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/cplocal.s?rev=366300&view=auto
==============================================================================
--- llvm/trunk/test/MC/Mips/cplocal.s (added)
+++ llvm/trunk/test/MC/Mips/cplocal.s Wed Jul 17 01:11:31 2019
@@ -0,0 +1,45 @@
+# RUN: llvm-mc -triple=mips64-unknown-linux-gnuabin32 -position-independent %s \
+# RUN:   | FileCheck -check-prefix=ASM-PIC32 %s
+# RUN: llvm-mc -triple=mips64-unknown-linux-gnu -position-independent %s \
+# RUN:   | FileCheck -check-prefix=ASM-PIC64 %s
+# RUN: llvm-mc -triple=mips64-unknown-linux-gnuabin32 %s \
+# RUN:   | FileCheck -check-prefix=ASM-NPIC %s
+# RUN: llvm-mc -triple=mips64-unknown-linux-gnu %s \
+# RUN:   | FileCheck -check-prefix=ASM-NPIC %s
+
+# RUN: llvm-mc -triple=mips64-unknown-linux-gnuabin32 \
+# RUN:         -position-independent -filetype=obj -o - %s \
+# RUN:   | llvm-objdump -d -r - | FileCheck -check-prefix=OBJ32 %s
+# RUN: llvm-mc -triple=mips64-unknown-linux-gnu \
+# RUN:         -position-independent -filetype=obj -o - %s \
+# RUN:   | llvm-objdump -d -r - | FileCheck -check-prefix=OBJ64 %s
+
+# ASM-PIC32:  .text
+# ASM-PIC32:  .cplocal $4
+# ASM-PIC32:  lw $25, %call16(foo)($4)
+# ASM-PIC32:  jalr $25
+
+# ASM-PIC64:  .text
+# ASM-PIC64:  .cplocal $4
+# ASM-PIC64:  ld $25, %call16(foo)($4)
+# ASM-PIC64:  jalr $25
+
+# ASM-NPIC:  .text
+# ASM-NPIC:  .cplocal $4
+# ASM-NPIC:  jal foo
+
+# OBJ32:   lw $25, 0($4)
+# OBJ32: R_MIPS_CALL16 foo
+# OBJ32:   jalr $25
+# OBJ32: R_MIPS_JALR foo
+
+# OBJ64:   ld $25, 0($4)
+# OBJ64: R_MIPS_CALL16/R_MIPS_NONE/R_MIPS_NONE foo
+# OBJ64:   jalr $25
+# OBJ64: R_MIPS_JALR/R_MIPS_NONE/R_MIPS_NONE foo
+
+  .text
+  .cplocal $4
+  jal foo
+foo:
+  nop




More information about the llvm-commits mailing list