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