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