MBlazeAsmParser.cpp revision 94b9550a32d189704a8eae55505edf62662c0534
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  case Match_Success:
327    Out.EmitInstruction(Inst);
328    return false;
329  case Match_MissingFeature:
330    return Error(IDLoc, "instruction use requires an option to be enabled");
331  case Match_MnemonicFail:
332      return Error(IDLoc, "unrecognized instruction mnemonic");
333  case Match_ConversionFail:
334    return Error(IDLoc, "unable to convert operands to instruction");
335  case Match_InvalidOperand:
336    ErrorLoc = IDLoc;
337    if (ErrorInfo != ~0U) {
338      if (ErrorInfo >= Operands.size())
339        return Error(IDLoc, "too few operands for instruction");
340
341      ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc();
342      if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
343    }
344
345    return Error(ErrorLoc, "invalid operand for instruction");
346  }
347
348  llvm_unreachable("Implement any new match types added!");
349  return true;
350}
351
352MBlazeOperand *MBlazeAsmParser::
353ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
354  if (Operands.size() != 4)
355    return 0;
356
357  MBlazeOperand &Base = *(MBlazeOperand*)Operands[2];
358  MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3];
359
360  SMLoc S = Base.getStartLoc();
361  SMLoc O = Offset.getStartLoc();
362  SMLoc E = Offset.getEndLoc();
363
364  if (!Base.isReg()) {
365    Error(S, "base address must be a register");
366    return 0;
367  }
368
369  if (!Offset.isReg() && !Offset.isImm()) {
370    Error(O, "offset must be a register or immediate");
371    return 0;
372  }
373
374  MBlazeOperand *Op;
375  if (Offset.isReg())
376    Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E);
377  else
378    Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E);
379
380  delete Operands.pop_back_val();
381  delete Operands.pop_back_val();
382  Operands.push_back(Op);
383
384  return Op;
385}
386
387bool MBlazeAsmParser::ParseRegister(unsigned &RegNo,
388                                    SMLoc &StartLoc, SMLoc &EndLoc) {
389  return (ParseRegister(RegNo) == 0);
390}
391
392MBlazeOperand *MBlazeAsmParser::ParseRegister(unsigned &RegNo) {
393  SMLoc S = Parser.getTok().getLoc();
394  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
395
396  switch (getLexer().getKind()) {
397  default: return 0;
398  case AsmToken::Identifier:
399    RegNo = MatchRegisterName(getLexer().getTok().getIdentifier());
400    if (RegNo == 0)
401      return 0;
402
403    getLexer().Lex();
404    return MBlazeOperand::CreateReg(RegNo, S, E);
405  }
406}
407
408static unsigned MatchFslRegister(StringRef String) {
409  if (!String.startswith("rfsl"))
410    return -1;
411
412  unsigned regNum;
413  if (String.substr(4).getAsInteger(10,regNum))
414    return -1;
415
416  return regNum;
417}
418
419MBlazeOperand *MBlazeAsmParser::ParseFsl() {
420  SMLoc S = Parser.getTok().getLoc();
421  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
422
423  switch (getLexer().getKind()) {
424  default: return 0;
425  case AsmToken::Identifier:
426    unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier());
427    if (reg >= 16)
428      return 0;
429
430    getLexer().Lex();
431    const MCExpr *EVal = MCConstantExpr::Create(reg,getContext());
432    return MBlazeOperand::CreateFslImm(EVal,S,E);
433  }
434}
435
436MBlazeOperand *MBlazeAsmParser::ParseImmediate() {
437  SMLoc S = Parser.getTok().getLoc();
438  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
439
440  const MCExpr *EVal;
441  switch (getLexer().getKind()) {
442  default: return 0;
443  case AsmToken::LParen:
444  case AsmToken::Plus:
445  case AsmToken::Minus:
446  case AsmToken::Integer:
447  case AsmToken::Identifier:
448    if (getParser().ParseExpression(EVal))
449      return 0;
450
451    return MBlazeOperand::CreateImm(EVal, S, E);
452  }
453}
454
455MBlazeOperand *MBlazeAsmParser::
456ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
457  MBlazeOperand *Op;
458
459  // Attempt to parse the next token as a register name
460  unsigned RegNo;
461  Op = ParseRegister(RegNo);
462
463  // Attempt to parse the next token as an FSL immediate
464  if (!Op)
465    Op = ParseFsl();
466
467  // Attempt to parse the next token as an immediate
468  if (!Op)
469    Op = ParseImmediate();
470
471  // If the token could not be parsed then fail
472  if (!Op) {
473    Error(Parser.getTok().getLoc(), "unknown operand");
474    return 0;
475  }
476
477  // Push the parsed operand into the list of operands
478  Operands.push_back(Op);
479  return Op;
480}
481
482/// Parse an mblaze instruction mnemonic followed by its operands.
483bool MBlazeAsmParser::
484ParseInstruction(StringRef Name, SMLoc NameLoc,
485                 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
486  // The first operands is the token for the instruction name
487  size_t dotLoc = Name.find('.');
488  Operands.push_back(MBlazeOperand::CreateToken(Name.substr(0,dotLoc),NameLoc));
489  if (dotLoc < Name.size())
490    Operands.push_back(MBlazeOperand::CreateToken(Name.substr(dotLoc),NameLoc));
491
492  // If there are no more operands then finish
493  if (getLexer().is(AsmToken::EndOfStatement))
494    return false;
495
496  // Parse the first operand
497  if (!ParseOperand(Operands))
498    return true;
499
500  while (getLexer().isNot(AsmToken::EndOfStatement) &&
501         getLexer().is(AsmToken::Comma)) {
502    // Consume the comma token
503    getLexer().Lex();
504
505    // Parse the next operand
506    if (!ParseOperand(Operands))
507      return true;
508  }
509
510  // If the instruction requires a memory operand then we need to
511  // replace the last two operands (base+offset) with a single
512  // memory operand.
513  if (Name.startswith("lw") || Name.startswith("sw") ||
514      Name.startswith("lh") || Name.startswith("sh") ||
515      Name.startswith("lb") || Name.startswith("sb"))
516    return (ParseMemory(Operands) == NULL);
517
518  return false;
519}
520
521/// ParseDirective parses the arm specific directives
522bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) {
523  StringRef IDVal = DirectiveID.getIdentifier();
524  if (IDVal == ".word")
525    return ParseDirectiveWord(2, DirectiveID.getLoc());
526  return true;
527}
528
529/// ParseDirectiveWord
530///  ::= .word [ expression (, expression)* ]
531bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
532  if (getLexer().isNot(AsmToken::EndOfStatement)) {
533    for (;;) {
534      const MCExpr *Value;
535      if (getParser().ParseExpression(Value))
536        return true;
537
538      getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
539
540      if (getLexer().is(AsmToken::EndOfStatement))
541        break;
542
543      // FIXME: Improve diagnostic.
544      if (getLexer().isNot(AsmToken::Comma))
545        return Error(L, "unexpected token in directive");
546      Parser.Lex();
547    }
548  }
549
550  Parser.Lex();
551  return false;
552}
553
554extern "C" void LLVMInitializeMBlazeAsmLexer();
555
556/// Force static initialization.
557extern "C" void LLVMInitializeMBlazeAsmParser() {
558  RegisterMCAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
559  LLVMInitializeMBlazeAsmLexer();
560}
561
562#define GET_REGISTER_MATCHER
563#define GET_MATCHER_IMPLEMENTATION
564#include "MBlazeGenAsmMatcher.inc"
565