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