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