[llvm] r217432 - [mips] Add assembler support for .set push/pop directive.

Toma Tabacu toma.tabacu at imgtec.com
Tue Sep 9 03:15:39 PDT 2014


Author: tomatabacu
Date: Tue Sep  9 05:15:38 2014
New Revision: 217432

URL: http://llvm.org/viewvc/llvm-project?rev=217432&view=rev
Log:
[mips] Add assembler support for .set push/pop directive.

Summary:
These directives are used to save the current assembler options (in the case of ".set push") and restore the previously saved options (in the case of ".set pop").

Contains work done by Matheus Almeida.

Reviewers: dsanders

Reviewed By: dsanders

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

Added:
    llvm/trunk/test/MC/Mips/set-push-pop-directives-bad.s
    llvm/trunk/test/MC/Mips/set-push-pop-directives.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=217432&r1=217431&r2=217432&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp Tue Sep  9 05:15:38 2014
@@ -13,6 +13,7 @@
 #include "MipsTargetStreamer.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
@@ -26,6 +27,7 @@
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/TargetRegistry.h"
+#include <memory>
 
 using namespace llvm;
 
@@ -38,19 +40,30 @@ class MCInstrInfo;
 namespace {
 class MipsAssemblerOptions {
 public:
-  MipsAssemblerOptions() : ATReg(1), Reorder(true), Macro(true) {}
+  MipsAssemblerOptions(uint64_t Features_) : 
+    ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
 
-  unsigned getATRegNum() { return ATReg; }
+  MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
+    ATReg = Opts->getATRegNum();
+    Reorder = Opts->isReorder();
+    Macro = Opts->isMacro();
+    Features = Opts->getFeatures();
+  }
+
+  unsigned getATRegNum() const { return ATReg; }
   bool setATReg(unsigned Reg);
 
-  bool isReorder() { return Reorder; }
+  bool isReorder() const { return Reorder; }
   void setReorder() { Reorder = true; }
   void setNoReorder() { Reorder = false; }
 
-  bool isMacro() { return Macro; }
+  bool isMacro() const { return Macro; }
   void setMacro() { Macro = true; }
   void setNoMacro() { Macro = false; }
 
+  uint64_t getFeatures() const { return Features; }
+  void setFeatures(uint64_t Features_) { Features = Features_; }
+
   // Set of features that are either architecture features or referenced
   // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
   // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
@@ -69,6 +82,7 @@ private:
   unsigned ATReg;
   bool Reorder;
   bool Macro;
+  uint64_t Features;
 };
 }
 
@@ -81,7 +95,7 @@ class MipsAsmParser : public MCTargetAsm
 
   MCSubtargetInfo &STI;
   MCAsmParser &Parser;
-  MipsAssemblerOptions Options;
+  SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
   MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
                        // nullptr, which indicates that no function is currently
                        // selected. This usually happens after an '.end func'
@@ -181,6 +195,8 @@ class MipsAsmParser : public MCTargetAsm
   bool parseSetNoReorderDirective();
   bool parseSetNoMips16Directive();
   bool parseSetFpDirective();
+  bool parseSetPopDirective();
+  bool parseSetPushDirective();
 
   bool parseSetAssignment();
 
@@ -252,6 +268,7 @@ class MipsAsmParser : public MCTargetAsm
     STI.setFeatureBits(FeatureBits);
     setAvailableFeatures(
         ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
+    AssemblerOptions.back()->setFeatures(getAvailableFeatures());
   }
 
   void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
@@ -259,6 +276,7 @@ class MipsAsmParser : public MCTargetAsm
       setAvailableFeatures(
           ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
     }
+    AssemblerOptions.back()->setFeatures(getAvailableFeatures());
   }
 
   void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
@@ -266,6 +284,7 @@ class MipsAsmParser : public MCTargetAsm
       setAvailableFeatures(
           ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
     }
+    AssemblerOptions.back()->setFeatures(getAvailableFeatures());
   }
 
 public:
