LLVM 24.0.0git
CSKYAsmParser.cpp
Go to the documentation of this file.
1//===---- CSKYAsmParser.cpp - Parse CSKY 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
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/Statistic.h"
21#include "llvm/MC/MCContext.h"
22#include "llvm/MC/MCExpr.h"
23#include "llvm/MC/MCInst.h"
24#include "llvm/MC/MCInstrInfo.h"
30#include "llvm/MC/MCStreamer.h"
35#include "llvm/Support/Debug.h"
37
38using namespace llvm;
39
40#define DEBUG_TYPE "csky-asm-parser"
41
42// Include the auto-generated portion of the compress emitter.
43#define GEN_COMPRESS_INSTR
44#include "CSKYGenCompressInstEmitter.inc"
45
46STATISTIC(CSKYNumInstrsCompressed,
47 "Number of C-SKY Compressed instructions emitted");
48
49namespace {
50struct CSKYOperand;
51
52class CSKYAsmParser : public MCTargetAsmParser {
53 const CSKYMCOptions &CLOpts;
54 const MCRegisterInfo *MRI;
55
56 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
57 unsigned Kind) override;
58
59 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
60 int64_t Lower, int64_t Upper,
61 const Twine &Msg);
62
63 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
64
65 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
66 OperandVector &Operands, MCStreamer &Out,
67 uint64_t &ErrorInfo,
68 bool MatchingInlineAsm) override;
69
70 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
71
72 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
73 SMLoc NameLoc, OperandVector &Operands) override;
74
75 ParseStatus parseDirective(AsmToken DirectiveID) override;
76
77 // Helper to actually emit an instruction to the MCStreamer. Also, when
78 // possible, compression of the instruction is performed.
79 void emitToStreamer(MCStreamer &S, const MCInst &Inst);
80
81 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
82 SMLoc &EndLoc) override;
83
84 bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
85 MCStreamer &Out);
86 bool processLRW(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
87 bool processJSRI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
88 bool processJMPI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
89
90 CSKYTargetStreamer &getTargetStreamer() {
91 assert(getParser().getStreamer().getTargetStreamer() &&
92 "do not have a target streamer");
93 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
94 return static_cast<CSKYTargetStreamer &>(TS);
95 }
96
97// Auto-generated instruction matching functions
98#define GET_ASSEMBLER_HEADER
99#include "CSKYGenAsmMatcher.inc"
100
102 ParseStatus parseRegister(OperandVector &Operands);
103 ParseStatus parseBaseRegImm(OperandVector &Operands);
104 ParseStatus parseCSKYSymbol(OperandVector &Operands);
105 ParseStatus parseConstpoolSymbol(OperandVector &Operands);
106 ParseStatus parseDataSymbol(OperandVector &Operands);
107 ParseStatus parsePSRFlag(OperandVector &Operands);
108 ParseStatus parseRegSeq(OperandVector &Operands);
109 ParseStatus parseRegList(OperandVector &Operands);
110
111 bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
112
113 bool parseDirectiveAttribute();
114
115public:
116 enum CSKYMatchResultTy {
117 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
118 Match_RequiresSameSrcAndDst,
119 Match_InvalidRegOutOfRange,
120#define GET_OPERAND_DIAGNOSTIC_TYPES
121#include "CSKYGenAsmMatcher.inc"
122#undef GET_OPERAND_DIAGNOSTIC_TYPES
123 };
124
125 CSKYAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
126 const MCInstrInfo &MII)
127 : MCTargetAsmParser(STI, MII),
128 CLOpts(CSKY_MC::getCLOpts(Parser.getContext().getTargetOptions())) {
129
131
132 // Cache the MCRegisterInfo.
133 MRI = getContext().getRegisterInfo();
134
135 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
136 if (CLOpts.add_build_attributes)
137 getTargetStreamer().emitTargetAttributes(STI, /*HardFloatABI=*/false);
138 }
139};
140
141/// Instances of this class represent a parsed machine instruction.
142struct CSKYOperand : public MCParsedAsmOperand {
143
144 enum KindTy {
145 Token,
146 Register,
147 Immediate,
148 RegisterSeq,
149 CPOP,
150 RegisterList
151 } Kind;
152
153 struct RegOp {
154 MCRegister RegNum;
155 };
156
157 struct ImmOp {
158 const MCExpr *Val;
159 };
160
161 struct ConstpoolOp {
162 const MCExpr *Val;
163 };
164
165 struct RegSeqOp {
166 MCRegister RegNumFrom;
167 MCRegister RegNumTo;
168 };
169
170 struct RegListOp {
171 MCRegister List1From;
172 MCRegister List1To;
173 MCRegister List2From;
174 MCRegister List2To;
175 MCRegister List3From;
176 MCRegister List3To;
177 MCRegister List4From;
178 MCRegister List4To;
179 };
180
181 SMLoc StartLoc, EndLoc;
182 union {
183 StringRef Tok;
184 RegOp Reg;
185 ImmOp Imm;
186 ConstpoolOp CPool;
187 RegSeqOp RegSeq;
188 RegListOp RegList;
189 };
190
191 CSKYOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
192
193public:
194 CSKYOperand(const CSKYOperand &o) : MCParsedAsmOperand() {
195 Kind = o.Kind;
196 StartLoc = o.StartLoc;
197 EndLoc = o.EndLoc;
198 switch (Kind) {
199 case Register:
200 Reg = o.Reg;
201 break;
202 case RegisterSeq:
203 RegSeq = o.RegSeq;
204 break;
205 case CPOP:
206 CPool = o.CPool;
207 break;
208 case Immediate:
209 Imm = o.Imm;
210 break;
211 case Token:
212 Tok = o.Tok;
213 break;
214 case RegisterList:
215 RegList = o.RegList;
216 break;
217 }
218 }
219
220 bool isToken() const override { return Kind == Token; }
221 bool isReg() const override { return Kind == Register; }
222 bool isImm() const override { return Kind == Immediate; }
223 bool isRegisterSeq() const { return Kind == RegisterSeq; }
224 bool isRegisterList() const { return Kind == RegisterList; }
225 bool isConstPoolOp() const { return Kind == CPOP; }
226
227 bool isMem() const override { return false; }
228
229 static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm) {
230 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
231 Imm = CE->getValue();
232 return true;
233 }
234
235 return false;
236 }
237
238 template <unsigned num, unsigned shift = 0> bool isUImm() const {
239 if (!isImm())
240 return false;
241
242 int64_t Imm;
243 bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
244 return IsConstantImm && isShiftedUInt<num, shift>(Imm);
245 }
246
247 template <unsigned num> bool isOImm() const {
248 if (!isImm())
249 return false;
250
251 int64_t Imm;
252 bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
253 return IsConstantImm && isUInt<num>(Imm - 1);
254 }
255
256 template <unsigned num, unsigned shift = 0> bool isSImm() const {
257 if (!isImm())
258 return false;
259
260 int64_t Imm;
261 bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
262 return IsConstantImm && isShiftedInt<num, shift>(Imm);
263 }
264
265 bool isUImm1() const { return isUImm<1>(); }
266 bool isUImm2() const { return isUImm<2>(); }
267 bool isUImm3() const { return isUImm<3>(); }
268 bool isUImm4() const { return isUImm<4>(); }
269 bool isUImm5() const { return isUImm<5>(); }
270 bool isUImm6() const { return isUImm<6>(); }
271 bool isUImm7() const { return isUImm<7>(); }
272 bool isUImm8() const { return isUImm<8>(); }
273 bool isUImm12() const { return isUImm<12>(); }
274 bool isUImm16() const { return isUImm<16>(); }
275 bool isUImm20() const { return isUImm<20>(); }
276 bool isUImm24() const { return isUImm<24>(); }
277
278 bool isOImm3() const { return isOImm<3>(); }
279 bool isOImm4() const { return isOImm<4>(); }
280 bool isOImm5() const { return isOImm<5>(); }
281 bool isOImm6() const { return isOImm<6>(); }
282 bool isOImm8() const { return isOImm<8>(); }
283 bool isOImm12() const { return isOImm<12>(); }
284 bool isOImm16() const { return isOImm<16>(); }
285
286 bool isSImm8() const { return isSImm<8>(); }
287
288 bool isUImm5Shift1() { return isUImm<5, 1>(); }
289 bool isUImm5Shift2() { return isUImm<5, 2>(); }
290 bool isUImm7Shift1() { return isUImm<7, 1>(); }
291 bool isUImm7Shift2() { return isUImm<7, 2>(); }
292 bool isUImm7Shift3() { return isUImm<7, 3>(); }
293 bool isUImm8Shift2() { return isUImm<8, 2>(); }
294 bool isUImm8Shift3() { return isUImm<8, 3>(); }
295 bool isUImm8Shift8() { return isUImm<8, 8>(); }
296 bool isUImm8Shift16() { return isUImm<8, 16>(); }
297 bool isUImm8Shift24() { return isUImm<8, 24>(); }
298 bool isUImm12Shift1() { return isUImm<12, 1>(); }
299 bool isUImm12Shift2() { return isUImm<12, 2>(); }
300 bool isUImm16Shift8() { return isUImm<16, 8>(); }
301 bool isUImm16Shift16() { return isUImm<16, 16>(); }
302 bool isUImm24Shift8() { return isUImm<24, 8>(); }
303
304 bool isSImm16Shift1() { return isSImm<16, 1>(); }
305
306 bool isCSKYSymbol() const { return isImm(); }
307
308 bool isConstpool() const { return isConstPoolOp(); }
309 bool isDataSymbol() const { return isConstPoolOp(); }
310
311 bool isPSRFlag() const {
312 int64_t Imm;
313 // Must be of 'immediate' type and a constant.
314 if (!isImm() || !evaluateConstantImm(getImm(), Imm))
315 return false;
316
317 return isUInt<5>(Imm);
318 }
319
320 template <unsigned MIN, unsigned MAX> bool isRegSeqTemplate() const {
321 if (!isRegisterSeq())
322 return false;
323
324 std::pair<unsigned, unsigned> regSeq = getRegSeq();
325
326 return MIN <= regSeq.first && regSeq.first <= regSeq.second &&
327 regSeq.second <= MAX;
328 }
329
330 bool isRegSeq() const { return isRegSeqTemplate<CSKY::R0, CSKY::R31>(); }
331
332 bool isRegSeqV1() const {
333 return isRegSeqTemplate<CSKY::F0_32, CSKY::F15_32>();
334 }
335
336 bool isRegSeqV2() const {
337 return isRegSeqTemplate<CSKY::F0_32, CSKY::F31_32>();
338 }
339
340 static bool isLegalRegList(unsigned from, unsigned to) {
341 if (from == 0 && to == 0)
342 return true;
343
344 if (from == to) {
345 if (from != CSKY::R4 && from != CSKY::R15 && from != CSKY::R16 &&
346 from != CSKY::R28)
347 return false;
348
349 return true;
350 } else {
351 if (from != CSKY::R4 && from != CSKY::R16)
352 return false;
353
354 if (from == CSKY::R4 && to > CSKY::R4 && to < CSKY::R12)
355 return true;
356 else if (from == CSKY::R16 && to > CSKY::R16 && to < CSKY::R18)
357 return true;
358 else
359 return false;
360 }
361 }
362
363 bool isRegList() const {
364 if (!isRegisterList())
365 return false;
366
367 auto regList = getRegList();
368
369 if (!isLegalRegList(regList.List1From, regList.List1To))
370 return false;
371 if (!isLegalRegList(regList.List2From, regList.List2To))
372 return false;
373 if (!isLegalRegList(regList.List3From, regList.List3To))
374 return false;
375 if (!isLegalRegList(regList.List4From, regList.List4To))
376 return false;
377
378 return true;
379 }
380
381 bool isExtImm6() {
382 if (!isImm())
383 return false;
384
385 int64_t Imm;
386 bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
387 if (!IsConstantImm)
388 return false;
389
390 int uimm4 = Imm & 0xf;
391
392 return isShiftedUInt<6, 0>(Imm) && uimm4 >= 0 && uimm4 <= 14;
393 }
394
395 /// Gets location of the first token of this operand.
396 SMLoc getStartLoc() const override { return StartLoc; }
397 /// Gets location of the last token of this operand.
398 SMLoc getEndLoc() const override { return EndLoc; }
399
400 MCRegister getReg() const override {
401 assert(Kind == Register && "Invalid type access!");
402 return Reg.RegNum;
403 }
404
405 std::pair<MCRegister, MCRegister> getRegSeq() const {
406 assert(Kind == RegisterSeq && "Invalid type access!");
407 return {RegSeq.RegNumFrom, RegSeq.RegNumTo};
408 }
409
410 RegListOp getRegList() const {
411 assert(Kind == RegisterList && "Invalid type access!");
412 return RegList;
413 }
414
415 const MCExpr *getImm() const {
416 assert(Kind == Immediate && "Invalid type access!");
417 return Imm.Val;
418 }
419
420 const MCExpr *getConstpoolOp() const {
421 assert(Kind == CPOP && "Invalid type access!");
422 return CPool.Val;
423 }
424
425 StringRef getToken() const {
426 assert(Kind == Token && "Invalid type access!");
427 return Tok;
428 }
429
430 void print(raw_ostream &OS, const MCAsmInfo &MAI) const override {
431 const CSKYMCOptions &CLOpts = CSKY_MC::getCLOpts(MAI.getTargetOptions());
432 auto RegName = [&](MCRegister Reg) {
433 if (Reg)
435 else
436 return "noreg";
437 };
438
439 switch (Kind) {
440 case CPOP:
441 MAI.printExpr(OS, *getConstpoolOp());
442 break;
443 case Immediate:
444 MAI.printExpr(OS, *getImm());
445 break;
446 case KindTy::Register:
447 OS << "<register " << RegName(getReg()) << ">";
448 break;
449 case RegisterSeq:
450 OS << "<register-seq ";
451 OS << RegName(getRegSeq().first) << "-" << RegName(getRegSeq().second)
452 << ">";
453 break;
454 case RegisterList:
455 OS << "<register-list ";
456 OS << RegName(getRegList().List1From) << "-"
457 << RegName(getRegList().List1To) << ",";
458 OS << RegName(getRegList().List2From) << "-"
459 << RegName(getRegList().List2To) << ",";
460 OS << RegName(getRegList().List3From) << "-"
461 << RegName(getRegList().List3To) << ",";
462 OS << RegName(getRegList().List4From) << "-"
463 << RegName(getRegList().List4To);
464 break;
465 case Token:
466 OS << "'" << getToken() << "'";
467 break;
468 }
469 }
470
471 static std::unique_ptr<CSKYOperand> createToken(StringRef Str, SMLoc S) {
472 auto Op = std::make_unique<CSKYOperand>(Token);
473 Op->Tok = Str;
474 Op->StartLoc = S;
475 Op->EndLoc = S;
476 return Op;
477 }
478
479 static std::unique_ptr<CSKYOperand> createReg(MCRegister RegNo, SMLoc S,
480 SMLoc E) {
481 auto Op = std::make_unique<CSKYOperand>(Register);
482 Op->Reg.RegNum = RegNo;
483 Op->StartLoc = S;
484 Op->EndLoc = E;
485 return Op;
486 }
487
488 static std::unique_ptr<CSKYOperand>
489 createRegSeq(MCRegister RegNoFrom, MCRegister RegNoTo, SMLoc S) {
490 auto Op = std::make_unique<CSKYOperand>(RegisterSeq);
491 Op->RegSeq.RegNumFrom = RegNoFrom;
492 Op->RegSeq.RegNumTo = RegNoTo;
493 Op->StartLoc = S;
494 Op->EndLoc = S;
495 return Op;
496 }
497
498 static std::unique_ptr<CSKYOperand>
499 createRegList(const SmallVector<MCRegister, 4> &reglist, SMLoc S) {
500 auto Op = std::make_unique<CSKYOperand>(RegisterList);
501 Op->RegList.List1From = 0;
502 Op->RegList.List1To = 0;
503 Op->RegList.List2From = 0;
504 Op->RegList.List2To = 0;
505 Op->RegList.List3From = 0;
506 Op->RegList.List3To = 0;
507 Op->RegList.List4From = 0;
508 Op->RegList.List4To = 0;
509
510 for (unsigned i = 0; i < reglist.size(); i += 2) {
511 if (Op->RegList.List1From == 0) {
512 Op->RegList.List1From = reglist[i];
513 Op->RegList.List1To = reglist[i + 1];
514 } else if (Op->RegList.List2From == 0) {
515 Op->RegList.List2From = reglist[i];
516 Op->RegList.List2To = reglist[i + 1];
517 } else if (Op->RegList.List3From == 0) {
518 Op->RegList.List3From = reglist[i];
519 Op->RegList.List3To = reglist[i + 1];
520 } else if (Op->RegList.List4From == 0) {
521 Op->RegList.List4From = reglist[i];
522 Op->RegList.List4To = reglist[i + 1];
523 } else {
524 assert(0);
525 }
526 }
527
528 Op->StartLoc = S;
529 Op->EndLoc = S;
530 return Op;
531 }
532
533 static std::unique_ptr<CSKYOperand> createImm(const MCExpr *Val, SMLoc S,
534 SMLoc E) {
535 auto Op = std::make_unique<CSKYOperand>(Immediate);
536 Op->Imm.Val = Val;
537 Op->StartLoc = S;
538 Op->EndLoc = E;
539 return Op;
540 }
541
542 static std::unique_ptr<CSKYOperand> createConstpoolOp(const MCExpr *Val,
543 SMLoc S, SMLoc E) {
544 auto Op = std::make_unique<CSKYOperand>(CPOP);
545 Op->CPool.Val = Val;
546 Op->StartLoc = S;
547 Op->EndLoc = E;
548 return Op;
549 }
550
551 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
552 assert(Expr && "Expr shouldn't be null!");
553 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
554 Inst.addOperand(MCOperand::createImm(CE->getValue()));
555 else
557 }
558
559 // Used by the TableGen Code.
560 void addRegOperands(MCInst &Inst, unsigned N) const {
561 assert(N == 1 && "Invalid number of operands!");
563 }
564
565 void addImmOperands(MCInst &Inst, unsigned N) const {
566 assert(N == 1 && "Invalid number of operands!");
567 addExpr(Inst, getImm());
568 }
569
570 void addConstpoolOperands(MCInst &Inst, unsigned N) const {
571 assert(N == 1 && "Invalid number of operands!");
572 Inst.addOperand(MCOperand::createExpr(getConstpoolOp()));
573 }
574
575 void addRegSeqOperands(MCInst &Inst, unsigned N) const {
576 assert(N == 2 && "Invalid number of operands!");
577 auto regSeq = getRegSeq();
578
579 Inst.addOperand(MCOperand::createReg(regSeq.first));
580 Inst.addOperand(MCOperand::createReg(regSeq.second));
581 }
582
583 static unsigned getListValue(unsigned ListFrom, unsigned ListTo) {
584 if (ListFrom == ListTo && ListFrom == CSKY::R15)
585 return (1 << 4);
586 else if (ListFrom == ListTo && ListFrom == CSKY::R28)
587 return (1 << 8);
588 else if (ListFrom == CSKY::R4)
589 return ListTo - ListFrom + 1;
590 else if (ListFrom == CSKY::R16)
591 return ((ListTo - ListFrom + 1) << 5);
592 else
593 return 0;
594 }
595
596 void addRegListOperands(MCInst &Inst, unsigned N) const {
597 assert(N == 1 && "Invalid number of operands!");
598 auto regList = getRegList();
599
600 unsigned V = 0;
601
602 unsigned T = getListValue(regList.List1From, regList.List1To);
603 if (T != 0)
604 V = V | T;
605
606 T = getListValue(regList.List2From, regList.List2To);
607 if (T != 0)
608 V = V | T;
609
610 T = getListValue(regList.List3From, regList.List3To);
611 if (T != 0)
612 V = V | T;
613
614 T = getListValue(regList.List4From, regList.List4To);
615 if (T != 0)
616 V = V | T;
617
619 }
620
621 bool isValidForTie(const CSKYOperand &Other) const {
622 if (Kind != Other.Kind)
623 return false;
624
625 switch (Kind) {
626 default:
627 llvm_unreachable("Unexpected kind");
628 return false;
629 case Register:
630 return Reg.RegNum == Other.Reg.RegNum;
631 }
632 }
633};
634} // end anonymous namespace.
635
636#define GET_REGISTER_MATCHER
637#define GET_SUBTARGET_FEATURE_NAME
638#define GET_MATCHER_IMPLEMENTATION
639#define GET_MNEMONIC_SPELL_CHECKER
640#include "CSKYGenAsmMatcher.inc"
641
643 assert(Reg >= CSKY::F0_32 && Reg <= CSKY::F31_32 && "Invalid register");
644 return Reg - CSKY::F0_32 + CSKY::F0_64;
645}
646
647static std::string CSKYMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
648 unsigned VariantID = 0);
649
650bool CSKYAsmParser::generateImmOutOfRangeError(
652 const Twine &Msg = "immediate must be an integer in the range") {
653 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
654 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
655}
656
657bool CSKYAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
659 MCStreamer &Out,
660 uint64_t &ErrorInfo,
661 bool MatchingInlineAsm) {
662 MCInst Inst;
663 FeatureBitset MissingFeatures;
664
665 auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
666 MatchingInlineAsm);
667 switch (Result) {
668 default:
669 break;
670 case Match_Success:
671 return processInstruction(Inst, IDLoc, Operands, Out);
672 case Match_MissingFeature: {
673 assert(MissingFeatures.any() && "Unknown missing features!");
674 ListSeparator LS;
675 std::string Msg = "instruction requires the following: ";
676 for (unsigned Feature : MissingFeatures) {
677 Msg += LS;
678 Msg += getSubtargetFeatureName(Feature);
679 }
680 return Error(IDLoc, Msg);
681 }
682 case Match_MnemonicFail: {
683 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
684 std::string Suggestion =
685 CSKYMnemonicSpellCheck(((CSKYOperand &)*Operands[0]).getToken(), FBS);
686 return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
687 }
688 case Match_InvalidTiedOperand:
689 case Match_InvalidOperand: {
690 SMLoc ErrorLoc = IDLoc;
691 if (ErrorInfo != ~0U) {
692 if (ErrorInfo >= Operands.size())
693 return Error(ErrorLoc, "too few operands for instruction");
694
695 ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
696 if (ErrorLoc == SMLoc())
697 ErrorLoc = IDLoc;
698 }
699 return Error(ErrorLoc, "invalid operand for instruction");
700 }
701 }
702
703 // Handle the case when the error message is of specific type
704 // other than the generic Match_InvalidOperand, and the
705 // corresponding operand is missing.
706 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
707 SMLoc ErrorLoc = IDLoc;
708 if (ErrorInfo != ~0U && ErrorInfo >= Operands.size())
709 return Error(ErrorLoc, "too few operands for instruction");
710 }
711
712 switch (Result) {
713 default:
714 break;
715 case Match_InvalidSImm8:
716 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 7),
717 (1 << 7) - 1);
718 case Match_InvalidOImm3:
719 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 3));
720 case Match_InvalidOImm4:
721 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 4));
722 case Match_InvalidOImm5:
723 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5));
724 case Match_InvalidOImm6:
725 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6));
726 case Match_InvalidOImm8:
727 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 8));
728 case Match_InvalidOImm12:
729 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 12));
730 case Match_InvalidOImm16:
731 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 16));
732 case Match_InvalidUImm1:
733 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 1) - 1);
734 case Match_InvalidUImm2:
735 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
736 case Match_InvalidUImm3:
737 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
738 case Match_InvalidUImm4:
739 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
740 case Match_InvalidUImm5:
741 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
742 case Match_InvalidUImm6:
743 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
744 case Match_InvalidUImm7:
745 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);
746 case Match_InvalidUImm8:
747 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 8) - 1);
748 case Match_InvalidUImm12:
749 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1);
750 case Match_InvalidUImm16:
751 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 16) - 1);
752 case Match_InvalidUImm5Shift1:
753 return generateImmOutOfRangeError(
754 Operands, ErrorInfo, 0, (1 << 5) - 2,
755 "immediate must be a multiple of 2 bytes in the range");
756 case Match_InvalidUImm12Shift1:
757 return generateImmOutOfRangeError(
758 Operands, ErrorInfo, 0, (1 << 12) - 2,
759 "immediate must be a multiple of 2 bytes in the range");
760 case Match_InvalidUImm5Shift2:
761 return generateImmOutOfRangeError(
762 Operands, ErrorInfo, 0, (1 << 5) - 4,
763 "immediate must be a multiple of 4 bytes in the range");
764 case Match_InvalidUImm7Shift1:
765 return generateImmOutOfRangeError(
766 Operands, ErrorInfo, 0, (1 << 7) - 2,
767 "immediate must be a multiple of 2 bytes in the range");
768 case Match_InvalidUImm7Shift2:
769 return generateImmOutOfRangeError(
770 Operands, ErrorInfo, 0, (1 << 7) - 4,
771 "immediate must be a multiple of 4 bytes in the range");
772 case Match_InvalidUImm8Shift2:
773 return generateImmOutOfRangeError(
774 Operands, ErrorInfo, 0, (1 << 8) - 4,
775 "immediate must be a multiple of 4 bytes in the range");
776 case Match_InvalidUImm8Shift3:
777 return generateImmOutOfRangeError(
778 Operands, ErrorInfo, 0, (1 << 8) - 8,
779 "immediate must be a multiple of 8 bytes in the range");
780 case Match_InvalidUImm8Shift8:
781 return generateImmOutOfRangeError(
782 Operands, ErrorInfo, 0, (1 << 8) - 256,
783 "immediate must be a multiple of 256 bytes in the range");
784 case Match_InvalidUImm12Shift2:
785 return generateImmOutOfRangeError(
786 Operands, ErrorInfo, 0, (1 << 12) - 4,
787 "immediate must be a multiple of 4 bytes in the range");
788 case Match_InvalidCSKYSymbol: {
789 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
790 return Error(ErrorLoc, "operand must be a symbol name");
791 }
792 case Match_InvalidConstpool: {
793 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
794 return Error(ErrorLoc, "operand must be a constpool symbol name");
795 }
796 case Match_InvalidPSRFlag: {
797 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
798 return Error(ErrorLoc, "psrset operand is not valid");
799 }
800 case Match_InvalidRegSeq: {
801 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
802 return Error(ErrorLoc, "Register sequence is not valid");
803 }
804 case Match_InvalidRegOutOfRange: {
805 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
806 return Error(ErrorLoc, "register is out of range");
807 }
808 case Match_RequiresSameSrcAndDst: {
809 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
810 return Error(ErrorLoc, "src and dst operand must be same");
811 }
812 case Match_InvalidRegList: {
813 SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
814 return Error(ErrorLoc, "invalid register list");
815 }
816 }
817 LLVM_DEBUG(dbgs() << "Result = " << Result);
818 llvm_unreachable("Unknown match type detected!");
819}
820
821bool CSKYAsmParser::processLRW(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) {
822 Inst.setLoc(IDLoc);
823
824 unsigned Opcode;
825 MCOperand Op;
826 if (Inst.getOpcode() == CSKY::PseudoLRW16)
827 Opcode = CSKY::LRW16;
828 else
829 Opcode = CSKY::LRW32;
830
831 if (Inst.getOperand(1).isImm()) {
832 if (isUInt<8>(Inst.getOperand(1).getImm()) &&
833 Inst.getOperand(0).getReg() <= CSKY::R7) {
834 Opcode = CSKY::MOVI16;
835 } else if (getSTI().hasFeature(CSKY::HasE2) &&
836 isUInt<16>(Inst.getOperand(1).getImm())) {
837 Opcode = CSKY::MOVI32;
838 } else {
839 auto *Expr = getTargetStreamer().addConstantPoolEntry(
841 Inst.getLoc());
842 Inst.erase(std::prev(Inst.end()));
844 }
845 } else {
846 const MCExpr *AdjustExpr = nullptr;
847 if (const auto *CSKYExpr =
849 if (CSKYExpr->getSpecifier() == CSKY::S_TLSGD ||
850 CSKYExpr->getSpecifier() == CSKY::S_TLSIE ||
851 CSKYExpr->getSpecifier() == CSKY::S_TLSLDM) {
852 MCSymbol *Dot = getContext().createNamedTempSymbol();
853 Out.emitLabel(Dot);
854 AdjustExpr = MCSymbolRefExpr::create(Dot, getContext());
855 }
856 }
857 auto *Expr = getTargetStreamer().addConstantPoolEntry(
858 Inst.getOperand(1).getExpr(), Inst.getLoc(), AdjustExpr);
859 Inst.erase(std::prev(Inst.end()));
861 }
862
863 Inst.setOpcode(Opcode);
864
865 Out.emitInstruction(Inst, getSTI());
866 return false;
867}
868
869bool CSKYAsmParser::processJSRI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) {
870 Inst.setLoc(IDLoc);
871
872 if (Inst.getOperand(0).isImm()) {
873 const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
875 Inst.getLoc());
876 Inst.setOpcode(CSKY::JSRI32);
877 Inst.erase(std::prev(Inst.end()));
879 } else {
880 const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
881 Inst.getOperand(0).getExpr(), Inst.getLoc());
882 Inst.setOpcode(CSKY::JBSR32);
884 }
885
886 Out.emitInstruction(Inst, getSTI());
887 return false;
888}
889
890bool CSKYAsmParser::processJMPI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) {
891 Inst.setLoc(IDLoc);
892
893 if (Inst.getOperand(0).isImm()) {
894 const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
896 Inst.getLoc());
897 Inst.setOpcode(CSKY::JMPI32);
898 Inst.erase(std::prev(Inst.end()));
900 } else {
901 const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
902 Inst.getOperand(0).getExpr(), Inst.getLoc());
903 Inst.setOpcode(CSKY::JBR32);
905 }
906
907 Out.emitInstruction(Inst, getSTI());
908 return false;
909}
910
911bool CSKYAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
913 MCStreamer &Out) {
914
915 switch (Inst.getOpcode()) {
916 default:
917 break;
918 case CSKY::LDQ32:
919 case CSKY::STQ32:
920 if (Inst.getOperand(1).getReg() != CSKY::R4 ||
921 Inst.getOperand(2).getReg() != CSKY::R7) {
922 return Error(IDLoc, "Register sequence is not valid. 'r4-r7' expected");
923 }
924 Inst.setOpcode(Inst.getOpcode() == CSKY::LDQ32 ? CSKY::LDM32 : CSKY::STM32);
925 break;
926 case CSKY::SEXT32:
927 case CSKY::ZEXT32:
928 if (Inst.getOperand(2).getImm() < Inst.getOperand(3).getImm())
929 return Error(IDLoc, "msb must be greater or equal to lsb");
930 break;
931 case CSKY::INS32:
932 if (Inst.getOperand(3).getImm() < Inst.getOperand(4).getImm())
933 return Error(IDLoc, "msb must be greater or equal to lsb");
934 break;
935 case CSKY::IDLY32:
936 if (Inst.getOperand(0).getImm() > 32 || Inst.getOperand(0).getImm() < 0)
937 return Error(IDLoc, "n must be in range [0,32]");
938 break;
939 case CSKY::ADDC32:
940 case CSKY::SUBC32:
941 case CSKY::ADDC16:
942 case CSKY::SUBC16:
943 Inst.erase(std::next(Inst.begin()));
944 Inst.erase(std::prev(Inst.end()));
945 Inst.insert(std::next(Inst.begin()), MCOperand::createReg(CSKY::C));
946 Inst.insert(Inst.end(), MCOperand::createReg(CSKY::C));
947 break;
948 case CSKY::CMPNEI32:
949 case CSKY::CMPNEI16:
950 case CSKY::CMPNE32:
951 case CSKY::CMPNE16:
952 case CSKY::CMPHSI32:
953 case CSKY::CMPHSI16:
954 case CSKY::CMPHS32:
955 case CSKY::CMPHS16:
956 case CSKY::CMPLTI32:
957 case CSKY::CMPLTI16:
958 case CSKY::CMPLT32:
959 case CSKY::CMPLT16:
960 case CSKY::BTSTI32:
961 Inst.erase(Inst.begin());
962 Inst.insert(Inst.begin(), MCOperand::createReg(CSKY::C));
963 break;
964 case CSKY::MVCV32:
965 Inst.erase(std::next(Inst.begin()));
966 Inst.insert(Inst.end(), MCOperand::createReg(CSKY::C));
967 break;
968 case CSKY::PseudoLRW16:
969 case CSKY::PseudoLRW32:
970 return processLRW(Inst, IDLoc, Out);
971 case CSKY::PseudoJSRI32:
972 return processJSRI(Inst, IDLoc, Out);
973 case CSKY::PseudoJMPI32:
974 return processJMPI(Inst, IDLoc, Out);
975 case CSKY::JBSR32:
976 case CSKY::JBR16:
977 case CSKY::JBT16:
978 case CSKY::JBF16:
979 case CSKY::JBR32:
980 case CSKY::JBT32:
981 case CSKY::JBF32:
982 unsigned Num = Inst.getNumOperands() - 1;
983 assert(Inst.getOperand(Num).isExpr());
984
985 const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
986 Inst.getOperand(Num).getExpr(), Inst.getLoc());
987
989 break;
990 }
991
992 emitToStreamer(Out, Inst);
993 return false;
994}
995
996// Attempts to match Name as a register (either using the default name or
997// alternative ABI names), setting RegNo to the matching register. Upon
998// failure, returns true and sets RegNo to 0.
1000 StringRef Name) {
1001 Reg = MatchRegisterName(Name);
1002
1003 if (Reg == CSKY::NoRegister)
1004 Reg = MatchRegisterAltName(Name);
1005
1006 return Reg == CSKY::NoRegister;
1007}
1008
1009bool CSKYAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
1010 SMLoc &EndLoc) {
1011 const AsmToken &Tok = getParser().getTok();
1012 StartLoc = Tok.getLoc();
1013 EndLoc = Tok.getEndLoc();
1014 StringRef Name = getLexer().getTok().getIdentifier();
1015
1016 if (!matchRegisterNameHelper(getSTI(), Reg, Name)) {
1017 getParser().Lex(); // Eat identifier token.
1018 return false;
1019 }
1020
1021 return true;
1022}
1023
1024ParseStatus CSKYAsmParser::parseRegister(OperandVector &Operands) {
1025 SMLoc S = getLoc();
1026 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1027
1028 switch (getLexer().getKind()) {
1029 default:
1030 return ParseStatus::NoMatch;
1031 case AsmToken::Identifier: {
1032 StringRef Name = getLexer().getTok().getIdentifier();
1033 MCRegister Reg;
1034
1035 if (matchRegisterNameHelper(getSTI(), Reg, Name))
1036 return ParseStatus::NoMatch;
1037
1038 getLexer().Lex();
1039 Operands.push_back(CSKYOperand::createReg(Reg, S, E));
1040
1041 return ParseStatus::Success;
1042 }
1043 }
1044}
1045
1046ParseStatus CSKYAsmParser::parseBaseRegImm(OperandVector &Operands) {
1047 assert(getLexer().is(AsmToken::LParen));
1048
1049 Operands.push_back(CSKYOperand::createToken("(", getLoc()));
1050
1051 auto Tok = getParser().Lex(); // Eat '('
1052
1053 if (!parseRegister(Operands).isSuccess()) {
1054 getLexer().UnLex(Tok);
1055 Operands.pop_back();
1056 return ParseStatus::NoMatch;
1057 }
1058
1059 if (getLexer().is(AsmToken::RParen)) {
1060 Operands.push_back(CSKYOperand::createToken(")", getLoc()));
1061 getParser().Lex(); // Eat ')'
1062 return ParseStatus::Success;
1063 }
1064
1065 if (getLexer().isNot(AsmToken::Comma))
1066 return Error(getLoc(), "expected ','");
1067
1068 getParser().Lex(); // Eat ','
1069
1070 if (parseRegister(Operands).isSuccess()) {
1071 if (getLexer().isNot(AsmToken::LessLess))
1072 return Error(getLoc(), "expected '<<'");
1073
1074 Operands.push_back(CSKYOperand::createToken("<<", getLoc()));
1075
1076 getParser().Lex(); // Eat '<<'
1077
1078 if (!parseImmediate(Operands).isSuccess())
1079 return Error(getLoc(), "expected imm");
1080
1081 } else if (!parseImmediate(Operands).isSuccess()) {
1082 return Error(getLoc(), "expected imm");
1083 }
1084
1085 if (getLexer().isNot(AsmToken::RParen))
1086 return Error(getLoc(), "expected ')'");
1087
1088 Operands.push_back(CSKYOperand::createToken(")", getLoc()));
1089
1090 getParser().Lex(); // Eat ')'
1091
1092 return ParseStatus::Success;
1093}
1094
1095ParseStatus CSKYAsmParser::parseImmediate(OperandVector &Operands) {
1096 switch (getLexer().getKind()) {
1097 default:
1098 return ParseStatus::NoMatch;
1099 case AsmToken::LParen:
1100 case AsmToken::Minus:
1101 case AsmToken::Plus:
1102 case AsmToken::Integer:
1103 case AsmToken::String:
1104 break;
1105 }
1106
1107 const MCExpr *IdVal;
1108 SMLoc S = getLoc();
1109 if (getParser().parseExpression(IdVal))
1110 return Error(getLoc(), "unknown expression");
1111
1112 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1113 Operands.push_back(CSKYOperand::createImm(IdVal, S, E));
1114 return ParseStatus::Success;
1115}
1116
1117/// Looks at a token type and creates the relevant operand from this
1118/// information, adding to Operands. If operand was parsed, returns false, else
1119/// true.
1120bool CSKYAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1121 // Check if the current operand has a custom associated parser, if so, try to
1122 // custom parse the operand, or fallback to the general approach.
1123 ParseStatus Result =
1124 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
1125 if (Result.isSuccess())
1126 return false;
1127 if (Result.isFailure())
1128 return true;
1129
1130 // Attempt to parse token as register
1131 auto Res = parseRegister(Operands);
1132 if (Res.isSuccess())
1133 return false;
1134 if (Res.isFailure())
1135 return true;
1136
1137 // Attempt to parse token as (register, imm)
1138 if (getLexer().is(AsmToken::LParen)) {
1139 Res = parseBaseRegImm(Operands);
1140 if (Res.isSuccess())
1141 return false;
1142 if (Res.isFailure())
1143 return true;
1144 }
1145
1146 Res = parseImmediate(Operands);
1147 if (Res.isSuccess())
1148 return false;
1149 if (Res.isFailure())
1150 return true;
1151
1152 // Finally we have exhausted all options and must declare defeat.
1153 Error(getLoc(), "unknown operand");
1154 return true;
1155}
1156
1157ParseStatus CSKYAsmParser::parseCSKYSymbol(OperandVector &Operands) {
1158 SMLoc S = getLoc();
1159 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1160 const MCExpr *Res;
1161
1162 if (getLexer().getKind() != AsmToken::Identifier)
1163 return ParseStatus::NoMatch;
1164
1165 StringRef Identifier;
1166 AsmToken Tok = getLexer().getTok();
1167
1168 if (getParser().parseIdentifier(Identifier))
1169 return Error(getLoc(), "unknown identifier");
1170
1172 if (Identifier.consume_back("@GOT"))
1173 Kind = CSKY::S_GOT;
1174 else if (Identifier.consume_back("@GOTOFF"))
1176 else if (Identifier.consume_back("@PLT"))
1177 Kind = CSKY::S_PLT;
1178 else if (Identifier.consume_back("@GOTPC"))
1180 else if (Identifier.consume_back("@TLSGD32"))
1182 else if (Identifier.consume_back("@GOTTPOFF"))
1184 else if (Identifier.consume_back("@TPOFF"))
1186 else if (Identifier.consume_back("@TLSLDM32"))
1188 else if (Identifier.consume_back("@TLSLDO32"))
1190
1191 MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier);
1192
1193 if (!Sym)
1194 Sym = getContext().getOrCreateSymbol(Identifier);
1195
1196 if (Sym->isVariable()) {
1197 const MCExpr *V = Sym->getVariableValue();
1198 if (!isa<MCSymbolRefExpr>(V)) {
1199 getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1200 return Error(getLoc(), "unknown symbol");
1201 }
1202 Res = V;
1203 } else
1204 Res = MCSymbolRefExpr::create(Sym, getContext());
1205
1206 MCBinaryExpr::Opcode Opcode;
1207 switch (getLexer().getKind()) {
1208 default:
1209 if (Kind != CSKY::S_None)
1210 Res = MCSpecifierExpr::create(Res, Kind, getContext());
1211
1212 Operands.push_back(CSKYOperand::createImm(Res, S, E));
1213 return ParseStatus::Success;
1214 case AsmToken::Plus:
1215 Opcode = MCBinaryExpr::Add;
1216 break;
1217 case AsmToken::Minus:
1218 Opcode = MCBinaryExpr::Sub;
1219 break;
1220 }
1221
1222 getLexer().Lex(); // eat + or -
1223
1224 const MCExpr *Expr;
1225 if (getParser().parseExpression(Expr))
1226 return Error(getLoc(), "unknown expression");
1227 Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1228 Operands.push_back(CSKYOperand::createImm(Res, S, E));
1229 return ParseStatus::Success;
1230}
1231
1232ParseStatus CSKYAsmParser::parseDataSymbol(OperandVector &Operands) {
1233 SMLoc S = getLoc();
1234 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1235 const MCExpr *Res;
1236
1237 if (!parseOptionalToken(AsmToken::LBrac))
1238 return ParseStatus::NoMatch;
1239 if (getLexer().getKind() != AsmToken::Identifier) {
1240 const MCExpr *Expr;
1241 if (getParser().parseExpression(Expr))
1242 return Error(getLoc(), "unknown expression");
1243
1244 if (parseToken(AsmToken::RBrac, "expected ']'"))
1245 return ParseStatus::Failure;
1246
1247 Operands.push_back(CSKYOperand::createConstpoolOp(Expr, S, E));
1248 return ParseStatus::Success;
1249 }
1250
1251 AsmToken Tok = getLexer().getTok();
1252 StringRef Identifier;
1253
1254 if (getParser().parseIdentifier(Identifier))
1255 return Error(getLoc(), "unknown identifier " + Identifier);
1256
1258 if (Identifier.consume_back("@GOT"))
1260 else if (Identifier.consume_back("@PLT"))
1262
1263 MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier);
1264
1265 if (!Sym)
1266 Sym = getContext().getOrCreateSymbol(Identifier);
1267
1268 if (Sym->isVariable()) {
1269 const MCExpr *V = Sym->getVariableValue();
1270 if (!isa<MCSymbolRefExpr>(V)) {
1271 getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1272 return Error(getLoc(), "unknown symbol");
1273 }
1274 Res = V;
1275 } else {
1276 Res = MCSymbolRefExpr::create(Sym, getContext());
1277 }
1278
1279 MCBinaryExpr::Opcode Opcode;
1280 switch (getLexer().getKind()) {
1281 default:
1282 return Error(getLoc(), "unknown symbol");
1283 case AsmToken::RBrac:
1284
1285 getLexer().Lex(); // Eat ']'.
1286
1287 if (Kind != CSKY::S_None)
1288 Res = MCSpecifierExpr::create(Res, Kind, getContext());
1289
1290 Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1291 return ParseStatus::Success;
1292 case AsmToken::Plus:
1293 Opcode = MCBinaryExpr::Add;
1294 break;
1295 case AsmToken::Minus:
1296 Opcode = MCBinaryExpr::Sub;
1297 break;
1298 }
1299
1300 getLexer().Lex(); // eat + or -
1301
1302 const MCExpr *Expr;
1303 if (getParser().parseExpression(Expr))
1304 return Error(getLoc(), "unknown expression");
1305 if (parseToken(AsmToken::RBrac, "expected ']'"))
1306 return ParseStatus::Failure;
1307
1308 Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1309 Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1310 return ParseStatus::Success;
1311}
1312
1313ParseStatus CSKYAsmParser::parseConstpoolSymbol(OperandVector &Operands) {
1314 SMLoc S = getLoc();
1315 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1316 const MCExpr *Res;
1317
1318 if (!parseOptionalToken(AsmToken::LBrac))
1319 return ParseStatus::NoMatch;
1320
1321 if (getLexer().getKind() != AsmToken::Identifier) {
1322 const MCExpr *Expr;
1323 if (getParser().parseExpression(Expr))
1324 return Error(getLoc(), "unknown expression");
1325 if (parseToken(AsmToken::RBrac))
1326 return ParseStatus::Failure;
1327
1328 Operands.push_back(CSKYOperand::createConstpoolOp(Expr, S, E));
1329 return ParseStatus::Success;
1330 }
1331
1332 AsmToken Tok = getLexer().getTok();
1333 StringRef Identifier;
1334
1335 if (getParser().parseIdentifier(Identifier))
1336 return Error(getLoc(), "unknown identifier");
1337
1338 MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier);
1339
1340 if (!Sym)
1341 Sym = getContext().getOrCreateSymbol(Identifier);
1342
1343 if (Sym->isVariable()) {
1344 const MCExpr *V = Sym->getVariableValue();
1345 if (!isa<MCSymbolRefExpr>(V)) {
1346 getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1347 return Error(getLoc(), "unknown symbol");
1348 }
1349 Res = V;
1350 } else {
1351 Res = MCSymbolRefExpr::create(Sym, getContext());
1352 }
1353
1354 MCBinaryExpr::Opcode Opcode;
1355 switch (getLexer().getKind()) {
1356 default:
1357 return Error(getLoc(), "unknown symbol");
1358 case AsmToken::RBrac:
1359
1360 getLexer().Lex(); // Eat ']'.
1361
1362 Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1363 return ParseStatus::Success;
1364 case AsmToken::Plus:
1365 Opcode = MCBinaryExpr::Add;
1366 break;
1367 case AsmToken::Minus:
1368 Opcode = MCBinaryExpr::Sub;
1369 break;
1370 }
1371
1372 getLexer().Lex(); // eat + or -
1373
1374 const MCExpr *Expr;
1375 if (getParser().parseExpression(Expr))
1376 return Error(getLoc(), "unknown expression");
1377 if (parseToken(AsmToken::RBrac, "expected ']'"))
1378 return ParseStatus::Failure;
1379
1380 Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1381 Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1382 return ParseStatus::Success;
1383}
1384
1385ParseStatus CSKYAsmParser::parsePSRFlag(OperandVector &Operands) {
1386 SMLoc S = getLoc();
1387 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1388
1389 unsigned Flag = 0;
1390
1391 while (getLexer().isNot(AsmToken::EndOfStatement)) {
1392 StringRef Identifier;
1393 if (getParser().parseIdentifier(Identifier))
1394 return Error(getLoc(), "unknown identifier " + Identifier);
1395
1396 if (Identifier == "sie")
1397 Flag = (1 << 4) | Flag;
1398 else if (Identifier == "ee")
1399 Flag = (1 << 3) | Flag;
1400 else if (Identifier == "ie")
1401 Flag = (1 << 2) | Flag;
1402 else if (Identifier == "fe")
1403 Flag = (1 << 1) | Flag;
1404 else if (Identifier == "af")
1405 Flag = (1 << 0) | Flag;
1406 else
1407 return Error(getLoc(), "expected " + Identifier);
1408
1409 if (getLexer().is(AsmToken::EndOfStatement))
1410 break;
1411
1412 if (parseToken(AsmToken::Comma, "expected ','"))
1413 return ParseStatus::Failure;
1414 }
1415
1416 Operands.push_back(
1417 CSKYOperand::createImm(MCConstantExpr::create(Flag, getContext()), S, E));
1418 return ParseStatus::Success;
1419}
1420
1421ParseStatus CSKYAsmParser::parseRegSeq(OperandVector &Operands) {
1422 SMLoc S = getLoc();
1423
1424 if (!parseRegister(Operands).isSuccess())
1425 return ParseStatus::NoMatch;
1426
1427 auto Ry = Operands.back()->getReg();
1428 Operands.pop_back();
1429
1430 if (parseToken(AsmToken::Minus, "expected '-'"))
1431 return ParseStatus::Failure;
1432 if (!parseRegister(Operands).isSuccess())
1433 return Error(getLoc(), "invalid register");
1434
1435 auto Rz = Operands.back()->getReg();
1436 Operands.pop_back();
1437
1438 Operands.push_back(CSKYOperand::createRegSeq(Ry, Rz, S));
1439 return ParseStatus::Success;
1440}
1441
1442ParseStatus CSKYAsmParser::parseRegList(OperandVector &Operands) {
1443 SMLoc S = getLoc();
1445 while (true) {
1446
1447 if (!parseRegister(Operands).isSuccess())
1448 return Error(getLoc(), "invalid register");
1449
1450 auto Ry = Operands.back()->getReg();
1451 Operands.pop_back();
1452
1453 if (parseOptionalToken(AsmToken::Minus)) {
1454 if (!parseRegister(Operands).isSuccess())
1455 return Error(getLoc(), "invalid register");
1456
1457 auto Rz = Operands.back()->getReg();
1458 Operands.pop_back();
1459
1460 reglist.push_back(Ry);
1461 reglist.push_back(Rz);
1462
1463 if (getLexer().is(AsmToken::EndOfStatement))
1464 break;
1465 (void)parseOptionalToken(AsmToken::Comma);
1466 } else if (parseOptionalToken(AsmToken::Comma)) {
1467 reglist.push_back(Ry);
1468 reglist.push_back(Ry);
1469 } else if (getLexer().is(AsmToken::EndOfStatement)) {
1470 reglist.push_back(Ry);
1471 reglist.push_back(Ry);
1472 break;
1473 } else {
1474 return Error(getLoc(), "invalid register list");
1475 }
1476 }
1477
1478 Operands.push_back(CSKYOperand::createRegList(reglist, S));
1479 return ParseStatus::Success;
1480}
1481
1482bool CSKYAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,
1483 SMLoc NameLoc, OperandVector &Operands) {
1484 // First operand is token for instruction.
1485 Operands.push_back(CSKYOperand::createToken(Name, NameLoc));
1486
1487 // If there are no more operands, then finish.
1488 if (getLexer().is(AsmToken::EndOfStatement))
1489 return false;
1490
1491 // Parse first operand.
1492 if (parseOperand(Operands, Name))
1493 return true;
1494
1495 // Parse until end of statement, consuming commas between operands.
1496 while (parseOptionalToken(AsmToken::Comma))
1497 if (parseOperand(Operands, Name))
1498 return true;
1499
1500 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1501 SMLoc Loc = getLexer().getLoc();
1502 getParser().eatToEndOfStatement();
1503 return Error(Loc, "unexpected token");
1504 }
1505
1506 getParser().Lex(); // Consume the EndOfStatement.
1507 return false;
1508}
1509
1510ParseStatus CSKYAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1511 SMLoc &EndLoc) {
1512 const AsmToken &Tok = getParser().getTok();
1513 StartLoc = Tok.getLoc();
1514 EndLoc = Tok.getEndLoc();
1515
1516 StringRef Name = getLexer().getTok().getIdentifier();
1517
1518 if (matchRegisterNameHelper(getSTI(), Reg, Name))
1519 return ParseStatus::NoMatch;
1520
1521 getParser().Lex(); // Eat identifier token.
1522 return ParseStatus::Success;
1523}
1524
1525ParseStatus CSKYAsmParser::parseDirective(AsmToken DirectiveID) {
1526 StringRef IDVal = DirectiveID.getString();
1527
1528 if (IDVal == ".csky_attribute")
1529 return parseDirectiveAttribute();
1530
1531 return ParseStatus::NoMatch;
1532}
1533
1534/// parseDirectiveAttribute
1535/// ::= .attribute expression ',' ( expression | "string" )
1536bool CSKYAsmParser::parseDirectiveAttribute() {
1537 MCAsmParser &Parser = getParser();
1538 int64_t Tag;
1539 SMLoc TagLoc;
1540 TagLoc = Parser.getTok().getLoc();
1541 if (Parser.getTok().is(AsmToken::Identifier)) {
1542 StringRef Name = Parser.getTok().getIdentifier();
1543 std::optional<unsigned> Ret =
1545 if (!Ret)
1546 return Error(TagLoc, "attribute name not recognised: " + Name);
1547 Tag = *Ret;
1548 Parser.Lex();
1549 } else {
1550 const MCExpr *AttrExpr;
1551
1552 TagLoc = Parser.getTok().getLoc();
1553 if (Parser.parseExpression(AttrExpr))
1554 return true;
1555
1556 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
1557 if (!CE)
1558 return Error(TagLoc, "expected numeric constant");
1559
1560 Tag = CE->getValue();
1561 }
1562
1563 if (Parser.parseComma())
1564 return true;
1565
1566 StringRef StringValue;
1567 int64_t IntegerValue = 0;
1568 bool IsIntegerValue = ((Tag != CSKYAttrs::CSKY_ARCH_NAME) &&
1571
1572 SMLoc ValueExprLoc = Parser.getTok().getLoc();
1573 if (IsIntegerValue) {
1574 const MCExpr *ValueExpr;
1575 if (Parser.parseExpression(ValueExpr))
1576 return true;
1577
1578 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
1579 if (!CE)
1580 return Error(ValueExprLoc, "expected numeric constant");
1581 IntegerValue = CE->getValue();
1582 } else {
1583 if (Parser.getTok().isNot(AsmToken::String))
1584 return Error(Parser.getTok().getLoc(), "expected string constant");
1585
1586 StringValue = Parser.getTok().getStringContents();
1587 Parser.Lex();
1588 }
1589
1590 if (Parser.parseEOL())
1591 return true;
1592
1593 if (IsIntegerValue)
1594 getTargetStreamer().emitAttribute(Tag, IntegerValue);
1596 getTargetStreamer().emitTextAttribute(Tag, StringValue);
1597 else {
1599 ? CSKY::parseArch(StringValue)
1600 : CSKY::parseCPUArch(StringValue);
1601 if (ID == CSKY::ArchKind::INVALID)
1602 return Error(ValueExprLoc, (Tag == CSKYAttrs::CSKY_ARCH_NAME)
1603 ? "unknown arch name"
1604 : "unknown cpu name");
1605
1606 getTargetStreamer().emitTextAttribute(Tag, StringValue);
1607 }
1608
1609 return false;
1610}
1611
1612unsigned CSKYAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
1613 unsigned Kind) {
1614 CSKYOperand &Op = static_cast<CSKYOperand &>(AsmOp);
1615
1616 if (!Op.isReg())
1617 return Match_InvalidOperand;
1618
1619 MCRegister Reg = Op.getReg();
1620
1621 if (getCSKYMCRegisterClass(CSKY::FPR32RegClassID).contains(Reg)) {
1622 // As the parser couldn't differentiate an FPR64 from an FPR32, coerce the
1623 // register from FPR32 to FPR64 if necessary.
1624 if (Kind == MCK_FPR64 || Kind == MCK_sFPR64) {
1625 Op.Reg.RegNum = convertFPR32ToFPR64(Reg);
1626 if (Kind == MCK_sFPR64 &&
1627 (Op.Reg.RegNum < CSKY::F0_64 || Op.Reg.RegNum > CSKY::F15_64))
1628 return Match_InvalidRegOutOfRange;
1629 if (Kind == MCK_FPR64 &&
1630 (Op.Reg.RegNum < CSKY::F0_64 || Op.Reg.RegNum > CSKY::F31_64))
1631 return Match_InvalidRegOutOfRange;
1632 return Match_Success;
1633 }
1634 }
1635
1636 if (getCSKYMCRegisterClass(CSKY::GPRRegClassID).contains(Reg)) {
1637 if (Kind == MCK_GPRPair) {
1638 Op.Reg.RegNum = MRI->getEncodingValue(Reg) + CSKY::R0_R1;
1639 return Match_Success;
1640 }
1641 }
1642
1643 return Match_InvalidOperand;
1644}
1645
1646void CSKYAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
1647 MCInst CInst;
1648 bool Res = false;
1649 if (CLOpts.asm_compressed_inst)
1650 Res = compressInst(CInst, Inst, getSTI());
1651 if (Res)
1652 ++CSKYNumInstrsCompressed;
1653 S.emitInstruction((Res ? CInst : Inst), getSTI());
1654}
1655
static MCRegister MatchRegisterName(StringRef Name)
static const char * getSubtargetFeatureName(uint64_t Val)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
uint64_t Imm
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static bool matchRegisterNameHelper(const MCSubtargetInfo &STI, MCRegister &Reg, StringRef Name)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYAsmParser()
static MCRegister convertFPR32ToFPR64(MCRegister Reg)
static std::string CSKYMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS, unsigned VariantID=0)
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
#define RegName(no)
static bool hasFeature(StringRef Feature, const FeatureBitset &FeatureBits, ArrayRef< SubtargetFeatureKV > ProcFeatures)
Register Reg
#define T
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
static bool isUImm2(const MachineOperand &MO)
SI Fold Operands
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
const char * Msg
This file contains some templates that are useful if you are working with the STL at all.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:480
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
This file contains some functions that are useful when dealing with strings.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
#define LLVM_DEBUG(...)
Definition Debug.h:119
bool parseImmediate(MCInst &MI, uint64_t &Size, ArrayRef< uint8_t > Bytes)
LLVM_ABI SMLoc getLoc() const
Definition AsmLexer.cpp:31
bool isNot(TokenKind K) const
Definition MCAsmMacro.h:76
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition MCAsmMacro.h:103
StringRef getStringContents() const
Get the contents of a string token (without quotes).
Definition MCAsmMacro.h:83
bool is(TokenKind K) const
Definition MCAsmMacro.h:75
LLVM_ABI SMLoc getEndLoc() const
Definition AsmLexer.cpp:33
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
Definition MCAsmMacro.h:92
static const char * getRegisterName(const CSKYMCOptions &CLOpts, MCRegister Reg)
Base class for user error types.
Definition Error.h:354
Container class for subtarget features.
void printExpr(raw_ostream &, const MCExpr &) const
const MCTargetOptions & getTargetOptions() const
Definition MCAsmInfo.h:451
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression.
const AsmToken & getTok() const
Get the current AsmToken from the stream.
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:201
@ Sub
Subtraction.
Definition MCExpr.h:323
@ Add
Addition.
Definition MCExpr.h:301
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
void erase(iterator I)
Definition MCInst.h:224
unsigned getNumOperands() const
Definition MCInst.h:212
SMLoc getLoc() const
Definition MCInst.h:208
void setLoc(SMLoc loc)
Definition MCInst.h:207
unsigned getOpcode() const
Definition MCInst.h:202
iterator insert(iterator I, const MCOperand &Op)
Definition MCInst.h:232
void addOperand(const MCOperand Op)
Definition MCInst.h:215
iterator begin()
Definition MCInst.h:227
iterator end()
Definition MCInst.h:229
void setOpcode(unsigned Op)
Definition MCInst.h:201
const MCOperand & getOperand(unsigned i) const
Definition MCInst.h:210
static MCOperand createExpr(const MCExpr *Val)
Definition MCInst.h:166
int64_t getImm() const
Definition MCInst.h:84
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
bool isImm() const
Definition MCInst.h:66
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
const MCExpr * getExpr() const
Definition MCInst.h:118
bool isExpr() const
Definition MCInst.h:69
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
uint16_t getEncodingValue(MCRegister Reg) const
Returns the encoding for Reg.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:743
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
Generic base class for all target subtargets.
const FeatureBitset & getFeatureBits() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
bool isVariable() const
isVariable - Check if this is a variable symbol.
Definition MCSymbol.h:267
const MCExpr * getVariableValue() const
Get the expression of the variable symbol.
Definition MCSymbol.h:270
MCTargetAsmParser - Generic interface to target specific assembly parsers.
Ternary parse status returned by various parse* methods.
static constexpr StatusTy Failure
static constexpr StatusTy Success
static constexpr StatusTy NoMatch
Represents a location in source code.
Definition SMLoc.h:22
static SMLoc getFromPointer(const char *Ptr)
Definition SMLoc.h:35
constexpr const char * getPointer() const
Definition SMLoc.h:33
void push_back(const T &Elt)
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const AArch64MCOptions & getCLOpts(const MCTargetOptions &Options)
LLVM_ABI const TagNameMap & getCSKYAttributeTags()
const CSKYMCOptions & getCLOpts(const MCTargetOptions &Options)
uint8_t Specifier
LLVM_ABI ArchKind parseCPUArch(StringRef CPU)
LLVM_ABI ArchKind parseArch(StringRef Arch)
LLVM_ABI std::optional< unsigned > attrTypeFromString(StringRef tag, TagNameMap tagNameMap)
Flag
These should be considered private to the implementation of the MCInstrDesc class.
@ CE
Windows NT (Windows on ARM)
Definition MCAsmInfo.h:51
This is an optimization pass for GlobalISel generic memory operations.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
static bool isMem(const MachineInstr &MI, unsigned Op)
LLVM_ABI std::pair< StringRef, StringRef > getToken(StringRef Source, StringRef Delimiters=" \t\n\v\f\r")
getToken - This function extracts one token from source, ignoring any leading characters that appear ...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
SmallVectorImpl< std::unique_ptr< MCParsedAsmOperand > > OperandVector
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
Target & getTheCSKYTarget()
@ Other
Any other memory.
Definition ModRef.h:68
DWARFExpression::Operation Op
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
Definition MathExtras.h:183
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
Definition MathExtras.h:199
#define N
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...