[llvm-commits] [llvm] r85632 - /llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp

Kevin Enderby enderby at apple.com
Fri Oct 30 15:55:57 PDT 2009


Author: enderby
Date: Fri Oct 30 17:55:57 2009
New Revision: 85632

URL: http://llvm.org/viewvc/llvm-project?rev=85632&view=rev
Log:
Updates to the ARM target assembler for llvm-mc per review comments from
Daniel Dunbar.
- Reordered the fields in the ARMOperand Mem struct to make the struct smaller.
Making bool's into 1 bit fields and put the MCExpr* fields adjacent to each
other.
- Fixed a number of places in ARMAsmParser.cpp so they have doxygen comments.
- Change the name of ARMAsmParser::ParseRegister() to MaybeParseRegister and
added the bool ParseWriteBack parameter.
- Changed ARMAsmParser::ParseMemory() to call MaybeParseRegister().
- Added ARMAsmParser::ParseMemoryOffsetReg to factor out parsing the offset of a
memory operand.  And use it for both parsing both preindexed and post indexing
addressing forms in ARMAsmParser::ParseMemory.
- Changed the first argument to ParseShift() to a reference.
- Changed ParseShift() to check for Rrx first and return to reduce nesting.

Modified:
    llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp

Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=85632&r1=85631&r2=85632&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Fri Oct 30 17:55:57 2009
@@ -44,13 +44,21 @@
 
   bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
 
-  bool ParseRegister(ARMOperand &Op);
+  bool MaybeParseRegister(ARMOperand &Op, bool ParseWriteBack);
 
   bool ParseRegisterList(ARMOperand &Op);
 
   bool ParseMemory(ARMOperand &Op);
 
-  bool ParseShift(enum ShiftType *St, const MCExpr *&ShiftAmount);
+  bool ParseMemoryOffsetReg(bool &Negative,
+                            bool &OffsetRegShifted,
+                            enum ShiftType &ShiftType,
+                            const MCExpr *&ShiftAmount,
+                            const MCExpr *&Offset,
+                            bool &OffsetIsReg,
+                            int OffsetRegNum);
+
+  bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount);
 
   bool ParseOperand(ARMOperand &Op);
 
@@ -123,16 +131,17 @@
     // This is for all forms of ARM address expressions
     struct {
       unsigned BaseRegNum;
-      bool OffsetIsReg;
-      const MCExpr *Offset; // used when OffsetIsReg is false
       unsigned OffsetRegNum; // used when OffsetIsReg is true
-      bool OffsetRegShifted; // only used when OffsetIsReg is true
-      enum ShiftType ShiftType;  // used when OffsetRegShifted is true
+      const MCExpr *Offset; // used when OffsetIsReg is false
       const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
-      bool Preindexed;
-      bool Postindexed;
-      bool Negative; // only used when OffsetIsReg is true
-      bool Writeback;
+      enum ShiftType ShiftType;  // used when OffsetRegShifted is true
+      unsigned
+        OffsetRegShifted : 1, // only used when OffsetIsReg is true
+        Preindexed : 1,
+        Postindexed : 1,
+        OffsetIsReg : 1,
+        Negative : 1, // only used when OffsetIsReg is true
+        Writeback : 1;
     } Mem;
 
   };
@@ -208,12 +217,12 @@
 
 } // end anonymous namespace.
 
