MBlazeAsmParser.cpp revision 60f923c5e2d752ce5c6e042db8279122eff798dd
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"
27using namespace llvm;
28
29namespace {
30struct MBlazeOperand;
31
32class 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
61public:
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.
73struct 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) {}
110public:
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
278void 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
301static unsigned MatchRegisterName(StringRef Name);
302
303/// }
304//
305bool MBlazeAsmParser::
306MatchAndEmitInstruction(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
338MBlazeOperand *MBlazeAsmParser::
339ParseMemory(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
373MBlazeOperand *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
388static 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
399MBlazeOperand *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
415MBlazeOperand *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
434MBlazeOperand *MBlazeAsmParser::
435ParseOperand(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.
464bool MBlazeAsmParser::
465ParseInstruction(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
504bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) {
505  return true;
506}
507
508extern "C" void LLVMInitializeMBlazeAsmLexer();
509
510/// Force static initialization.
511extern "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"
519