ARMAsmParser.cpp revision fa42fad8bf7b0058ba031a275e1e8ce53b2cb1ad
1//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "ARM.h"
11#include "ARMSubtarget.h"
12#include "llvm/MC/MCParser/MCAsmLexer.h"
13#include "llvm/MC/MCParser/MCAsmParser.h"
14#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
15#include "llvm/MC/MCStreamer.h"
16#include "llvm/MC/MCExpr.h"
17#include "llvm/MC/MCInst.h"
18#include "llvm/Target/TargetRegistry.h"
19#include "llvm/Target/TargetAsmParser.h"
20#include "llvm/Support/SourceMgr.h"
21#include "llvm/Support/raw_ostream.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/ADT/StringSwitch.h"
24#include "llvm/ADT/Twine.h"
25using namespace llvm;
26
27// The shift types for register controlled shifts in arm memory addressing
28enum ShiftType {
29  Lsl,
30  Lsr,
31  Asr,
32  Ror,
33  Rrx
34};
35
36namespace {
37  struct ARMOperand;
38
39class ARMAsmParser : public TargetAsmParser {
40  MCAsmParser &Parser;
41  TargetMachine &TM;
42
43private:
44  MCAsmParser &getParser() const { return Parser; }
45
46  MCAsmLexer &getLexer() const { return Parser.getLexer(); }
47
48  void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
49
50  bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
51
52  ARMOperand *MaybeParseRegister(bool ParseWriteBack);
53  ARMOperand *ParseRegisterList();
54  ARMOperand *ParseMemory();
55
56  bool ParseMemoryOffsetReg(bool &Negative,
57                            bool &OffsetRegShifted,
58                            enum ShiftType &ShiftType,
59                            const MCExpr *&ShiftAmount,
60                            const MCExpr *&Offset,
61                            bool &OffsetIsReg,
62                            int &OffsetRegNum,
63                            SMLoc &E);
64
65  bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount, SMLoc &E);
66
67  ARMOperand *ParseOperand();
68
69  bool ParseDirectiveWord(unsigned Size, SMLoc L);
70
71  bool ParseDirectiveThumb(SMLoc L);
72
73  bool ParseDirectiveThumbFunc(SMLoc L);
74
75  bool ParseDirectiveCode(SMLoc L);
76
77  bool ParseDirectiveSyntax(SMLoc L);
78
79  bool MatchAndEmitInstruction(SMLoc IDLoc,
80                               SmallVectorImpl<MCParsedAsmOperand*> &Operands,
81                               MCStreamer &Out);
82
83  /// @name Auto-generated Match Functions
84  /// {
85
86#define GET_ASSEMBLER_HEADER
87#include "ARMGenAsmMatcher.inc"
88
89  /// }
90
91
92public:
93  ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
94    : TargetAsmParser(T), Parser(_Parser), TM(_TM) {}
95
96  virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
97                                SmallVectorImpl<MCParsedAsmOperand*> &Operands);
98
99  virtual bool ParseDirective(AsmToken DirectiveID);
100};
101} // end anonymous namespace
102
103namespace {
104
105/// ARMOperand - Instances of this class represent a parsed ARM machine
106/// instruction.
107struct ARMOperand : public MCParsedAsmOperand {
108public:
109  enum KindTy {
110    CondCode,
111    Immediate,
112    Memory,
113    Register,
114    Token
115  } Kind;
116
117  SMLoc StartLoc, EndLoc;
118
119  union {
120    struct {
121      ARMCC::CondCodes Val;
122    } CC;
123
124    struct {
125      const char *Data;
126      unsigned Length;
127    } Tok;
128
129    struct {
130      unsigned RegNum;
131      bool Writeback;
132    } Reg;
133
134    struct {
135      const MCExpr *Val;
136    } Imm;
137
138    // This is for all forms of ARM address expressions
139    struct {
140      unsigned BaseRegNum;
141      unsigned OffsetRegNum; // used when OffsetIsReg is true
142      const MCExpr *Offset; // used when OffsetIsReg is false
143      const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
144      enum ShiftType ShiftType;  // used when OffsetRegShifted is true
145      unsigned
146        OffsetRegShifted : 1, // only used when OffsetIsReg is true
147        Preindexed : 1,
148        Postindexed : 1,
149        OffsetIsReg : 1,
150        Negative : 1, // only used when OffsetIsReg is true
151        Writeback : 1;
152    } Mem;
153
154  };
155
156  //ARMOperand(KindTy K, SMLoc S, SMLoc E)
157  //  : Kind(K), StartLoc(S), EndLoc(E) {}
158
159  ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
160    Kind = o.Kind;
161    StartLoc = o.StartLoc;
162    EndLoc = o.EndLoc;
163    switch (Kind) {
164    case CondCode:
165      CC = o.CC;
166      break;
167    case Token:
168      Tok = o.Tok;
169      break;
170    case Register:
171      Reg = o.Reg;
172      break;
173    case Immediate:
174      Imm = o.Imm;
175      break;
176    case Memory:
177      Mem = o.Mem;
178      break;
179    }
180  }
181
182  /// getStartLoc - Get the location of the first token of this operand.
183  SMLoc getStartLoc() const { return StartLoc; }
184  /// getEndLoc - Get the location of the last token of this operand.
185  SMLoc getEndLoc() const { return EndLoc; }
186
187  ARMCC::CondCodes getCondCode() const {
188    assert(Kind == CondCode && "Invalid access!");
189    return CC.Val;
190  }
191
192  StringRef getToken() const {
193    assert(Kind == Token && "Invalid access!");
194    return StringRef(Tok.Data, Tok.Length);
195  }
196
197  unsigned getReg() const {
198    assert(Kind == Register && "Invalid access!");
199    return Reg.RegNum;
200  }
201
202  const MCExpr *getImm() const {
203    assert(Kind == Immediate && "Invalid access!");
204    return Imm.Val;
205  }
206
207  bool isCondCode() const { return Kind == CondCode; }
208
209  bool isImm() const { return Kind == Immediate; }
210
211  bool isReg() const { return Kind == Register; }
212
213  bool isToken() const {return Kind == Token; }
214
215  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
216    // Add as immediates when possible.
217    if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
218      Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
219    else
220      Inst.addOperand(MCOperand::CreateExpr(Expr));
221  }
222
223  void addCondCodeOperands(MCInst &Inst, unsigned N) const {
224    assert(N == 2 && "Invalid number of operands!");
225    Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
226    // FIXME: What belongs here?
227    Inst.addOperand(MCOperand::CreateReg(0));
228  }
229
230  void addRegOperands(MCInst &Inst, unsigned N) const {
231    assert(N == 1 && "Invalid number of operands!");
232    Inst.addOperand(MCOperand::CreateReg(getReg()));
233  }
234
235  void addImmOperands(MCInst &Inst, unsigned N) const {
236    assert(N == 1 && "Invalid number of operands!");
237    addExpr(Inst, getImm());
238  }
239
240  virtual void dump(raw_ostream &OS) const;
241
242  static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
243    ARMOperand *Op = new ARMOperand(CondCode);
244    Op->CC.Val = CC;
245    Op->StartLoc = S;
246    Op->EndLoc = S;
247    return Op;
248  }
249
250  static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
251    ARMOperand *Op = new ARMOperand(Token);
252    Op->Tok.Data = Str.data();
253    Op->Tok.Length = Str.size();
254    Op->StartLoc = S;
255    Op->EndLoc = S;
256    return Op;
257  }
258
259  static ARMOperand *CreateReg(unsigned RegNum, bool Writeback, SMLoc S,
260                               SMLoc E) {
261    ARMOperand *Op = new ARMOperand(Register);
262    Op->Reg.RegNum = RegNum;
263    Op->Reg.Writeback = Writeback;
264    Op->StartLoc = S;
265    Op->EndLoc = E;
266    return Op;
267  }
268
269  static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
270    ARMOperand *Op = new ARMOperand(Immediate);
271    Op->Imm.Val = Val;
272    Op->StartLoc = S;
273    Op->EndLoc = E;
274    return Op;
275  }
276
277  static ARMOperand *CreateMem(unsigned BaseRegNum, bool OffsetIsReg,
278                               const MCExpr *Offset, unsigned OffsetRegNum,
279                               bool OffsetRegShifted, enum ShiftType ShiftType,
280                               const MCExpr *ShiftAmount, bool Preindexed,
281                               bool Postindexed, bool Negative, bool Writeback,
282                               SMLoc S, SMLoc E) {
283    ARMOperand *Op = new ARMOperand(Memory);
284    Op->Mem.BaseRegNum = BaseRegNum;
285    Op->Mem.OffsetIsReg = OffsetIsReg;
286    Op->Mem.Offset = Offset;
287    Op->Mem.OffsetRegNum = OffsetRegNum;
288    Op->Mem.OffsetRegShifted = OffsetRegShifted;
289    Op->Mem.ShiftType = ShiftType;
290    Op->Mem.ShiftAmount = ShiftAmount;
291    Op->Mem.Preindexed = Preindexed;
292    Op->Mem.Postindexed = Postindexed;
293    Op->Mem.Negative = Negative;
294    Op->Mem.Writeback = Writeback;
295
296    Op->StartLoc = S;
297    Op->EndLoc = E;
298    return Op;
299  }
300
301private:
302  ARMOperand(KindTy K) : Kind(K) {}
303};
304
305} // end anonymous namespace.
306
307void ARMOperand::dump(raw_ostream &OS) const {
308  switch (Kind) {
309  case CondCode:
310    OS << ARMCondCodeToString(getCondCode());
311    break;
312  case Immediate:
313    getImm()->print(OS);
314    break;
315  case Memory:
316    OS << "<memory>";
317    break;
318  case Register:
319    OS << "<register " << getReg() << ">";
320    break;
321  case Token:
322    OS << "'" << getToken() << "'";
323    break;
324  }
325}
326
327/// @name Auto-generated Match Functions
328/// {
329
330static unsigned MatchRegisterName(StringRef Name);
331
332/// }
333
334/// Try to parse a register name.  The token must be an Identifier when called,
335/// and if it is a register name the token is eaten and a Reg operand is created
336/// and returned.  Otherwise return null.
337///
338/// TODO this is likely to change to allow different register types and or to
339/// parse for a specific register type.
340ARMOperand *ARMAsmParser::MaybeParseRegister(bool ParseWriteBack) {
341  SMLoc S, E;
342  const AsmToken &Tok = Parser.getTok();
343  assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
344
345  // FIXME: Validate register for the current architecture; we have to do
346  // validation later, so maybe there is no need for this here.
347  int RegNum;
348
349  RegNum = MatchRegisterName(Tok.getString());
350  if (RegNum == -1)
351    return 0;
352
353  S = Tok.getLoc();
354
355  Parser.Lex(); // Eat identifier token.
356
357  E = Parser.getTok().getLoc();
358
359  bool Writeback = false;
360  if (ParseWriteBack) {
361    const AsmToken &ExclaimTok = Parser.getTok();
362    if (ExclaimTok.is(AsmToken::Exclaim)) {
363      E = ExclaimTok.getLoc();
364      Writeback = true;
365      Parser.Lex(); // Eat exclaim token
366    }
367  }
368
369  return ARMOperand::CreateReg(RegNum, Writeback, S, E);
370}
371
372/// Parse a register list, return it if successful else return null.  The first
373/// token must be a '{' when called.
374ARMOperand *ARMAsmParser::ParseRegisterList() {
375  SMLoc S, E;
376  assert(Parser.getTok().is(AsmToken::LCurly) &&
377         "Token is not an Left Curly Brace");
378  S = Parser.getTok().getLoc();
379  Parser.Lex(); // Eat left curly brace token.
380
381  const AsmToken &RegTok = Parser.getTok();
382  SMLoc RegLoc = RegTok.getLoc();
383  if (RegTok.isNot(AsmToken::Identifier)) {
384    Error(RegLoc, "register expected");
385    return 0;
386  }
387  int RegNum = MatchRegisterName(RegTok.getString());
388  if (RegNum == -1) {
389    Error(RegLoc, "register expected");
390    return 0;
391  }
392
393  Parser.Lex(); // Eat identifier token.
394  unsigned RegList = 1 << RegNum;
395
396  int HighRegNum = RegNum;
397  // TODO ranges like "{Rn-Rm}"
398  while (Parser.getTok().is(AsmToken::Comma)) {
399    Parser.Lex(); // Eat comma token.
400
401    const AsmToken &RegTok = Parser.getTok();
402    SMLoc RegLoc = RegTok.getLoc();
403    if (RegTok.isNot(AsmToken::Identifier)) {
404      Error(RegLoc, "register expected");
405      return 0;
406    }
407    int RegNum = MatchRegisterName(RegTok.getString());
408    if (RegNum == -1) {
409      Error(RegLoc, "register expected");
410      return 0;
411    }
412
413    if (RegList & (1 << RegNum))
414      Warning(RegLoc, "register duplicated in register list");
415    else if (RegNum <= HighRegNum)
416      Warning(RegLoc, "register not in ascending order in register list");
417    RegList |= 1 << RegNum;
418    HighRegNum = RegNum;
419
420    Parser.Lex(); // Eat identifier token.
421  }
422  const AsmToken &RCurlyTok = Parser.getTok();
423  if (RCurlyTok.isNot(AsmToken::RCurly)) {
424    Error(RCurlyTok.getLoc(), "'}' expected");
425    return 0;
426  }
427  E = RCurlyTok.getLoc();
428  Parser.Lex(); // Eat left curly brace token.
429
430  // FIXME: Need to return an operand!
431  Error(E, "FIXME: register list parsing not implemented");
432  return 0;
433}
434
435/// Parse an arm memory expression, return false if successful else return true
436/// or an error.  The first token must be a '[' when called.
437/// TODO Only preindexing and postindexing addressing are started, unindexed
438/// with option, etc are still to do.
439ARMOperand *ARMAsmParser::ParseMemory() {
440  SMLoc S, E;
441  assert(Parser.getTok().is(AsmToken::LBrac) &&
442         "Token is not an Left Bracket");
443  S = Parser.getTok().getLoc();
444  Parser.Lex(); // Eat left bracket token.
445
446  const AsmToken &BaseRegTok = Parser.getTok();
447  if (BaseRegTok.isNot(AsmToken::Identifier)) {
448    Error(BaseRegTok.getLoc(), "register expected");
449    return 0;
450  }
451  int BaseRegNum = 0;
452  if (ARMOperand *Op = MaybeParseRegister(false))
453    BaseRegNum = Op->getReg();
454  else {
455    Error(BaseRegTok.getLoc(), "register expected");
456    return 0;
457  }
458
459  bool Preindexed = false;
460  bool Postindexed = false;
461  bool OffsetIsReg = false;
462  bool Negative = false;
463  bool Writeback = false;
464
465  // First look for preindexed address forms, that is after the "[Rn" we now
466  // have to see if the next token is a comma.
467  const AsmToken &Tok = Parser.getTok();
468  if (Tok.is(AsmToken::Comma)) {
469    Preindexed = true;
470    Parser.Lex(); // Eat comma token.
471    int OffsetRegNum;
472    bool OffsetRegShifted;
473    enum ShiftType ShiftType;
474    const MCExpr *ShiftAmount;
475    const MCExpr *Offset;
476    if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
477                             Offset, OffsetIsReg, OffsetRegNum, E))
478      return 0;
479    const AsmToken &RBracTok = Parser.getTok();
480    if (RBracTok.isNot(AsmToken::RBrac)) {
481      Error(RBracTok.getLoc(), "']' expected");
482      return 0;
483    }
484    E = RBracTok.getLoc();
485    Parser.Lex(); // Eat right bracket token.
486
487    const AsmToken &ExclaimTok = Parser.getTok();
488    if (ExclaimTok.is(AsmToken::Exclaim)) {
489      E = ExclaimTok.getLoc();
490      Writeback = true;
491      Parser.Lex(); // Eat exclaim token
492    }
493    return ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
494                                 OffsetRegShifted, ShiftType, ShiftAmount,
495                                 Preindexed, Postindexed, Negative, Writeback,
496                                 S, E);
497  }
498  // The "[Rn" we have so far was not followed by a comma.
499  else if (Tok.is(AsmToken::RBrac)) {
500    // This is a post indexing addressing forms, that is a ']' follows after
501    // the "[Rn".
502    Postindexed = true;
503    Writeback = true;
504    E = Tok.getLoc();
505    Parser.Lex(); // Eat right bracket token.
506
507    int OffsetRegNum = 0;
508    bool OffsetRegShifted = false;
509    enum ShiftType ShiftType;
510    const MCExpr *ShiftAmount;
511    const MCExpr *Offset;
512
513    const AsmToken &NextTok = Parser.getTok();
514    if (NextTok.isNot(AsmToken::EndOfStatement)) {
515      if (NextTok.isNot(AsmToken::Comma)) {
516        Error(NextTok.getLoc(), "',' expected");
517        return 0;
518      }
519      Parser.Lex(); // Eat comma token.
520      if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
521                               ShiftAmount, Offset, OffsetIsReg, OffsetRegNum,
522                               E))
523        return 0;
524    }
525
526    return ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
527                                 OffsetRegShifted, ShiftType, ShiftAmount,
528                                 Preindexed, Postindexed, Negative, Writeback,
529                                 S, E);
530  }
531
532  return 0;
533}
534
535/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn],"
536/// we will parse the following (were +/- means that a plus or minus is
537/// optional):
538///   +/-Rm
539///   +/-Rm, shift
540///   #offset
541/// we return false on success or an error otherwise.
542bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
543                                        bool &OffsetRegShifted,
544                                        enum ShiftType &ShiftType,
545                                        const MCExpr *&ShiftAmount,
546                                        const MCExpr *&Offset,
547                                        bool &OffsetIsReg,
548                                        int &OffsetRegNum,
549                                        SMLoc &E) {
550  Negative = false;
551  OffsetRegShifted = false;
552  OffsetIsReg = false;
553  OffsetRegNum = -1;
554  const AsmToken &NextTok = Parser.getTok();
555  E = NextTok.getLoc();
556  if (NextTok.is(AsmToken::Plus))
557    Parser.Lex(); // Eat plus token.
558  else if (NextTok.is(AsmToken::Minus)) {
559    Negative = true;
560    Parser.Lex(); // Eat minus token
561  }
562  // See if there is a register following the "[Rn," or "[Rn]," we have so far.
563  const AsmToken &OffsetRegTok = Parser.getTok();
564  if (OffsetRegTok.is(AsmToken::Identifier)) {
565    if (ARMOperand *Op = MaybeParseRegister(false)) {
566      OffsetIsReg = true;
567      E = Op->getEndLoc();
568      OffsetRegNum = Op->getReg();
569      delete Op;
570    }
571  }
572  // If we parsed a register as the offset then their can be a shift after that
573  if (OffsetRegNum != -1) {
574    // Look for a comma then a shift
575    const AsmToken &Tok = Parser.getTok();
576    if (Tok.is(AsmToken::Comma)) {
577      Parser.Lex(); // Eat comma token.
578
579      const AsmToken &Tok = Parser.getTok();
580      if (ParseShift(ShiftType, ShiftAmount, E))
581        return Error(Tok.getLoc(), "shift expected");
582      OffsetRegShifted = true;
583    }
584  }
585  else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
586    // Look for #offset following the "[Rn," or "[Rn],"
587    const AsmToken &HashTok = Parser.getTok();
588    if (HashTok.isNot(AsmToken::Hash))
589      return Error(HashTok.getLoc(), "'#' expected");
590
591    Parser.Lex(); // Eat hash token.
592
593    if (getParser().ParseExpression(Offset))
594     return true;
595    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
596  }
597  return false;
598}
599
600/// ParseShift as one of these two:
601///   ( lsl | lsr | asr | ror ) , # shift_amount
602///   rrx
603/// and returns true if it parses a shift otherwise it returns false.
604bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount,
605                              SMLoc &E) {
606  const AsmToken &Tok = Parser.getTok();
607  if (Tok.isNot(AsmToken::Identifier))
608    return true;
609  StringRef ShiftName = Tok.getString();
610  if (ShiftName == "lsl" || ShiftName == "LSL")
611    St = Lsl;
612  else if (ShiftName == "lsr" || ShiftName == "LSR")
613    St = Lsr;
614  else if (ShiftName == "asr" || ShiftName == "ASR")
615    St = Asr;
616  else if (ShiftName == "ror" || ShiftName == "ROR")
617    St = Ror;
618  else if (ShiftName == "rrx" || ShiftName == "RRX")
619    St = Rrx;
620  else
621    return true;
622  Parser.Lex(); // Eat shift type token.
623
624  // Rrx stands alone.
625  if (St == Rrx)
626    return false;
627
628  // Otherwise, there must be a '#' and a shift amount.
629  const AsmToken &HashTok = Parser.getTok();
630  if (HashTok.isNot(AsmToken::Hash))
631    return Error(HashTok.getLoc(), "'#' expected");
632  Parser.Lex(); // Eat hash token.
633
634  if (getParser().ParseExpression(ShiftAmount))
635    return true;
636
637  return false;
638}
639
640/// Parse a arm instruction operand.  For now this parses the operand regardless
641/// of the mnemonic.
642ARMOperand *ARMAsmParser::ParseOperand() {
643  SMLoc S, E;
644
645  switch (getLexer().getKind()) {
646  case AsmToken::Identifier:
647    if (ARMOperand *Op = MaybeParseRegister(true))
648      return Op;
649
650    // This was not a register so parse other operands that start with an
651    // identifier (like labels) as expressions and create them as immediates.
652    const MCExpr *IdVal;
653    S = Parser.getTok().getLoc();
654    if (getParser().ParseExpression(IdVal))
655      return 0;
656    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
657    return ARMOperand::CreateImm(IdVal, S, E);
658  case AsmToken::LBrac:
659    return ParseMemory();
660  case AsmToken::LCurly:
661    return ParseRegisterList();
662  case AsmToken::Hash:
663    // #42 -> immediate.
664    // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
665    S = Parser.getTok().getLoc();
666    Parser.Lex();
667    const MCExpr *ImmVal;
668    if (getParser().ParseExpression(ImmVal))
669      return 0;
670    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
671    return ARMOperand::CreateImm(ImmVal, S, E);
672  default:
673    Error(Parser.getTok().getLoc(), "unexpected token in operand");
674    return 0;
675  }
676}
677
678/// Parse an arm instruction mnemonic followed by its operands.
679bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
680                               SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
681  // Create the leading tokens for the mnemonic, split by '.' characters.
682  size_t Start = 0, Next = Name.find('.');
683  StringRef Head = Name.slice(Start, Next);
684
685  // Determine the predicate, if any.
686  //
687  // FIXME: We need a way to check whether a prefix supports predication,
688  // otherwise we will end up with an ambiguity for instructions that happen to
689  // end with a predicate name.
690  unsigned CC = StringSwitch<unsigned>(Head.substr(Head.size()-2))
691    .Case("eq", ARMCC::EQ)
692    .Case("ne", ARMCC::NE)
693    .Case("hs", ARMCC::HS)
694    .Case("lo", ARMCC::LO)
695    .Case("mi", ARMCC::MI)
696    .Case("pl", ARMCC::PL)
697    .Case("vs", ARMCC::VS)
698    .Case("vc", ARMCC::VC)
699    .Case("hi", ARMCC::HI)
700    .Case("ls", ARMCC::LS)
701    .Case("ge", ARMCC::GE)
702    .Case("lt", ARMCC::LT)
703    .Case("gt", ARMCC::GT)
704    .Case("le", ARMCC::LE)
705    .Case("al", ARMCC::AL)
706    .Default(~0U);
707
708  if (CC != ~0U)
709    Head = Head.slice(0, Head.size() - 2);
710  else
711    CC = ARMCC::AL;
712
713  Operands.push_back(ARMOperand::CreateToken(Head, NameLoc));
714  Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), NameLoc));
715
716  // Add the remaining tokens in the mnemonic.
717  while (Next != StringRef::npos) {
718    Start = Next;
719    Next = Name.find('.', Start + 1);
720    Head = Name.slice(Start, Next);
721
722    Operands.push_back(ARMOperand::CreateToken(Head, NameLoc));
723  }
724
725  // Read the remaining operands.
726  if (getLexer().isNot(AsmToken::EndOfStatement)) {
727    // Read the first operand.
728    if (ARMOperand *Op = ParseOperand())
729      Operands.push_back(Op);
730    else {
731      Parser.EatToEndOfStatement();
732      return true;
733    }
734
735    while (getLexer().is(AsmToken::Comma)) {
736      Parser.Lex();  // Eat the comma.
737
738      // Parse and remember the operand.
739      if (ARMOperand *Op = ParseOperand())
740        Operands.push_back(Op);
741      else {
742        Parser.EatToEndOfStatement();
743        return true;
744      }
745    }
746  }
747
748  if (getLexer().isNot(AsmToken::EndOfStatement)) {
749    Parser.EatToEndOfStatement();
750    return TokError("unexpected token in argument list");
751  }
752  Parser.Lex(); // Consume the EndOfStatement
753  return false;
754}
755
756bool ARMAsmParser::
757MatchAndEmitInstruction(SMLoc IDLoc,
758                        SmallVectorImpl<MCParsedAsmOperand*> &Operands,
759                        MCStreamer &Out) {
760  MCInst Inst;
761  unsigned ErrorInfo;
762  if (MatchInstructionImpl(Operands, Inst, ErrorInfo) == Match_Success) {
763    Out.EmitInstruction(Inst);
764    return false;
765  }
766
767  // FIXME: We should give nicer diagnostics about the exact failure.
768  Error(IDLoc, "unrecognized instruction");
769  return true;
770}
771
772
773
774/// ParseDirective parses the arm specific directives
775bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
776  StringRef IDVal = DirectiveID.getIdentifier();
777  if (IDVal == ".word")
778    return ParseDirectiveWord(4, DirectiveID.getLoc());
779  else if (IDVal == ".thumb")
780    return ParseDirectiveThumb(DirectiveID.getLoc());
781  else if (IDVal == ".thumb_func")
782    return ParseDirectiveThumbFunc(DirectiveID.getLoc());
783  else if (IDVal == ".code")
784    return ParseDirectiveCode(DirectiveID.getLoc());
785  else if (IDVal == ".syntax")
786    return ParseDirectiveSyntax(DirectiveID.getLoc());
787  return true;
788}
789
790/// ParseDirectiveWord
791///  ::= .word [ expression (, expression)* ]
792bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
793  if (getLexer().isNot(AsmToken::EndOfStatement)) {
794    for (;;) {
795      const MCExpr *Value;
796      if (getParser().ParseExpression(Value))
797        return true;
798
799      getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
800
801      if (getLexer().is(AsmToken::EndOfStatement))
802        break;
803
804      // FIXME: Improve diagnostic.
805      if (getLexer().isNot(AsmToken::Comma))
806        return Error(L, "unexpected token in directive");
807      Parser.Lex();
808    }
809  }
810
811  Parser.Lex();
812  return false;
813}
814
815/// ParseDirectiveThumb
816///  ::= .thumb
817bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
818  if (getLexer().isNot(AsmToken::EndOfStatement))
819    return Error(L, "unexpected token in directive");
820  Parser.Lex();
821
822  // TODO: set thumb mode
823  // TODO: tell the MC streamer the mode
824  // getParser().getStreamer().Emit???();
825  return false;
826}
827
828/// ParseDirectiveThumbFunc
829///  ::= .thumbfunc symbol_name
830bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
831  const AsmToken &Tok = Parser.getTok();
832  if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
833    return Error(L, "unexpected token in .syntax directive");
834  Parser.Lex(); // Consume the identifier token.
835
836  if (getLexer().isNot(AsmToken::EndOfStatement))
837    return Error(L, "unexpected token in directive");
838  Parser.Lex();
839
840  // TODO: mark symbol as a thumb symbol
841  // getParser().getStreamer().Emit???();
842  return false;
843}
844
845/// ParseDirectiveSyntax
846///  ::= .syntax unified | divided
847bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
848  const AsmToken &Tok = Parser.getTok();
849  if (Tok.isNot(AsmToken::Identifier))
850    return Error(L, "unexpected token in .syntax directive");
851  StringRef Mode = Tok.getString();
852  if (Mode == "unified" || Mode == "UNIFIED")
853    Parser.Lex();
854  else if (Mode == "divided" || Mode == "DIVIDED")
855    Parser.Lex();
856  else
857    return Error(L, "unrecognized syntax mode in .syntax directive");
858
859  if (getLexer().isNot(AsmToken::EndOfStatement))
860    return Error(Parser.getTok().getLoc(), "unexpected token in directive");
861  Parser.Lex();
862
863  // TODO tell the MC streamer the mode
864  // getParser().getStreamer().Emit???();
865  return false;
866}
867
868/// ParseDirectiveCode
869///  ::= .code 16 | 32
870bool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
871  const AsmToken &Tok = Parser.getTok();
872  if (Tok.isNot(AsmToken::Integer))
873    return Error(L, "unexpected token in .code directive");
874  int64_t Val = Parser.getTok().getIntVal();
875  if (Val == 16)
876    Parser.Lex();
877  else if (Val == 32)
878    Parser.Lex();
879  else
880    return Error(L, "invalid operand to .code directive");
881
882  if (getLexer().isNot(AsmToken::EndOfStatement))
883    return Error(Parser.getTok().getLoc(), "unexpected token in directive");
884  Parser.Lex();
885
886  // TODO tell the MC streamer the mode
887  // getParser().getStreamer().Emit???();
888  return false;
889}
890
891extern "C" void LLVMInitializeARMAsmLexer();
892
893/// Force static initialization.
894extern "C" void LLVMInitializeARMAsmParser() {
895  RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
896  RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);
897  LLVMInitializeARMAsmLexer();
898}
899
900#define GET_REGISTER_MATCHER
901#define GET_MATCHER_IMPLEMENTATION
902#include "ARMGenAsmMatcher.inc"
903