-// Try to parse a register name.  The token must be an Identifier when called,
-// and if it is a register name a Reg operand is created, the token is eaten
-// and false is returned.  Else true is returned and no token is eaten.
-// TODO this is likely to change to allow different register types and or to
-// parse for a specific register type.
-bool ARMAsmParser::ParseRegister(ARMOperand &Op) {
+/// Try to parse a register name.  The token must be an Identifier when called,
+/// and if it is a register name a Reg operand is created, the token is eaten
+/// and false is returned.  Else true is returned and no token is eaten.
+/// TODO this is likely to change to allow different register types and or to
+/// parse for a specific register type.
+bool ARMAsmParser::MaybeParseRegister(ARMOperand &Op, bool ParseWriteBack) {
   const AsmToken &Tok = getLexer().getTok();
   assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
 
@@ -227,10 +236,12 @@
   getLexer().Lex(); // Eat identifier token.
 
   bool Writeback = false;
-  const AsmToken &ExclaimTok = getLexer().getTok();
-  if (ExclaimTok.is(AsmToken::Exclaim)) {
-    Writeback = true;
-    getLexer().Lex(); // Eat exclaim token
+  if (ParseWriteBack) {
+    const AsmToken &ExclaimTok = getLexer().getTok();
+    if (ExclaimTok.is(AsmToken::Exclaim)) {
+      Writeback = true;
+      getLexer().Lex(); // Eat exclaim token
+    }
   }
 
   Op = ARMOperand::CreateReg(RegNum, Writeback);
@@ -238,8 +249,8 @@
   return false;
 }
 
-// Parse a register list, return false if successful else return true or an 
-// error.  The first token must be a '{' when called.
+/// Parse a register list, return false if successful else return true or an 
+/// error.  The first token must be a '{' when called.
 bool ARMAsmParser::ParseRegisterList(ARMOperand &Op) {
   assert(getLexer().getTok().is(AsmToken::LCurly) &&
          "Token is not an Left Curly Brace");
@@ -285,10 +296,10 @@
   return false;
 }
 
-// Parse an arm memory expression, return false if successful else return true
-// or an error.  The first token must be a '[' when called.
-// TODO Only preindexing and postindexing addressing are started, unindexed
-// with option, etc are still to do.
+/// Parse an arm memory expression, return false if successful else return true
+/// or an error.  The first token must be a '[' when called.
+/// TODO Only preindexing and postindexing addressing are started, unindexed
+/// with option, etc are still to do.
 bool ARMAsmParser::ParseMemory(ARMOperand &Op) {
   assert(getLexer().getTok().is(AsmToken::LBrac) &&
          "Token is not an Left Bracket");
@@ -297,10 +308,9 @@
   const AsmToken &BaseRegTok = getLexer().getTok();
   if (BaseRegTok.isNot(AsmToken::Identifier))
     return Error(BaseRegTok.getLoc(), "register expected");
-  int BaseRegNum = MatchRegisterName(BaseRegTok.getString());
-  if (BaseRegNum == -1)
+  if (MaybeParseRegister(Op, false))
     return Error(BaseRegTok.getLoc(), "register expected");
-  getLexer().Lex(); // Eat identifier token.
+  int BaseRegNum = Op.getReg();
 
   bool Preindexed = false;
   bool Postindexed = false;
@@ -308,55 +318,20 @@
   bool Negative = false;
   bool Writeback = false;
 
-  // First look for preindexed address forms:
-  //  [Rn, +/-Rm]
-  //  [Rn, #offset]
-  //  [Rn, +/-Rm, shift]
-  // that is after the "[Rn" we now have see if the next token is a comma.
+  // First look for preindexed address forms, that is after the "[Rn" we now
+  // have to see if the next token is a comma.
   const AsmToken &Tok = getLexer().getTok();
   if (Tok.is(AsmToken::Comma)) {
     Preindexed = true;
     getLexer().Lex(); // Eat comma token.
-
-    const AsmToken &NextTok = getLexer().getTok();
-    if (NextTok.is(AsmToken::Plus))
-      getLexer().Lex(); // Eat plus token.
-    else if (NextTok.is(AsmToken::Minus)) {
-      Negative = true;
-      getLexer().Lex(); // Eat minus token
-    }
-
-    // See if there is a register following the "[Rn," we have so far.
-    const AsmToken &OffsetRegTok = getLexer().getTok();
-    int OffsetRegNum = MatchRegisterName(OffsetRegTok.getString());
-    bool OffsetRegShifted = false;
+    int OffsetRegNum;
+    bool OffsetRegShifted;
     enum ShiftType ShiftType;
     const MCExpr *ShiftAmount;
     const MCExpr *Offset;
-    if (OffsetRegNum != -1) {
-      OffsetIsReg = true;
-      getLexer().Lex(); // Eat identifier token for the offset register.
-      // Look for a comma then a shift
-      const AsmToken &Tok = getLexer().getTok();
-      if (Tok.is(AsmToken::Comma)) {
-        getLexer().Lex(); // Eat comma token.
-
-        const AsmToken &Tok = getLexer().getTok();
-        if (ParseShift(&ShiftType, ShiftAmount))
-          return Error(Tok.getLoc(), "shift expected");
-        OffsetRegShifted = true;
-      }
-    }
-    else { // "[Rn," we have so far was not followed by "Rm"
-      // Look for #offset following the "[Rn,"
-      const AsmToken &HashTok = getLexer().getTok();
-      if (HashTok.isNot(AsmToken::Hash))
-        return Error(HashTok.getLoc(), "'#' expected");
-      getLexer().Lex(); // Eat hash token.
-
-      if (getParser().ParseExpression(Offset))
-       return true;
-    }
+    if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
+                            Offset, OffsetIsReg, OffsetRegNum))
+      return true;
     const AsmToken &RBracTok = getLexer().getTok();
     if (RBracTok.isNot(AsmToken::RBrac))
       return Error(RBracTok.getLoc(), "']' expected");
@@ -374,11 +349,8 @@
   }
   // The "[Rn" we have so far was not followed by a comma.
   else if (Tok.is(AsmToken::RBrac)) {
-    // This is a post indexing addressing forms:
-    //  [Rn], #offset
-    //  [Rn], +/-Rm
-    //  [Rn], +/-Rm, shift
-    // that is a ']' follows after the "[Rn".
+    // This is a post indexing addressing forms, that is a ']' follows after
+    // the "[Rn".
     Postindexed = true;
     Writeback = true;
     getLexer().Lex(); // Eat right bracket token.
@@ -394,42 +366,9 @@
       if (NextTok.isNot(AsmToken::Comma))
 	return Error(NextTok.getLoc(), "',' expected");
       getLexer().Lex(); // Eat comma token.
-
-      const AsmToken &PlusMinusTok = getLexer().getTok();
-      if (PlusMinusTok.is(AsmToken::Plus))
-	getLexer().Lex(); // Eat plus token.
-      else if (PlusMinusTok.is(AsmToken::Minus)) {
-	Negative = true;
-	getLexer().Lex(); // Eat minus token
-      }
-
-      // See if there is a register following the "[Rn]," we have so far.
-      const AsmToken &OffsetRegTok = getLexer().getTok();
-      OffsetRegNum = MatchRegisterName(OffsetRegTok.getString());
-      if (OffsetRegNum != -1) {
-	OffsetIsReg = true;
-	getLexer().Lex(); // Eat identifier token for the offset register.
-	// Look for a comma then a shift
-	const AsmToken &Tok = getLexer().getTok();
-	if (Tok.is(AsmToken::Comma)) {
-	  getLexer().Lex(); // Eat comma token.
-
-	  const AsmToken &Tok = getLexer().getTok();
-	  if (ParseShift(&ShiftType, ShiftAmount))
-	    return Error(Tok.getLoc(), "shift expected");
-	  OffsetRegShifted = true;
-	}
-      }
-      else { // "[Rn]," we have so far was not followed by "Rm"
-	// Look for #offset following the "[Rn],"
-	const AsmToken &HashTok = getLexer().getTok();
-	if (HashTok.isNot(AsmToken::Hash))
-	  return Error(HashTok.getLoc(), "'#' expected");
-	getLexer().Lex(); // Eat hash token.
-
-	if (getParser().ParseExpression(Offset))
-	 return true;
-      }
+      if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
+                              ShiftAmount, Offset, OffsetIsReg, OffsetRegNum))
+        return true;
     }
 
     Op = ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
