s/std::vector/SmallVector/
[oota-llvm.git] / lib / Target / ARM / AsmParser / ARMAsmParser.cpp
index f5dc38bcfed04ac84c2c2a3d72a0b3e971405b8e..12225b00ed0556c03541b6c73900be24f6f1253e 100644 (file)
@@ -13,6 +13,7 @@
 #include "llvm/MC/MCParser/MCAsmLexer.h"
 #include "llvm/MC/MCParser/MCAsmParser.h"
 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+#include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
@@ -35,25 +36,24 @@ enum ShiftType {
 };
 
 namespace {
-  struct ARMOperand;
+
+class ARMOperand;
 
 class ARMAsmParser : public TargetAsmParser {
   MCAsmParser &Parser;
   TargetMachine &TM;
 
-private:
   MCAsmParser &getParser() const { return Parser; }
-
   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
 
   void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
-
   bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
 
   int TryParseRegister();
   ARMOperand *TryParseRegisterWithWriteBack();
   ARMOperand *ParseRegisterList();
   ARMOperand *ParseMemory();
+  ARMOperand *ParseOperand();
 
   bool ParseMemoryOffsetReg(bool &Negative,
                             bool &OffsetRegShifted,
@@ -63,19 +63,11 @@ private:
                             bool &OffsetIsReg,
                             int &OffsetRegNum,
                             SMLoc &E);
-
   bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount, SMLoc &E);
-
-  ARMOperand *ParseOperand();
-
   bool ParseDirectiveWord(unsigned Size, SMLoc L);
-
   bool ParseDirectiveThumb(SMLoc L);
-
   bool ParseDirectiveThumbFunc(SMLoc L);
-
   bool ParseDirectiveCode(SMLoc L);
-
   bool ParseDirectiveSyntax(SMLoc L);
 
   bool MatchAndEmitInstruction(SMLoc IDLoc,
@@ -90,7 +82,6 @@ private:
 
   /// }
 
-
 public:
   ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
     : TargetAsmParser(T), Parser(_Parser), TM(_TM) {
@@ -101,7 +92,6 @@ public:
 
   virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
                                 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
-
   virtual bool ParseDirective(AsmToken DirectiveID);
 };
 } // end anonymous namespace
@@ -110,13 +100,13 @@ namespace {
 
 /// ARMOperand - Instances of this class represent a parsed ARM machine
 /// instruction.
-struct ARMOperand : public MCParsedAsmOperand {
-public:
+class ARMOperand : public MCParsedAsmOperand {
   enum KindTy {
     CondCode,
     Immediate,
     Memory,
     Register,
+    RegisterList,
     Token
   } Kind;
 
@@ -137,6 +127,10 @@ public:
       bool Writeback;
     } Reg;
 
+    struct {
+      SmallVector<unsigned, 32> *Registers;
+    } RegList;
+
     struct {
       const MCExpr *Val;
     } Imm;
@@ -144,21 +138,21 @@ public:
     // This is for all forms of ARM address expressions
     struct {
       unsigned BaseRegNum;
-      unsigned OffsetRegNum; // used when OffsetIsReg is true
-      const MCExpr *Offset; // used when OffsetIsReg is false
-      const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
-      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;
+      unsigned OffsetRegNum;         // used when OffsetIsReg is true
+      const MCExpr *Offset;          // used when OffsetIsReg is false
+      const MCExpr *ShiftAmount;     // used when OffsetRegShifted is true
+      enum ShiftType ShiftType;      // used when OffsetRegShifted is true
+      unsigned OffsetRegShifted : 1; // only used when OffsetIsReg is true
+      unsigned Preindexed : 1;
+      unsigned Postindexed : 1;
+      unsigned OffsetIsReg : 1;
+      unsigned Negative : 1;         // only used when OffsetIsReg is true
+      unsigned Writeback : 1;
     } Mem;
-
   };
 
+  ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
+public:
   ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
     Kind = o.Kind;
     StartLoc = o.StartLoc;
@@ -173,6 +167,9 @@ public:
     case Register:
       Reg = o.Reg;
       break;
+    case RegisterList:
+      RegList = o.RegList;
+      break;
     case Immediate:
       Imm = o.Imm;
       break;
@@ -181,6 +178,10 @@ public:
       break;
     }
   }
+  ~ARMOperand() {
+    if (isRegList())
+      delete RegList.Registers;
+  }
 
   /// getStartLoc - Get the location of the first token of this operand.
   SMLoc getStartLoc() const { return StartLoc; }
