This patch is a partial implementation of mips .set assembler directive. Directive...
authorJack Carter <jcarter@mips.com>
Thu, 4 Oct 2012 02:29:46 +0000 (02:29 +0000)
committerJack Carter <jcarter@mips.com>
Thu, 4 Oct 2012 02:29:46 +0000 (02:29 +0000)
.set option
The patch implements following options

    at - lets the assembler use the $at register for macros,
         but generates warnings if the source program uses $at

    noat - let source programs use $at without issuingwarnings.

    noreorder - prevents the assembler from reordering machine
                language instructions.
    nomacro - causes the assembler to print a warning whenever
              an assembler operation generates more than one
              machine language instruction.
    macro - lets the assembler generate multiple machine instructions
            from a single assembler instruction
    reorder - lets the assembler reorder machine language
               instructions to improve performance

The above variants are parsed and their boolean values set or unset.
The code to actually use them will come later.

Following options are not implemented yet:

nomips16
nomicromips
move
nomove

Contributer: Vladimir Medic

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

lib/Target/Mips/AsmParser/MipsAsmParser.cpp
test/MC/Mips/mips_directives.s

index 349abef16be62cc1b7c4382cfd4c24776ca28bef..ff55905dfe73945d570f97d7d9b31336722fa26d 100644 (file)
 using namespace llvm;
 
 namespace {
+class MipsAssemblerOptions {
+public:
+  MipsAssemblerOptions():
+    aTReg(1), reorder(true), macro(true) {
+  }
+
+  unsigned getATRegNum() {return aTReg;}
+  bool setATReg(unsigned Reg);
 
+  bool isReorder() {return reorder;}
+  void setReorder() {reorder = true;}
+  void setNoreorder() {reorder = false;}
+
+  bool isMacro() {return macro;}
+  void setMacro() {macro = true;}
+  void setNomacro() {macro = false;}
+
+private:
+  unsigned aTReg;
+  bool reorder;
+  bool macro;
+};
+}
+
+namespace {
 class MipsAsmParser : public MCTargetAsmParser {
 
   enum FpFormatTy {
@@ -37,6 +61,8 @@ class MipsAsmParser : public MCTargetAsmParser {
 
   MCSubtargetInfo &STI;
   MCAsmParser &Parser;
+  MipsAssemblerOptions *Options;
+
 
 #define GET_ASSEMBLER_HEADER
 #include "MipsGenAsmMatcher.inc"
@@ -66,8 +92,20 @@ class MipsAsmParser : public MCTargetAsmParser {
   bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
                                StringRef Mnemonic);
 
+  bool reportParseError(StringRef ErrorMsg);
+
   bool parseMemOffset(const MCExpr *&Res);
   bool parseRelocOperand(const MCExpr *&Res);
+
+  bool parseDirectiveSet();
+
+  bool parseSetAtDirective();
+  bool parseSetNoAtDirective();
+  bool parseSetMacroDirective();
+  bool parseSetNoMacroDirective();
+  bool parseSetReorderDirective();
+  bool parseSetNoReorderDirective();
+
   MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
 
   bool isMips64() const {
@@ -96,11 +134,13 @@ class MipsAsmParser : public MCTargetAsmParser {
 
   unsigned getReg(int RC,int RegNo);
 
+  unsigned getATReg();
 public:
   MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
     : MCTargetAsmParser(), STI(sti), Parser(parser) {
     // Initialize the set of available features.
     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
+    Options = new MipsAssemblerOptions();
   }
 
   MCAsmParser &getParser() const { return Parser; }
@@ -395,11 +435,27 @@ void MipsAsmParser::setFpFormat(StringRef Format) {
     .Default(FP_FORMAT_NONE);
 }
 
-unsigned MipsAsmParser::getReg(int RC,int RegNo){
+bool MipsAssemblerOptions::setATReg(unsigned Reg) {
+  if (Reg > 31)
+    return false;
+
+  aTReg = Reg;
+  return true;
+}
+
+unsigned MipsAsmParser::getATReg() {
+  unsigned Reg = Options->getATRegNum();
+  if (isMips64())
+    return getReg(Mips::CPU64RegsRegClassID,Reg);
+  else
+    return getReg(Mips::CPURegsRegClassID,Reg);
+}
+
+unsigned MipsAsmParser::getReg(int RC,int RegNo) {
   return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
 }
 
-int MipsAsmParser::matchRegisterByNumber(unsigned RegNum,StringRef Mnemonic) {
+int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic) {
 
   if (Mnemonic.lower() == "rdhwr") {
     //at the moment only hwreg29 is supported
@@ -411,7 +467,7 @@ int MipsAsmParser::matchRegisterByNumber(unsigned RegNum,StringRef Mnemonic) {
   if (RegNum > 31)
     return -1;
 
-  return getReg(Mips::CPURegsRegClassID,RegNum);
+  return getReg(Mips::CPURegsRegClassID, RegNum);
 }
 
 int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
@@ -544,14 +600,14 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
 
     Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
     return false;
-  }//case AsmToken::Percent
-  }//switch(getLexer().getKind())
+  } // case AsmToken::Percent
+  } // switch(getLexer().getKind())
   return true;
 }
 
 bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
 
-  Parser.Lex(); //eat % token
+  Parser.Lex(); // eat % token
   const AsmToken &Tok = Parser.getTok(); //get next token, operation
   if (Tok.isNot(AsmToken::Identifier))
     return true;
@@ -559,21 +615,21 @@ bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
   std::string Str = Tok.getIdentifier().str();
 
   Parser.Lex(); //eat identifier
-  //now make expression from the rest of the operand
+  // now make expression from the rest of the operand
   const MCExpr *IdVal;
   SMLoc EndLoc;
 
   if (getLexer().getKind() == AsmToken::LParen) {
     while (1) {
-      Parser.Lex(); //eat '(' token
+      Parser.Lex(); // eat '(' token
       if (getLexer().getKind() == AsmToken::Percent) {
-        Parser.Lex(); //eat % token
+        Parser.Lex(); // eat % token
         const AsmToken &nextTok = Parser.getTok();
         if (nextTok.isNot(AsmToken::Identifier))
           return true;
         Str += "(%";
         Str += nextTok.getIdentifier();
-        Parser.Lex(); //eat identifier
+        Parser.Lex(); // eat identifier
         if (getLexer().getKind() != AsmToken::LParen)
           return true;
       } else
@@ -583,12 +639,12 @@ bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
       return true;
 
     while (getLexer().getKind() == AsmToken::RParen)
-      Parser.Lex(); //eat ')' token
+      Parser.Lex(); // eat ')' token
 
   } else
-    return true; //parenthesis must follow reloc operand
+    return true; // parenthesis must follow reloc operand
 
-  //Check the type of the expression
+  // Check the type of the expression
   if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
     //it's a constant, evaluate lo or hi value
     int Val = MCE->getValue();
@@ -602,7 +658,7 @@ bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
   }
 
   if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
-    //it's a symbol, create symbolic expression from symbol
+    // it's a symbol, create symbolic expression from symbol
     StringRef Symbol = MSRE->getSymbol().getName();
     MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
     Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
@@ -634,7 +690,7 @@ bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
   case AsmToken::Percent:
     return parseRelocOperand(Res);
   case AsmToken::LParen:
-    return false;  //it's probably assuming 0
+    return false;  // it's probably assuming 0
   }
   return true;
 }
@@ -644,13 +700,13 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
 
   const MCExpr *IdVal = 0;
   SMLoc S;
-  //first operand is the offset
+  // first operand is the offset
   S = Parser.getTok().getLoc();
 
   if (parseMemOffset(IdVal))
     return MatchOperand_ParseFail;
 
-  const AsmToken &Tok = Parser.getTok(); //get next token
+  const AsmToken &Tok = Parser.getTok(); // get next token
   if (Tok.isNot(AsmToken::LParen)) {
     Error(Parser.getTok().getLoc(), "'(' expected");
     return MatchOperand_ParseFail;
@@ -667,11 +723,11 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
     }
 
   } else {
-    Error(Parser.getTok().getLoc(),"unexpected token in operand");
+    Error(Parser.getTok().getLoc(), "unexpected token in operand");
     return MatchOperand_ParseFail;
   }
 
-  const AsmToken &Tok2 = Parser.getTok(); //get next token
+  const AsmToken &Tok2 = Parser.getTok(); // get next token
   if (Tok2.isNot(AsmToken::RParen)) {
     Error(Parser.getTok().getLoc(), "')' expected");
     return MatchOperand_ParseFail;
@@ -684,12 +740,12 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
   if (IdVal == 0)
     IdVal = MCConstantExpr::Create(0, getContext());
 
-  //now replace register operand with the mem operand
+  // now replace register operand with the mem operand
   MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
   int RegNo = op->getReg();
-  //remove register from operands
+  // remove register from operands
   Operands.pop_back();
-  //and add memory operand
+  // and add memory operand
   Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
   delete op;
   return MatchOperand_Success;
@@ -746,17 +802,17 @@ static int ConvertCcString(StringRef CondString) {
 
 bool MipsAsmParser::
 parseMathOperation(StringRef Name, SMLoc NameLoc,
-                        SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
-  //split the format
+                   SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+  // split the format
   size_t Start = Name.find('.'), Next = Name.rfind('.');
   StringRef Format1 = Name.slice(Start, Next);
-  //and add the first format to the operands
+  // and add the first format to the operands
   Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
-  //now for the second format
+  // now for the second format
   StringRef Format2 = Name.slice(Next, StringRef::npos);
   Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
 
-  //set the format for the first register
+  // set the format for the first register
   setFpFormat(Format1);
 
   // Read the remaining operands.
@@ -800,7 +856,7 @@ parseMathOperation(StringRef Name, SMLoc NameLoc,
 bool MipsAsmParser::
 ParseInstruction(StringRef Name, SMLoc NameLoc,
                  SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
-  //floating point instructions: should register be treated as double?
+  // floating point instructions: should register be treated as double?
   if (requestsDoubleOperand(Name)) {
     setFpFormat(FP_FORMAT_D);
   Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
@@ -814,8 +870,8 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
     Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
 
     if (Next != StringRef::npos) {
-      //there is a format token in mnemonic
-      //StringRef Rest = Name.slice(Next, StringRef::npos);
+      // there is a format token in mnemonic
+      // StringRef Rest = Name.slice(Next, StringRef::npos);
       size_t Dot = Name.find('.', Next+1);
       StringRef Format = Name.slice(Next, Dot);
       if (Dot == StringRef::npos) //only one '.' in a string, it's a format
@@ -833,11 +889,11 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
           Operands.push_back(MipsOperand::CreateImm(
               MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
         } else {
-          //trunc, ceil, floor ...
+          // trunc, ceil, floor ...
           return parseMathOperation(Name, NameLoc, Operands);
         }
 
-        //the rest is a format
+        // the rest is a format
         Format = Name.slice(Dot, StringRef::npos);
         Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
       }
@@ -877,47 +933,186 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
   return false;
 }
 
-bool MipsAsmParser::
-ParseDirective(AsmToken DirectiveID) {
+bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
+   SMLoc Loc = getLexer().getLoc();
+   Parser.EatToEndOfStatement();
+   return Error(Loc, ErrorMsg);
+}
+
+bool MipsAsmParser::parseSetNoAtDirective() {
+  // line should look like:
+  //  .set noat
+  // set at reg to 0
+  Options->setATReg(0);
+  // eat noat
+  Parser.Lex();
+  // if this is not the end of the statement, report error
+  if (getLexer().isNot(AsmToken::EndOfStatement)) {
+    reportParseError("unexpected token in statement");
+    return false;
+  }
+  Parser.Lex(); // Consume the EndOfStatement
+  return false;
+}
+bool MipsAsmParser::parseSetAtDirective() {
+  // line can be
+  //  .set at - defaults to $1
+  // or .set at=$reg
+  getParser().Lex();
+  if (getLexer().is(AsmToken::EndOfStatement)) {
+    Options->setATReg(1);
+    Parser.Lex(); // Consume the EndOfStatement
+    return false;
+  } else if (getLexer().is(AsmToken::Equal)) {
+    getParser().Lex(); //eat '='
+    if (getLexer().isNot(AsmToken::Dollar)) {
+      reportParseError("unexpected token in statement");
+      return false;
+    }
+    Parser.Lex(); // eat '$'
+    if (getLexer().isNot(AsmToken::Integer)) {
+      reportParseError("unexpected token in statement");
+      return false;
+    }
+    const AsmToken &Reg = Parser.getTok();
+    if (!Options->setATReg(Reg.getIntVal())) {
+      reportParseError("unexpected token in statement");
+      return false;
+    }
+    getParser().Lex(); //eat reg
+
+    if (getLexer().isNot(AsmToken::EndOfStatement)) {
+      reportParseError("unexpected token in statement");
+      return false;
+     }
+    Parser.Lex(); // Consume the EndOfStatement
+    return false;
+  } else {
+    reportParseError("unexpected token in statement");
+    return false;
+  }
+}
+
+bool MipsAsmParser::parseSetReorderDirective() {
+  Parser.Lex();
+  // if this is not the end of the statement, report error
+  if (getLexer().isNot(AsmToken::EndOfStatement)) {
+    reportParseError("unexpected token in statement");
+    return false;
+  }
+  Options->setReorder();
+  Parser.Lex(); // Consume the EndOfStatement
+  return false;
+}
+
+bool MipsAsmParser::parseSetNoReorderDirective() {
+    Parser.Lex();
+    // if this is not the end of the statement, report error
+    if (getLexer().isNot(AsmToken::EndOfStatement)) {
+      reportParseError("unexpected token in statement");
+      return false;
+    }
+    Options->setNoreorder();
+    Parser.Lex(); // Consume the EndOfStatement
+    return false;
+}
+
+bool MipsAsmParser::parseSetMacroDirective() {
+  Parser.Lex();
+  // if this is not the end of the statement, report error
+  if (getLexer().isNot(AsmToken::EndOfStatement)) {
+    reportParseError("unexpected token in statement");
+    return false;
+  }
+  Options->setMacro();
+  Parser.Lex(); // Consume the EndOfStatement
+  return false;
+}
+
+bool MipsAsmParser::parseSetNoMacroDirective() {
+  Parser.Lex();
+  // if this is not the end of the statement, report error
+  if (getLexer().isNot(AsmToken::EndOfStatement)) {
+    reportParseError("`noreorder' must be set before `nomacro'");
+    return false;
+  }
+  if (Options->isReorder()) {
+    reportParseError("`noreorder' must be set before `nomacro'");
+    return false;
+  }
+  Options->setNomacro();
+  Parser.Lex(); // Consume the EndOfStatement
+  return false;
+}
+bool MipsAsmParser::parseDirectiveSet() {
+
+  // get next token
+  const AsmToken &Tok = Parser.getTok();
+
+  if (Tok.getString() == "noat") {
+    return parseSetNoAtDirective();
+  } else if (Tok.getString() == "at") {
+    return parseSetAtDirective();
+  } else if (Tok.getString() == "reorder") {
+    return parseSetReorderDirective();
+  } else if (Tok.getString() == "noreorder") {
+    return parseSetNoReorderDirective();
+  } else if (Tok.getString() == "macro") {
+    return parseSetMacroDirective();
+  } else if (Tok.getString() == "nomacro") {
+    return parseSetNoMacroDirective();
+  } else if (Tok.getString() == "nomips16") {
+    // ignore this directive for now
+    Parser.EatToEndOfStatement();
+    return false;
+  } else if (Tok.getString() == "nomicromips") {
+    // ignore this directive for now
+    Parser.EatToEndOfStatement();
+    return false;
+  }
+  return true;
+}
+
+bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
 
   if (DirectiveID.getString() == ".ent") {
-    //ignore this directive for now
+    // ignore this directive for now
     Parser.Lex();
     return false;
   }
 
   if (DirectiveID.getString() == ".end") {
-    //ignore this directive for now
+    // ignore this directive for now
     Parser.Lex();
     return false;
   }
 
   if (DirectiveID.getString() == ".frame") {
-    //ignore this directive for now
+    // ignore this directive for now
     Parser.EatToEndOfStatement();
     return false;
   }
 
   if (DirectiveID.getString() == ".set") {
-    //ignore this directive for now
-    Parser.EatToEndOfStatement();
-    return false;
+    // ignore this directive for now
+    //Parser.EatToEndOfStatement();
+    return parseDirectiveSet();
   }
 
   if (DirectiveID.getString() == ".fmask") {
-    //ignore this directive for now
+    // ignore this directive for now
     Parser.EatToEndOfStatement();
     return false;
   }
 
   if (DirectiveID.getString() == ".mask") {
-    //ignore this directive for now
+    // ignore this directive for now
     Parser.EatToEndOfStatement();
     return false;
   }
 
   if (DirectiveID.getString() == ".gpword") {
-    //ignore this directive for now
+    // ignore this directive for now
     Parser.EatToEndOfStatement();
     return false;
   }
index f9d846078bfb68723eb2bd5adb021cff6eb750f5..e2f75a827d0a1ee8cd20cb902b15cfffba90b780 100644 (file)
@@ -1,10 +1,16 @@
 # RUN: llvm-mc -triple mips-unknown-unknown %s
-
+#this test produces no output so there isS no FileCheck call
 $BB0_2:
+  .ent directives_test
        .frame  $sp,0,$ra
        .mask   0x00000000,0
        .fmask  0x00000000,0
        .set    noreorder
        .set    nomacro
+       .set    noat
 $JTI0_0:
        .gpword ($BB0_2)
+       .set  at=$12
+       .set macro
+       .set reorder
+       .end directives_test