c4244c720193c8a852cc940fbdf99defe64738db
[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 ParseMemory(ARMOperand &Op);
50
51   bool ParseShift(enum ShiftType *St, const MCExpr *ShiftAmount);
52
53   bool ParseOperand(ARMOperand &Op);
54
55   bool ParseDirectiveWord(unsigned Size, SMLoc L);
56
57   // TODO - For now hacked versions of the next two are in here in this file to
58   // allow some parser testing until the table gen versions are implemented.
59
60   /// @name Auto-generated Match Functions
61   /// {
62   bool MatchInstruction(SmallVectorImpl<ARMOperand> &Operands,
63                         MCInst &Inst);
64
65   /// MatchRegisterName - Match the given string to a register name, or 0 if
66   /// there is no match.
67   unsigned MatchRegisterName(const StringRef &Name);
68
69   /// }
70
71
72 public:
73   ARMAsmParser(const Target &T, MCAsmParser &_Parser)
74     : TargetAsmParser(T), Parser(_Parser) {}
75
76   virtual bool ParseInstruction(const StringRef &Name, MCInst &Inst);
77
78   virtual bool ParseDirective(AsmToken DirectiveID);
79 };
80   
81 } // end anonymous namespace
82
83 namespace {
84
85 /// ARMOperand - Instances of this class represent a parsed ARM machine
86 /// instruction.
87 struct ARMOperand {
88   enum {
89     Token,
90     Register,
91     Memory
92   } Kind;
93
94
95   union {
96     struct {
97       const char *Data;
98       unsigned Length;
99     } Tok;
100
101     struct {
102       unsigned RegNum;
103       bool Writeback;
104     } Reg;
105
106     // This is for all forms of ARM address expressions
107     struct {
108       unsigned BaseRegNum;
109       bool OffsetIsReg;
110       const MCExpr *Offset; // used when OffsetIsReg is false
111       unsigned OffsetRegNum; // used when OffsetIsReg is true
112       bool OffsetRegShifted; // only used when OffsetIsReg is true
113       enum ShiftType ShiftType;  // used when OffsetRegShifted is true
114       const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
115       bool Preindexed;
116       bool Postindexed;
117       bool Negative; // only used when OffsetIsReg is true
118       bool Writeback;
119     } Mem;
120
121   };
122
123   StringRef getToken() const {
124     assert(Kind == Token && "Invalid access!");
125     return StringRef(Tok.Data, Tok.Length);
126   }
127
128   unsigned getReg() const {
129     assert(Kind == Register && "Invalid access!");
130     return Reg.RegNum;
131   }
132
133   bool isToken() const {return Kind == Token; }
134
135   bool isReg() const { return Kind == Register; }
136
137   void addRegOperands(MCInst &Inst, unsigned N) const {
138     assert(N == 1 && "Invalid number of operands!");
139     Inst.addOperand(MCOperand::CreateReg(getReg()));
140   }
141
142   static ARMOperand CreateToken(StringRef Str) {
143     ARMOperand Res;
144     Res.Kind = Token;
145     Res.Tok.Data = Str.data();
146     Res.Tok.Length = Str.size();
147     return Res;
148   }
149
150   static ARMOperand CreateReg(unsigned RegNum, bool Writeback) {
151     ARMOperand Res;
152     Res.Kind = Register;
153     Res.Reg.RegNum = RegNum;
154     Res.Reg.Writeback = Writeback;
155     return Res;
156   }
157
158   static ARMOperand CreateMem(unsigned BaseRegNum, bool OffsetIsReg,
159                               const MCExpr *Offset, unsigned OffsetRegNum,
160                               bool OffsetRegShifted, enum ShiftType ShiftType,
161                               const MCExpr *ShiftAmount, bool Preindexed,
162                               bool Postindexed, bool Negative, bool Writeback) {
163     ARMOperand Res;
164     Res.Kind = Memory;
165     Res.Mem.BaseRegNum = BaseRegNum;
166     Res.Mem.OffsetIsReg = OffsetIsReg;
167     Res.Mem.Offset = Offset;
168     Res.Mem.OffsetRegNum = OffsetRegNum;
169     Res.Mem.OffsetRegShifted = OffsetRegShifted;
170     Res.Mem.ShiftType = ShiftType;
171     Res.Mem.ShiftAmount = ShiftAmount;
172     Res.Mem.Preindexed = Preindexed;
173     Res.Mem.Postindexed = Postindexed;
174     Res.Mem.Negative = Negative;
175     Res.Mem.Writeback = Writeback;
176     return Res;
177   }
178 };
179
180 } // end anonymous namespace.
181
182 // Try to parse a register name.  The token must be an Identifier when called,
183 // and if it is a register name a Reg operand is created, the token is eaten
184 // and false is returned.  Else true is returned and no token is eaten.
185 // TODO this is likely to change to allow different register types and or to
186 // parse for a specific register type.
187 bool ARMAsmParser::ParseRegister(ARMOperand &Op) {
188   const AsmToken &Tok = getLexer().getTok();
189   assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
190
191   // FIXME: Validate register for the current architecture; we have to do
192   // validation later, so maybe there is no need for this here.
193   unsigned RegNum;
194
195   RegNum = MatchRegisterName(Tok.getString());
196   if (RegNum == 0)
197     return true;
198   getLexer().Lex(); // Eat identifier token.
199
200   bool Writeback = false;
201   const AsmToken &ExclaimTok = getLexer().getTok();
202   if (ExclaimTok.is(AsmToken::Exclaim)) {
203     Writeback = true;
204     getLexer().Lex(); // Eat exclaim token
205   }
206
207   Op = ARMOperand::CreateReg(RegNum, Writeback);
208
209   return false;
210 }
211
212 // Try to parse an arm memory expression.  It must start with a '[' token.
213 // TODO Only preindexing and postindexing addressing are started, unindexed
214 // with option, etc are still to do.
215 bool ARMAsmParser::ParseMemory(ARMOperand &Op) {
216   const AsmToken &LBracTok = getLexer().getTok();
217   assert(LBracTok.is(AsmToken::LBrac) && "Token is not an Left Bracket");
218   getLexer().Lex(); // Eat left bracket token.
219
220   const AsmToken &BaseRegTok = getLexer().getTok();
221   if (BaseRegTok.isNot(AsmToken::Identifier))
222     return Error(BaseRegTok.getLoc(), "register expected");
223   unsigned BaseRegNum = MatchRegisterName(BaseRegTok.getString());
224   if (BaseRegNum == 0)
225     return Error(BaseRegTok.getLoc(), "register expected");
226   getLexer().Lex(); // Eat identifier token.
227
228   bool Preindexed = false;
229   bool Postindexed = false;
230   bool OffsetIsReg = false;
231   bool Negative = false;
232   bool Writeback = false;
233
234   // First look for preindexed address forms:
235   //  [Rn, +/-Rm]
236   //  [Rn, #offset]
237   //  [Rn, +/-Rm, shift]
238   // that is after the "[Rn" we now have see if the next token is a comma.
239   const AsmToken &Tok = getLexer().getTok();
240   if (Tok.is(AsmToken::Comma)) {
241     Preindexed = true;
242     getLexer().Lex(); // Eat comma token.
243
244     const AsmToken &NextTok = getLexer().getTok();
245     if (NextTok.is(AsmToken::Plus))
246       getLexer().Lex(); // Eat plus token.
247     else if (NextTok.is(AsmToken::Minus)) {
248       Negative = true;
249       getLexer().Lex(); // Eat minus token
250     }
251
252     // See if there is a register following the "[Rn," we have so far.
253     const AsmToken &OffsetRegTok = getLexer().getTok();
254     unsigned OffsetRegNum = MatchRegisterName(OffsetRegTok.getString());
255     bool OffsetRegShifted = false;
256     enum ShiftType ShiftType;
257     const MCExpr *ShiftAmount;
258     const MCExpr *Offset;
259     if (OffsetRegNum != 0) {
260       OffsetIsReg = true;
261       getLexer().Lex(); // Eat identifier token for the offset register.
262       // Look for a comma then a shift
263       const AsmToken &Tok = getLexer().getTok();
264       if (Tok.is(AsmToken::Comma)) {
265         getLexer().Lex(); // Eat comma token.
266
267         const AsmToken &Tok = getLexer().getTok();
268         if (ParseShift(&ShiftType, ShiftAmount))
269           return Error(Tok.getLoc(), "shift expected");
270         OffsetRegShifted = true;
271       }
272     }
273     else { // "[Rn," we have so far was not followed by "Rm"
274       // Look for #offset following the "[Rn,"
275       const AsmToken &HashTok = getLexer().getTok();
276       if (HashTok.isNot(AsmToken::Hash))
277         return Error(HashTok.getLoc(), "'#' expected");
278       getLexer().Lex(); // Eat hash token.
279
280       if (getParser().ParseExpression(Offset))
281        return true;
282     }
283     const AsmToken &RBracTok = getLexer().getTok();
284     if (RBracTok.isNot(AsmToken::RBrac))
285       return Error(RBracTok.getLoc(), "']' expected");
286     getLexer().Lex(); // Eat right bracket token.
287
288     const AsmToken &ExclaimTok = getLexer().getTok();
289     if (ExclaimTok.is(AsmToken::Exclaim)) {
290       Writeback = true;
291       getLexer().Lex(); // Eat exclaim token
292     }
293     Op = ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
294                                OffsetRegShifted, ShiftType, ShiftAmount,
295                                Preindexed, Postindexed, Negative, Writeback);
296     return false;
297   }
298   // The "[Rn" we have so far was not followed by a comma.
299   else if (Tok.is(AsmToken::RBrac)) {
300     // This is a post indexing addressing forms:
301     //  [Rn], #offset
302     //  [Rn], +/-Rm
303     //  [Rn], +/-Rm, shift
304     // that is a ']' follows after the "[Rn".
305     Postindexed = true;
306     Writeback = true;
307     getLexer().Lex(); // Eat right bracket token.
308
309     const AsmToken &CommaTok = getLexer().getTok();
310     if (CommaTok.isNot(AsmToken::Comma))
311       return Error(CommaTok.getLoc(), "',' expected");
312     getLexer().Lex(); // Eat comma token.
313
314     const AsmToken &NextTok = getLexer().getTok();
315     if (NextTok.is(AsmToken::Plus))
316       getLexer().Lex(); // Eat plus token.
317     else if (NextTok.is(AsmToken::Minus)) {
318       Negative = true;
319       getLexer().Lex(); // Eat minus token
320     }
321
322     // See if there is a register following the "[Rn]," we have so far.
323     const AsmToken &OffsetRegTok = getLexer().getTok();
324     unsigned OffsetRegNum = MatchRegisterName(OffsetRegTok.getString());
325     bool OffsetRegShifted = false;
326     enum ShiftType ShiftType;
327     const MCExpr *ShiftAmount;
328     const MCExpr *Offset;
329     if (OffsetRegNum != 0) {
330       OffsetIsReg = true;
331       getLexer().Lex(); // Eat identifier token for the offset register.
332       // Look for a comma then a shift
333       const AsmToken &Tok = getLexer().getTok();
334       if (Tok.is(AsmToken::Comma)) {
335         getLexer().Lex(); // Eat comma token.
336
337         const AsmToken &Tok = getLexer().getTok();
338         if (ParseShift(&ShiftType, ShiftAmount))
339           return Error(Tok.getLoc(), "shift expected");
340         OffsetRegShifted = true;
341       }
342     }
343     else { // "[Rn]," we have so far was not followed by "Rm"
344       // Look for #offset following the "[Rn],"
345       const AsmToken &HashTok = getLexer().getTok();
346       if (HashTok.isNot(AsmToken::Hash))
347         return Error(HashTok.getLoc(), "'#' expected");
348       getLexer().Lex(); // Eat hash token.
349
350       if (getParser().ParseExpression(Offset))
351        return true;
352     }
353     Op = ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
354                                OffsetRegShifted, ShiftType, ShiftAmount,
355                                Preindexed, Postindexed, Negative, Writeback);
356     return false;
357   }
358
359   return true;
360 }
361
362 /// ParseShift as one of these two:
363 ///   ( lsl | lsr | asr | ror ) , # shift_amount
364 ///   rrx
365 /// and returns true if it parses a shift otherwise it returns false.
366 bool ARMAsmParser::ParseShift(ShiftType *St, const MCExpr *ShiftAmount) {
367   const AsmToken &Tok = getLexer().getTok();
368   if (Tok.isNot(AsmToken::Identifier))
369     return true;
370   const StringRef &ShiftName = Tok.getString();
371   if (ShiftName == "lsl" || ShiftName == "LSL")
372     *St = Lsl;
373   else if (ShiftName == "lsr" || ShiftName == "LSR")
374     *St = Lsr;
375   else if (ShiftName == "asr" || ShiftName == "ASR")
376     *St = Asr;
377   else if (ShiftName == "ror" || ShiftName == "ROR")
378     *St = Ror;
379   else if (ShiftName == "rrx" || ShiftName == "RRX")
380     *St = Rrx;
381   else
382     return true;
383   getLexer().Lex(); // Eat shift type token.
384
385   // For all but a Rotate right there must be a '#' and a shift amount
386   if (*St != Rrx) {
387     // Look for # following the shift type
388     const AsmToken &HashTok = getLexer().getTok();
389     if (HashTok.isNot(AsmToken::Hash))
390       return Error(HashTok.getLoc(), "'#' expected");
391     getLexer().Lex(); // Eat hash token.
392
393     if (getParser().ParseExpression(ShiftAmount))
394       return true;
395   }
396
397   return false;
398 }
399
400 // A hack to allow some testing
401 unsigned ARMAsmParser::MatchRegisterName(const StringRef &Name) {
402   if (Name == "r1")
403     return 1;
404   else if (Name == "r2")
405     return 2;
406   else if (Name == "r3")
407     return 3;
408   else if (Name == "sp")
409     return 13;
410   return 0;
411 }
412
413 // A hack to allow some testing
414 bool ARMAsmParser::MatchInstruction(SmallVectorImpl<ARMOperand> &Operands,
415                                     MCInst &Inst) {
416   struct ARMOperand Op0 = Operands[0];
417   assert(Op0.Kind == ARMOperand::Token && "First operand not a Token");
418   const StringRef &Mnemonic = Op0.getToken();
419   if (Mnemonic == "add" ||
420       Mnemonic == "stmfd" ||
421       Mnemonic == "str" ||
422       Mnemonic == "ldmfd" ||
423       Mnemonic == "ldr")
424     return false;
425
426   return true;
427 }
428
429 // TODO - this is a work in progress
430 bool ARMAsmParser::ParseOperand(ARMOperand &Op) {
431   switch (getLexer().getKind()) {
432   case AsmToken::Identifier:
433     if (!ParseRegister(Op))
434       return false;
435     // TODO parse other operands that start with an identifier
436     return true;
437   case AsmToken::LBrac:
438     if (!ParseMemory(Op))
439       return false;
440   default:
441     return true;
442   }
443 }
444
445 bool ARMAsmParser::ParseInstruction(const StringRef &Name, MCInst &Inst) {
446   SmallVector<ARMOperand, 7> Operands;
447
448   Operands.push_back(ARMOperand::CreateToken(Name));
449
450   SMLoc Loc = getLexer().getTok().getLoc();
451   if (getLexer().isNot(AsmToken::EndOfStatement)) {
452
453     // Read the first operand.
454     Operands.push_back(ARMOperand());
455     if (ParseOperand(Operands.back()))
456       return true;
457
458     while (getLexer().is(AsmToken::Comma)) {
459       getLexer().Lex();  // Eat the comma.
460
461       // Parse and remember the operand.
462       Operands.push_back(ARMOperand());
463       if (ParseOperand(Operands.back()))
464         return true;
465     }
466   }
467   if (!MatchInstruction(Operands, Inst))
468     return false;
469
470   Error(Loc, "ARMAsmParser::ParseInstruction only partly implemented");
471   return true;
472 }
473
474 bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
475   StringRef IDVal = DirectiveID.getIdentifier();
476   if (IDVal == ".word")
477     return ParseDirectiveWord(4, DirectiveID.getLoc());
478   return true;
479 }
480
481 /// ParseDirectiveWord
482 ///  ::= .word [ expression (, expression)* ]
483 bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
484   if (getLexer().isNot(AsmToken::EndOfStatement)) {
485     for (;;) {
486       const MCExpr *Value;
487       if (getParser().ParseExpression(Value))
488         return true;
489
490       getParser().getStreamer().EmitValue(Value, Size);
491
492       if (getLexer().is(AsmToken::EndOfStatement))
493         break;
494       
495       // FIXME: Improve diagnostic.
496       if (getLexer().isNot(AsmToken::Comma))
497         return Error(L, "unexpected token in directive");
498       getLexer().Lex();
499     }
500   }
501
502   getLexer().Lex();
503   return false;
504 }
505
506 // Force static initialization.
507 extern "C" void LLVMInitializeARMAsmParser() {
508   RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
509   RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);
510 }