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