ARMAsmParser.cpp revision fa315de8f44ddb318a7c6ff913e80d71d7c68859
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/Twine.h"
26using namespace llvm;
27
28namespace {
29struct ARMOperand;
30
31// The shift types for register controlled shifts in arm memory addressing
32enum ShiftType {
33  Lsl,
34  Lsr,
35  Asr,
36  Ror,
37  Rrx
38};
39
40class ARMAsmParser : public TargetAsmParser {
41  MCAsmParser &Parser;
42  TargetMachine &TM;
43
44private:
45  MCAsmParser &getParser() const { return Parser; }
46
47  MCAsmLexer &getLexer() const { return Parser.getLexer(); }
48
49  void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
50
51  bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
52
53  bool MaybeParseRegister(OwningPtr<ARMOperand> &Op, bool ParseWriteBack);
54
55  bool ParseRegisterList(OwningPtr<ARMOperand> &Op);
56
57  bool ParseMemory(OwningPtr<ARMOperand> &Op);
58
59  bool ParseMemoryOffsetReg(bool &Negative,
60                            bool &OffsetRegShifted,
61                            enum ShiftType &ShiftType,
62                            const MCExpr *&ShiftAmount,
63                            const MCExpr *&Offset,
64                            bool &OffsetIsReg,
65                            int &OffsetRegNum,
66                            SMLoc &E);
67
68  bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount, SMLoc &E);
69
70  bool ParseOperand(OwningPtr<ARMOperand> &Op);
71
72  bool ParseDirectiveWord(unsigned Size, SMLoc L);
73
74  bool ParseDirectiveThumb(SMLoc L);
75
76  bool ParseDirectiveThumbFunc(SMLoc L);
77
78  bool ParseDirectiveCode(SMLoc L);
79
80  bool ParseDirectiveSyntax(SMLoc L);
81
82  /// @name Auto-generated Match Functions
83  /// {
84
85  unsigned ComputeAvailableFeatures(const ARMSubtarget *Subtarget) const;
86
87  bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
88                        MCInst &Inst);
89
90  /// }
91
92
93public:
94  ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
95    : TargetAsmParser(T), Parser(_Parser), TM(_TM) {}
96
97  virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
98                                SmallVectorImpl<MCParsedAsmOperand*> &Operands);
99
100  virtual bool ParseDirective(AsmToken DirectiveID);
101};
102
103/// ARMOperand - Instances of this class represent a parsed ARM machine
104/// instruction.
105struct ARMOperand : public MCParsedAsmOperand {
106private:
107  ARMOperand() {}
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 == 1 && "Invalid number of operands!");
225    Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
226  }
227
228  void addRegOperands(MCInst &Inst, unsigned N) const {
229    assert(N == 1 && "Invalid number of operands!");
230    Inst.addOperand(MCOperand::CreateReg(getReg()));
231  }
232
233  void addImmOperands(MCInst &Inst, unsigned N) const {
234    assert(N == 1 && "Invalid number of operands!");
235    addExpr(Inst, getImm());
236  }
237
238  virtual void dump(raw_ostream &OS) const;
239
240  static void CreateToken(OwningPtr<ARMOperand> &Op, StringRef Str,
241                          SMLoc S) {
242    Op.reset(new ARMOperand);
243    Op->Kind = Token;
244    Op->Tok.Data = Str.data();
245    Op->Tok.Length = Str.size();
246    Op->StartLoc = S;
247    Op->EndLoc = S;
248  }
249
250  static void CreateReg(OwningPtr<ARMOperand> &Op, unsigned RegNum,
251                        bool Writeback, SMLoc S, SMLoc E) {
252    Op.reset(new ARMOperand);
253    Op->Kind = Register;
254    Op->Reg.RegNum = RegNum;
255    Op->Reg.Writeback = Writeback;
256
257    Op->StartLoc = S;
258    Op->EndLoc = E;
259  }
260
261  static void CreateImm(OwningPtr<ARMOperand> &Op, const MCExpr *Val,
262                        SMLoc S, SMLoc E) {
263    Op.reset(new ARMOperand);
264    Op->Kind = Immediate;
265    Op->Imm.Val = Val;
266
267    Op->StartLoc = S;
268    Op->EndLoc = E;
269  }
270
271  static void CreateMem(OwningPtr<ARMOperand> &Op,
272                        unsigned BaseRegNum, bool OffsetIsReg,
273                        const MCExpr *Offset, unsigned OffsetRegNum,
274                        bool OffsetRegShifted, enum ShiftType ShiftType,
275                        const MCExpr *ShiftAmount, bool Preindexed,
276                        bool Postindexed, bool Negative, bool Writeback,
277                        SMLoc S, SMLoc E) {
278    Op.reset(new ARMOperand);
279    Op->Kind = Memory;
280    Op->Mem.BaseRegNum = BaseRegNum;
281    Op->Mem.OffsetIsReg = OffsetIsReg;
282    Op->Mem.Offset = Offset;
283    Op->Mem.OffsetRegNum = OffsetRegNum;
284    Op->Mem.OffsetRegShifted = OffsetRegShifted;
285    Op->Mem.ShiftType = ShiftType;
286    Op->Mem.ShiftAmount = ShiftAmount;
287    Op->Mem.Preindexed = Preindexed;
288    Op->Mem.Postindexed = Postindexed;
289    Op->Mem.Negative = Negative;
290    Op->Mem.Writeback = Writeback;
291
292    Op->StartLoc = S;
293    Op->EndLoc = E;
294  }
295};
296
297} // end anonymous namespace.
298
299void ARMOperand::dump(raw_ostream &OS) const {
300  switch (Kind) {
301  case CondCode:
302    OS << ARMCondCodeToString(getCondCode());
303    break;
304  case Immediate:
305    getImm()->print(OS);
306    break;
307  case Memory:
308    OS << "<memory>";
309    break;
310  case Register:
311    OS << "<register " << getReg() << ">";
312    break;
313  case Token:
314    OS << "'" << getToken() << "'";
315    break;
316  }
317}
318
319/// @name Auto-generated Match Functions
320/// {
321
322static unsigned MatchRegisterName(StringRef Name);
323
324/// }
325
326/// Try to parse a register name.  The token must be an Identifier when called,
327/// and if it is a register name a Reg operand is created, the token is eaten
328/// and false is returned.  Else true is returned and no token is eaten.
329/// TODO this is likely to change to allow different register types and or to
330/// parse for a specific register type.
331bool ARMAsmParser::MaybeParseRegister
332  (OwningPtr<ARMOperand> &Op, bool ParseWriteBack) {
333  SMLoc S, E;
334  const AsmToken &Tok = Parser.getTok();
335  assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
336
337  // FIXME: Validate register for the current architecture; we have to do
338  // validation later, so maybe there is no need for this here.
339  int RegNum;
340
341  RegNum = MatchRegisterName(Tok.getString());
342  if (RegNum == -1)
343    return true;
344
345  S = Tok.getLoc();
346
347  Parser.Lex(); // Eat identifier token.
348
349  E = Parser.getTok().getLoc();
350
351  bool Writeback = false;
352  if (ParseWriteBack) {
353    const AsmToken &ExclaimTok = Parser.getTok();
354    if (ExclaimTok.is(AsmToken::Exclaim)) {
355      E = ExclaimTok.getLoc();
356      Writeback = true;
357      Parser.Lex(); // Eat exclaim token
358    }
359  }
360
361  ARMOperand::CreateReg(Op, RegNum, Writeback, S, E);
362
363  return false;
364}
365
366/// Parse a register list, return false if successful else return true or an
367/// error.  The first token must be a '{' when called.
368bool ARMAsmParser::ParseRegisterList(OwningPtr<ARMOperand> &Op) {
369  SMLoc S, E;
370  assert(Parser.getTok().is(AsmToken::LCurly) &&
371         "Token is not an Left Curly Brace");
372  S = Parser.getTok().getLoc();
373  Parser.Lex(); // Eat left curly brace token.
374
375  const AsmToken &RegTok = Parser.getTok();
376  SMLoc RegLoc = RegTok.getLoc();
377  if (RegTok.isNot(AsmToken::Identifier))
378    return Error(RegLoc, "register expected");
379  int RegNum = MatchRegisterName(RegTok.getString());
380  if (RegNum == -1)
381    return Error(RegLoc, "register expected");
382  Parser.Lex(); // Eat identifier token.
383  unsigned RegList = 1 << RegNum;
384
385  int HighRegNum = RegNum;
386  // TODO ranges like "{Rn-Rm}"
387  while (Parser.getTok().is(AsmToken::Comma)) {
388    Parser.Lex(); // Eat comma token.
389
390    const AsmToken &RegTok = Parser.getTok();
391    SMLoc RegLoc = RegTok.getLoc();
392    if (RegTok.isNot(AsmToken::Identifier))
393      return Error(RegLoc, "register expected");
394    int RegNum = MatchRegisterName(RegTok.getString());
395    if (RegNum == -1)
396      return Error(RegLoc, "register expected");
397
398    if (RegList & (1 << RegNum))
399      Warning(RegLoc, "register duplicated in register list");
400    else if (RegNum <= HighRegNum)
401      Warning(RegLoc, "register not in ascending order in register list");
402    RegList |= 1 << RegNum;
403    HighRegNum = RegNum;
404
405    Parser.Lex(); // Eat identifier token.
406  }
407  const AsmToken &RCurlyTok = Parser.getTok();
408  if (RCurlyTok.isNot(AsmToken::RCurly))
409    return Error(RCurlyTok.getLoc(), "'}' expected");
410  E = RCurlyTok.getLoc();
411  Parser.Lex(); // Eat left curly brace token.
412
413  return false;
414}
415
416/// Parse an arm memory expression, return false if successful else return true
417/// or an error.  The first token must be a '[' when called.
418/// TODO Only preindexing and postindexing addressing are started, unindexed
419/// with option, etc are still to do.
420bool ARMAsmParser::ParseMemory(OwningPtr<ARMOperand> &Op) {
421  SMLoc S, E;
422  assert(Parser.getTok().is(AsmToken::LBrac) &&
423         "Token is not an Left Bracket");
424  S = Parser.getTok().getLoc();
425  Parser.Lex(); // Eat left bracket token.
426
427  const AsmToken &BaseRegTok = Parser.getTok();
428  if (BaseRegTok.isNot(AsmToken::Identifier))
429    return Error(BaseRegTok.getLoc(), "register expected");
430  if (MaybeParseRegister(Op, false))
431    return Error(BaseRegTok.getLoc(), "register expected");
432  int BaseRegNum = Op->getReg();
433
434  bool Preindexed = false;
435  bool Postindexed = false;
436  bool OffsetIsReg = false;
437  bool Negative = false;
438  bool Writeback = false;
439
440  // First look for preindexed address forms, that is after the "[Rn" we now
441  // have to see if the next token is a comma.
442  const AsmToken &Tok = Parser.getTok();
443  if (Tok.is(AsmToken::Comma)) {
444    Preindexed = true;
445    Parser.Lex(); // Eat comma token.
446    int OffsetRegNum;
447    bool OffsetRegShifted;
448    enum ShiftType ShiftType;
449    const MCExpr *ShiftAmount;
450    const MCExpr *Offset;
451    if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
452                            Offset, OffsetIsReg, OffsetRegNum, E))
453      return true;
454    const AsmToken &RBracTok = Parser.getTok();
455    if (RBracTok.isNot(AsmToken::RBrac))
456      return Error(RBracTok.getLoc(), "']' expected");
457    E = RBracTok.getLoc();
458    Parser.Lex(); // Eat right bracket token.
459
460    const AsmToken &ExclaimTok = Parser.getTok();
461    if (ExclaimTok.is(AsmToken::Exclaim)) {
462      E = ExclaimTok.getLoc();
463      Writeback = true;
464      Parser.Lex(); // Eat exclaim token
465    }
466    ARMOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
467                          OffsetRegShifted, ShiftType, ShiftAmount,
468                          Preindexed, Postindexed, Negative, Writeback, S, E);
469    return false;
470  }
471  // The "[Rn" we have so far was not followed by a comma.
472  else if (Tok.is(AsmToken::RBrac)) {
473    // This is a post indexing addressing forms, that is a ']' follows after
474    // the "[Rn".
475    Postindexed = true;
476    Writeback = true;
477    E = Tok.getLoc();
478    Parser.Lex(); // Eat right bracket token.
479
480    int OffsetRegNum = 0;
481    bool OffsetRegShifted = false;
482    enum ShiftType ShiftType;
483    const MCExpr *ShiftAmount;
484    const MCExpr *Offset;
485
486    const AsmToken &NextTok = Parser.getTok();
487    if (NextTok.isNot(AsmToken::EndOfStatement)) {
488      if (NextTok.isNot(AsmToken::Comma))
489        return Error(NextTok.getLoc(), "',' expected");
490      Parser.Lex(); // Eat comma token.
491      if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
492                              ShiftAmount, Offset, OffsetIsReg, OffsetRegNum,
493                              E))
494        return true;
495    }
496
497    ARMOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
498                          OffsetRegShifted, ShiftType, ShiftAmount,
499                          Preindexed, Postindexed, Negative, Writeback, S, E);
500    return false;
501  }
502
503  return true;
504}
505
506/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn],"
507/// we will parse the following (were +/- means that a plus or minus is
508/// optional):
509///   +/-Rm
510///   +/-Rm, shift
511///   #offset
512/// we return false on success or an error otherwise.
513bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
514                                        bool &OffsetRegShifted,
515                                        enum ShiftType &ShiftType,
516                                        const MCExpr *&ShiftAmount,
517                                        const MCExpr *&Offset,
518                                        bool &OffsetIsReg,
519                                        int &OffsetRegNum,
520                                        SMLoc &E) {
521  OwningPtr<ARMOperand> Op;
522  Negative = false;
523  OffsetRegShifted = false;
524  OffsetIsReg = false;
525  OffsetRegNum = -1;
526  const AsmToken &NextTok = Parser.getTok();
527  E = NextTok.getLoc();
528  if (NextTok.is(AsmToken::Plus))
529    Parser.Lex(); // Eat plus token.
530  else if (NextTok.is(AsmToken::Minus)) {
531    Negative = true;
532    Parser.Lex(); // Eat minus token
533  }
534  // See if there is a register following the "[Rn," or "[Rn]," we have so far.
535  const AsmToken &OffsetRegTok = Parser.getTok();
536  if (OffsetRegTok.is(AsmToken::Identifier)) {
537    OffsetIsReg = !MaybeParseRegister(Op, false);
538    if (OffsetIsReg) {
539      E = Op->getEndLoc();
540      OffsetRegNum = Op->getReg();
541    }
542  }
543  // If we parsed a register as the offset then their can be a shift after that
544  if (OffsetRegNum != -1) {
545    // Look for a comma then a shift
546    const AsmToken &Tok = Parser.getTok();
547    if (Tok.is(AsmToken::Comma)) {
548      Parser.Lex(); // Eat comma token.
549
550      const AsmToken &Tok = Parser.getTok();
551      if (ParseShift(ShiftType, ShiftAmount, E))
552        return Error(Tok.getLoc(), "shift expected");
553      OffsetRegShifted = true;
554    }
555  }
556  else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
557    // Look for #offset following the "[Rn," or "[Rn],"
558    const AsmToken &HashTok = Parser.getTok();
559    if (HashTok.isNot(AsmToken::Hash))
560      return Error(HashTok.getLoc(), "'#' expected");
561
562    Parser.Lex(); // Eat hash token.
563
564    if (getParser().ParseExpression(Offset))
565     return true;
566    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
567  }
568  return false;
569}
570
571/// ParseShift as one of these two:
572///   ( lsl | lsr | asr | ror ) , # shift_amount
573///   rrx
574/// and returns true if it parses a shift otherwise it returns false.
575bool ARMAsmParser::ParseShift(ShiftType &St,
576                              const MCExpr *&ShiftAmount,
577                              SMLoc &E) {
578  const AsmToken &Tok = Parser.getTok();
579  if (Tok.isNot(AsmToken::Identifier))
580    return true;
581  StringRef ShiftName = Tok.getString();
582  if (ShiftName == "lsl" || ShiftName == "LSL")
583    St = Lsl;
584  else if (ShiftName == "lsr" || ShiftName == "LSR")
585    St = Lsr;
586  else if (ShiftName == "asr" || ShiftName == "ASR")
587    St = Asr;
588  else if (ShiftName == "ror" || ShiftName == "ROR")
589    St = Ror;
590  else if (ShiftName == "rrx" || ShiftName == "RRX")
591    St = Rrx;
592  else
593    return true;
594  Parser.Lex(); // Eat shift type token.
595
596  // Rrx stands alone.
597  if (St == Rrx)
598    return false;
599
600  // Otherwise, there must be a '#' and a shift amount.
601  const AsmToken &HashTok = Parser.getTok();
602  if (HashTok.isNot(AsmToken::Hash))
603    return Error(HashTok.getLoc(), "'#' expected");
604  Parser.Lex(); // Eat hash token.
605
606  if (getParser().ParseExpression(ShiftAmount))
607    return true;
608
609  return false;
610}
611
612/// Parse a arm instruction operand.  For now this parses the operand regardless
613/// of the mnemonic.
614bool ARMAsmParser::ParseOperand(OwningPtr<ARMOperand> &Op) {
615  SMLoc S, E;
616
617  switch (getLexer().getKind()) {
618  case AsmToken::Identifier:
619    if (!MaybeParseRegister(Op, true))
620      return false;
621    // This was not a register so parse other operands that start with an
622    // identifier (like labels) as expressions and create them as immediates.
623    const MCExpr *IdVal;
624    S = Parser.getTok().getLoc();
625    if (getParser().ParseExpression(IdVal))
626      return true;
627    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
628    ARMOperand::CreateImm(Op, IdVal, S, E);
629    return false;
630  case AsmToken::LBrac:
631    return ParseMemory(Op);
632  case AsmToken::LCurly:
633    return ParseRegisterList(Op);
634  case AsmToken::Hash:
635    // #42 -> immediate.
636    // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
637    S = Parser.getTok().getLoc();
638    Parser.Lex();
639    const MCExpr *ImmVal;
640    if (getParser().ParseExpression(ImmVal))
641      return true;
642    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
643    ARMOperand::CreateImm(Op, ImmVal, S, E);
644    return false;
645  default:
646    return Error(Parser.getTok().getLoc(), "unexpected token in operand");
647  }
648}
649
650/// Parse an arm instruction mnemonic followed by its operands.
651bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
652                               SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
653  OwningPtr<ARMOperand> Op;
654  ARMOperand::CreateToken(Op, Name, NameLoc);
655
656  Operands.push_back(Op.take());
657
658  if (getLexer().isNot(AsmToken::EndOfStatement)) {
659
660    // Read the first operand.
661    OwningPtr<ARMOperand> Op;
662    if (ParseOperand(Op)) return true;
663    Operands.push_back(Op.take());
664
665    while (getLexer().is(AsmToken::Comma)) {
666      Parser.Lex();  // Eat the comma.
667
668      // Parse and remember the operand.
669      if (ParseOperand(Op)) return true;
670      Operands.push_back(Op.take());
671    }
672  }
673  return false;
674}
675
676/// ParseDirective parses the arm specific directives
677bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
678  StringRef IDVal = DirectiveID.getIdentifier();
679  if (IDVal == ".word")
680    return ParseDirectiveWord(4, DirectiveID.getLoc());
681  else if (IDVal == ".thumb")
682    return ParseDirectiveThumb(DirectiveID.getLoc());
683  else if (IDVal == ".thumb_func")
684    return ParseDirectiveThumbFunc(DirectiveID.getLoc());
685  else if (IDVal == ".code")
686    return ParseDirectiveCode(DirectiveID.getLoc());
687  else if (IDVal == ".syntax")
688    return ParseDirectiveSyntax(DirectiveID.getLoc());
689  return true;
690}
691
692/// ParseDirectiveWord
693///  ::= .word [ expression (, expression)* ]
694bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
695  if (getLexer().isNot(AsmToken::EndOfStatement)) {
696    for (;;) {
697      const MCExpr *Value;
698      if (getParser().ParseExpression(Value))
699        return true;
700
701      getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
702
703      if (getLexer().is(AsmToken::EndOfStatement))
704        break;
705
706      // FIXME: Improve diagnostic.
707      if (getLexer().isNot(AsmToken::Comma))
708        return Error(L, "unexpected token in directive");
709      Parser.Lex();
710    }
711  }
712
713  Parser.Lex();
714  return false;
715}
716
717/// ParseDirectiveThumb
718///  ::= .thumb
719bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
720  if (getLexer().isNot(AsmToken::EndOfStatement))
721    return Error(L, "unexpected token in directive");
722  Parser.Lex();
723
724  // TODO: set thumb mode
725  // TODO: tell the MC streamer the mode
726  // getParser().getStreamer().Emit???();
727  return false;
728}
729
730/// ParseDirectiveThumbFunc
731///  ::= .thumbfunc symbol_name
732bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
733  const AsmToken &Tok = Parser.getTok();
734  if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
735    return Error(L, "unexpected token in .syntax directive");
736  StringRef ATTRIBUTE_UNUSED SymbolName = Parser.getTok().getIdentifier();
737  Parser.Lex(); // Consume the identifier token.
738
739  if (getLexer().isNot(AsmToken::EndOfStatement))
740    return Error(L, "unexpected token in directive");
741  Parser.Lex();
742
743  // TODO: mark symbol as a thumb symbol
744  // getParser().getStreamer().Emit???();
745  return false;
746}
747
748/// ParseDirectiveSyntax
749///  ::= .syntax unified | divided
750bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
751  const AsmToken &Tok = Parser.getTok();
752  if (Tok.isNot(AsmToken::Identifier))
753    return Error(L, "unexpected token in .syntax directive");
754  StringRef Mode = Tok.getString();
755  if (Mode == "unified" || Mode == "UNIFIED")
756    Parser.Lex();
757  else if (Mode == "divided" || Mode == "DIVIDED")
758    Parser.Lex();
759  else
760    return Error(L, "unrecognized syntax mode in .syntax directive");
761
762  if (getLexer().isNot(AsmToken::EndOfStatement))
763    return Error(Parser.getTok().getLoc(), "unexpected token in directive");
764  Parser.Lex();
765
766  // TODO tell the MC streamer the mode
767  // getParser().getStreamer().Emit???();
768  return false;
769}
770
771/// ParseDirectiveCode
772///  ::= .code 16 | 32
773bool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
774  const AsmToken &Tok = Parser.getTok();
775  if (Tok.isNot(AsmToken::Integer))
776    return Error(L, "unexpected token in .code directive");
777  int64_t Val = Parser.getTok().getIntVal();
778  if (Val == 16)
779    Parser.Lex();
780  else if (Val == 32)
781    Parser.Lex();
782  else
783    return Error(L, "invalid operand to .code directive");
784
785  if (getLexer().isNot(AsmToken::EndOfStatement))
786    return Error(Parser.getTok().getLoc(), "unexpected token in directive");
787  Parser.Lex();
788
789  // TODO tell the MC streamer the mode
790  // getParser().getStreamer().Emit???();
791  return false;
792}
793
794extern "C" void LLVMInitializeARMAsmLexer();
795
796/// Force static initialization.
797extern "C" void LLVMInitializeARMAsmParser() {
798  RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
799  RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);
800  LLVMInitializeARMAsmLexer();
801}
802
803#include "ARMGenAsmMatcher.inc"
804