@@ -282,6 +301,16 @@ public:
       : MCTargetAsmParser(), STI(sti), Parser(parser) {
     // Initialize the set of available features.
     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
+    
+    // Remember the initial assembler options. The user can not modify these.
+    MipsAssemblerOptions *TmpAOPtr = 
+      new MipsAssemblerOptions(getAvailableFeatures());
+    AssemblerOptions.push_back(std::unique_ptr<MipsAssemblerOptions>(TmpAOPtr));
+    
+    // Create an assembler options environment for the user to modify.
+    TmpAOPtr = new MipsAssemblerOptions(getAvailableFeatures());
+    AssemblerOptions.push_back(std::unique_ptr<MipsAssemblerOptions>(TmpAOPtr));
+    TmpAOPtr = nullptr;
 
     getTargetStreamer().updateABIInfo(*this);
 
@@ -1017,7 +1046,7 @@ bool MipsAsmParser::processInstruction(M
                                                       "nop instruction");
   }
 
-  if (MCID.hasDelaySlot() && Options.isReorder()) {
+  if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
     // If this instruction has a delay slot and .set reorder is active,
     // emit a NOP after it.
     Instructions.push_back(Inst);
@@ -1562,7 +1591,8 @@ bool MipsAsmParser::MatchAndEmitInstruct
 }
 
 void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
