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