1 //===-- VEAsmParser.cpp - Parse VE assembly to MCInst instructions --------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "MCTargetDesc/VEMCExpr.h"
10 #include "MCTargetDesc/VEMCTargetDesc.h"
11 #include "TargetInfo/VETargetInfo.h"
12 #include "VE.h"
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/ADT/Twine.h"
17 #include "llvm/MC/MCContext.h"
18 #include "llvm/MC/MCExpr.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCParser/MCAsmLexer.h"
21 #include "llvm/MC/MCParser/MCAsmParser.h"
22 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
23 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
24 #include "llvm/MC/MCRegisterInfo.h"
25 #include "llvm/MC/MCStreamer.h"
26 #include "llvm/MC/MCSubtargetInfo.h"
27 #include "llvm/MC/MCSymbol.h"
28 #include "llvm/Support/TargetRegistry.h"
29 #include "llvm/Support/raw_ostream.h"
30 #include <algorithm>
31 #include <memory>
32 
33 using namespace llvm;
34 
35 #define DEBUG_TYPE "ve-asmparser"
36 
37 namespace {
38 
39 class VEOperand;
40 
41 class VEAsmParser : public MCTargetAsmParser {
42   MCAsmParser &Parser;
43 
44   /// @name Auto-generated Match Functions
45   /// {
46 
47 #define GET_ASSEMBLER_HEADER
48 #include "VEGenAsmMatcher.inc"
49 
50   /// }
51 
52   // public interface of the MCTargetAsmParser.
53   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
54                                OperandVector &Operands, MCStreamer &Out,
55                                uint64_t &ErrorInfo,
56                                bool MatchingInlineAsm) override;
57   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
58   int parseRegisterName(unsigned (*matchFn)(StringRef));
59   OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
60                                         SMLoc &EndLoc) override;
61   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
62                         SMLoc NameLoc, OperandVector &Operands) override;
63   bool ParseDirective(AsmToken DirectiveID) override;
64 
65   // Custom parse functions for VE specific operands.
66   OperandMatchResultTy parseMEMOperand(OperandVector &Operands);
67   OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Name);
68   OperandMatchResultTy parseVEAsmOperand(std::unique_ptr<VEOperand> &Operand);
69 
70 public:
71   VEAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
72               const MCInstrInfo &MII, const MCTargetOptions &Options)
73       : MCTargetAsmParser(Options, sti, MII), Parser(parser) {
74     // Initialize the set of available features.
75     setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
76   }
77 };
78 
79 } // end anonymous namespace
80 
81 namespace {
82 
83 /// VEOperand - Instances of this class represent a parsed VE machine
84 /// instruction.
85 class VEOperand : public MCParsedAsmOperand {
86 private:
87   enum KindTy {
88     k_Token,
89     k_Register,
90     k_Immediate,
91     // SX-Aurora ASX form is disp(index, base).
92     k_MemoryRegRegImm,  // base=reg, index=reg, disp=imm
93     k_MemoryRegImmImm,  // base=reg, index=imm, disp=imm
94     k_MemoryZeroRegImm, // base=0, index=reg, disp=imm
95     k_MemoryZeroImmImm, // base=0, index=imm, disp=imm
96   } Kind;
97 
98   SMLoc StartLoc, EndLoc;
99 
100   struct Token {
101     const char *Data;
102     unsigned Length;
103   };
104 
105   struct RegOp {
106     unsigned RegNum;
107   };
108 
109   struct ImmOp {
110     const MCExpr *Val;
111   };
112 
113   struct MemOp {
114     unsigned Base;
115     unsigned IndexReg;
116     const MCExpr *Index;
117     const MCExpr *Offset;
118   };
119 
120   union {
121     struct Token Tok;
122     struct RegOp Reg;
123     struct ImmOp Imm;
124     struct MemOp Mem;
125   };
126 
127 public:
128   VEOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
129 
130   bool isToken() const override { return Kind == k_Token; }
131   bool isReg() const override { return Kind == k_Register; }
132   bool isImm() const override { return Kind == k_Immediate; }
133   bool isMem() const override {
134     return isMEMrri() || isMEMrii() || isMEMzri() || isMEMzii() || isMEMri() ||
135            isMEMzi();
136   }
137   bool isMEMrri() const { return Kind == k_MemoryRegRegImm; }
138   bool isMEMrii() const { return Kind == k_MemoryRegImmImm; }
139   bool isMEMzri() const { return Kind == k_MemoryZeroRegImm; }
140   bool isMEMzii() const { return Kind == k_MemoryZeroImmImm; }
141   // isMEMri and isMEMzi will be implemented later.
142   bool isMEMri() const { return false; }
143   bool isMEMzi() const { return false; }
144   bool isSImm7() {
145     if (!isImm())
146       return false;
147 
148     // Constant case
149     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {
150       int64_t Value = ConstExpr->getValue();
151       return isInt<7>(Value);
152     }
153     return false;
154   }
155 
156   StringRef getToken() const {
157     assert(Kind == k_Token && "Invalid access!");
158     return StringRef(Tok.Data, Tok.Length);
159   }
160 
161   unsigned getReg() const override {
162     assert((Kind == k_Register) && "Invalid access!");
163     return Reg.RegNum;
164   }
165 
166   const MCExpr *getImm() const {
167     assert((Kind == k_Immediate) && "Invalid access!");
168     return Imm.Val;
169   }
170 
171   unsigned getMemBase() const {
172     assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm) &&
173            "Invalid access!");
174     return Mem.Base;
175   }
176 
177   unsigned getMemIndexReg() const {
178     assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryZeroRegImm) &&
179            "Invalid access!");
180     return Mem.IndexReg;
181   }
182 
183   const MCExpr *getMemIndex() const {
184     assert((Kind == k_MemoryRegImmImm || Kind == k_MemoryZeroImmImm) &&
185            "Invalid access!");
186     return Mem.Index;
187   }
188 
189   const MCExpr *getMemOffset() const {
190     assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm ||
191             Kind == k_MemoryZeroImmImm || Kind == k_MemoryZeroRegImm) &&
192            "Invalid access!");
193     return Mem.Offset;
194   }
195 
196   void setMemOffset(const MCExpr *off) {
197     assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm ||
198             Kind == k_MemoryZeroImmImm || Kind == k_MemoryZeroRegImm) &&
199            "Invalid access!");
200     Mem.Offset = off;
201   }
202 
203   /// getStartLoc - Get the location of the first token of this operand.
204   SMLoc getStartLoc() const override { return StartLoc; }
205   /// getEndLoc - Get the location of the last token of this operand.
206   SMLoc getEndLoc() const override { return EndLoc; }
207 
208   void print(raw_ostream &OS) const override {
209     switch (Kind) {
210     case k_Token:
211       OS << "Token: " << getToken() << "\n";
212       break;
213     case k_Register:
214       OS << "Reg: #" << getReg() << "\n";
215       break;
216     case k_Immediate:
217       OS << "Imm: " << getImm() << "\n";
218       break;
219     case k_MemoryRegRegImm:
220       assert(getMemOffset() != nullptr);
221       OS << "Mem: #" << getMemBase() << "+#" << getMemIndexReg() << "+"
222          << *getMemOffset() << "\n";
223       break;
224     case k_MemoryRegImmImm:
225       assert(getMemIndex() != nullptr && getMemOffset() != nullptr);
226       OS << "Mem: #" << getMemBase() << "+" << *getMemIndex() << "+"
227          << *getMemOffset() << "\n";
228       break;
229     case k_MemoryZeroRegImm:
230       assert(getMemOffset() != nullptr);
231       OS << "Mem: 0+#" << getMemIndexReg() << "+" << *getMemOffset() << "\n";
232       break;
233     case k_MemoryZeroImmImm:
234       assert(getMemIndex() != nullptr && getMemOffset() != nullptr);
235       OS << "Mem: 0+" << *getMemIndex() << "+" << *getMemOffset() << "\n";
236       break;
237     }
238   }
239 
240   void addRegOperands(MCInst &Inst, unsigned N) const {
241     assert(N == 1 && "Invalid number of operands!");
242     Inst.addOperand(MCOperand::createReg(getReg()));
243   }
244 
245   void addImmOperands(MCInst &Inst, unsigned N) const {
246     assert(N == 1 && "Invalid number of operands!");
247     const MCExpr *Expr = getImm();
248     addExpr(Inst, Expr);
249   }
250 
251   void addSImm7Operands(MCInst &Inst, unsigned N) const {
252     addImmOperands(Inst, N);
253   }
254 
255   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
256     // Add as immediate when possible.  Null MCExpr = 0.
257     if (!Expr)
258       Inst.addOperand(MCOperand::createImm(0));
259     else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
260       Inst.addOperand(MCOperand::createImm(CE->getValue()));
261     else
262       Inst.addOperand(MCOperand::createExpr(Expr));
263   }
264 
265   void addMEMrriOperands(MCInst &Inst, unsigned N) const {
266     assert(N == 3 && "Invalid number of operands!");
267 
268     Inst.addOperand(MCOperand::createReg(getMemBase()));
269     Inst.addOperand(MCOperand::createReg(getMemIndexReg()));
270     addExpr(Inst, getMemOffset());
271   }
272 
273   void addMEMriiOperands(MCInst &Inst, unsigned N) const {
274     assert(N == 3 && "Invalid number of operands!");
275 
276     Inst.addOperand(MCOperand::createReg(getMemBase()));
277     addExpr(Inst, getMemIndex());
278     addExpr(Inst, getMemOffset());
279   }
280 
281   void addMEMzriOperands(MCInst &Inst, unsigned N) const {
282     assert(N == 3 && "Invalid number of operands!");
283 
284     Inst.addOperand(MCOperand::createImm(0));
285     Inst.addOperand(MCOperand::createReg(getMemIndexReg()));
286     addExpr(Inst, getMemOffset());
287   }
288 
289   void addMEMziiOperands(MCInst &Inst, unsigned N) const {
290     assert(N == 3 && "Invalid number of operands!");
291 
292     Inst.addOperand(MCOperand::createImm(0));
293     addExpr(Inst, getMemIndex());
294     addExpr(Inst, getMemOffset());
295   }
296 
297   void addMEMriOperands(MCInst &Inst, unsigned N) const {
298     // FIXME: implement
299   }
300 
301   void addMEMziOperands(MCInst &Inst, unsigned N) const {
302     // FIXME: implement
303   }
304 
305   static std::unique_ptr<VEOperand> CreateToken(StringRef Str, SMLoc S) {
306     auto Op = std::make_unique<VEOperand>(k_Token);
307     Op->Tok.Data = Str.data();
308     Op->Tok.Length = Str.size();
309     Op->StartLoc = S;
310     Op->EndLoc = S;
311     return Op;
312   }
313 
314   static std::unique_ptr<VEOperand> CreateReg(unsigned RegNum, SMLoc S,
315                                               SMLoc E) {
316     auto Op = std::make_unique<VEOperand>(k_Register);
317     Op->Reg.RegNum = RegNum;
318     Op->StartLoc = S;
319     Op->EndLoc = E;
320     return Op;
321   }
322 
323   static std::unique_ptr<VEOperand> CreateImm(const MCExpr *Val, SMLoc S,
324                                               SMLoc E) {
325     auto Op = std::make_unique<VEOperand>(k_Immediate);
326     Op->Imm.Val = Val;
327     Op->StartLoc = S;
328     Op->EndLoc = E;
329     return Op;
330   }
331 
332   static std::unique_ptr<VEOperand>
333   MorphToMEMrri(unsigned Base, unsigned Index, std::unique_ptr<VEOperand> Op) {
334     const MCExpr *Imm = Op->getImm();
335     Op->Kind = k_MemoryRegRegImm;
336     Op->Mem.Base = Base;
337     Op->Mem.IndexReg = Index;
338     Op->Mem.Index = nullptr;
339     Op->Mem.Offset = Imm;
340     return Op;
341   }
342 
343   static std::unique_ptr<VEOperand>
344   MorphToMEMrii(unsigned Base, const MCExpr *Index,
345                 std::unique_ptr<VEOperand> Op) {
346     const MCExpr *Imm = Op->getImm();
347     Op->Kind = k_MemoryRegImmImm;
348     Op->Mem.Base = Base;
349     Op->Mem.IndexReg = 0;
350     Op->Mem.Index = Index;
351     Op->Mem.Offset = Imm;
352     return Op;
353   }
354 
355   static std::unique_ptr<VEOperand>
356   MorphToMEMzri(unsigned Index, std::unique_ptr<VEOperand> Op) {
357     const MCExpr *Imm = Op->getImm();
358     Op->Kind = k_MemoryZeroRegImm;
359     Op->Mem.Base = 0;
360     Op->Mem.IndexReg = Index;
361     Op->Mem.Index = nullptr;
362     Op->Mem.Offset = Imm;
363     return Op;
364   }
365 
366   static std::unique_ptr<VEOperand>
367   MorphToMEMzii(const MCExpr *Index, std::unique_ptr<VEOperand> Op) {
368     const MCExpr *Imm = Op->getImm();
369     Op->Kind = k_MemoryZeroImmImm;
370     Op->Mem.Base = 0;
371     Op->Mem.IndexReg = 0;
372     Op->Mem.Index = Index;
373     Op->Mem.Offset = Imm;
374     return Op;
375   }
376 };
377 
378 } // end anonymous namespace
379 
380 bool VEAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
381                                           OperandVector &Operands,
382                                           MCStreamer &Out, uint64_t &ErrorInfo,
383                                           bool MatchingInlineAsm) {
384   MCInst Inst;
385   unsigned MatchResult =
386       MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
387   switch (MatchResult) {
388   case Match_Success:
389     Inst.setLoc(IDLoc);
390     Out.emitInstruction(Inst, getSTI());
391     return false;
392 
393   case Match_MissingFeature:
394     return Error(IDLoc,
395                  "instruction requires a CPU feature not currently enabled");
396 
397   case Match_InvalidOperand: {
398     SMLoc ErrorLoc = IDLoc;
399     if (ErrorInfo != ~0ULL) {
400       if (ErrorInfo >= Operands.size())
401         return Error(IDLoc, "too few operands for instruction");
402 
403       ErrorLoc = ((VEOperand &)*Operands[ErrorInfo]).getStartLoc();
404       if (ErrorLoc == SMLoc())
405         ErrorLoc = IDLoc;
406     }
407 
408     return Error(ErrorLoc, "invalid operand for instruction");
409   }
410   case Match_MnemonicFail:
411     return Error(IDLoc, "invalid instruction mnemonic");
412   }
413   llvm_unreachable("Implement any new match types added!");
414 }
415 
416 bool VEAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
417                                 SMLoc &EndLoc) {
418   if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success)
419     return Error(StartLoc, "invalid register name");
420   return false;
421 }
422 
423 /// Parses a register name using a given matching function.
424 /// Checks for lowercase or uppercase if necessary.
425 int VEAsmParser::parseRegisterName(unsigned (*matchFn)(StringRef)) {
426   StringRef Name = Parser.getTok().getString();
427 
428   int RegNum = matchFn(Name);
429 
430   // GCC supports case insensitive register names. All of the VE registers
431   // are all lower case.
432   if (RegNum == VE::NoRegister) {
433     RegNum = matchFn(Name.lower());
434   }
435 
436   return RegNum;
437 }
438 
439 /// Maps from the set of all register names to a register number.
440 /// \note Generated by TableGen.
441 static unsigned MatchRegisterName(StringRef Name);
442 
443 /// Maps from the set of all alternative registernames to a register number.
444 /// \note Generated by TableGen.
445 static unsigned MatchRegisterAltName(StringRef Name);
446 
447 OperandMatchResultTy
448 VEAsmParser::tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) {
449   const AsmToken Tok = Parser.getTok();
450   StartLoc = Tok.getLoc();
451   EndLoc = Tok.getEndLoc();
452   RegNo = 0;
453   if (getLexer().getKind() != AsmToken::Percent)
454     return MatchOperand_NoMatch;
455   Parser.Lex();
456 
457   RegNo = parseRegisterName(&MatchRegisterName);
458   if (RegNo == VE::NoRegister)
459     RegNo = parseRegisterName(&MatchRegisterAltName);
460 
461   if (RegNo != VE::NoRegister) {
462     Parser.Lex();
463     return MatchOperand_Success;
464   }
465 
466   getLexer().UnLex(Tok);
467   return MatchOperand_NoMatch;
468 }
469 
470 bool VEAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
471                                    SMLoc NameLoc, OperandVector &Operands) {
472 
473   // First operand in MCInst is instruction mnemonic.
474   Operands.push_back(VEOperand::CreateToken(Name, NameLoc));
475 
476   if (getLexer().isNot(AsmToken::EndOfStatement)) {
477     // Read the first operand.
478     if (parseOperand(Operands, Name) != MatchOperand_Success) {
479       SMLoc Loc = getLexer().getLoc();
480       return Error(Loc, "unexpected token");
481     }
482 
483     while (getLexer().is(AsmToken::Comma)) {
484       Parser.Lex(); // Eat the comma.
485       // Parse and remember the operand.
486       if (parseOperand(Operands, Name) != MatchOperand_Success) {
487         SMLoc Loc = getLexer().getLoc();
488         return Error(Loc, "unexpected token");
489       }
490     }
491   }
492   if (getLexer().isNot(AsmToken::EndOfStatement)) {
493     SMLoc Loc = getLexer().getLoc();
494     return Error(Loc, "unexpected token");
495   }
496   Parser.Lex(); // Consume the EndOfStatement.
497   return false;
498 }
499 
500 bool VEAsmParser::ParseDirective(AsmToken DirectiveID) {
501   // Let the MC layer to handle other directives.
502   return true;
503 }
504 
505 OperandMatchResultTy VEAsmParser::parseMEMOperand(OperandVector &Operands) {
506   LLVM_DEBUG(dbgs() << "parseMEMOperand\n");
507   const AsmToken &Tok = Parser.getTok();
508   SMLoc S = Tok.getLoc();
509   SMLoc E = Tok.getEndLoc();
510   // Parse ASX format
511   //   disp
512   //   disp(, base)
513   //   disp(index)
514   //   disp(index, base)
515   //   (, base)
516   //   (index)
517   //   (index, base)
518 
519   std::unique_ptr<VEOperand> Offset;
520   switch (getLexer().getKind()) {
521   default:
522     return MatchOperand_NoMatch;
523 
524   case AsmToken::Minus:
525   case AsmToken::Integer:
526   case AsmToken::Dot: {
527     const MCExpr *EVal;
528     if (!getParser().parseExpression(EVal, E))
529       Offset = VEOperand::CreateImm(EVal, S, E);
530     else
531       return MatchOperand_NoMatch;
532     break;
533   }
534   case AsmToken::LParen:
535     // empty disp (= 0)
536     Offset =
537         VEOperand::CreateImm(MCConstantExpr::create(0, getContext()), S, E);
538     break;
539   }
540 
541   switch (getLexer().getKind()) {
542   default:
543     return MatchOperand_ParseFail;
544 
545   case AsmToken::EndOfStatement:
546     Operands.push_back(VEOperand::MorphToMEMzii(
547         MCConstantExpr::create(0, getContext()), std::move(Offset)));
548     return MatchOperand_Success;
549 
550   case AsmToken::LParen:
551     Parser.Lex(); // Eat the (
552     break;
553   }
554 
555   const MCExpr *IndexValue = nullptr;
556   unsigned IndexReg = 0;
557 
558   switch (getLexer().getKind()) {
559   default:
560     if (ParseRegister(IndexReg, S, E))
561       return MatchOperand_ParseFail;
562     break;
563 
564   case AsmToken::Minus:
565   case AsmToken::Integer:
566   case AsmToken::Dot:
567     if (getParser().parseExpression(IndexValue, E))
568       return MatchOperand_ParseFail;
569     break;
570 
571   case AsmToken::Comma:
572     // empty index
573     IndexValue = MCConstantExpr::create(0, getContext());
574     break;
575   }
576 
577   switch (getLexer().getKind()) {
578   default:
579     return MatchOperand_ParseFail;
580 
581   case AsmToken::RParen:
582     Parser.Lex(); // Eat the )
583     Operands.push_back(
584         IndexValue ? VEOperand::MorphToMEMzii(IndexValue, std::move(Offset))
585                    : VEOperand::MorphToMEMzri(IndexReg, std::move(Offset)));
586     return MatchOperand_Success;
587 
588   case AsmToken::Comma:
589     Parser.Lex(); // Eat the ,
590     break;
591   }
592 
593   unsigned BaseReg = 0;
594   if (ParseRegister(BaseReg, S, E))
595     return MatchOperand_ParseFail;
596 
597   if (!Parser.getTok().is(AsmToken::RParen))
598     return MatchOperand_ParseFail;
599 
600   Parser.Lex(); // Eat the )
601   Operands.push_back(
602       IndexValue
603           ? VEOperand::MorphToMEMrii(BaseReg, IndexValue, std::move(Offset))
604           : VEOperand::MorphToMEMrri(BaseReg, IndexReg, std::move(Offset)));
605 
606   return MatchOperand_Success;
607 }
608 
609 OperandMatchResultTy VEAsmParser::parseOperand(OperandVector &Operands,
610                                                StringRef Mnemonic) {
611   LLVM_DEBUG(dbgs() << "parseOperand\n");
612   OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
613 
614   // If there wasn't a custom match, try the generic matcher below. Otherwise,
615   // there was a match, but an error occurred, in which case, just return that
616   // the operand parsing failed.
617   if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail)
618     return ResTy;
619 
620   switch (getLexer().getKind()) {
621   case AsmToken::LParen:
622     // FIXME: Parsing "(" + %vreg + ", " + %vreg + ")"
623     // FALLTHROUGH
624   default: {
625     std::unique_ptr<VEOperand> Op;
626     ResTy = parseVEAsmOperand(Op);
627     if (ResTy != MatchOperand_Success || !Op)
628       return MatchOperand_ParseFail;
629 
630     // Push the parsed operand into the list of operands
631     Operands.push_back(std::move(Op));
632 
633     if (!Parser.getTok().is(AsmToken::LParen))
634       break;
635 
636     // FIXME: Parsing %vec-reg + "(" + %sclar-reg/number + ")"
637     break;
638   }
639   }
640 
641   return MatchOperand_Success;
642 }
643 
644 OperandMatchResultTy
645 VEAsmParser::parseVEAsmOperand(std::unique_ptr<VEOperand> &Op) {
646   LLVM_DEBUG(dbgs() << "parseVEAsmOperand\n");
647   SMLoc S = Parser.getTok().getLoc();
648   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
649   const MCExpr *EVal;
650 
651   Op = nullptr;
652   switch (getLexer().getKind()) {
653   default:
654     break;
655 
656   case AsmToken::Percent:
657     unsigned RegNo;
658     if (tryParseRegister(RegNo, S, E) == MatchOperand_Success)
659       Op = VEOperand::CreateReg(RegNo, S, E);
660     break;
661 
662   case AsmToken::Minus:
663   case AsmToken::Integer:
664   case AsmToken::Dot:
665     if (!getParser().parseExpression(EVal, E))
666       Op = VEOperand::CreateImm(EVal, S, E);
667     break;
668 
669   case AsmToken::Identifier: {
670     StringRef Identifier;
671     if (!getParser().parseIdentifier(Identifier)) {
672       E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
673       MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
674 
675       const MCExpr *Res =
676           MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
677       Op = VEOperand::CreateImm(Res, S, E);
678     }
679     break;
680   }
681   }
682   return (Op) ? MatchOperand_Success : MatchOperand_ParseFail;
683 }
684 
685 // Force static initialization.
686 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeVEAsmParser() {
687   RegisterMCAsmParser<VEAsmParser> A(getTheVETarget());
688 }
689 
690 #define GET_REGISTER_MATCHER
691 #define GET_MATCHER_IMPLEMENTATION
692 #include "VEGenAsmMatcher.inc"
693