-  if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
+  if ((RegIndex != 0) && 
+      ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
     if (RegIndex == 1)
       Warning(Loc, "Used $at without \".set noat\"");
     else
@@ -1711,7 +1741,7 @@ bool MipsAssemblerOptions::setATReg(unsi
 }
 
 int MipsAsmParser::getATReg(SMLoc Loc) {
-  int AT = Options.getATRegNum();
+  int AT = AssemblerOptions.back()->getATRegNum();
   if (AT == 0)
     reportParseError(Loc,
                      "Pseudo instruction requires $at, which is not available");
@@ -2467,7 +2497,7 @@ bool MipsAsmParser::reportParseError(SML
 bool MipsAsmParser::parseSetNoAtDirective() {
   // Line should look like: ".set noat".
   // set at reg to 0.
-  Options.setATReg(0);
+  AssemblerOptions.back()->setATReg(0);
   // eat noat
   Parser.Lex();
   // If this is not the end of the statement, report an error.
@@ -2485,7 +2515,7 @@ bool MipsAsmParser::parseSetAtDirective(
   int AtRegNo;
   getParser().Lex();
   if (getLexer().is(AsmToken::EndOfStatement)) {
-    Options.setATReg(1);
+    AssemblerOptions.back()->setATReg(1);
     Parser.Lex(); // Consume the EndOfStatement.
     return false;
   } else if (getLexer().is(AsmToken::Equal)) {
@@ -2510,7 +2540,7 @@ bool MipsAsmParser::parseSetAtDirective(
       return false;
     }
 
-    if (!Options.setATReg(AtRegNo)) {
+    if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
       reportParseError("unexpected token in statement");
       return false;
     }
@@ -2535,7 +2565,7 @@ bool MipsAsmParser::parseSetReorderDirec
     reportParseError("unexpected token in statement");
     return false;
   }
-  Options.setReorder();
+  AssemblerOptions.back()->setReorder();
   getTargetStreamer().emitDirectiveSetReorder();
   Parser.Lex(); // Consume the EndOfStatement.
   return false;
@@ -2548,7 +2578,7 @@ bool MipsAsmParser::parseSetNoReorderDir
     reportParseError("unexpected token in statement");
     return false;
   }
-  Options.setNoReorder();
+  AssemblerOptions.back()->setNoReorder();
   getTargetStreamer().emitDirectiveSetNoReorder();
   Parser.Lex(); // Consume the EndOfStatement.
   return false;
@@ -2561,7 +2591,7 @@ bool MipsAsmParser::parseSetMacroDirecti
     reportParseError("unexpected token in statement");
     return false;
   }
-  Options.setMacro();
+  AssemblerOptions.back()->setMacro();
   Parser.Lex(); // Consume the EndOfStatement.
   return false;
 }
@@ -2573,11 +2603,11 @@ bool MipsAsmParser::parseSetNoMacroDirec
     reportParseError("`noreorder' must be set before `nomacro'");
     return false;
   }
-  if (Options.isReorder()) {
+  if (AssemblerOptions.back()->isReorder()) {
     reportParseError("`noreorder' must be set before `nomacro'");
     return false;
   }
-  Options.setNoMacro();
+  AssemblerOptions.back()->setNoMacro();
   Parser.Lex(); // Consume the EndOfStatement.
   return false;
 }
@@ -2644,6 +2674,39 @@ bool MipsAsmParser::parseSetFpDirective(
   return false;
 }
 
+bool MipsAsmParser::parseSetPopDirective() {
+  SMLoc Loc = getLexer().getLoc();
+
+  Parser.Lex();
+  if (getLexer().isNot(AsmToken::EndOfStatement))
+    return reportParseError("unexpected token, expected end of statement");
+
+  // Always keep an element on the options "stack" to prevent the user
+  // from changing the initial options. This is how we remember them.
+  if (AssemblerOptions.size() == 2)
+    return reportParseError(Loc, ".set pop with no .set push");
+
+  AssemblerOptions.pop_back();
+  setAvailableFeatures(AssemblerOptions.back()->getFeatures());
+
+  getTargetStreamer().emitDirectiveSetPop();
+  return false;
+}
+
+bool MipsAsmParser::parseSetPushDirective() {
+  Parser.Lex();
+  if (getLexer().isNot(AsmToken::EndOfStatement))
+    return reportParseError("unexpected token, expected end of statement");
+
+  // Create a copy of the current assembler options environment and push it.
+  MipsAssemblerOptions *TmpAOPtr = 
+    new MipsAssemblerOptions(AssemblerOptions.back().get());
+  AssemblerOptions.push_back(std::unique_ptr<MipsAssemblerOptions>(TmpAOPtr));
+
+  getTargetStreamer().emitDirectiveSetPush();
+  return false;
+}
+
 bool MipsAsmParser::parseSetAssignment() {
   StringRef Name;
   const MCExpr *Value;
@@ -2781,7 +2844,7 @@ bool MipsAsmParser::eatComma(StringRef E
 }
 
 bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
-  if (Options.isReorder())
+  if (AssemblerOptions.back()->isReorder())
     Warning(Loc, ".cpload in reorder section");
 
   // FIXME: Warn if cpload is used in Mips16 mode.
@@ -2896,6 +2959,10 @@ bool MipsAsmParser::parseDirectiveSet()
     return parseSetArchDirective();
   } else if (Tok.getString() == "fp") {
     return parseSetFpDirective();
+  } else if (Tok.getString() == "pop") {
+    return parseSetPopDirective();
+  } else if (Tok.getString() == "push") {
+    return parseSetPushDirective();
   } else if (Tok.getString() == "reorder") {
     return parseSetReorderDirective();
   } else if (Tok.getString() == "noreorder") {

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=217432&r1=217431&r2=217432&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp Tue Sep  9 05:15:38 2014
@@ -70,6 +70,8 @@ void MipsTargetStreamer::emitDirectiveSe
 void MipsTargetStreamer::emitDirectiveSetMips64() { forbidModuleDirective(); }
 void MipsTargetStreamer::emitDirectiveSetMips64R2() { forbidModuleDirective(); }
 void MipsTargetStreamer::emitDirectiveSetMips64R6() { forbidModuleDirective(); }
+void MipsTargetStreamer::emitDirectiveSetPop() {}
+void MipsTargetStreamer::emitDirectiveSetPush() {}
 void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); }
 void MipsTargetStreamer::emitDirectiveCpload(unsigned RegNo) {}
 void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
@@ -241,6 +243,11 @@ void MipsTargetAsmStreamer::emitDirectiv
   OS << "\t.set\tdsp\n";
   MipsTargetStreamer::emitDirectiveSetDsp();
 }
