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