@@ -202,6 +203,11 @@ public:
     return Reg.RegNum;
   }
 
+  const SmallVectorImpl<unsigned> &getRegList() const {
+    assert(Kind == RegisterList && "Invalid access!");
+    return *RegList.Registers;
+  }
+
   const MCExpr *getImm() const {
     assert(Kind == Immediate && "Invalid access!");
     return Imm.Val;
@@ -210,8 +216,23 @@ public:
   bool isCondCode() const { return Kind == CondCode; }
   bool isImm() const { return Kind == Immediate; }
   bool isReg() const { return Kind == Register; }
+  bool isRegList() const { return Kind == RegisterList; }
   bool isToken() const { return Kind == Token; }
   bool isMemory() const { return Kind == Memory; }
+  bool isMemMode5() const {
+    if (!isMemory() || Mem.OffsetIsReg || Mem.OffsetRegShifted ||
+        Mem.Writeback || Mem.Negative)
+      return false;
+    // If there is an offset expression, make sure it's valid.
+    if (!Mem.Offset)
+      return true;
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
+    if (!CE)
+      return false;
+    // The offset must be a multiple of 4 in the range 0-1020.
+    int64_t Value = CE->getValue();
+    return ((Value & 0x3) == 0 && Value <= 1020 && Value >= -1020);
+  }
 
   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
     // Add as immediates when possible.  Null MCExpr = 0.
@@ -235,32 +256,24 @@ public:
     Inst.addOperand(MCOperand::CreateReg(getReg()));
   }
 
-  void addImmOperands(MCInst &Inst, unsigned N) const {
+  void addRegListOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
-    addExpr(Inst, getImm());
+    const SmallVectorImpl<unsigned> &RegList = getRegList();
+    for (SmallVectorImpl<unsigned>::const_iterator
+           I = RegList.begin(), E = RegList.end(); I != E; ++I)
+      Inst.addOperand(MCOperand::CreateReg(*I));
   }
 
-
-  bool isMemMode5() const {
-    if (!isMemory() || Mem.OffsetIsReg || Mem.OffsetRegShifted ||
-        Mem.Writeback || Mem.Negative)
-      return false;
-    // If there is an offset expression, make sure it's valid.
-    if (!Mem.Offset)
-      return true;
-    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
-    if (!CE)
-      return false;
-    // The offset must be a multiple of 4 in the range 0-1020.
-    int64_t Value = CE->getValue();
-    return ((Value & 0x3) == 0 && Value <= 1020 && Value >= -1020);
+  void addImmOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    addExpr(Inst, getImm());
   }
 
   void addMemMode5Operands(MCInst &Inst, unsigned N) const {
     assert(N == 2 && isMemMode5() && "Invalid number of operands!");
 
     Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
-    assert(!Mem.OffsetIsReg && "invalid mode 5 operand");
+    assert(!Mem.OffsetIsReg && "Invalid mode 5 operand");
 
     // FIXME: #-0 is encoded differently than #0. Does the parser preserve
     // the difference?
@@ -311,6 +324,20 @@ public:
     return Op;
   }
 
+  static ARMOperand *
+  CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
+                SMLoc S, SMLoc E) {
+    ARMOperand *Op = new ARMOperand(RegisterList);
+    Op->RegList.Registers = new SmallVector<unsigned, 32>();
+    for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
+           I = Regs.begin(), E = Regs.end(); I != E; ++I)
+      Op->RegList.Registers->push_back(I->first);
+    std::sort(Op->RegList.Registers->begin(), Op->RegList.Registers->end());
+    Op->StartLoc = S;
+    Op->EndLoc = E;
+    return Op;
+  }
+
   static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
     ARMOperand *Op = new ARMOperand(Immediate);
     Op->Imm.Val = Val;
@@ -342,9 +369,6 @@ public:
     Op->EndLoc = E;
     return Op;
   }
-
-private:
-  ARMOperand(KindTy K) : Kind(K) {}
 };
 
 } // end anonymous namespace.