+
+void MipsTargetAsmStreamer::emitDirectiveSetPop() { OS << "\t.set\tpop\n"; }
+
+void MipsTargetAsmStreamer::emitDirectiveSetPush() { OS << "\t.set\tpush\n"; }
+
 // Print a 32 bit hex number with all numbers.
 static void printHex32(unsigned Value, raw_ostream &OS) {
   OS << "0x";

Modified: llvm/trunk/lib/Target/Mips/MipsTargetStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsTargetStreamer.h?rev=217432&r1=217431&r2=217432&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsTargetStreamer.h (original)
+++ llvm/trunk/lib/Target/Mips/MipsTargetStreamer.h Tue Sep  9 05:15:38 2014
@@ -61,6 +61,8 @@ public:
   virtual void emitDirectiveSetMips64R2();
   virtual void emitDirectiveSetMips64R6();
   virtual void emitDirectiveSetDsp();
+  virtual void emitDirectiveSetPop();
+  virtual void emitDirectiveSetPush();
 
   // PIC support
   virtual void emitDirectiveCpload(unsigned RegNo);
@@ -161,6 +163,8 @@ public:
   void emitDirectiveSetMips64R2() override;
   void emitDirectiveSetMips64R6() override;
   void emitDirectiveSetDsp() override;
+  void emitDirectiveSetPop() override;
+  void emitDirectiveSetPush() override;
 
   // PIC support
   void emitDirectiveCpload(unsigned RegNo) override;

Added: llvm/trunk/test/MC/Mips/set-push-pop-directives-bad.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/set-push-pop-directives-bad.s?rev=217432&view=auto
==============================================================================
--- llvm/trunk/test/MC/Mips/set-push-pop-directives-bad.s (added)
+++ llvm/trunk/test/MC/Mips/set-push-pop-directives-bad.s Tue Sep  9 05:15:38 2014
@@ -0,0 +1,14 @@
+# RUN: not llvm-mc %s -triple=mipsel-unknown-linux -mcpu=mips32r2 2>%t1
+# RUN:   FileCheck %s < %t1
+
+        .text
+        .set pop
+# CHECK: :[[@LINE-1]]:14: error: .set pop with no .set push
+        .set push
+        .set pop
+        .set pop
+# CHECK: :[[@LINE-1]]:14: error: .set pop with no .set push
+        .set push foo
+# CHECK: :[[@LINE-1]]:19: error: unexpected token, expected end of statement
+        .set pop bar
+# CHECK: :[[@LINE-1]]:18: error: unexpected token, expected end of statement

Added: llvm/trunk/test/MC/Mips/set-push-pop-directives.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/set-push-pop-directives.s?rev=217432&view=auto
==============================================================================
--- llvm/trunk/test/MC/Mips/set-push-pop-directives.s (added)
+++ llvm/trunk/test/MC/Mips/set-push-pop-directives.s Tue Sep  9 05:15:38 2014
@@ -0,0 +1,53 @@
+# RUN: llvm-mc %s -triple=mipsel-unknown-linux -mcpu=mips32r2 -mattr=+msa | \
+# RUN:   FileCheck %s
+# .set push creates a copy of the current environment.
+# .set pop restores the previous environment.
+# FIXME: Also test resetting of .set macro/nomacro option.
+
+    .text
+    # The first environment on the stack (with initial values).
+    lw       $1, 65536($1)
+    b        1336
+    addvi.b  $w15, $w13, 18
+    
+    # Create a new environment.
+    .set push
+    .set at=$ra           # Test the ATReg option.
+    lw       $1, 65536($1)
+    .set noreorder        # Test the Reorder option.
+    b        1336
+    .set nomsa            # Test the Features option (ASE).
+    .set mips32r6         # Test the Features option (ISA).
+    mod      $2, $4, $6
+
+    # Switch back to the first environment.
+    .set pop
+    lw       $1, 65536($1)
+    b        1336
+    addvi.b  $w15, $w13, 18
+
+# CHECK:  lui      $1, 1
+# CHECK:  addu     $1, $1, $1
+# CHECK:  lw       $1, 0($1)
+# CHECK:  b        1336
+# CHECK:  nop
+# CHECK:  addvi.b  $w15, $w13, 18
+
+# CHECK:  .set push
+# CHECK:  lui      $ra, 1
+# CHECK:  addu     $ra, $ra, $1
+# CHECK:  lw       $1, 0($ra)
+# CHECK:  .set noreorder   
+# CHECK:  b        1336
+# CHECK-NOT:  nop
+# CHECK:  .set nomsa       
+# CHECK:  .set mips32r6    
+# CHECK:  mod      $2, $4, $6
+
+# CHECK:  .set pop
+# CHECK:  lui      $1, 1
+# CHECK:  addu     $1, $1, $1
+# CHECK:  lw       $1, 0($1)
+# CHECK:  b        1336
+# CHECK:  nop
+# CHECK:  addvi.b  $w15, $w13, 18





More information about the llvm-commits mailing list