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