@@ -441,45 +380,105 @@
   return true;
 }
 
+/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn],"
+/// we will parse the following (were +/- means that a plus or minus is
+/// optional):
+///   +/-Rm
+///   +/-Rm, shift
+///   #offset
+/// we return false on success or an error otherwise.
+bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
+					bool &OffsetRegShifted,
+                                        enum ShiftType &ShiftType,
+                                        const MCExpr *&ShiftAmount,
+                                        const MCExpr *&Offset,
+                                        bool &OffsetIsReg,
+                                        int OffsetRegNum) {
+  ARMOperand Op;
+  Negative = false;
+  OffsetRegShifted = false;
+  OffsetIsReg = false;
+  OffsetRegNum = -1;
+  const AsmToken &NextTok = getLexer().getTok();
+  if (NextTok.is(AsmToken::Plus))
+    getLexer().Lex(); // Eat plus token.
+  else if (NextTok.is(AsmToken::Minus)) {
+    Negative = true;
+    getLexer().Lex(); // Eat minus token
+  }
+  // See if there is a register following the "[Rn," or "[Rn]," we have so far.
+  const AsmToken &OffsetRegTok = getLexer().getTok();
+  if (OffsetRegTok.is(AsmToken::Identifier)) {
+    OffsetIsReg = !MaybeParseRegister(Op, false);
+    if (OffsetIsReg)
+      OffsetRegNum = Op.getReg();
+  }
+  // If we parsed a register as the offset then their can be a shift after that
+  if (OffsetRegNum != -1) {
+    // Look for a comma then a shift
+    const AsmToken &Tok = getLexer().getTok();
+    if (Tok.is(AsmToken::Comma)) {
+      getLexer().Lex(); // Eat comma token.
+
+      const AsmToken &Tok = getLexer().getTok();
+      if (ParseShift(ShiftType, ShiftAmount))
+	return Error(Tok.getLoc(), "shift expected");
+      OffsetRegShifted = true;
+    }
+  }
+  else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
+    // Look for #offset following the "[Rn," or "[Rn],"
+    const AsmToken &HashTok = getLexer().getTok();
+    if (HashTok.isNot(AsmToken::Hash))
+      return Error(HashTok.getLoc(), "'#' expected");
+    getLexer().Lex(); // Eat hash token.
+
+    if (getParser().ParseExpression(Offset))
+     return true;
+  }
+  return false;
+}
+
 /// ParseShift as one of these two:
 ///   ( lsl | lsr | asr | ror ) , # shift_amount
 ///   rrx
 /// and returns true if it parses a shift otherwise it returns false.
