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