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