Fix ARM memory operand parsing of post indexing with just a base register, that
[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     return false;
539
540   return true;
541 }
542
543 // Parse a arm instruction operand.  For now this parses the operand regardless
544 // of the mnemonic.
545 bool ARMAsmParser::ParseOperand(ARMOperand &Op) {
546   switch (getLexer().getKind()) {
547   case AsmToken::Identifier:
548     if (!ParseRegister(Op))
549       return false;
550     // This was not a register so parse other operands that start with an
551     // identifier (like labels) as expressions and create them as immediates.
552     const MCExpr *IdVal;
553     if (getParser().ParseExpression(IdVal))
554       return true;
555     Op = ARMOperand::CreateImm(IdVal);
556     return false;
557   case AsmToken::LBrac:
558     return ParseMemory(Op);
559   case AsmToken::LCurly:
560     return ParseRegisterList(Op);
561   case AsmToken::Hash:
562     // #42 -> immediate.
563     // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
564     getLexer().Lex();
565     const MCExpr *ImmVal;
566     if (getParser().ParseExpression(ImmVal))
567       return true;
568     Op = ARMOperand::CreateImm(ImmVal);
569     return false;
570   default:
571     return Error(getLexer().getTok().getLoc(), "unexpected token in operand");
572   }
573 }
574
575 // Parse an arm instruction mnemonic followed by its operands.
576 bool ARMAsmParser::ParseInstruction(const StringRef &Name, MCInst &Inst) {
577   SmallVector<ARMOperand, 7> Operands;
578
579   Operands.push_back(ARMOperand::CreateToken(Name));
580
581   SMLoc Loc = getLexer().getTok().getLoc();
582   if (getLexer().isNot(AsmToken::EndOfStatement)) {
583
584     // Read the first operand.
585     Operands.push_back(ARMOperand());
586     if (ParseOperand(Operands.back()))
587       return true;
588
589     while (getLexer().is(AsmToken::Comma)) {
590       getLexer().Lex();  // Eat the comma.
591
592       // Parse and remember the operand.
593       Operands.push_back(ARMOperand());
594       if (ParseOperand(Operands.back()))
595         return true;
596     }
597   }
598   if (!MatchInstruction(Operands, Inst))
599     return false;
600
601   Error(Loc, "ARMAsmParser::ParseInstruction only partly implemented");
602   return true;
603 }
604
605 /// ParseDirective parses the arm specific directives
606 bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
607   StringRef IDVal = DirectiveID.getIdentifier();
608   if (IDVal == ".word")
609     return ParseDirectiveWord(4, DirectiveID.getLoc());
610   else if (IDVal == ".thumb")
611     return ParseDirectiveThumb(DirectiveID.getLoc());
612   else if (IDVal == ".thumb_func")
613     return ParseDirectiveThumbFunc(DirectiveID.getLoc());
614   else if (IDVal == ".code")
615     return ParseDirectiveCode(DirectiveID.getLoc());
616   else if (IDVal == ".syntax")
617     return ParseDirectiveSyntax(DirectiveID.getLoc());
618   return true;
619 }
620
621 /// ParseDirectiveWord
622 ///  ::= .word [ expression (, expression)* ]
623 bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
624   if (getLexer().isNot(AsmToken::EndOfStatement)) {
625     for (;;) {
626       const MCExpr *Value;
627       if (getParser().ParseExpression(Value))
628         return true;
629
630       getParser().getStreamer().EmitValue(Value, Size);
631
632       if (getLexer().is(AsmToken::EndOfStatement))
633         break;
634       
635       // FIXME: Improve diagnostic.
636       if (getLexer().isNot(AsmToken::Comma))
637         return Error(L, "unexpected token in directive");
638       getLexer().Lex();
639     }
640   }
641
642   getLexer().Lex();
643   return false;
644 }
645
646 /// ParseDirectiveThumb
647 ///  ::= .thumb
648 bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
649   if (getLexer().isNot(AsmToken::EndOfStatement))
650     return Error(L, "unexpected token in directive");
651   getLexer().Lex();
652
653   // TODO: set thumb mode
654   // TODO: tell the MC streamer the mode
655   // getParser().getStreamer().Emit???();
656   return false;
657 }
658
659 /// ParseDirectiveThumbFunc
660 ///  ::= .thumbfunc symbol_name
661 bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
662   const AsmToken &Tok = getLexer().getTok();
663   if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
664     return Error(L, "unexpected token in .syntax directive");
665   StringRef SymbolName = getLexer().getTok().getIdentifier();
666   getLexer().Lex(); // Consume the identifier token.
667
668   if (getLexer().isNot(AsmToken::EndOfStatement))
669     return Error(L, "unexpected token in directive");
670   getLexer().Lex();
671
672   // TODO: mark symbol as a thumb symbol
673   // getParser().getStreamer().Emit???();
674   return false;
675 }
676
677 /// ParseDirectiveSyntax
678 ///  ::= .syntax unified | divided
679 bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
680   const AsmToken &Tok = getLexer().getTok();
681   if (Tok.isNot(AsmToken::Identifier))
682     return Error(L, "unexpected token in .syntax directive");
683   const StringRef &Mode = Tok.getString();
684   bool unified_syntax;
685   if (Mode == "unified" || Mode == "UNIFIED") {
686     getLexer().Lex();
687     unified_syntax = true;
688   }
689   else if (Mode == "divided" || Mode == "DIVIDED") {
690     getLexer().Lex();
691     unified_syntax = false;
692   }
693   else
694     return Error(L, "unrecognized syntax mode in .syntax directive");
695
696   if (getLexer().isNot(AsmToken::EndOfStatement))
697     return Error(getLexer().getTok().getLoc(), "unexpected token in directive");
698   getLexer().Lex();
699
700   // TODO tell the MC streamer the mode
701   // getParser().getStreamer().Emit???();
702   return false;
703 }
704
705 /// ParseDirectiveCode
706 ///  ::= .code 16 | 32
707 bool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
708   const AsmToken &Tok = getLexer().getTok();
709   if (Tok.isNot(AsmToken::Integer))
710     return Error(L, "unexpected token in .code directive");
711   int64_t Val = getLexer().getTok().getIntVal();
712   bool thumb_mode;
713   if (Val == 16) {
714     getLexer().Lex();
715     thumb_mode = true;
716   }
717   else if (Val == 32) {
718     getLexer().Lex();
719     thumb_mode = false;
720   }
721   else
722     return Error(L, "invalid operand to .code directive");
723
724   if (getLexer().isNot(AsmToken::EndOfStatement))
725     return Error(getLexer().getTok().getLoc(), "unexpected token in directive");
726   getLexer().Lex();
727
728   // TODO tell the MC streamer the mode
729   // getParser().getStreamer().Emit???();
730   return false;
731 }
732
733 // Force static initialization.
734 extern "C" void LLVMInitializeARMAsmParser() {
735   RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
736   RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);
737 }