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