@@ -363,6 +387,19 @@ void ARMOperand::dump(raw_ostream &OS) const {
   case Register:
     OS << "<register " << getReg() << ">";
     break;
+  case RegisterList: {
+    OS << "<register_list ";
+
+    const SmallVectorImpl<unsigned> &RegList = getRegList();
+    for (SmallVectorImpl<unsigned>::const_iterator
+           I = RegList.begin(), E = RegList.end(); I != E; ) {
+      OS << *I;
+      if (++I < E) OS << ", ";
+    }
+
+    OS << ">";
+    break;
+  }
   case Token:
     OS << "'" << getToken() << "'";
     break;
@@ -386,8 +423,8 @@ int ARMAsmParser::TryParseRegister() {
 
   // FIXME: Validate register for the current architecture; we have to do
   // validation later, so maybe there is no need for this here.
-  int RegNum = MatchRegisterName(Tok.getString());
-  if (RegNum == -1)
+  unsigned RegNum = MatchRegisterName(Tok.getString());
+  if (RegNum == 0)
     return -1;
   Parser.Lex(); // Eat identifier token.
   return RegNum;
@@ -403,7 +440,8 @@ int ARMAsmParser::TryParseRegister() {
 ARMOperand *ARMAsmParser::TryParseRegisterWithWriteBack() {
   SMLoc S = Parser.getTok().getLoc();
   int RegNo = TryParseRegister();
-  if (RegNo == -1) return 0;
+  if (RegNo == -1)
+    return 0;
 
   SMLoc E = Parser.getTok().getLoc();
 
@@ -421,31 +459,17 @@ ARMOperand *ARMAsmParser::TryParseRegisterWithWriteBack() {
 /// Parse a register list, return it if successful else return null.  The first
 /// token must be a '{' when called.
 ARMOperand *ARMAsmParser::ParseRegisterList() {
-  SMLoc S, E;
   assert(Parser.getTok().is(AsmToken::LCurly) &&
-         "Token is not an Left Curly Brace");
-  S = Parser.getTok().getLoc();
-  Parser.Lex(); // Eat left curly brace token.
-
-  const AsmToken &RegTok = Parser.getTok();
-  SMLoc RegLoc = RegTok.getLoc();
-  if (RegTok.isNot(AsmToken::Identifier)) {
-    Error(RegLoc, "register expected");
-    return 0;
-  }
-  int RegNum = MatchRegisterName(RegTok.getString());
-  if (RegNum == -1) {
-    Error(RegLoc, "register expected");
-    return 0;
-  }
+         "Token is not a Left Curly Brace");
+  SMLoc S = Parser.getTok().getLoc();
 
-  Parser.Lex(); // Eat identifier token.
-  unsigned RegList = 1 << RegNum;
+  // Read the rest of the registers in the list.
+  unsigned PrevRegNum = 0;
+  SmallVector<std::pair<unsigned, SMLoc>, 32> Registers;
 
-  int HighRegNum = RegNum;
-  // TODO ranges like "{Rn-Rm}"
-  while (Parser.getTok().is(AsmToken::Comma)) {
-    Parser.Lex(); // Eat comma token.
+  do {
+    bool IsRange = Parser.getTok().is(AsmToken::Minus);
+    Parser.Lex(); // Eat non-identifier token.
 
     const AsmToken &RegTok = Parser.getTok();
     SMLoc RegLoc = RegTok.getLoc();
@@ -453,42 +477,72 @@ ARMOperand *ARMAsmParser::ParseRegisterList() {
       Error(RegLoc, "register expected");
       return 0;
     }
-    int RegNum = MatchRegisterName(RegTok.getString());
+
+    int RegNum = TryParseRegister();
     if (RegNum == -1) {
       Error(RegLoc, "register expected");
       return 0;
     }
 
-    if (RegList & (1 << RegNum))
-      Warning(RegLoc, "register duplicated in register list");
-    else if (RegNum <= HighRegNum)
-      Warning(RegLoc, "register not in ascending order in register list");
-    RegList |= 1 << RegNum;
-    HighRegNum = RegNum;
+    if (IsRange) {
+      int Reg = PrevRegNum;
+      do {
+        ++Reg;
+        Registers.push_back(std::make_pair(Reg, RegLoc));
+      } while (Reg != RegNum);
+    } else {
+      Registers.push_back(std::make_pair(RegNum, RegLoc));
+    }
 
-    Parser.Lex(); // Eat identifier token.
-  }
+    PrevRegNum = RegNum;
+  } while (Parser.getTok().is(AsmToken::Comma) ||
+           Parser.getTok().is(AsmToken::Minus));
+
+  // Process the right curly brace of the list.
   const AsmToken &RCurlyTok = Parser.getTok();
   if (RCurlyTok.isNot(AsmToken::RCurly)) {
     Error(RCurlyTok.getLoc(), "'}' expected");
     return 0;
   }
-  E = RCurlyTok.getLoc();
-  Parser.Lex(); // Eat left curly brace token.
 
-  // FIXME: Need to return an operand!
-  Error(E, "FIXME: register list parsing not implemented");
-  return 0;
+  SMLoc E = RCurlyTok.getLoc();
+  Parser.Lex(); // Eat right curly brace token.
+  // Verify the register list.
+  SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
+    RI = Registers.begin(), RE = Registers.end();
+
+  unsigned HighRegNum = RI->first;
+  DenseMap<unsigned, bool> RegMap;
+  RegMap[RI->first] = true;
+
+  for (++RI; RI != RE; ++RI) {
+    const std::pair<unsigned, SMLoc> &RegInfo = *RI;
+
+    if (RegMap[RegInfo.first]) {
+      Error(RegInfo.second, "register duplicated in register list");
+      return 0;
+    }
+
+    if (RegInfo.first < HighRegNum)
+      Warning(RegInfo.second,
+              "register not in ascending order in register list");
+
+    RegMap[RegInfo.first] = true;
+    HighRegNum = std::max(RegInfo.first, HighRegNum);
+  }
+
+  return ARMOperand::CreateRegList(Registers, S, E);
 }
 
-/// Parse an arm memory expression, return false if successful else return true
+/// 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.
 ARMOperand *ARMAsmParser::ParseMemory() {
   SMLoc S, E;
   assert(Parser.getTok().is(AsmToken::LBrac) &&
-         "Token is not an Left Bracket");
+         "Token is not a Left Bracket");
   S = Parser.getTok().getLoc();
   Parser.Lex(); // Eat left bracket token.
 
@@ -617,7 +671,7 @@ bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
     }
   }
 
-  // If we parsed a register as the offset then their can be a shift after that
+  // If we parsed a register as the offset then there can be a shift after that.
   if (OffsetRegNum != -1) {
     // Look for a comma then a shift
     const AsmToken &Tok = Parser.getTok();
@@ -689,8 +743,10 @@ bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount,
 /// of the mnemonic.
 ARMOperand *ARMAsmParser::ParseOperand() {
   SMLoc S, E;
-
   switch (getLexer().getKind()) {
+  default:
+    Error(Parser.getTok().getLoc(), "unexpected token in operand");
+    return 0;
   case AsmToken::Identifier:
     if (ARMOperand *Op = TryParseRegisterWithWriteBack())
       return Op;
@@ -717,9 +773,6 @@ ARMOperand *ARMAsmParser::ParseOperand() {
       return 0;
     E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
     return ARMOperand::CreateImm(ImmVal, S, E);
-  default:
-    Error(Parser.getTok().getLoc(), "unexpected token in operand");
-    return 0;
   }
 }
 
@@ -805,6 +858,7 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
     Parser.EatToEndOfStatement();
     return TokError("unexpected token in argument list");
   }
+
   Parser.Lex(); // Consume the EndOfStatement
   return false;
 }
@@ -819,7 +873,6 @@ MatchAndEmitInstruction(SMLoc IDLoc,
   case Match_Success:
     Out.EmitInstruction(Inst);
     return false;
-
   case Match_MissingFeature:
     Error(IDLoc, "instruction requires a CPU feature not currently enabled");
     return true;
@@ -840,10 +893,9 @@ MatchAndEmitInstruction(SMLoc IDLoc,
   }
 
   llvm_unreachable("Implement any new match types added!");
+  return true;
 }
 
-
-
 /// ParseDirective parses the arm specific directives
 bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
   StringRef IDVal = DirectiveID.getIdentifier();
@@ -903,15 +955,16 @@ bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
 bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
   const AsmToken &Tok = Parser.getTok();
   if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
-    return Error(L, "unexpected token in .syntax directive");
+    return Error(L, "unexpected token in .thumb_func directive");
+  StringRef Name = Tok.getString();
   Parser.Lex(); // Consume the identifier token.
-
   if (getLexer().isNot(AsmToken::EndOfStatement))
     return Error(L, "unexpected token in directive");
   Parser.Lex();
 
-  // TODO: mark symbol as a thumb symbol
-  // getParser().getStreamer().Emit???();
+  // Mark symbol as a thumb symbol.
+  MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
+  getParser().getStreamer().EmitThumbFunc(Func);
   return false;
 }
 
@@ -956,8 +1009,11 @@ bool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
     return Error(Parser.getTok().getLoc(), "unexpected token in directive");
   Parser.Lex();
 
-  // TODO tell the MC streamer the mode
-  // getParser().getStreamer().Emit???();
+  if (Val == 16)
+    getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
+  else
+    getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
+
   return false;
 }