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