[ms-inline asm] Use the new API introduced in r165830 in lieu of the
[oota-llvm.git] / lib / Target / MBlaze / AsmParser / MBlazeAsmParser.cpp
1 //===-- MBlazeAsmParser.cpp - Parse MBlaze asm 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 "MCTargetDesc/MBlazeBaseInfo.h"
11 #include "llvm/MC/MCParser/MCAsmLexer.h"
12 #include "llvm/MC/MCParser/MCAsmParser.h"
13 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
14 #include "llvm/MC/MCStreamer.h"
15 #include "llvm/MC/MCExpr.h"
16 #include "llvm/MC/MCInst.h"
17 #include "llvm/MC/MCTargetAsmParser.h"
18 #include "llvm/Support/SourceMgr.h"
19 #include "llvm/Support/TargetRegistry.h"
20 #include "llvm/Support/raw_ostream.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/Twine.h"
23 using namespace llvm;
24
25 namespace {
26 struct MBlazeOperand;
27
28 class MBlazeAsmParser : public MCTargetAsmParser {
29   MCAsmParser &Parser;
30
31   MCAsmParser &getParser() const { return Parser; }
32   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
33
34   void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
35   bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
36
37   MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
38   MBlazeOperand *ParseRegister(unsigned &RegNo);
39   MBlazeOperand *ParseImmediate();
40   MBlazeOperand *ParseFsl();
41   MBlazeOperand* ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
42
43   virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
44
45   bool ParseDirectiveWord(unsigned Size, SMLoc L);
46
47   bool MatchAndEmitInstruction(SMLoc IDLoc,
48                                SmallVectorImpl<MCParsedAsmOperand*> &Operands,
49                                MCStreamer &Out);
50
51   /// @name Auto-generated Match Functions
52   /// {
53
54 #define GET_ASSEMBLER_HEADER
55 #include "MBlazeGenAsmMatcher.inc"
56
57   /// }
58
59 public:
60   MBlazeAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
61     : MCTargetAsmParser(), Parser(_Parser) {}
62
63   virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
64                                 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
65
66   virtual bool ParseDirective(AsmToken DirectiveID);
67 };
68
69 /// MBlazeOperand - Instances of this class represent a parsed MBlaze machine
70 /// instruction.
71 struct MBlazeOperand : public MCParsedAsmOperand {
72   enum KindTy {
73     Token,
74     Immediate,
75     Register,
76     Memory,
77     Fsl
78   } Kind;
79
80   SMLoc StartLoc, EndLoc;
81
82   union {
83     struct {
84       const char *Data;
85       unsigned Length;
86     } Tok;
87
88     struct {
89       unsigned RegNum;
90     } Reg;
91
92     struct {
93       const MCExpr *Val;
94     } Imm;
95
96     struct {
97       unsigned Base;
98       unsigned OffReg;
99       const MCExpr *Off;
100     } Mem;
101
102     struct {
103       const MCExpr *Val;
104     } FslImm;
105   };
106
107   MBlazeOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
108 public:
109   MBlazeOperand(const MBlazeOperand &o) : MCParsedAsmOperand() {
110     Kind = o.Kind;
111     StartLoc = o.StartLoc;
112     EndLoc = o.EndLoc;
113     switch (Kind) {
114     case Register:
115       Reg = o.Reg;
116       break;
117     case Immediate:
118       Imm = o.Imm;
119       break;
120     case Token:
121       Tok = o.Tok;
122       break;
123     case Memory:
124       Mem = o.Mem;
125       break;
126     case Fsl:
127       FslImm = o.FslImm;
128       break;
129     }
130   }
131
132   /// getStartLoc - Get the location of the first token of this operand.
133   SMLoc getStartLoc() const { return StartLoc; }
134
135   /// getEndLoc - Get the location of the last token of this operand.
136   SMLoc getEndLoc() const { return EndLoc; }
137
138   unsigned getReg() const {
139     assert(Kind == Register && "Invalid access!");
140     return Reg.RegNum;
141   }
142
143   const MCExpr *getImm() const {
144     assert(Kind == Immediate && "Invalid access!");
145     return Imm.Val;
146   }
147
148   const MCExpr *getFslImm() const {
149     assert(Kind == Fsl && "Invalid access!");
150     return FslImm.Val;
151   }
152
153   unsigned getMemBase() const {
154     assert(Kind == Memory && "Invalid access!");
155     return Mem.Base;
156   }
157
158   const MCExpr* getMemOff() const {
159     assert(Kind == Memory && "Invalid access!");
160     return Mem.Off;
161   }
162
163   unsigned getMemOffReg() const {
164     assert(Kind == Memory && "Invalid access!");
165     return Mem.OffReg;
166   }
167
168   bool isToken() const { return Kind == Token; }
169   bool isImm() const { return Kind == Immediate; }
170   bool isMem() const { return Kind == Memory; }
171   bool isFsl() const { return Kind == Fsl; }
172   bool isReg() const { return Kind == Register; }
173
174   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
175     // Add as immediates when possible.  Null MCExpr = 0.
176     if (Expr == 0)
177       Inst.addOperand(MCOperand::CreateImm(0));
178     else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
179       Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
180     else
181       Inst.addOperand(MCOperand::CreateExpr(Expr));
182   }
183
184   void addRegOperands(MCInst &Inst, unsigned N) const {
185     assert(N == 1 && "Invalid number of operands!");
186     Inst.addOperand(MCOperand::CreateReg(getReg()));
187   }
188
189   void addImmOperands(MCInst &Inst, unsigned N) const {
190     assert(N == 1 && "Invalid number of operands!");
191     addExpr(Inst, getImm());
192   }
193
194   void addFslOperands(MCInst &Inst, unsigned N) const {
195     assert(N == 1 && "Invalid number of operands!");
196     addExpr(Inst, getFslImm());
197   }
198
199   void addMemOperands(MCInst &Inst, unsigned N) const {
200     assert(N == 2 && "Invalid number of operands!");
201
202     Inst.addOperand(MCOperand::CreateReg(getMemBase()));
203
204     unsigned RegOff = getMemOffReg();
205     if (RegOff)
206       Inst.addOperand(MCOperand::CreateReg(RegOff));
207     else
208       addExpr(Inst, getMemOff());
209   }
210
211   StringRef getToken() const {
212     assert(Kind == Token && "Invalid access!");
213     return StringRef(Tok.Data, Tok.Length);
214   }
215
216   virtual void print(raw_ostream &OS) const;
217
218   static MBlazeOperand *CreateToken(StringRef Str, SMLoc S) {
219     MBlazeOperand *Op = new MBlazeOperand(Token);
220     Op->Tok.Data = Str.data();
221     Op->Tok.Length = Str.size();
222     Op->StartLoc = S;
223     Op->EndLoc = S;
224     return Op;
225   }
226
227   static MBlazeOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
228     MBlazeOperand *Op = new MBlazeOperand(Register);
229     Op->Reg.RegNum = RegNum;
230     Op->StartLoc = S;
231     Op->EndLoc = E;
232     return Op;
233   }
234
235   static MBlazeOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
236     MBlazeOperand *Op = new MBlazeOperand(Immediate);
237     Op->Imm.Val = Val;
238     Op->StartLoc = S;
239     Op->EndLoc = E;
240     return Op;
241   }
242
243   static MBlazeOperand *CreateFslImm(const MCExpr *Val, SMLoc S, SMLoc E) {
244     MBlazeOperand *Op = new MBlazeOperand(Fsl);
245     Op->Imm.Val = Val;
246     Op->StartLoc = S;
247     Op->EndLoc = E;
248     return Op;
249   }
250
251   static MBlazeOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
252                                   SMLoc E) {
253     MBlazeOperand *Op = new MBlazeOperand(Memory);
254     Op->Mem.Base = Base;
255     Op->Mem.Off = Off;
256     Op->Mem.OffReg = 0;
257     Op->StartLoc = S;
258     Op->EndLoc = E;
259     return Op;
260   }
261
262   static MBlazeOperand *CreateMem(unsigned Base, unsigned Off, SMLoc S,
263                                   SMLoc E) {
264     MBlazeOperand *Op = new MBlazeOperand(Memory);
265     Op->Mem.Base = Base;
266     Op->Mem.OffReg = Off;
267     Op->Mem.Off = 0;
268     Op->StartLoc = S;
269     Op->EndLoc = E;
270     return Op;
271   }
272 };
273
274 } // end anonymous namespace.
275
276 void MBlazeOperand::print(raw_ostream &OS) const {
277   switch (Kind) {
278   case Immediate:
279     getImm()->print(OS);
280     break;
281   case Register:
282     OS << "<register R";
283     OS << getMBlazeRegisterNumbering(getReg()) << ">";
284     break;
285   case Token:
286     OS << "'" << getToken() << "'";
287     break;
288   case Memory: {
289     OS << "<memory R";
290     OS << getMBlazeRegisterNumbering(getMemBase());
291     OS << ", ";
292
293     unsigned RegOff = getMemOffReg();
294     if (RegOff)
295       OS << "R" << getMBlazeRegisterNumbering(RegOff);
296     else
297       OS << getMemOff();
298     OS << ">";
299     }
300     break;
301   case Fsl:
302     getFslImm()->print(OS);
303     break;
304   }
305 }
306
307 /// @name Auto-generated Match Functions
308 /// {
309
310 static unsigned MatchRegisterName(StringRef Name);
311
312 /// }
313 //
314 bool MBlazeAsmParser::
315 MatchAndEmitInstruction(SMLoc IDLoc,
316                         SmallVectorImpl<MCParsedAsmOperand*> &Operands,
317                         MCStreamer &Out) {
318   MCInst Inst;
319   unsigned ErrorInfo;
320   switch (MatchInstructionImpl(Operands, Inst, ErrorInfo,
321                                /*matchingInlineAsm*/ false)) {
322   default: break;
323   case Match_Success:
324     Out.EmitInstruction(Inst);
325     return false;
326   case Match_MissingFeature:
327     return Error(IDLoc, "instruction use requires an option to be enabled");
328   case Match_MnemonicFail:
329       return Error(IDLoc, "unrecognized instruction mnemonic");
330   case Match_InvalidOperand: {
331     SMLoc ErrorLoc = IDLoc;
332     if (ErrorInfo != ~0U) {
333       if (ErrorInfo >= Operands.size())
334         return Error(IDLoc, "too few operands for instruction");
335
336       ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc();
337       if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
338     }
339
340     return Error(ErrorLoc, "invalid operand for instruction");
341   }
342   }
343
344   llvm_unreachable("Implement any new match types added!");
345 }
346
347 MBlazeOperand *MBlazeAsmParser::
348 ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
349   if (Operands.size() != 4)
350     return 0;
351
352   MBlazeOperand &Base = *(MBlazeOperand*)Operands[2];
353   MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3];
354
355   SMLoc S = Base.getStartLoc();
356   SMLoc O = Offset.getStartLoc();
357   SMLoc E = Offset.getEndLoc();
358
359   if (!Base.isReg()) {
360     Error(S, "base address must be a register");
361     return 0;
362   }
363
364   if (!Offset.isReg() && !Offset.isImm()) {
365     Error(O, "offset must be a register or immediate");
366     return 0;
367   }
368
369   MBlazeOperand *Op;
370   if (Offset.isReg())
371     Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E);
372   else
373     Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E);
374
375   delete Operands.pop_back_val();
376   delete Operands.pop_back_val();
377   Operands.push_back(Op);
378
379   return Op;
380 }
381
382 bool MBlazeAsmParser::ParseRegister(unsigned &RegNo,
383                                     SMLoc &StartLoc, SMLoc &EndLoc) {
384   return (ParseRegister(RegNo) == 0);
385 }
386
387 MBlazeOperand *MBlazeAsmParser::ParseRegister(unsigned &RegNo) {
388   SMLoc S = Parser.getTok().getLoc();
389   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
390
391   switch (getLexer().getKind()) {
392   default: return 0;
393   case AsmToken::Identifier:
394     RegNo = MatchRegisterName(getLexer().getTok().getIdentifier());
395     if (RegNo == 0)
396       return 0;
397
398     getLexer().Lex();
399     return MBlazeOperand::CreateReg(RegNo, S, E);
400   }
401 }
402
403 static unsigned MatchFslRegister(StringRef String) {
404   if (!String.startswith("rfsl"))
405     return -1;
406
407   unsigned regNum;
408   if (String.substr(4).getAsInteger(10,regNum))
409     return -1;
410
411   return regNum;
412 }
413
414 MBlazeOperand *MBlazeAsmParser::ParseFsl() {
415   SMLoc S = Parser.getTok().getLoc();
416   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
417
418   switch (getLexer().getKind()) {
419   default: return 0;
420   case AsmToken::Identifier:
421     unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier());
422     if (reg >= 16)
423       return 0;
424
425     getLexer().Lex();
426     const MCExpr *EVal = MCConstantExpr::Create(reg,getContext());
427     return MBlazeOperand::CreateFslImm(EVal,S,E);
428   }
429 }
430
431 MBlazeOperand *MBlazeAsmParser::ParseImmediate() {
432   SMLoc S = Parser.getTok().getLoc();
433   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
434
435   const MCExpr *EVal;
436   switch (getLexer().getKind()) {
437   default: return 0;
438   case AsmToken::LParen:
439   case AsmToken::Plus:
440   case AsmToken::Minus:
441   case AsmToken::Integer:
442   case AsmToken::Identifier:
443     if (getParser().ParseExpression(EVal))
444       return 0;
445
446     return MBlazeOperand::CreateImm(EVal, S, E);
447   }
448 }
449
450 MBlazeOperand *MBlazeAsmParser::
451 ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
452   MBlazeOperand *Op;
453
454   // Attempt to parse the next token as a register name
455   unsigned RegNo;
456   Op = ParseRegister(RegNo);
457
458   // Attempt to parse the next token as an FSL immediate
459   if (!Op)
460     Op = ParseFsl();
461
462   // Attempt to parse the next token as an immediate
463   if (!Op)
464     Op = ParseImmediate();
465
466   // If the token could not be parsed then fail
467   if (!Op) {
468     Error(Parser.getTok().getLoc(), "unknown operand");
469     return 0;
470   }
471
472   // Push the parsed operand into the list of operands
473   Operands.push_back(Op);
474   return Op;
475 }
476
477 /// Parse an mblaze instruction mnemonic followed by its operands.
478 bool MBlazeAsmParser::
479 ParseInstruction(StringRef Name, SMLoc NameLoc,
480                  SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
481   // The first operands is the token for the instruction name
482   size_t dotLoc = Name.find('.');
483   Operands.push_back(MBlazeOperand::CreateToken(Name.substr(0,dotLoc),NameLoc));
484   if (dotLoc < Name.size())
485     Operands.push_back(MBlazeOperand::CreateToken(Name.substr(dotLoc),NameLoc));
486
487   // If there are no more operands then finish
488   if (getLexer().is(AsmToken::EndOfStatement))
489     return false;
490
491   // Parse the first operand
492   if (!ParseOperand(Operands))
493     return true;
494
495   while (getLexer().isNot(AsmToken::EndOfStatement) &&
496          getLexer().is(AsmToken::Comma)) {
497     // Consume the comma token
498     getLexer().Lex();
499
500     // Parse the next operand
501     if (!ParseOperand(Operands))
502       return true;
503   }
504
505   // If the instruction requires a memory operand then we need to
506   // replace the last two operands (base+offset) with a single
507   // memory operand.
508   if (Name.startswith("lw") || Name.startswith("sw") ||
509       Name.startswith("lh") || Name.startswith("sh") ||
510       Name.startswith("lb") || Name.startswith("sb"))
511     return (ParseMemory(Operands) == NULL);
512
513   return false;
514 }
515
516 /// ParseDirective parses the MBlaze specific directives
517 bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) {
518   StringRef IDVal = DirectiveID.getIdentifier();
519   if (IDVal == ".word")
520     return ParseDirectiveWord(2, DirectiveID.getLoc());
521   return true;
522 }
523
524 /// ParseDirectiveWord
525 ///  ::= .word [ expression (, expression)* ]
526 bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
527   if (getLexer().isNot(AsmToken::EndOfStatement)) {
528     for (;;) {
529       const MCExpr *Value;
530       if (getParser().ParseExpression(Value))
531         return true;
532
533       getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
534
535       if (getLexer().is(AsmToken::EndOfStatement))
536         break;
537
538       // FIXME: Improve diagnostic.
539       if (getLexer().isNot(AsmToken::Comma))
540         return Error(L, "unexpected token in directive");
541       Parser.Lex();
542     }
543   }
544
545   Parser.Lex();
546   return false;
547 }
548
549 extern "C" void LLVMInitializeMBlazeAsmLexer();
550
551 /// Force static initialization.
552 extern "C" void LLVMInitializeMBlazeAsmParser() {
553   RegisterMCAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
554   LLVMInitializeMBlazeAsmLexer();
555 }
556
557 #define GET_REGISTER_MATCHER
558 #define GET_MATCHER_IMPLEMENTATION
559 #include "MBlazeGenAsmMatcher.inc"