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