-bool ARMAsmParser::ParseShift(ShiftType *St, const MCExpr *&ShiftAmount) {
+bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount) {
   const AsmToken &Tok = getLexer().getTok();
   if (Tok.isNot(AsmToken::Identifier))
     return true;
   const StringRef &ShiftName = Tok.getString();
   if (ShiftName == "lsl" || ShiftName == "LSL")
-    *St = Lsl;
+    St = Lsl;
   else if (ShiftName == "lsr" || ShiftName == "LSR")
-    *St = Lsr;
+    St = Lsr;
   else if (ShiftName == "asr" || ShiftName == "ASR")
-    *St = Asr;
+    St = Asr;
   else if (ShiftName == "ror" || ShiftName == "ROR")
-    *St = Ror;
+    St = Ror;
   else if (ShiftName == "rrx" || ShiftName == "RRX")
-    *St = Rrx;
+    St = Rrx;
   else
     return true;
   getLexer().Lex(); // Eat shift type token.
 
-  // For all but a Rotate right there must be a '#' and a shift amount
-  if (*St != Rrx) {
-    // Look for # following the shift type
-    const AsmToken &HashTok = getLexer().getTok();
-    if (HashTok.isNot(AsmToken::Hash))
-      return Error(HashTok.getLoc(), "'#' expected");
-    getLexer().Lex(); // Eat hash token.
+  // Rrx stands alone.
+  if (St == Rrx)
+    return false;
 
-    if (getParser().ParseExpression(ShiftAmount))
-      return true;
-  }
+  // Otherwise, there must be a '#' and a shift amount.
+  const AsmToken &HashTok = getLexer().getTok();
+  if (HashTok.isNot(AsmToken::Hash))
+    return Error(HashTok.getLoc(), "'#' expected");
+  getLexer().Lex(); // Eat hash token.
+
+  if (getParser().ParseExpression(ShiftAmount))
+    return true;
 
   return false;
 }
 
-// A hack to allow some testing, to be replaced by a real table gen version.
+/// A hack to allow some testing, to be replaced by a real table gen version.
 int ARMAsmParser::MatchRegisterName(const StringRef &Name) {
   if (Name == "r0" || Name == "R0")
     return 0;
@@ -518,7 +517,7 @@
   return -1;
 }
 
-// A hack to allow some testing, to be replaced by a real table gen version.
+/// A hack to allow some testing, to be replaced by a real table gen version.
 bool ARMAsmParser::MatchInstruction(SmallVectorImpl<ARMOperand> &Operands,
                                     MCInst &Inst) {
   struct ARMOperand Op0 = Operands[0];
@@ -549,12 +548,12 @@
   return true;
 }
 
-// Parse a arm instruction operand.  For now this parses the operand regardless
-// of the mnemonic.
+/// Parse a arm instruction operand.  For now this parses the operand regardless
+/// of the mnemonic.
 bool ARMAsmParser::ParseOperand(ARMOperand &Op) {
   switch (getLexer().getKind()) {
   case AsmToken::Identifier:
-    if (!ParseRegister(Op))
+    if (!MaybeParseRegister(Op, true))
       return false;
     // This was not a register so parse other operands that start with an
     // identifier (like labels) as expressions and create them as immediates.
@@ -581,7 +580,7 @@
   }
 }
 
-// Parse an arm instruction mnemonic followed by its operands.
+/// Parse an arm instruction mnemonic followed by its operands.
 bool ARMAsmParser::ParseInstruction(const StringRef &Name, MCInst &Inst) {
   SmallVector<ARMOperand, 7> Operands;
 
@@ -739,7 +738,7 @@
   return false;
 }
 
-// Force static initialization.
+/// Force static initialization.
 extern "C" void LLVMInitializeARMAsmParser() {
   RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
   RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);





More information about the llvm-commits mailing list