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