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