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