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