xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
1*fe6060f1SDimitry Andric //===-- CSKYAsmParser.cpp - Parse CSKY assembly to MCInst instructions --===//
2*fe6060f1SDimitry Andric //
3*fe6060f1SDimitry Andric //                     The LLVM Compiler Infrastructure
4*fe6060f1SDimitry Andric //
5*fe6060f1SDimitry Andric // This file is distributed under the University of Illinois Open Source
6*fe6060f1SDimitry Andric // License. See LICENSE.TXT for details.
7*fe6060f1SDimitry Andric //
8*fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
9*fe6060f1SDimitry Andric 
10*fe6060f1SDimitry Andric #include "MCTargetDesc/CSKYMCExpr.h"
11*fe6060f1SDimitry Andric #include "MCTargetDesc/CSKYMCTargetDesc.h"
12*fe6060f1SDimitry Andric #include "TargetInfo/CSKYTargetInfo.h"
13*fe6060f1SDimitry Andric #include "llvm/ADT/STLExtras.h"
14*fe6060f1SDimitry Andric #include "llvm/ADT/StringSwitch.h"
15*fe6060f1SDimitry Andric #include "llvm/CodeGen/Register.h"
16*fe6060f1SDimitry Andric #include "llvm/MC/MCContext.h"
17*fe6060f1SDimitry Andric #include "llvm/MC/MCExpr.h"
18*fe6060f1SDimitry Andric #include "llvm/MC/MCInst.h"
19*fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
20*fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21*fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
22*fe6060f1SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
23*fe6060f1SDimitry Andric #include "llvm/MC/MCStreamer.h"
24*fe6060f1SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
25*fe6060f1SDimitry Andric #include "llvm/Support/Casting.h"
26*fe6060f1SDimitry Andric #include "llvm/Support/TargetRegistry.h"
27*fe6060f1SDimitry Andric 
28*fe6060f1SDimitry Andric using namespace llvm;
29*fe6060f1SDimitry Andric 
30*fe6060f1SDimitry Andric namespace {
31*fe6060f1SDimitry Andric struct CSKYOperand;
32*fe6060f1SDimitry Andric 
33*fe6060f1SDimitry Andric class CSKYAsmParser : public MCTargetAsmParser {
34*fe6060f1SDimitry Andric 
35*fe6060f1SDimitry Andric   bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
36*fe6060f1SDimitry Andric                                   int64_t Lower, int64_t Upper, Twine Msg);
37*fe6060f1SDimitry Andric 
38*fe6060f1SDimitry Andric   SMLoc getLoc() const { return getParser().getTok().getLoc(); }
39*fe6060f1SDimitry Andric 
40*fe6060f1SDimitry Andric   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
41*fe6060f1SDimitry Andric                                OperandVector &Operands, MCStreamer &Out,
42*fe6060f1SDimitry Andric                                uint64_t &ErrorInfo,
43*fe6060f1SDimitry Andric                                bool MatchingInlineAsm) override;
44*fe6060f1SDimitry Andric 
45*fe6060f1SDimitry Andric   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
46*fe6060f1SDimitry Andric 
47*fe6060f1SDimitry Andric   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
48*fe6060f1SDimitry Andric                         SMLoc NameLoc, OperandVector &Operands) override;
49*fe6060f1SDimitry Andric 
50*fe6060f1SDimitry Andric   bool ParseDirective(AsmToken DirectiveID) override;
51*fe6060f1SDimitry Andric 
52*fe6060f1SDimitry Andric   OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
53*fe6060f1SDimitry Andric                                         SMLoc &EndLoc) override;
54*fe6060f1SDimitry Andric 
55*fe6060f1SDimitry Andric // Auto-generated instruction matching functions
56*fe6060f1SDimitry Andric #define GET_ASSEMBLER_HEADER
57*fe6060f1SDimitry Andric #include "CSKYGenAsmMatcher.inc"
58*fe6060f1SDimitry Andric 
59*fe6060f1SDimitry Andric   OperandMatchResultTy parseImmediate(OperandVector &Operands);
60*fe6060f1SDimitry Andric   OperandMatchResultTy parseRegister(OperandVector &Operands);
61*fe6060f1SDimitry Andric   OperandMatchResultTy parseBaseRegImm(OperandVector &Operands);
62*fe6060f1SDimitry Andric   OperandMatchResultTy parseCSKYSymbol(OperandVector &Operands);
63*fe6060f1SDimitry Andric   OperandMatchResultTy parseConstpoolSymbol(OperandVector &Operands);
64*fe6060f1SDimitry Andric 
65*fe6060f1SDimitry Andric   bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
66*fe6060f1SDimitry Andric 
67*fe6060f1SDimitry Andric public:
68*fe6060f1SDimitry Andric   enum CSKYMatchResultTy {
69*fe6060f1SDimitry Andric     Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
70*fe6060f1SDimitry Andric #define GET_OPERAND_DIAGNOSTIC_TYPES
71*fe6060f1SDimitry Andric #include "CSKYGenAsmMatcher.inc"
72*fe6060f1SDimitry Andric #undef GET_OPERAND_DIAGNOSTIC_TYPES
73*fe6060f1SDimitry Andric   };
74*fe6060f1SDimitry Andric 
75*fe6060f1SDimitry Andric   CSKYAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
76*fe6060f1SDimitry Andric                 const MCInstrInfo &MII, const MCTargetOptions &Options)
77*fe6060f1SDimitry Andric       : MCTargetAsmParser(Options, STI, MII) {
78*fe6060f1SDimitry Andric     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
79*fe6060f1SDimitry Andric   }
80*fe6060f1SDimitry Andric };
81*fe6060f1SDimitry Andric 
82*fe6060f1SDimitry Andric /// Instances of this class represent a parsed machine instruction.
83*fe6060f1SDimitry Andric struct CSKYOperand : public MCParsedAsmOperand {
84*fe6060f1SDimitry Andric   enum KindTy {
85*fe6060f1SDimitry Andric     Token,
86*fe6060f1SDimitry Andric     Register,
87*fe6060f1SDimitry Andric     Immediate,
88*fe6060f1SDimitry Andric   } Kind;
89*fe6060f1SDimitry Andric 
90*fe6060f1SDimitry Andric   struct RegOp {
91*fe6060f1SDimitry Andric     unsigned RegNum;
92*fe6060f1SDimitry Andric   };
93*fe6060f1SDimitry Andric 
94*fe6060f1SDimitry Andric   struct ImmOp {
95*fe6060f1SDimitry Andric     const MCExpr *Val;
96*fe6060f1SDimitry Andric   };
97*fe6060f1SDimitry Andric 
98*fe6060f1SDimitry Andric   SMLoc StartLoc, EndLoc;
99*fe6060f1SDimitry Andric   union {
100*fe6060f1SDimitry Andric     StringRef Tok;
101*fe6060f1SDimitry Andric     RegOp Reg;
102*fe6060f1SDimitry Andric     ImmOp Imm;
103*fe6060f1SDimitry Andric   };
104*fe6060f1SDimitry Andric 
105*fe6060f1SDimitry Andric   CSKYOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
106*fe6060f1SDimitry Andric 
107*fe6060f1SDimitry Andric public:
108*fe6060f1SDimitry Andric   CSKYOperand(const CSKYOperand &o) : MCParsedAsmOperand() {
109*fe6060f1SDimitry Andric     Kind = o.Kind;
110*fe6060f1SDimitry Andric     StartLoc = o.StartLoc;
111*fe6060f1SDimitry Andric     EndLoc = o.EndLoc;
112*fe6060f1SDimitry Andric     switch (Kind) {
113*fe6060f1SDimitry Andric     case Register:
114*fe6060f1SDimitry Andric       Reg = o.Reg;
115*fe6060f1SDimitry Andric       break;
116*fe6060f1SDimitry Andric     case Immediate:
117*fe6060f1SDimitry Andric       Imm = o.Imm;
118*fe6060f1SDimitry Andric       break;
119*fe6060f1SDimitry Andric     case Token:
120*fe6060f1SDimitry Andric       Tok = o.Tok;
121*fe6060f1SDimitry Andric       break;
122*fe6060f1SDimitry Andric     }
123*fe6060f1SDimitry Andric   }
124*fe6060f1SDimitry Andric 
125*fe6060f1SDimitry Andric   bool isToken() const override { return Kind == Token; }
126*fe6060f1SDimitry Andric   bool isReg() const override { return Kind == Register; }
127*fe6060f1SDimitry Andric   bool isImm() const override { return Kind == Immediate; }
128*fe6060f1SDimitry Andric   bool isMem() const override { return false; }
129*fe6060f1SDimitry Andric 
130*fe6060f1SDimitry Andric   static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm) {
131*fe6060f1SDimitry Andric     if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
132*fe6060f1SDimitry Andric       Imm = CE->getValue();
133*fe6060f1SDimitry Andric       return true;
134*fe6060f1SDimitry Andric     }
135*fe6060f1SDimitry Andric 
136*fe6060f1SDimitry Andric     return false;
137*fe6060f1SDimitry Andric   }
138*fe6060f1SDimitry Andric 
139*fe6060f1SDimitry Andric   template <unsigned num, unsigned shift = 0> bool isUImm() const {
140*fe6060f1SDimitry Andric     if (!isImm())
141*fe6060f1SDimitry Andric       return false;
142*fe6060f1SDimitry Andric 
143*fe6060f1SDimitry Andric     int64_t Imm;
144*fe6060f1SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
145*fe6060f1SDimitry Andric     return IsConstantImm && isShiftedUInt<num, shift>(Imm);
146*fe6060f1SDimitry Andric   }
147*fe6060f1SDimitry Andric 
148*fe6060f1SDimitry Andric   template <unsigned num> bool isOImm() const {
149*fe6060f1SDimitry Andric     if (!isImm())
150*fe6060f1SDimitry Andric       return false;
151*fe6060f1SDimitry Andric 
152*fe6060f1SDimitry Andric     int64_t Imm;
153*fe6060f1SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
154*fe6060f1SDimitry Andric     return IsConstantImm && isUInt<num>(Imm - 1);
155*fe6060f1SDimitry Andric   }
156*fe6060f1SDimitry Andric 
157*fe6060f1SDimitry Andric   template <unsigned num, unsigned shift = 0> bool isSImm() const {
158*fe6060f1SDimitry Andric     if (!isImm())
159*fe6060f1SDimitry Andric       return false;
160*fe6060f1SDimitry Andric 
161*fe6060f1SDimitry Andric     int64_t Imm;
162*fe6060f1SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
163*fe6060f1SDimitry Andric     return IsConstantImm && isShiftedInt<num, shift>(Imm);
164*fe6060f1SDimitry Andric   }
165*fe6060f1SDimitry Andric 
166*fe6060f1SDimitry Andric   bool isUImm2() const { return isUImm<2>(); }
167*fe6060f1SDimitry Andric   bool isUImm5() const { return isUImm<5>(); }
168*fe6060f1SDimitry Andric   bool isUImm12() const { return isUImm<12>(); }
169*fe6060f1SDimitry Andric   bool isUImm16() const { return isUImm<16>(); }
170*fe6060f1SDimitry Andric 
171*fe6060f1SDimitry Andric   bool isOImm12() const { return isOImm<12>(); }
172*fe6060f1SDimitry Andric   bool isOImm16() const { return isOImm<16>(); }
173*fe6060f1SDimitry Andric 
174*fe6060f1SDimitry Andric   bool isUImm12Shift1() { return isUImm<12, 1>(); }
175*fe6060f1SDimitry Andric   bool isUImm12Shift2() { return isUImm<12, 2>(); }
176*fe6060f1SDimitry Andric 
177*fe6060f1SDimitry Andric   bool isSImm16Shift1() { return isSImm<16, 1>(); }
178*fe6060f1SDimitry Andric 
179*fe6060f1SDimitry Andric   bool isCSKYSymbol() const {
180*fe6060f1SDimitry Andric     int64_t Imm;
181*fe6060f1SDimitry Andric     // Must be of 'immediate' type but not a constant.
182*fe6060f1SDimitry Andric     return isImm() && !evaluateConstantImm(getImm(), Imm);
183*fe6060f1SDimitry Andric   }
184*fe6060f1SDimitry Andric 
185*fe6060f1SDimitry Andric   bool isConstpoolSymbol() const {
186*fe6060f1SDimitry Andric     int64_t Imm;
187*fe6060f1SDimitry Andric     // Must be of 'immediate' type but not a constant.
188*fe6060f1SDimitry Andric     return isImm() && !evaluateConstantImm(getImm(), Imm);
189*fe6060f1SDimitry Andric   }
190*fe6060f1SDimitry Andric 
191*fe6060f1SDimitry Andric   /// Gets location of the first token of this operand.
192*fe6060f1SDimitry Andric   SMLoc getStartLoc() const override { return StartLoc; }
193*fe6060f1SDimitry Andric   /// Gets location of the last token of this operand.
194*fe6060f1SDimitry Andric   SMLoc getEndLoc() const override { return EndLoc; }
195*fe6060f1SDimitry Andric 
196*fe6060f1SDimitry Andric   unsigned getReg() const override {
197*fe6060f1SDimitry Andric     assert(Kind == Register && "Invalid type access!");
198*fe6060f1SDimitry Andric     return Reg.RegNum;
199*fe6060f1SDimitry Andric   }
200*fe6060f1SDimitry Andric 
201*fe6060f1SDimitry Andric   const MCExpr *getImm() const {
202*fe6060f1SDimitry Andric     assert(Kind == Immediate && "Invalid type access!");
203*fe6060f1SDimitry Andric     return Imm.Val;
204*fe6060f1SDimitry Andric   }
205*fe6060f1SDimitry Andric 
206*fe6060f1SDimitry Andric   StringRef getToken() const {
207*fe6060f1SDimitry Andric     assert(Kind == Token && "Invalid type access!");
208*fe6060f1SDimitry Andric     return Tok;
209*fe6060f1SDimitry Andric   }
210*fe6060f1SDimitry Andric 
211*fe6060f1SDimitry Andric   void print(raw_ostream &OS) const override {
212*fe6060f1SDimitry Andric     switch (Kind) {
213*fe6060f1SDimitry Andric     case Immediate:
214*fe6060f1SDimitry Andric       OS << *getImm();
215*fe6060f1SDimitry Andric       break;
216*fe6060f1SDimitry Andric     case Register:
217*fe6060f1SDimitry Andric       OS << "<register x" << getReg() << ">";
218*fe6060f1SDimitry Andric       break;
219*fe6060f1SDimitry Andric     case Token:
220*fe6060f1SDimitry Andric       OS << "'" << getToken() << "'";
221*fe6060f1SDimitry Andric       break;
222*fe6060f1SDimitry Andric     }
223*fe6060f1SDimitry Andric   }
224*fe6060f1SDimitry Andric 
225*fe6060f1SDimitry Andric   static std::unique_ptr<CSKYOperand> createToken(StringRef Str, SMLoc S) {
226*fe6060f1SDimitry Andric     auto Op = std::make_unique<CSKYOperand>(Token);
227*fe6060f1SDimitry Andric     Op->Tok = Str;
228*fe6060f1SDimitry Andric     Op->StartLoc = S;
229*fe6060f1SDimitry Andric     Op->EndLoc = S;
230*fe6060f1SDimitry Andric     return Op;
231*fe6060f1SDimitry Andric   }
232*fe6060f1SDimitry Andric 
233*fe6060f1SDimitry Andric   static std::unique_ptr<CSKYOperand> createReg(unsigned RegNo, SMLoc S,
234*fe6060f1SDimitry Andric                                                 SMLoc E) {
235*fe6060f1SDimitry Andric     auto Op = std::make_unique<CSKYOperand>(Register);
236*fe6060f1SDimitry Andric     Op->Reg.RegNum = RegNo;
237*fe6060f1SDimitry Andric     Op->StartLoc = S;
238*fe6060f1SDimitry Andric     Op->EndLoc = E;
239*fe6060f1SDimitry Andric     return Op;
240*fe6060f1SDimitry Andric   }
241*fe6060f1SDimitry Andric 
242*fe6060f1SDimitry Andric   static std::unique_ptr<CSKYOperand> createImm(const MCExpr *Val, SMLoc S,
243*fe6060f1SDimitry Andric                                                 SMLoc E) {
244*fe6060f1SDimitry Andric     auto Op = std::make_unique<CSKYOperand>(Immediate);
245*fe6060f1SDimitry Andric     Op->Imm.Val = Val;
246*fe6060f1SDimitry Andric     Op->StartLoc = S;
247*fe6060f1SDimitry Andric     Op->EndLoc = E;
248*fe6060f1SDimitry Andric     return Op;
249*fe6060f1SDimitry Andric   }
250*fe6060f1SDimitry Andric 
251*fe6060f1SDimitry Andric   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
252*fe6060f1SDimitry Andric     assert(Expr && "Expr shouldn't be null!");
253*fe6060f1SDimitry Andric     if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
254*fe6060f1SDimitry Andric       Inst.addOperand(MCOperand::createImm(CE->getValue()));
255*fe6060f1SDimitry Andric     else
256*fe6060f1SDimitry Andric       Inst.addOperand(MCOperand::createExpr(Expr));
257*fe6060f1SDimitry Andric   }
258*fe6060f1SDimitry Andric 
259*fe6060f1SDimitry Andric   // Used by the TableGen Code.
260*fe6060f1SDimitry Andric   void addRegOperands(MCInst &Inst, unsigned N) const {
261*fe6060f1SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
262*fe6060f1SDimitry Andric     Inst.addOperand(MCOperand::createReg(getReg()));
263*fe6060f1SDimitry Andric   }
264*fe6060f1SDimitry Andric 
265*fe6060f1SDimitry Andric   void addImmOperands(MCInst &Inst, unsigned N) const {
266*fe6060f1SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
267*fe6060f1SDimitry Andric     addExpr(Inst, getImm());
268*fe6060f1SDimitry Andric   }
269*fe6060f1SDimitry Andric };
270*fe6060f1SDimitry Andric } // end anonymous namespace.
271*fe6060f1SDimitry Andric 
272*fe6060f1SDimitry Andric #define GET_REGISTER_MATCHER
273*fe6060f1SDimitry Andric #define GET_SUBTARGET_FEATURE_NAME
274*fe6060f1SDimitry Andric #define GET_MATCHER_IMPLEMENTATION
275*fe6060f1SDimitry Andric #define GET_MNEMONIC_SPELL_CHECKER
276*fe6060f1SDimitry Andric #include "CSKYGenAsmMatcher.inc"
277*fe6060f1SDimitry Andric 
278*fe6060f1SDimitry Andric static std::string CSKYMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
279*fe6060f1SDimitry Andric                                           unsigned VariantID = 0);
280*fe6060f1SDimitry Andric 
281*fe6060f1SDimitry Andric bool CSKYAsmParser::generateImmOutOfRangeError(
282*fe6060f1SDimitry Andric     OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
283*fe6060f1SDimitry Andric     Twine Msg = "immediate must be an integer in the range") {
284*fe6060f1SDimitry Andric   SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
285*fe6060f1SDimitry Andric   return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
286*fe6060f1SDimitry Andric }
287*fe6060f1SDimitry Andric 
288*fe6060f1SDimitry Andric bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
289*fe6060f1SDimitry Andric                                             OperandVector &Operands,
290*fe6060f1SDimitry Andric                                             MCStreamer &Out,
291*fe6060f1SDimitry Andric                                             uint64_t &ErrorInfo,
292*fe6060f1SDimitry Andric                                             bool MatchingInlineAsm) {
293*fe6060f1SDimitry Andric   MCInst Inst;
294*fe6060f1SDimitry Andric   FeatureBitset MissingFeatures;
295*fe6060f1SDimitry Andric 
296*fe6060f1SDimitry Andric   auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
297*fe6060f1SDimitry Andric                                      MatchingInlineAsm);
298*fe6060f1SDimitry Andric   switch (Result) {
299*fe6060f1SDimitry Andric   default:
300*fe6060f1SDimitry Andric     break;
301*fe6060f1SDimitry Andric   case Match_Success:
302*fe6060f1SDimitry Andric     Inst.setLoc(IDLoc);
303*fe6060f1SDimitry Andric     Out.emitInstruction(Inst, getSTI());
304*fe6060f1SDimitry Andric     return false;
305*fe6060f1SDimitry Andric   case Match_MissingFeature: {
306*fe6060f1SDimitry Andric     assert(MissingFeatures.any() && "Unknown missing features!");
307*fe6060f1SDimitry Andric     ListSeparator LS;
308*fe6060f1SDimitry Andric     std::string Msg = "instruction requires the following: ";
309*fe6060f1SDimitry Andric     for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
310*fe6060f1SDimitry Andric       if (MissingFeatures[i]) {
311*fe6060f1SDimitry Andric         Msg += LS;
312*fe6060f1SDimitry Andric         Msg += getSubtargetFeatureName(i);
313*fe6060f1SDimitry Andric       }
314*fe6060f1SDimitry Andric     }
315*fe6060f1SDimitry Andric     return Error(IDLoc, Msg);
316*fe6060f1SDimitry Andric   }
317*fe6060f1SDimitry Andric   case Match_MnemonicFail: {
318*fe6060f1SDimitry Andric     FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
319*fe6060f1SDimitry Andric     std::string Suggestion =
320*fe6060f1SDimitry Andric         CSKYMnemonicSpellCheck(((CSKYOperand &)*Operands[0]).getToken(), FBS);
321*fe6060f1SDimitry Andric     return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
322*fe6060f1SDimitry Andric   }
323*fe6060f1SDimitry Andric   case Match_InvalidTiedOperand:
324*fe6060f1SDimitry Andric   case Match_InvalidOperand: {
325*fe6060f1SDimitry Andric     SMLoc ErrorLoc = IDLoc;
326*fe6060f1SDimitry Andric     if (ErrorInfo != ~0U) {
327*fe6060f1SDimitry Andric       if (ErrorInfo >= Operands.size())
328*fe6060f1SDimitry Andric         return Error(ErrorLoc, "too few operands for instruction");
329*fe6060f1SDimitry Andric 
330*fe6060f1SDimitry Andric       ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
331*fe6060f1SDimitry Andric       if (ErrorLoc == SMLoc())
332*fe6060f1SDimitry Andric         ErrorLoc = IDLoc;
333*fe6060f1SDimitry Andric     }
334*fe6060f1SDimitry Andric     return Error(ErrorLoc, "invalid operand for instruction");
335*fe6060f1SDimitry Andric   }
336*fe6060f1SDimitry Andric   }
337*fe6060f1SDimitry Andric 
338*fe6060f1SDimitry Andric   // Handle the case when the error message is of specific type
339*fe6060f1SDimitry Andric   // other than the generic Match_InvalidOperand, and the
340*fe6060f1SDimitry Andric   // corresponding operand is missing.
341*fe6060f1SDimitry Andric   if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
342*fe6060f1SDimitry Andric     SMLoc ErrorLoc = IDLoc;
343*fe6060f1SDimitry Andric     if (ErrorInfo != ~0U && ErrorInfo >= Operands.size())
344*fe6060f1SDimitry Andric       return Error(ErrorLoc, "too few operands for instruction");
345*fe6060f1SDimitry Andric   }
346*fe6060f1SDimitry Andric 
347*fe6060f1SDimitry Andric   switch (Result) {
348*fe6060f1SDimitry Andric   default:
349*fe6060f1SDimitry Andric     break;
350*fe6060f1SDimitry Andric   case Match_InvalidOImm12:
351*fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 12));
352*fe6060f1SDimitry Andric   case Match_InvalidOImm16:
353*fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 16));
354*fe6060f1SDimitry Andric   case Match_InvalidUImm2:
355*fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
356*fe6060f1SDimitry Andric   case Match_InvalidUImm5:
357*fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
358*fe6060f1SDimitry Andric   case Match_InvalidUImm12:
359*fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1);
360*fe6060f1SDimitry Andric   case Match_InvalidUImm12Shift1:
361*fe6060f1SDimitry Andric     return generateImmOutOfRangeError(
362*fe6060f1SDimitry Andric         Operands, ErrorInfo, 0, (1 << 12) - 2,
363*fe6060f1SDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
364*fe6060f1SDimitry Andric   case Match_InvalidUImm12Shift2:
365*fe6060f1SDimitry Andric     return generateImmOutOfRangeError(
366*fe6060f1SDimitry Andric         Operands, ErrorInfo, 0, (1 << 12) - 4,
367*fe6060f1SDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
368*fe6060f1SDimitry Andric   case Match_InvalidUImm16:
369*fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 16) - 1);
370*fe6060f1SDimitry Andric   case Match_InvalidCSKYSymbol: {
371*fe6060f1SDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
372*fe6060f1SDimitry Andric     return Error(ErrorLoc, "operand must be a symbol name");
373*fe6060f1SDimitry Andric   }
374*fe6060f1SDimitry Andric   case Match_InvalidConstpool: {
375*fe6060f1SDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
376*fe6060f1SDimitry Andric     return Error(ErrorLoc, "operand must be a constpool symbol name");
377*fe6060f1SDimitry Andric   }
378*fe6060f1SDimitry Andric   }
379*fe6060f1SDimitry Andric 
380*fe6060f1SDimitry Andric   llvm_unreachable("Unknown match type detected!");
381*fe6060f1SDimitry Andric }
382*fe6060f1SDimitry Andric 
383*fe6060f1SDimitry Andric // Attempts to match Name as a register (either using the default name or
384*fe6060f1SDimitry Andric // alternative ABI names), setting RegNo to the matching register. Upon
385*fe6060f1SDimitry Andric // failure, returns true and sets RegNo to 0.
386*fe6060f1SDimitry Andric static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) {
387*fe6060f1SDimitry Andric   RegNo = MatchRegisterName(Name);
388*fe6060f1SDimitry Andric 
389*fe6060f1SDimitry Andric   if (RegNo == CSKY::NoRegister)
390*fe6060f1SDimitry Andric     RegNo = MatchRegisterAltName(Name);
391*fe6060f1SDimitry Andric 
392*fe6060f1SDimitry Andric   return RegNo == CSKY::NoRegister;
393*fe6060f1SDimitry Andric }
394*fe6060f1SDimitry Andric 
395*fe6060f1SDimitry Andric bool CSKYAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
396*fe6060f1SDimitry Andric                                   SMLoc &EndLoc) {
397*fe6060f1SDimitry Andric   const AsmToken &Tok = getParser().getTok();
398*fe6060f1SDimitry Andric   StartLoc = Tok.getLoc();
399*fe6060f1SDimitry Andric   EndLoc = Tok.getEndLoc();
400*fe6060f1SDimitry Andric   StringRef Name = getLexer().getTok().getIdentifier();
401*fe6060f1SDimitry Andric 
402*fe6060f1SDimitry Andric   if (!matchRegisterNameHelper((MCRegister &)RegNo, Name)) {
403*fe6060f1SDimitry Andric     getParser().Lex(); // Eat identifier token.
404*fe6060f1SDimitry Andric     return false;
405*fe6060f1SDimitry Andric   }
406*fe6060f1SDimitry Andric 
407*fe6060f1SDimitry Andric   return Error(StartLoc, "invalid register name");
408*fe6060f1SDimitry Andric }
409*fe6060f1SDimitry Andric 
410*fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::parseRegister(OperandVector &Operands) {
411*fe6060f1SDimitry Andric   SMLoc S = getLoc();
412*fe6060f1SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
413*fe6060f1SDimitry Andric 
414*fe6060f1SDimitry Andric   switch (getLexer().getKind()) {
415*fe6060f1SDimitry Andric   default:
416*fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
417*fe6060f1SDimitry Andric   case AsmToken::Identifier: {
418*fe6060f1SDimitry Andric     StringRef Name = getLexer().getTok().getIdentifier();
419*fe6060f1SDimitry Andric     MCRegister RegNo;
420*fe6060f1SDimitry Andric 
421*fe6060f1SDimitry Andric     if (matchRegisterNameHelper((MCRegister &)RegNo, Name))
422*fe6060f1SDimitry Andric       return MatchOperand_NoMatch;
423*fe6060f1SDimitry Andric 
424*fe6060f1SDimitry Andric     getLexer().Lex();
425*fe6060f1SDimitry Andric     Operands.push_back(CSKYOperand::createReg(RegNo, S, E));
426*fe6060f1SDimitry Andric 
427*fe6060f1SDimitry Andric     return MatchOperand_Success;
428*fe6060f1SDimitry Andric   }
429*fe6060f1SDimitry Andric   }
430*fe6060f1SDimitry Andric }
431*fe6060f1SDimitry Andric 
432*fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::parseBaseRegImm(OperandVector &Operands) {
433*fe6060f1SDimitry Andric   assert(getLexer().is(AsmToken::LParen));
434*fe6060f1SDimitry Andric 
435*fe6060f1SDimitry Andric   Operands.push_back(CSKYOperand::createToken("(", getLoc()));
436*fe6060f1SDimitry Andric 
437*fe6060f1SDimitry Andric   auto Tok = getParser().Lex(); // Eat '('
438*fe6060f1SDimitry Andric 
439*fe6060f1SDimitry Andric   if (parseRegister(Operands) != MatchOperand_Success) {
440*fe6060f1SDimitry Andric     getLexer().UnLex(Tok);
441*fe6060f1SDimitry Andric     Operands.pop_back();
442*fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
443*fe6060f1SDimitry Andric   }
444*fe6060f1SDimitry Andric 
445*fe6060f1SDimitry Andric   if (getLexer().isNot(AsmToken::Comma)) {
446*fe6060f1SDimitry Andric     Error(getLoc(), "expected ','");
447*fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
448*fe6060f1SDimitry Andric   }
449*fe6060f1SDimitry Andric 
450*fe6060f1SDimitry Andric   getParser().Lex(); // Eat ','
451*fe6060f1SDimitry Andric 
452*fe6060f1SDimitry Andric   if (parseRegister(Operands) == MatchOperand_Success) {
453*fe6060f1SDimitry Andric     if (getLexer().isNot(AsmToken::LessLess)) {
454*fe6060f1SDimitry Andric       Error(getLoc(), "expected '<<'");
455*fe6060f1SDimitry Andric       return MatchOperand_ParseFail;
456*fe6060f1SDimitry Andric     }
457*fe6060f1SDimitry Andric 
458*fe6060f1SDimitry Andric     Operands.push_back(CSKYOperand::createToken("<<", getLoc()));
459*fe6060f1SDimitry Andric 
460*fe6060f1SDimitry Andric     getParser().Lex(); // Eat '<<'
461*fe6060f1SDimitry Andric 
462*fe6060f1SDimitry Andric     if (parseImmediate(Operands) != MatchOperand_Success) {
463*fe6060f1SDimitry Andric       Error(getLoc(), "expected imm");
464*fe6060f1SDimitry Andric       return MatchOperand_ParseFail;
465*fe6060f1SDimitry Andric     }
466*fe6060f1SDimitry Andric 
467*fe6060f1SDimitry Andric   } else if (parseImmediate(Operands) != MatchOperand_Success) {
468*fe6060f1SDimitry Andric     Error(getLoc(), "expected imm");
469*fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
470*fe6060f1SDimitry Andric   }
471*fe6060f1SDimitry Andric 
472*fe6060f1SDimitry Andric   if (getLexer().isNot(AsmToken::RParen)) {
473*fe6060f1SDimitry Andric     Error(getLoc(), "expected ')'");
474*fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
475*fe6060f1SDimitry Andric   }
476*fe6060f1SDimitry Andric 
477*fe6060f1SDimitry Andric   Operands.push_back(CSKYOperand::createToken(")", getLoc()));
478*fe6060f1SDimitry Andric 
479*fe6060f1SDimitry Andric   getParser().Lex(); // Eat ')'
480*fe6060f1SDimitry Andric 
481*fe6060f1SDimitry Andric   return MatchOperand_Success;
482*fe6060f1SDimitry Andric }
483*fe6060f1SDimitry Andric 
484*fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::parseImmediate(OperandVector &Operands) {
485*fe6060f1SDimitry Andric   switch (getLexer().getKind()) {
486*fe6060f1SDimitry Andric   default:
487*fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
488*fe6060f1SDimitry Andric   case AsmToken::LParen:
489*fe6060f1SDimitry Andric   case AsmToken::Minus:
490*fe6060f1SDimitry Andric   case AsmToken::Plus:
491*fe6060f1SDimitry Andric   case AsmToken::Integer:
492*fe6060f1SDimitry Andric   case AsmToken::String:
493*fe6060f1SDimitry Andric     break;
494*fe6060f1SDimitry Andric   }
495*fe6060f1SDimitry Andric 
496*fe6060f1SDimitry Andric   const MCExpr *IdVal;
497*fe6060f1SDimitry Andric   SMLoc S = getLoc();
498*fe6060f1SDimitry Andric   if (getParser().parseExpression(IdVal))
499*fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
500*fe6060f1SDimitry Andric 
501*fe6060f1SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
502*fe6060f1SDimitry Andric   Operands.push_back(CSKYOperand::createImm(IdVal, S, E));
503*fe6060f1SDimitry Andric   return MatchOperand_Success;
504*fe6060f1SDimitry Andric }
505*fe6060f1SDimitry Andric 
506*fe6060f1SDimitry Andric /// Looks at a token type and creates the relevant operand from this
507*fe6060f1SDimitry Andric /// information, adding to Operands. If operand was parsed, returns false, else
508*fe6060f1SDimitry Andric /// true.
509*fe6060f1SDimitry Andric bool CSKYAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
510*fe6060f1SDimitry Andric   // Check if the current operand has a custom associated parser, if so, try to
511*fe6060f1SDimitry Andric   // custom parse the operand, or fallback to the general approach.
512*fe6060f1SDimitry Andric   OperandMatchResultTy Result =
513*fe6060f1SDimitry Andric       MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
514*fe6060f1SDimitry Andric   if (Result == MatchOperand_Success)
515*fe6060f1SDimitry Andric     return false;
516*fe6060f1SDimitry Andric   if (Result == MatchOperand_ParseFail)
517*fe6060f1SDimitry Andric     return true;
518*fe6060f1SDimitry Andric 
519*fe6060f1SDimitry Andric   // Attempt to parse token as register
520*fe6060f1SDimitry Andric   if (parseRegister(Operands) == MatchOperand_Success)
521*fe6060f1SDimitry Andric     return false;
522*fe6060f1SDimitry Andric 
523*fe6060f1SDimitry Andric   // Attempt to parse token as (register, imm)
524*fe6060f1SDimitry Andric   if (getLexer().is(AsmToken::LParen))
525*fe6060f1SDimitry Andric     if (parseBaseRegImm(Operands) == MatchOperand_Success)
526*fe6060f1SDimitry Andric       return false;
527*fe6060f1SDimitry Andric 
528*fe6060f1SDimitry Andric   // Attempt to parse token as a imm.
529*fe6060f1SDimitry Andric   if (parseImmediate(Operands) == MatchOperand_Success)
530*fe6060f1SDimitry Andric     return false;
531*fe6060f1SDimitry Andric 
532*fe6060f1SDimitry Andric   // Finally we have exhausted all options and must declare defeat.
533*fe6060f1SDimitry Andric   Error(getLoc(), "unknown operand");
534*fe6060f1SDimitry Andric   return true;
535*fe6060f1SDimitry Andric }
536*fe6060f1SDimitry Andric 
537*fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::parseCSKYSymbol(OperandVector &Operands) {
538*fe6060f1SDimitry Andric   SMLoc S = getLoc();
539*fe6060f1SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
540*fe6060f1SDimitry Andric 
541*fe6060f1SDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier)
542*fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
543*fe6060f1SDimitry Andric 
544*fe6060f1SDimitry Andric   StringRef Identifier;
545*fe6060f1SDimitry Andric   if (getParser().parseIdentifier(Identifier))
546*fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
547*fe6060f1SDimitry Andric 
548*fe6060f1SDimitry Andric   CSKYMCExpr::VariantKind Kind = CSKYMCExpr::VK_CSKY_None;
549*fe6060f1SDimitry Andric 
550*fe6060f1SDimitry Andric   if (Identifier.consume_back("@GOT"))
551*fe6060f1SDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_GOT;
552*fe6060f1SDimitry Andric   else if (Identifier.consume_back("@GOTOFF"))
553*fe6060f1SDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_GOTOFF;
554*fe6060f1SDimitry Andric   else if (Identifier.consume_back("@PLT"))
555*fe6060f1SDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_PLT;
556*fe6060f1SDimitry Andric   else if (Identifier.consume_back("@GOTPC"))
557*fe6060f1SDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_GOTPC;
558*fe6060f1SDimitry Andric 
559*fe6060f1SDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
560*fe6060f1SDimitry Andric   const MCExpr *Res =
561*fe6060f1SDimitry Andric       MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
562*fe6060f1SDimitry Andric 
563*fe6060f1SDimitry Andric   if (Kind != CSKYMCExpr::VK_CSKY_None)
564*fe6060f1SDimitry Andric     Res = CSKYMCExpr::create(Res, Kind, getContext());
565*fe6060f1SDimitry Andric 
566*fe6060f1SDimitry Andric   Operands.push_back(CSKYOperand::createImm(Res, S, E));
567*fe6060f1SDimitry Andric   return MatchOperand_Success;
568*fe6060f1SDimitry Andric }
569*fe6060f1SDimitry Andric 
570*fe6060f1SDimitry Andric OperandMatchResultTy
571*fe6060f1SDimitry Andric CSKYAsmParser::parseConstpoolSymbol(OperandVector &Operands) {
572*fe6060f1SDimitry Andric   SMLoc S = getLoc();
573*fe6060f1SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
574*fe6060f1SDimitry Andric 
575*fe6060f1SDimitry Andric   if (getLexer().getKind() != AsmToken::LBrac)
576*fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
577*fe6060f1SDimitry Andric 
578*fe6060f1SDimitry Andric   getLexer().Lex(); // Eat '['.
579*fe6060f1SDimitry Andric 
580*fe6060f1SDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier)
581*fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
582*fe6060f1SDimitry Andric 
583*fe6060f1SDimitry Andric   StringRef Identifier;
584*fe6060f1SDimitry Andric   if (getParser().parseIdentifier(Identifier))
585*fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
586*fe6060f1SDimitry Andric 
587*fe6060f1SDimitry Andric   if (getLexer().getKind() != AsmToken::RBrac)
588*fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
589*fe6060f1SDimitry Andric 
590*fe6060f1SDimitry Andric   getLexer().Lex(); // Eat ']'.
591*fe6060f1SDimitry Andric 
592*fe6060f1SDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
593*fe6060f1SDimitry Andric   const MCExpr *Res =
594*fe6060f1SDimitry Andric       MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
595*fe6060f1SDimitry Andric   Operands.push_back(CSKYOperand::createImm(Res, S, E));
596*fe6060f1SDimitry Andric   return MatchOperand_Success;
597*fe6060f1SDimitry Andric }
598*fe6060f1SDimitry Andric 
599*fe6060f1SDimitry Andric bool CSKYAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
600*fe6060f1SDimitry Andric                                      SMLoc NameLoc, OperandVector &Operands) {
601*fe6060f1SDimitry Andric   // First operand is token for instruction.
602*fe6060f1SDimitry Andric   Operands.push_back(CSKYOperand::createToken(Name, NameLoc));
603*fe6060f1SDimitry Andric 
604*fe6060f1SDimitry Andric   // If there are no more operands, then finish.
605*fe6060f1SDimitry Andric   if (getLexer().is(AsmToken::EndOfStatement))
606*fe6060f1SDimitry Andric     return false;
607*fe6060f1SDimitry Andric 
608*fe6060f1SDimitry Andric   // Parse first operand.
609*fe6060f1SDimitry Andric   if (parseOperand(Operands, Name))
610*fe6060f1SDimitry Andric     return true;
611*fe6060f1SDimitry Andric 
612*fe6060f1SDimitry Andric   // Parse until end of statement, consuming commas between operands.
613*fe6060f1SDimitry Andric   while (getLexer().is(AsmToken::Comma)) {
614*fe6060f1SDimitry Andric     // Consume comma token.
615*fe6060f1SDimitry Andric     getLexer().Lex();
616*fe6060f1SDimitry Andric 
617*fe6060f1SDimitry Andric     // Parse next operand.
618*fe6060f1SDimitry Andric     if (parseOperand(Operands, Name))
619*fe6060f1SDimitry Andric       return true;
620*fe6060f1SDimitry Andric   }
621*fe6060f1SDimitry Andric 
622*fe6060f1SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
623*fe6060f1SDimitry Andric     SMLoc Loc = getLexer().getLoc();
624*fe6060f1SDimitry Andric     getParser().eatToEndOfStatement();
625*fe6060f1SDimitry Andric     return Error(Loc, "unexpected token");
626*fe6060f1SDimitry Andric   }
627*fe6060f1SDimitry Andric 
628*fe6060f1SDimitry Andric   getParser().Lex(); // Consume the EndOfStatement.
629*fe6060f1SDimitry Andric   return false;
630*fe6060f1SDimitry Andric }
631*fe6060f1SDimitry Andric 
632*fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::tryParseRegister(unsigned &RegNo,
633*fe6060f1SDimitry Andric                                                      SMLoc &StartLoc,
634*fe6060f1SDimitry Andric                                                      SMLoc &EndLoc) {
635*fe6060f1SDimitry Andric   const AsmToken &Tok = getParser().getTok();
636*fe6060f1SDimitry Andric   StartLoc = Tok.getLoc();
637*fe6060f1SDimitry Andric   EndLoc = Tok.getEndLoc();
638*fe6060f1SDimitry Andric 
639*fe6060f1SDimitry Andric   StringRef Name = getLexer().getTok().getIdentifier();
640*fe6060f1SDimitry Andric 
641*fe6060f1SDimitry Andric   if (matchRegisterNameHelper((MCRegister &)RegNo, Name))
642*fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
643*fe6060f1SDimitry Andric 
644*fe6060f1SDimitry Andric   getParser().Lex(); // Eat identifier token.
645*fe6060f1SDimitry Andric   return MatchOperand_Success;
646*fe6060f1SDimitry Andric }
647*fe6060f1SDimitry Andric 
648*fe6060f1SDimitry Andric bool CSKYAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
649*fe6060f1SDimitry Andric 
650*fe6060f1SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYAsmParser() {
651*fe6060f1SDimitry Andric   RegisterMCAsmParser<CSKYAsmParser> X(getTheCSKYTarget());
652*fe6060f1SDimitry Andric }
653