LLVM 22.0.0git
LoongArchAsmParser.cpp
Go to the documentation of this file.
1// LoongArchAsmParser.cpp - Parse LoongArch 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
17#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCInstrInfo.h"
24#include "llvm/MC/MCStreamer.h"
26#include "llvm/MC/MCValue.h"
30
31using namespace llvm;
32
33#define DEBUG_TYPE "loongarch-asm-parser"
34
35namespace {
36class LoongArchAsmParser : public MCTargetAsmParser {
37 SmallVector<FeatureBitset, 4> FeatureBitStack;
38
39 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
40 bool is64Bit() const { return getSTI().hasFeature(LoongArch::Feature64Bit); }
41 LoongArchTargetStreamer &getTargetStreamer() {
42 assert(getParser().getStreamer().getTargetStreamer() &&
43 "do not have a target streamer");
44 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
45 return static_cast<LoongArchTargetStreamer &>(TS);
46 }
47
48 struct Inst {
49 unsigned Opc;
50 uint16_t Specifier;
51 Inst(unsigned Opc, uint16_t VK = 0) : Opc(Opc), Specifier(VK) {}
52 };
53 using InstSeq = SmallVector<Inst>;
54
55 /// Parse a register as used in CFI directives.
56 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
57 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
58 SMLoc &EndLoc) override;
59
60 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
61 SMLoc NameLoc, OperandVector &Operands) override;
62
63 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
66 bool MatchingInlineAsm) override;
67
68 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
69
70 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
71 unsigned Kind) override;
72
73 ParseStatus parseDirective(AsmToken DirectiveID) override;
74
75 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
76 int64_t Lower, int64_t Upper,
77 const Twine &Msg);
78
79 /// Helper for processing MC instructions that have been successfully matched
80 /// by matchAndEmitInstruction.
81 bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
82 MCStreamer &Out);
83
84// Auto-generated instruction matching functions.
85#define GET_ASSEMBLER_HEADER
86#include "LoongArchGenAsmMatcher.inc"
87
88 ParseStatus parseRegister(OperandVector &Operands);
90 ParseStatus parseOperandWithModifier(OperandVector &Operands);
91 ParseStatus parseSImm26Operand(OperandVector &Operands);
92 ParseStatus parseAtomicMemOp(OperandVector &Operands);
93
94 bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
95
96 bool parseDirectiveOption();
97
98 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
99 if (!(getSTI().hasFeature(Feature))) {
100 MCSubtargetInfo &STI = copySTI();
101 setAvailableFeatures(
102 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
103 }
104 }
105
106 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
107 if (getSTI().hasFeature(Feature)) {
108 MCSubtargetInfo &STI = copySTI();
109 setAvailableFeatures(
110 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
111 }
112 }
113
114 void pushFeatureBits() {
115 FeatureBitStack.push_back(getSTI().getFeatureBits());
116 }
117
118 bool popFeatureBits() {
119 if (FeatureBitStack.empty())
120 return true;
121
122 FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
123 copySTI().setFeatureBits(FeatureBits);
124 setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));
125
126 return false;
127 }
128
129 // Helper to emit the sequence of instructions generated by the
130 // "emitLoadAddress*" functions.
131 void emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
132 const MCExpr *Symbol, SmallVectorImpl<Inst> &Insts,
133 SMLoc IDLoc, MCStreamer &Out, bool RelaxHint = false);
134
135 // Helper to emit pseudo instruction "la.abs $rd, sym".
136 void emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
137
138 // Helper to emit pseudo instruction "la.pcrel $rd, sym".
139 void emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
140 // Helper to emit pseudo instruction "la.pcrel $rd, $rj, sym".
141 void emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
142
143 // Helper to emit pseudo instruction "la.got $rd, sym".
144 void emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
145 // Helper to emit pseudo instruction "la.got $rd, $rj, sym".
146 void emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
147
148 // Helper to emit pseudo instruction "la.tls.le $rd, sym".
149 void emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
150
151 // Helper to emit pseudo instruction "la.tls.ie $rd, sym".
152 void emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
153 // Helper to emit pseudo instruction "la.tls.ie $rd, $rj, sym".
154 void emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
155
156 // Helper to emit pseudo instruction "la.tls.ld $rd, sym".
157 void emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
158 // Helper to emit pseudo instruction "la.tls.ld $rd, $rj, sym".
159 void emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
160
161 // Helper to emit pseudo instruction "la.tls.gd $rd, sym".
162 void emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
163 // Helper to emit pseudo instruction "la.tls.gd $rd, $rj, sym".
164 void emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
165
166 // Helper to emit pseudo instruction "la.tls.desc $rd, sym".
167 void emitLoadAddressTLSDesc(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
168 // Helper to emit pseudo instruction "la.tls.desc $rd, $rj, sym".
169 void emitLoadAddressTLSDescLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
170
171 // Helper to emit pseudo instruction "li.w/d $rd, $imm".
172 void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
173
174 // Helper to emit pseudo instruction "call36 sym" or "tail36 $rj, sym".
175 void emitFuncCall36(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
176 bool IsTailCall);
177
178public:
179 enum LoongArchMatchResultTy {
180 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
181 Match_RequiresMsbNotLessThanLsb,
182 Match_RequiresOpnd2NotR0R1,
183 Match_RequiresAMORdDifferRkRj,
184 Match_RequiresLAORdDifferRj,
185 Match_RequiresLAORdR4,
186#define GET_OPERAND_DIAGNOSTIC_TYPES
187#include "LoongArchGenAsmMatcher.inc"
188#undef GET_OPERAND_DIAGNOSTIC_TYPES
189 };
190
191 static bool classifySymbolRef(const MCExpr *Expr,
193
194 LoongArchAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
195 const MCInstrInfo &MII, const MCTargetOptions &Options)
196 : MCTargetAsmParser(Options, STI, MII) {
197 Parser.addAliasForDirective(".half", ".2byte");
198 Parser.addAliasForDirective(".hword", ".2byte");
199 Parser.addAliasForDirective(".word", ".4byte");
200 Parser.addAliasForDirective(".dword", ".8byte");
201
202 // Initialize the set of available features.
203 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
204 }
205};
206
207// Instances of this class represent a parsed LoongArch machine instruction.
208class LoongArchOperand : public MCParsedAsmOperand {
209 enum class KindTy {
210 Token,
211 Register,
212 Immediate,
213 } Kind;
214
215 struct RegOp {
216 MCRegister RegNum;
217 };
218
219 struct ImmOp {
220 const MCExpr *Val;
221 };
222
223 SMLoc StartLoc, EndLoc;
224 union {
225 StringRef Tok;
226 struct RegOp Reg;
227 struct ImmOp Imm;
228 };
229
230public:
231 LoongArchOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
232
233 bool isToken() const override { return Kind == KindTy::Token; }
234 bool isReg() const override { return Kind == KindTy::Register; }
235 bool isImm() const override { return Kind == KindTy::Immediate; }
236 bool isMem() const override { return false; }
237 void setReg(MCRegister PhysReg) { Reg.RegNum = PhysReg; }
238 bool isGPR() const {
239 return Kind == KindTy::Register &&
240 LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains(
241 Reg.RegNum);
242 }
243
244 static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
246 if (auto *LE = dyn_cast<LoongArchMCExpr>(Expr)) {
247 VK = LE->getSpecifier();
248 return false;
249 }
250
251 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
252 Imm = CE->getValue();
253 return true;
254 }
255
256 return false;
257 }
258
259 template <unsigned N, int P = 0> bool isUImm() const {
260 if (!isImm())
261 return false;
262
263 int64_t Imm;
265 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
266 return IsConstantImm && isUInt<N>(Imm - P) &&
268 }
269
270 template <unsigned N, unsigned S = 0> bool isSImm() const {
271 if (!isImm())
272 return false;
273
274 int64_t Imm;
276 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
277 return IsConstantImm && isShiftedInt<N, S>(Imm) &&
279 }
280
281 bool isBareSymbol() const {
282 int64_t Imm;
284 // Must be of 'immediate' type but not a constant.
285 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
286 return false;
287 return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
289 }
290
291 bool isTPRelAddSymbol() const {
292 int64_t Imm;
294 // Must be of 'immediate' type but not a constant.
295 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
296 return false;
297 return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
298 VK == ELF::R_LARCH_TLS_LE_ADD_R;
299 }
300
301 bool isUImm1() const { return isUImm<1>(); }
302 bool isUImm2() const { return isUImm<2>(); }
303 bool isUImm2plus1() const { return isUImm<2, 1>(); }
304 bool isUImm3() const { return isUImm<3>(); }
305 bool isUImm4() const { return isUImm<4>(); }
306 bool isSImm5() const { return isSImm<5>(); }
307 bool isUImm5() const { return isUImm<5>(); }
308 bool isUImm6() const { return isUImm<6>(); }
309 bool isUImm7() const { return isUImm<7>(); }
310 bool isSImm8() const { return isSImm<8>(); }
311 bool isSImm8lsl1() const { return isSImm<8, 1>(); }
312 bool isSImm8lsl2() const { return isSImm<8, 2>(); }
313 bool isSImm8lsl3() const { return isSImm<8, 3>(); }
314 bool isUImm8() const { return isUImm<8>(); }
315 bool isSImm9lsl3() const { return isSImm<9, 3>(); }
316 bool isSImm10() const { return isSImm<10>(); }
317 bool isSImm10lsl2() const { return isSImm<10, 2>(); }
318 bool isSImm11lsl1() const { return isSImm<11, 1>(); }
319 bool isSImm12() const { return isSImm<12>(); }
320
321 bool isSImm12addlike() const {
322 if (!isImm())
323 return false;
324
325 int64_t Imm;
327 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
328 bool IsValidKind =
329 VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_PCALA_LO12 ||
330 VK == ELF::R_LARCH_GOT_PC_LO12 || VK == ELF::R_LARCH_TLS_IE_PC_LO12 ||
331 VK == ELF::R_LARCH_TLS_LE_LO12_R ||
332 VK == ELF::R_LARCH_TLS_DESC_PC_LO12 || VK == ELF::R_LARCH_TLS_DESC_LD;
333 return IsConstantImm
334 ? isInt<12>(Imm) && IsValidKind
335 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
336 IsValidKind;
337 }
338
339 bool isSImm12lu52id() const {
340 if (!isImm())
341 return false;
342
343 int64_t Imm;
345 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
346 bool IsValidKind =
347 VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_ABS64_HI12 ||
348 VK == ELF::R_LARCH_PCALA64_HI12 || VK == ELF::R_LARCH_GOT64_HI12 ||
349 VK == ELF::R_LARCH_GOT64_PC_HI12 || VK == ELF::R_LARCH_TLS_LE64_HI12 ||
350 VK == ELF::R_LARCH_TLS_IE64_HI12 ||
351 VK == ELF::R_LARCH_TLS_IE64_PC_HI12 ||
352 VK == ELF::R_LARCH_TLS_DESC64_HI12 ||
353 VK == ELF::R_LARCH_TLS_DESC64_PC_HI12;
354 return IsConstantImm
355 ? isInt<12>(Imm) && IsValidKind
356 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
357 IsValidKind;
358 }
359
360 bool isUImm12() const { return isUImm<12>(); }
361
362 bool isUImm12ori() const {
363 if (!isImm())
364 return false;
365
366 int64_t Imm;
368 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
369 bool IsValidKind =
370 VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_ABS_LO12 ||
371 VK == ELF::R_LARCH_PCALA_LO12 || VK == ELF::R_LARCH_GOT_LO12 ||
372 VK == ELF::R_LARCH_GOT_PC_LO12 || VK == ELF::R_LARCH_TLS_LE_LO12 ||
373 VK == ELF::R_LARCH_TLS_IE_LO12 || VK == ELF::R_LARCH_TLS_IE_PC_LO12 ||
374 VK == ELF::R_LARCH_TLS_DESC_LO12;
375 return IsConstantImm
376 ? isUInt<12>(Imm) && IsValidKind
377 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
378 IsValidKind;
379 }
380
381 bool isSImm13() const { return isSImm<13>(); }
382 bool isUImm14() const { return isUImm<14>(); }
383 bool isUImm15() const { return isUImm<15>(); }
384
385 bool isSImm14lsl2() const { return isSImm<14, 2>(); }
386 bool isSImm16() const { return isSImm<16>(); }
387
388 bool isSImm16lsl2() const {
389 if (!isImm())
390 return false;
391
392 int64_t Imm;
394 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
395 bool IsValidKind =
396 VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_B16 ||
397 VK == ELF::R_LARCH_PCALA_LO12 || VK == ELF::R_LARCH_TLS_DESC_CALL;
398 return IsConstantImm
399 ? isShiftedInt<16, 2>(Imm) && IsValidKind
400 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
401 IsValidKind;
402 }
403
404 bool isSImm20() const { return isSImm<20>(); }
405
406 bool isSImm20pcalau12i() const {
407 if (!isImm())
408 return false;
409
410 int64_t Imm;
412 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
413 bool IsValidKind =
414 VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_PCALA_HI20 ||
415 VK == ELF::R_LARCH_GOT_PC_HI20 || VK == ELF::R_LARCH_TLS_IE_PC_HI20 ||
416 VK == ELF::R_LARCH_TLS_LD_PC_HI20 ||
417 VK == ELF::R_LARCH_TLS_GD_PC_HI20 ||
418 VK == ELF::R_LARCH_TLS_DESC_PC_HI20;
419 return IsConstantImm
420 ? isInt<20>(Imm) && IsValidKind
421 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
422 IsValidKind;
423 }
424
425 bool isSImm20lu12iw() const {
426 if (!isImm())
427 return false;
428
429 int64_t Imm;
431 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
432 bool IsValidKind =
433 VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_ABS_HI20 ||
434 VK == ELF::R_LARCH_GOT_HI20 || VK == ELF::R_LARCH_TLS_GD_HI20 ||
435 VK == ELF::R_LARCH_TLS_LD_HI20 || VK == ELF::R_LARCH_TLS_IE_HI20 ||
436 VK == ELF::R_LARCH_TLS_LE_HI20 || VK == ELF::R_LARCH_TLS_LE_HI20_R ||
437 VK == ELF::R_LARCH_TLS_DESC_HI20;
438 return IsConstantImm
439 ? isInt<20>(Imm) && IsValidKind
440 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
441 IsValidKind;
442 }
443
444 bool isSImm20lu32id() const {
445 if (!isImm())
446 return false;
447
448 int64_t Imm;
450 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
451 bool IsValidKind =
452 VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_ABS64_LO20 ||
453 VK == ELF::R_LARCH_PCALA64_LO20 || VK == ELF::R_LARCH_GOT64_LO20 ||
454 VK == ELF::R_LARCH_GOT64_PC_LO20 || VK == ELF::R_LARCH_TLS_IE64_LO20 ||
455 VK == ELF::R_LARCH_TLS_IE64_PC_LO20 ||
456 VK == ELF::R_LARCH_TLS_LE64_LO20 ||
457 VK == ELF::R_LARCH_TLS_DESC64_PC_LO20 ||
458 VK == ELF::R_LARCH_TLS_DESC64_LO20;
459
460 return IsConstantImm
461 ? isInt<20>(Imm) && IsValidKind
462 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
463 IsValidKind;
464 }
465
466 bool isSImm20pcaddu18i() const {
467 if (!isImm())
468 return false;
469
470 int64_t Imm;
472 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
473 bool IsValidKind =
474 VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_CALL36;
475
476 return IsConstantImm
477 ? isInt<20>(Imm) && IsValidKind
478 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
479 IsValidKind;
480 }
481
482 bool isSImm20pcaddi() const {
483 if (!isImm())
484 return false;
485
486 int64_t Imm;
488 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
489 bool IsValidKind = VK == LoongArchMCExpr::VK_None ||
490 VK == ELF::R_LARCH_PCREL20_S2 ||
491 VK == ELF::R_LARCH_TLS_LD_PCREL20_S2 ||
492 VK == ELF::R_LARCH_TLS_GD_PCREL20_S2 ||
493 VK == ELF::R_LARCH_TLS_DESC_PCREL20_S2;
494 return IsConstantImm
495 ? isInt<20>(Imm) && IsValidKind
496 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
497 IsValidKind;
498 }
499
500 bool isSImm21lsl2() const {
501 if (!isImm())
502 return false;
503
504 int64_t Imm;
506 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
507 bool IsValidKind = VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_B21;
508 return IsConstantImm
509 ? isShiftedInt<21, 2>(Imm) && IsValidKind
510 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
511 IsValidKind;
512 }
513
514 bool isSImm26Operand() const {
515 if (!isImm())
516 return false;
517
518 int64_t Imm;
520 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
521 bool IsValidKind = VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_B26;
522 return IsConstantImm
523 ? isShiftedInt<26, 2>(Imm) && IsValidKind
524 : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
525 IsValidKind;
526 }
527
528 bool isImm32() const { return isSImm<32>() || isUImm<32>(); }
529 bool isImm64() const {
530 if (!isImm())
531 return false;
532 int64_t Imm;
534 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
535 return IsConstantImm && VK == LoongArchMCExpr::VK_None;
536 }
537
538 /// Gets location of the first token of this operand.
539 SMLoc getStartLoc() const override { return StartLoc; }
540 /// Gets location of the last token of this operand.
541 SMLoc getEndLoc() const override { return EndLoc; }
542
543 MCRegister getReg() const override {
544 assert(Kind == KindTy::Register && "Invalid type access!");
545 return Reg.RegNum;
546 }
547
548 const MCExpr *getImm() const {
549 assert(Kind == KindTy::Immediate && "Invalid type access!");
550 return Imm.Val;
551 }
552
553 StringRef getToken() const {
554 assert(Kind == KindTy::Token && "Invalid type access!");
555 return Tok;
556 }
557
558 void print(raw_ostream &OS, const MCAsmInfo &MAI) const override {
559 auto RegName = [](MCRegister Reg) {
560 if (Reg)
562 else
563 return "noreg";
564 };
565
566 switch (Kind) {
567 case KindTy::Immediate:
568 MAI.printExpr(OS, *getImm());
569 break;
570 case KindTy::Register:
571 OS << "<register " << RegName(getReg()) << ">";
572 break;
573 case KindTy::Token:
574 OS << "'" << getToken() << "'";
575 break;
576 }
577 }
578
579 static std::unique_ptr<LoongArchOperand> createToken(StringRef Str, SMLoc S) {
580 auto Op = std::make_unique<LoongArchOperand>(KindTy::Token);
581 Op->Tok = Str;
582 Op->StartLoc = S;
583 Op->EndLoc = S;
584 return Op;
585 }
586
587 static std::unique_ptr<LoongArchOperand> createReg(MCRegister Reg, SMLoc S,
588 SMLoc E) {
589 auto Op = std::make_unique<LoongArchOperand>(KindTy::Register);
590 Op->Reg.RegNum = Reg;
591 Op->StartLoc = S;
592 Op->EndLoc = E;
593 return Op;
594 }
595
596 static std::unique_ptr<LoongArchOperand> createImm(const MCExpr *Val, SMLoc S,
597 SMLoc E) {
598 auto Op = std::make_unique<LoongArchOperand>(KindTy::Immediate);
599 Op->Imm.Val = Val;
600 Op->StartLoc = S;
601 Op->EndLoc = E;
602 return Op;
603 }
604
605 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
606 if (auto CE = dyn_cast<MCConstantExpr>(Expr))
607 Inst.addOperand(MCOperand::createImm(CE->getValue()));
608 else
610 }
611
612 // Used by the TableGen Code.
613 void addRegOperands(MCInst &Inst, unsigned N) const {
614 assert(N == 1 && "Invalid number of operands!");
616 }
617 void addImmOperands(MCInst &Inst, unsigned N) const {
618 assert(N == 1 && "Invalid number of operands!");
619 addExpr(Inst, getImm());
620 }
621};
622} // end namespace
623
624#define GET_REGISTER_MATCHER
625#define GET_SUBTARGET_FEATURE_NAME
626#define GET_MATCHER_IMPLEMENTATION
627#define GET_MNEMONIC_SPELL_CHECKER
628#include "LoongArchGenAsmMatcher.inc"
629
631 assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register");
632 return Reg - LoongArch::F0 + LoongArch::F0_64;
633}
634
635// Attempts to match Name as a register (either using the default name or
636// alternative ABI names), setting RegNo to the matching register. Upon
637// failure, returns true and sets RegNo to 0.
639 RegNo = MatchRegisterName(Name);
640 // The 32-bit and 64-bit FPRs have the same asm name. Check that the initial
641 // match always matches the 32-bit variant, and not the 64-bit one.
642 assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64));
643 // The default FPR register class is based on the tablegen enum ordering.
644 static_assert(LoongArch::F0 < LoongArch::F0_64,
645 "FPR matching must be updated");
646 if (RegNo == LoongArch::NoRegister)
647 RegNo = MatchRegisterAltName(Name);
648
649 return RegNo == LoongArch::NoRegister;
650}
651
652bool LoongArchAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
653 SMLoc &EndLoc) {
654 if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
655 return Error(getLoc(), "invalid register name");
656
657 if (!LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains(Reg) &&
658 !LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg))
659 return Error(getLoc(), "invalid register name");
660
661 return false;
662}
663
664ParseStatus LoongArchAsmParser::tryParseRegister(MCRegister &Reg,
665 SMLoc &StartLoc,
666 SMLoc &EndLoc) {
667 const AsmToken &Tok = getParser().getTok();
668 StartLoc = Tok.getLoc();
669 EndLoc = Tok.getEndLoc();
670
671 parseOptionalToken(AsmToken::Dollar);
672 if (getLexer().getKind() != AsmToken::Identifier)
674
675 StringRef Name = Tok.getIdentifier();
676 if (matchRegisterNameHelper(Reg, Name))
678
679 getParser().Lex(); // Eat identifier token.
681}
682
683bool LoongArchAsmParser::classifySymbolRef(const MCExpr *Expr,
686
687 if (const LoongArchMCExpr *RE = dyn_cast<LoongArchMCExpr>(Expr)) {
688 Kind = RE->getSpecifier();
689 Expr = RE->getSubExpr();
690 }
691
692 MCValue Res;
693 if (Expr->evaluateAsRelocatable(Res, nullptr))
695 return false;
696}
697
698ParseStatus LoongArchAsmParser::parseRegister(OperandVector &Operands) {
699 if (!parseOptionalToken(AsmToken::Dollar))
701 if (getLexer().getKind() != AsmToken::Identifier)
703
704 StringRef Name = getLexer().getTok().getIdentifier();
705 MCRegister RegNo;
706 matchRegisterNameHelper(RegNo, Name);
707 if (RegNo == LoongArch::NoRegister)
709
710 SMLoc S = getLoc();
711 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
712 getLexer().Lex();
713 Operands.push_back(LoongArchOperand::createReg(RegNo, S, E));
714
716}
717
718ParseStatus LoongArchAsmParser::parseImmediate(OperandVector &Operands) {
719 SMLoc S = getLoc();
720 SMLoc E;
721 const MCExpr *Res;
722
723 switch (getLexer().getKind()) {
724 default:
726 case AsmToken::LParen:
727 case AsmToken::Dot:
728 case AsmToken::Minus:
729 case AsmToken::Plus:
731 case AsmToken::Tilde:
733 case AsmToken::String:
735 if (getParser().parseExpression(Res, E))
737 break;
739 return parseOperandWithModifier(Operands);
740 }
741
742 Operands.push_back(LoongArchOperand::createImm(Res, S, E));
744}
745
746ParseStatus
747LoongArchAsmParser::parseOperandWithModifier(OperandVector &Operands) {
748 SMLoc S = getLoc();
749 SMLoc E;
750
751 if (getLexer().getKind() != AsmToken::Percent)
752 return Error(getLoc(), "expected '%' for operand modifier");
753
754 getParser().Lex(); // Eat '%'
755
756 if (getLexer().getKind() != AsmToken::Identifier)
757 return Error(getLoc(), "expected valid identifier for operand modifier");
758 StringRef Identifier = getParser().getTok().getIdentifier();
759 auto VK = LoongArch::parseSpecifier(Identifier);
760 if (VK == LoongArchMCExpr::VK_None)
761 return Error(getLoc(), "invalid relocation specifier");
762
763 getParser().Lex(); // Eat the identifier
764 if (getLexer().getKind() != AsmToken::LParen)
765 return Error(getLoc(), "expected '('");
766 getParser().Lex(); // Eat '('
767
768 const MCExpr *SubExpr;
769 if (getParser().parseParenExpression(SubExpr, E))
771
772 const MCExpr *ModExpr = LoongArchMCExpr::create(SubExpr, VK, getContext());
773 Operands.push_back(LoongArchOperand::createImm(ModExpr, S, E));
775}
776
777ParseStatus LoongArchAsmParser::parseSImm26Operand(OperandVector &Operands) {
778 SMLoc S = getLoc();
779 const MCExpr *Res;
780
781 if (getLexer().getKind() == AsmToken::Percent)
782 return parseOperandWithModifier(Operands);
783
784 if (getLexer().getKind() != AsmToken::Identifier)
786
787 StringRef Identifier;
788 if (getParser().parseIdentifier(Identifier))
790
791 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
792
793 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
795 Operands.push_back(LoongArchOperand::createImm(Res, S, E));
797}
798
799ParseStatus LoongArchAsmParser::parseAtomicMemOp(OperandVector &Operands) {
800 // Parse "$r*".
801 if (!parseRegister(Operands).isSuccess())
803
804 // If there is a next operand and it is 0, ignore it. Otherwise print a
805 // diagnostic message.
806 if (parseOptionalToken(AsmToken::Comma)) {
807 int64_t ImmVal;
808 SMLoc ImmStart = getLoc();
809 if (getParser().parseIntToken(ImmVal, "expected optional integer offset"))
811 if (ImmVal)
812 return Error(ImmStart, "optional integer offset must be 0");
813 }
814
816}
817/// Looks at a token type and creates the relevant operand from this
818/// information, adding to Operands. Return true upon an error.
819bool LoongArchAsmParser::parseOperand(OperandVector &Operands,
820 StringRef Mnemonic) {
821 // Check if the current operand has a custom associated parser, if so, try to
822 // custom parse the operand, or fallback to the general approach.
823 ParseStatus Result =
824 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
825 if (Result.isSuccess())
826 return false;
827 if (Result.isFailure())
828 return true;
829
830 if (parseRegister(Operands).isSuccess() ||
831 parseImmediate(Operands).isSuccess())
832 return false;
833
834 // Finally we have exhausted all options and must declare defeat.
835 return Error(getLoc(), "unknown operand");
836}
837
838bool LoongArchAsmParser::parseInstruction(ParseInstructionInfo &Info,
839 StringRef Name, SMLoc NameLoc,
841 // First operand in MCInst is instruction mnemonic.
842 Operands.push_back(LoongArchOperand::createToken(Name, NameLoc));
843
844 // If there are no more operands, then finish.
845 if (parseOptionalToken(AsmToken::EndOfStatement))
846 return false;
847
848 // Parse first operand.
849 if (parseOperand(Operands, Name))
850 return true;
851
852 // Parse until end of statement, consuming commas between operands.
853 while (parseOptionalToken(AsmToken::Comma))
854 if (parseOperand(Operands, Name))
855 return true;
856
857 // Parse end of statement and return successfully.
858 if (parseOptionalToken(AsmToken::EndOfStatement))
859 return false;
860
861 SMLoc Loc = getLexer().getLoc();
862 getParser().eatToEndOfStatement();
863 return Error(Loc, "unexpected token");
864}
865
866void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
867 const MCExpr *Symbol,
868 SmallVectorImpl<Inst> &Insts,
869 SMLoc IDLoc, MCStreamer &Out,
870 bool RelaxHint) {
871 MCContext &Ctx = getContext();
872 for (LoongArchAsmParser::Inst &Inst : Insts) {
873 unsigned Opc = Inst.Opc;
874 auto VK = LoongArchMCExpr::Specifier(Inst.Specifier);
875 const LoongArchMCExpr *LE =
876 LoongArchMCExpr::create(Symbol, VK, Ctx, RelaxHint);
877 switch (Opc) {
878 default:
879 llvm_unreachable("unexpected opcode");
880 case LoongArch::PCALAU12I:
881 case LoongArch::LU12I_W:
882 Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addExpr(LE),
883 getSTI());
884 break;
885 case LoongArch::ORI:
886 case LoongArch::ADDI_W:
887 case LoongArch::LD_W:
888 case LoongArch::LD_D: {
889 if (VK == LoongArchMCExpr::VK_None) {
890 Out.emitInstruction(
891 MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addImm(0),
892 getSTI());
893 continue;
894 } else if (VK == ELF::R_LARCH_TLS_DESC_LD) {
895 Out.emitInstruction(MCInstBuilder(Opc)
896 .addReg(LoongArch::R1)
897 .addReg(DestReg)
898 .addExpr(LE),
899 getSTI());
900 continue;
901 }
902 Out.emitInstruction(
903 MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addExpr(LE),
904 getSTI());
905 break;
906 }
907 case LoongArch::LU32I_D:
908 Out.emitInstruction(MCInstBuilder(Opc)
909 .addReg(DestReg == TmpReg ? DestReg : TmpReg)
910 .addReg(DestReg == TmpReg ? DestReg : TmpReg)
911 .addExpr(LE),
912 getSTI());
913 break;
914 case LoongArch::LU52I_D:
915 Out.emitInstruction(
916 MCInstBuilder(Opc).addReg(TmpReg).addReg(TmpReg).addExpr(LE),
917 getSTI());
918 break;
919 case LoongArch::ADDI_D:
920 Out.emitInstruction(
921 MCInstBuilder(Opc)
922 .addReg(TmpReg)
923 .addReg(DestReg == TmpReg ? TmpReg : LoongArch::R0)
924 .addExpr(LE),
925 getSTI());
926 break;
927 case LoongArch::ADD_D:
928 case LoongArch::LDX_D:
929 Out.emitInstruction(
930 MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addReg(TmpReg),
931 getSTI());
932 break;
933 case LoongArch::JIRL:
934 Out.emitInstruction(MCInstBuilder(Opc)
935 .addReg(LoongArch::R1)
936 .addReg(LoongArch::R1)
937 .addExpr(LE),
938 getSTI());
939 break;
940 }
941 }
942}
943
944void LoongArchAsmParser::emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc,
945 MCStreamer &Out) {
946 // la.abs $rd, sym
947 // expands to:
948 // lu12i.w $rd, %abs_hi20(sym)
949 // ori $rd, $rd, %abs_lo12(sym)
950 //
951 // for 64bit appends:
952 // lu32i.d $rd, %abs64_lo20(sym)
953 // lu52i.d $rd, $rd, %abs64_hi12(sym)
954 MCRegister DestReg = Inst.getOperand(0).getReg();
955 const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_ABS
956 ? Inst.getOperand(1).getExpr()
957 : Inst.getOperand(2).getExpr();
958 InstSeq Insts;
959
960 // To distinguish between la.abs and %abs_hi20, la.abs will generate
961 // R_LARCH_MARK_LA and R_LARCH_ABS_HI20 relocations.
962 Insts.push_back(
963 LoongArchAsmParser::Inst(LoongArch::LU12I_W, ELF::R_LARCH_MARK_LA));
964 Insts.push_back(
965 LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_ABS_LO12));
966
967 if (is64Bit()) {
968 Insts.push_back(
969 LoongArchAsmParser::Inst(LoongArch::LU32I_D, ELF::R_LARCH_ABS64_LO20));
970 Insts.push_back(
971 LoongArchAsmParser::Inst(LoongArch::LU52I_D, ELF::R_LARCH_ABS64_HI12));
972 }
973
974 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
975}
976
977void LoongArchAsmParser::emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc,
978 MCStreamer &Out) {
979 // la.pcrel $rd, sym
980 // expands to:
981 // pcalau12i $rd, %pc_hi20(sym)
982 // addi.w/d $rd, rd, %pc_lo12(sym)
983 MCRegister DestReg = Inst.getOperand(0).getReg();
984 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
985 InstSeq Insts;
986 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
987
988 Insts.push_back(
989 LoongArchAsmParser::Inst(LoongArch::PCALAU12I, ELF::R_LARCH_PCALA_HI20));
990 Insts.push_back(LoongArchAsmParser::Inst(ADDI, ELF::R_LARCH_PCALA_LO12));
991
992 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
993 /*RelaxHint=*/true);
994}
995
996void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc,
997 MCStreamer &Out) {
998 // la.pcrel $rd, $rj, sym
999 // expands to:
1000 // pcalau12i $rd, %pc_hi20(sym)
1001 // addi.d $rj, $r0, %pc_lo12(sym)
1002 // lu32i.d $rj, %pc64_lo20(sym)
1003 // lu52i.d $rj, $rj, %pc64_hi12(sym)
1004 // add.d $rd, $rd, $rj
1005 MCRegister DestReg = Inst.getOperand(0).getReg();
1006 MCRegister TmpReg = Inst.getOperand(1).getReg();
1007 const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1008 InstSeq Insts;
1009
1010 Insts.push_back(
1011 LoongArchAsmParser::Inst(LoongArch::PCALAU12I, ELF::R_LARCH_PCALA_HI20));
1012 Insts.push_back(
1013 LoongArchAsmParser::Inst(LoongArch::ADDI_D, ELF::R_LARCH_PCALA_LO12));
1014 Insts.push_back(
1015 LoongArchAsmParser::Inst(LoongArch::LU32I_D, ELF::R_LARCH_PCALA64_LO20));
1016 Insts.push_back(
1017 LoongArchAsmParser::Inst(LoongArch::LU52I_D, ELF::R_LARCH_PCALA64_HI12));
1018 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1019
1020 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1021}
1022
1023void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc,
1024 MCStreamer &Out) {
1025 // la.got $rd, sym
1026 MCRegister DestReg = Inst.getOperand(0).getReg();
1027 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1028 InstSeq Insts;
1029 unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
1030
1031 if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
1032 // with feature: +la-glabal-with-abs
1033 // for 32bit:
1034 // lu12i.w $rd, %got_hi20(sym)
1035 // ori $rd, $rd, %got_lo12(sym)
1036 // ld.w $rd, $rd, 0
1037 //
1038 // for 64bit:
1039 // lu12i.w $rd, %got_hi20(sym)
1040 // ori $rd, $rd, %got_lo12(sym)
1041 // lu32i.d $rd, %got64_lo20(sym)
1042 // lu52i.d $rd, $rd, %got64_hi12(sym)
1043 // ld.d $rd, $rd, 0
1044 Insts.push_back(
1045 LoongArchAsmParser::Inst(LoongArch::LU12I_W, ELF::R_LARCH_GOT_HI20));
1046 Insts.push_back(
1047 LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_GOT_LO12));
1048
1049 if (is64Bit()) {
1050 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU32I_D,
1051 ELF::R_LARCH_GOT64_LO20));
1052 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU52I_D,
1053 ELF::R_LARCH_GOT64_HI12));
1054 }
1055 Insts.push_back(LoongArchAsmParser::Inst(LD));
1056 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1057 return;
1058 }
1059 // expands to:
1060 // pcalau12i $rd, %got_pc_hi20(sym)
1061 // ld.w/d $rd, $rd, %got_pc_lo12(sym)
1062 Insts.push_back(
1063 LoongArchAsmParser::Inst(LoongArch::PCALAU12I, ELF::R_LARCH_GOT_PC_HI20));
1064 Insts.push_back(LoongArchAsmParser::Inst(LD, ELF::R_LARCH_GOT_PC_LO12));
1065
1066 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
1067 /*RelaxHint=*/true);
1068}
1069
1070void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc,
1071 MCStreamer &Out) {
1072 // la.got $rd, $rj, sym
1073 // expands to:
1074 // pcalau12i $rd, %got_pc_hi20(sym)
1075 // addi.d $rj, $r0, %got_pc_lo12(sym)
1076 // lu32i.d $rj, %got64_pc_lo20(sym)
1077 // lu52i.d $rj, $rj, %got64_pc_hi12(sym)
1078 // ldx.d $rd, $rd, $rj
1079 MCRegister DestReg = Inst.getOperand(0).getReg();
1080 MCRegister TmpReg = Inst.getOperand(1).getReg();
1081 const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1082 InstSeq Insts;
1083
1084 Insts.push_back(
1085 LoongArchAsmParser::Inst(LoongArch::PCALAU12I, ELF::R_LARCH_GOT_PC_HI20));
1086 Insts.push_back(
1087 LoongArchAsmParser::Inst(LoongArch::ADDI_D, ELF::R_LARCH_GOT_PC_LO12));
1088 Insts.push_back(
1089 LoongArchAsmParser::Inst(LoongArch::LU32I_D, ELF::R_LARCH_GOT64_PC_LO20));
1090 Insts.push_back(
1091 LoongArchAsmParser::Inst(LoongArch::LU52I_D, ELF::R_LARCH_GOT64_PC_HI12));
1092 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D));
1093
1094 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1095}
1096
1097void LoongArchAsmParser::emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc,
1098 MCStreamer &Out) {
1099 // la.tls.le $rd, sym
1100 // expands to:
1101 // lu12i.w $rd, %le_hi20(sym)
1102 // ori $rd, $rd, %le_lo12(sym)
1103 MCRegister DestReg = Inst.getOperand(0).getReg();
1104 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1105 InstSeq Insts;
1106
1107 Insts.push_back(
1108 LoongArchAsmParser::Inst(LoongArch::LU12I_W, ELF::R_LARCH_TLS_LE_HI20));
1109 Insts.push_back(
1110 LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_TLS_LE_LO12));
1111
1112 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1113}
1114
1115void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc,
1116 MCStreamer &Out) {
1117 // la.tls.ie $rd, sym
1118 MCRegister DestReg = Inst.getOperand(0).getReg();
1119 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1120 InstSeq Insts;
1121 unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
1122
1123 if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
1124 // with feature: +la-glabal-with-abs
1125 // for 32bit:
1126 // lu12i.w $rd, %ie_hi20(sym)
1127 // ori $rd, $rd, %ie_lo12(sym)
1128 // ld.w $rd, $rd, 0
1129 //
1130 // for 64bit:
1131 // lu12i.w $rd, %ie_hi20(sym)
1132 // ori $rd, $rd, %ie_lo12(sym)
1133 // lu32i.d $rd, %ie64_lo20(sym)
1134 // lu52i.d $rd, $rd, %ie64_hi12(sym)
1135 // ld.d $rd, $rd, 0
1136 Insts.push_back(
1137 LoongArchAsmParser::Inst(LoongArch::LU12I_W, ELF::R_LARCH_TLS_IE_HI20));
1138 Insts.push_back(
1139 LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_TLS_IE_LO12));
1140
1141 if (is64Bit()) {
1142 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU32I_D,
1143 ELF::R_LARCH_TLS_IE64_LO20));
1144 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU52I_D,
1145 ELF::R_LARCH_TLS_IE64_HI12));
1146 }
1147 Insts.push_back(LoongArchAsmParser::Inst(LD));
1148 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1149 return;
1150 }
1151
1152 // expands to:
1153 // pcalau12i $rd, %ie_pc_hi20(sym)
1154 // ld.w/d $rd, $rd, %ie_pc_lo12(sym)
1155 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
1156 ELF::R_LARCH_TLS_IE_PC_HI20));
1157 Insts.push_back(LoongArchAsmParser::Inst(LD, ELF::R_LARCH_TLS_IE_PC_LO12));
1158
1159 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
1160 /*RelaxHint=*/true);
1161}
1162
1163void LoongArchAsmParser::emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc,
1164 MCStreamer &Out) {
1165 // la.tls.ie $rd, $rj, sym
1166 // expands to:
1167 // pcalau12i $rd, %ie_pc_hi20(sym)
1168 // addi.d $rj, $r0, %ie_pc_lo12(sym)
1169 // lu32i.d $rj, %ie64_pc_lo20(sym)
1170 // lu52i.d $rj, $rj, %ie64_pc_hi12(sym)
1171 // ldx.d $rd, $rd, $rj
1172 MCRegister DestReg = Inst.getOperand(0).getReg();
1173 MCRegister TmpReg = Inst.getOperand(1).getReg();
1174 const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1175 InstSeq Insts;
1176
1177 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
1178 ELF::R_LARCH_TLS_IE_PC_HI20));
1179 Insts.push_back(
1180 LoongArchAsmParser::Inst(LoongArch::ADDI_D, ELF::R_LARCH_TLS_IE_PC_LO12));
1181 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU32I_D,
1182 ELF::R_LARCH_TLS_IE64_PC_LO20));
1183 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU52I_D,
1184 ELF::R_LARCH_TLS_IE64_PC_HI12));
1185 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LDX_D));
1186
1187 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1188}
1189
1190void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc,
1191 MCStreamer &Out) {
1192 // la.tls.ld $rd, sym
1193 MCRegister DestReg = Inst.getOperand(0).getReg();
1194 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1195 InstSeq Insts;
1196 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1197
1198 if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
1199 // with feature: +la-glabal-with-abs
1200 // for 32bit:
1201 // lu12i.w $rd, %ld_hi20(sym)
1202 // ori $rd, $rd, %got_lo12(sym)
1203 //
1204 // for 64bit:
1205 // lu12i.w $rd, %ld_hi20(sym)
1206 // ori $rd, $rd, %got_lo12(sym)
1207 // lu32i.d $rd, %got64_lo20(sym)
1208 // lu52i.d $rd, $rd, %got64_hi12(sym)
1209 Insts.push_back(
1210 LoongArchAsmParser::Inst(LoongArch::LU12I_W, ELF::R_LARCH_TLS_LD_HI20));
1211 Insts.push_back(
1212 LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_GOT_LO12));
1213
1214 if (is64Bit()) {
1215 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU32I_D,
1216 ELF::R_LARCH_GOT64_LO20));
1217 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU52I_D,
1218 ELF::R_LARCH_GOT64_HI12));
1219 }
1220 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1221 return;
1222 }
1223
1224 // expands to:
1225 // pcalau12i $rd, %ld_pc_hi20(sym)
1226 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
1227 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
1228 ELF::R_LARCH_TLS_LD_PC_HI20));
1229 Insts.push_back(LoongArchAsmParser::Inst(ADDI, ELF::R_LARCH_GOT_PC_LO12));
1230
1231 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
1232 /*RelaxHint=*/true);
1233}
1234
1235void LoongArchAsmParser::emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc,
1236 MCStreamer &Out) {
1237 // la.tls.ld $rd, $rj, sym
1238 // expands to:
1239 // pcalau12i $rd, %ld_pc_hi20(sym)
1240 // addi.d $rj, $r0, %got_pc_lo12(sym)
1241 // lu32i.d $rj, %got64_pc_lo20(sym)
1242 // lu52i.d $rj, $rj, %got64_pc_hi12(sym)
1243 // add.d $rd, $rd, $rj
1244 MCRegister DestReg = Inst.getOperand(0).getReg();
1245 MCRegister TmpReg = Inst.getOperand(1).getReg();
1246 const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1247 InstSeq Insts;
1248
1249 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
1250 ELF::R_LARCH_TLS_LD_PC_HI20));
1251 Insts.push_back(
1252 LoongArchAsmParser::Inst(LoongArch::ADDI_D, ELF::R_LARCH_GOT_PC_LO12));
1253 Insts.push_back(
1254 LoongArchAsmParser::Inst(LoongArch::LU32I_D, ELF::R_LARCH_GOT64_PC_LO20));
1255 Insts.push_back(
1256 LoongArchAsmParser::Inst(LoongArch::LU52I_D, ELF::R_LARCH_GOT64_PC_HI12));
1257 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1258
1259 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1260}
1261
1262void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc,
1263 MCStreamer &Out) {
1264 // la.tls.gd $rd, sym
1265 MCRegister DestReg = Inst.getOperand(0).getReg();
1266 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1267 InstSeq Insts;
1268 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1269
1270 if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
1271 // with feature: +la-glabal-with-abs
1272 // for 32bit:
1273 // lu12i.w $rd, %gd_hi20(sym)
1274 // ori $rd, $rd, %got_lo12(sym)
1275 //
1276 // for 64bit:
1277 // lu12i.w $rd, %gd_hi20(sym)
1278 // ori $rd, $rd, %got_lo12(sym)
1279 // lu32i.d $rd, %got64_lo20(sym)
1280 // lu52i.d $rd, $rd, %got64_hi12(sym)
1281 Insts.push_back(
1282 LoongArchAsmParser::Inst(LoongArch::LU12I_W, ELF::R_LARCH_TLS_GD_HI20));
1283 Insts.push_back(
1284 LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_GOT_LO12));
1285
1286 if (is64Bit()) {
1287 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU32I_D,
1288 ELF::R_LARCH_GOT64_LO20));
1289 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU52I_D,
1290 ELF::R_LARCH_GOT64_HI12));
1291 }
1292 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1293 return;
1294 }
1295
1296 // expands to:
1297 // pcalau12i $rd, %gd_pc_hi20(sym)
1298 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
1299 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
1300 ELF::R_LARCH_TLS_GD_PC_HI20));
1301 Insts.push_back(LoongArchAsmParser::Inst(ADDI, ELF::R_LARCH_GOT_PC_LO12));
1302
1303 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
1304 /*RelaxHint=*/true);
1305}
1306
1307void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc,
1308 MCStreamer &Out) {
1309 // la.tls.gd $rd, $rj, sym
1310 // expands to:
1311 // pcalau12i $rd, %gd_pc_hi20(sym)
1312 // addi.d $rj, $r0, %got_pc_lo12(sym)
1313 // lu32i.d $rj, %got64_pc_lo20(sym)
1314 // lu52i.d $rj, $rj, %got64_pc_hi12(sym)
1315 // add.d $rd, $rd, $rj
1316 MCRegister DestReg = Inst.getOperand(0).getReg();
1317 MCRegister TmpReg = Inst.getOperand(1).getReg();
1318 const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1319 InstSeq Insts;
1320
1321 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
1322 ELF::R_LARCH_TLS_GD_PC_HI20));
1323 Insts.push_back(
1324 LoongArchAsmParser::Inst(LoongArch::ADDI_D, ELF::R_LARCH_GOT_PC_LO12));
1325 Insts.push_back(
1326 LoongArchAsmParser::Inst(LoongArch::LU32I_D, ELF::R_LARCH_GOT64_PC_LO20));
1327 Insts.push_back(
1328 LoongArchAsmParser::Inst(LoongArch::LU52I_D, ELF::R_LARCH_GOT64_PC_HI12));
1329 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1330
1331 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1332}
1333
1334void LoongArchAsmParser::emitLoadAddressTLSDesc(MCInst &Inst, SMLoc IDLoc,
1335 MCStreamer &Out) {
1336 // la.tls.desc $rd, sym
1337 MCRegister DestReg = Inst.getOperand(0).getReg();
1338 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1339 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1340 unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
1341 InstSeq Insts;
1342
1343 if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
1344 // with feature: +la-glabal-with-abs
1345 // for la32 expands to:
1346 // lu12i.w $rd, %desc_hi20(sym)
1347 // ori $rd, $rd, %desc_lo12(sym)
1348 // ld.w $ra, $rd, %desc_ld(sym)
1349 // jirl $ra, $ra, %desc_call(sym)
1350 //
1351 // for la64 expands to:
1352 // lu12i.w $rd, %desc_hi20(sym)
1353 // ori $rd, $rd, %desc_lo12(sym)
1354 // lu32i.d $rd, %desc64_lo20(sym)
1355 // lu52i.d $rd, $rd, %desc64_hi12(sym)
1356 // ld.d $ra, $rd, %desc_ld(sym)
1357 // jirl $ra, $ra, %desc_call(sym)
1358 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU12I_W,
1359 ELF::R_LARCH_TLS_DESC_HI20));
1360 Insts.push_back(
1361 LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_TLS_DESC_LO12));
1362
1363 if (is64Bit()) {
1364 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU32I_D,
1365 ELF::R_LARCH_TLS_DESC64_LO20));
1366 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU52I_D,
1367 ELF::R_LARCH_TLS_DESC64_HI12));
1368 }
1369
1370 Insts.push_back(LoongArchAsmParser::Inst(LD, ELF::R_LARCH_TLS_DESC_LD));
1371 Insts.push_back(
1372 LoongArchAsmParser::Inst(LoongArch::JIRL, ELF::R_LARCH_TLS_DESC_CALL));
1373
1374 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
1375 return;
1376 }
1377
1378 // expands to:
1379 // pcalau12i $rd, %desc_pc_hi20(sym)
1380 // addi.w/d $rd, $rd, %desc_pc_lo12(sym)
1381 // ld.w/d $ra, $rd, %desc_ld(sym)
1382 // jirl $ra, $ra, %desc_call(sym)
1383 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
1384 ELF::R_LARCH_TLS_DESC_PC_HI20));
1385 Insts.push_back(
1386 LoongArchAsmParser::Inst(ADDI, ELF::R_LARCH_TLS_DESC_PC_LO12));
1387 Insts.push_back(LoongArchAsmParser::Inst(LD, ELF::R_LARCH_TLS_DESC_LD));
1388 Insts.push_back(
1389 LoongArchAsmParser::Inst(LoongArch::JIRL, ELF::R_LARCH_TLS_DESC_CALL));
1390
1391 emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
1392 /*RelaxHint=*/true);
1393}
1394
1395void LoongArchAsmParser::emitLoadAddressTLSDescLarge(MCInst &Inst, SMLoc IDLoc,
1396 MCStreamer &Out) {
1397 // la.tls.desc $rd, $rj, sym
1398 // expands to:
1399 // pcalau12i $rd, %desc_pc_hi20(sym)
1400 // addi.d $rj, $r0, %desc_pc_lo12(sym)
1401 // lu32i.d $rj, %desc64_pc_lo20(sym)
1402 // lu52i.d $rj, $rj, %desc64_pc_hi12(sym)
1403 // add.d $rd, $rd, $rj
1404 // ld.w/d $ra, $rd, %desc_ld(sym)
1405 // jirl $ra, $ra, %desc_call(sym)
1406 MCRegister DestReg = Inst.getOperand(0).getReg();
1407 MCRegister TmpReg = Inst.getOperand(1).getReg();
1408 const MCExpr *Symbol = Inst.getOperand(2).getExpr();
1409 InstSeq Insts;
1410
1411 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
1412 ELF::R_LARCH_TLS_DESC_PC_HI20));
1413 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADDI_D,
1414 ELF::R_LARCH_TLS_DESC_PC_LO12));
1415 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU32I_D,
1416 ELF::R_LARCH_TLS_DESC64_PC_LO20));
1417 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::LU52I_D,
1418 ELF::R_LARCH_TLS_DESC64_PC_HI12));
1419 Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
1420 Insts.push_back(
1421 LoongArchAsmParser::Inst(LoongArch::LD_D, ELF::R_LARCH_TLS_DESC_LD));
1422 Insts.push_back(
1423 LoongArchAsmParser::Inst(LoongArch::JIRL, ELF::R_LARCH_TLS_DESC_CALL));
1424
1425 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1426}
1427
1428void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc,
1429 MCStreamer &Out) {
1430 MCRegister DestReg = Inst.getOperand(0).getReg();
1431 int64_t Imm = Inst.getOperand(1).getImm();
1432 MCRegister SrcReg = LoongArch::R0;
1433
1434 if (Inst.getOpcode() == LoongArch::PseudoLI_W)
1435 Imm = SignExtend64<32>(Imm);
1436
1437 for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Imm)) {
1438 switch (Inst.Opc) {
1439 case LoongArch::LU12I_W:
1440 Out.emitInstruction(
1441 MCInstBuilder(Inst.Opc).addReg(DestReg).addImm(Inst.Imm), getSTI());
1442 break;
1443 case LoongArch::ADDI_W:
1444 case LoongArch::ORI:
1445 case LoongArch::LU32I_D:
1446 case LoongArch::LU52I_D:
1447 Out.emitInstruction(
1448 MCInstBuilder(Inst.Opc).addReg(DestReg).addReg(SrcReg).addImm(
1449 Inst.Imm),
1450 getSTI());
1451 break;
1452 case LoongArch::BSTRINS_D:
1453 Out.emitInstruction(MCInstBuilder(Inst.Opc)
1454 .addReg(DestReg)
1455 .addReg(SrcReg)
1456 .addReg(SrcReg)
1457 .addImm(Inst.Imm >> 32)
1458 .addImm(Inst.Imm & 0xFF),
1459 getSTI());
1460 break;
1461 default:
1462 llvm_unreachable("unexpected opcode generated by LoongArchMatInt");
1463 }
1464 SrcReg = DestReg;
1465 }
1466}
1467
1468void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc,
1469 MCStreamer &Out, bool IsTailCall) {
1470 // call36 sym
1471 // expands to:
1472 // pcaddu18i $ra, %call36(sym)
1473 // jirl $ra, $ra, 0
1474 //
1475 // tail36 $rj, sym
1476 // expands to:
1477 // pcaddu18i $rj, %call36(sym)
1478 // jirl $r0, $rj, 0
1479 MCRegister ScratchReg =
1480 IsTailCall ? Inst.getOperand(0).getReg() : MCRegister(LoongArch::R1);
1481 const MCExpr *Sym =
1482 IsTailCall ? Inst.getOperand(1).getExpr() : Inst.getOperand(0).getExpr();
1483 const LoongArchMCExpr *LE = LoongArchMCExpr::create(
1484 Sym, ELF::R_LARCH_CALL36, getContext(), /*RelaxHint=*/true);
1485
1486 Out.emitInstruction(
1487 MCInstBuilder(LoongArch::PCADDU18I).addReg(ScratchReg).addExpr(LE),
1488 getSTI());
1489 Out.emitInstruction(
1490 MCInstBuilder(LoongArch::JIRL)
1491 .addReg(IsTailCall ? MCRegister(LoongArch::R0) : ScratchReg)
1492 .addReg(ScratchReg)
1493 .addImm(0),
1494 getSTI());
1495}
1496
1497bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
1499 MCStreamer &Out) {
1500 Inst.setLoc(IDLoc);
1501 switch (Inst.getOpcode()) {
1502 default:
1503 break;
1504 case LoongArch::PseudoLA_ABS:
1505 case LoongArch::PseudoLA_ABS_LARGE:
1506 emitLoadAddressAbs(Inst, IDLoc, Out);
1507 return false;
1508 case LoongArch::PseudoLA_PCREL:
1509 emitLoadAddressPcrel(Inst, IDLoc, Out);
1510 return false;
1511 case LoongArch::PseudoLA_PCREL_LARGE:
1512 emitLoadAddressPcrelLarge(Inst, IDLoc, Out);
1513 return false;
1514 case LoongArch::PseudoLA_GOT:
1515 emitLoadAddressGot(Inst, IDLoc, Out);
1516 return false;
1517 case LoongArch::PseudoLA_GOT_LARGE:
1518 emitLoadAddressGotLarge(Inst, IDLoc, Out);
1519 return false;
1520 case LoongArch::PseudoLA_TLS_LE:
1521 emitLoadAddressTLSLE(Inst, IDLoc, Out);
1522 return false;
1523 case LoongArch::PseudoLA_TLS_IE:
1524 emitLoadAddressTLSIE(Inst, IDLoc, Out);
1525 return false;
1526 case LoongArch::PseudoLA_TLS_IE_LARGE:
1527 emitLoadAddressTLSIELarge(Inst, IDLoc, Out);
1528 return false;
1529 case LoongArch::PseudoLA_TLS_LD:
1530 emitLoadAddressTLSLD(Inst, IDLoc, Out);
1531 return false;
1532 case LoongArch::PseudoLA_TLS_LD_LARGE:
1533 emitLoadAddressTLSLDLarge(Inst, IDLoc, Out);
1534 return false;
1535 case LoongArch::PseudoLA_TLS_GD:
1536 emitLoadAddressTLSGD(Inst, IDLoc, Out);
1537 return false;
1538 case LoongArch::PseudoLA_TLS_GD_LARGE:
1539 emitLoadAddressTLSGDLarge(Inst, IDLoc, Out);
1540 return false;
1541 case LoongArch::PseudoLA_TLS_DESC:
1542 emitLoadAddressTLSDesc(Inst, IDLoc, Out);
1543 return false;
1544 case LoongArch::PseudoLA_TLS_DESC_LARGE:
1545 emitLoadAddressTLSDescLarge(Inst, IDLoc, Out);
1546 return false;
1547 case LoongArch::PseudoLI_W:
1548 case LoongArch::PseudoLI_D:
1549 emitLoadImm(Inst, IDLoc, Out);
1550 return false;
1551 case LoongArch::PseudoCALL36:
1552 emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/false);
1553 return false;
1554 case LoongArch::PseudoTAIL36:
1555 emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/true);
1556 return false;
1557 }
1558 Out.emitInstruction(Inst, getSTI());
1559 return false;
1560}
1561
1562unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1563 unsigned Opc = Inst.getOpcode();
1564 const MCInstrDesc &MCID = MII.get(Opc);
1565 switch (Opc) {
1566 default:
1568 const bool IsAMCAS = LoongArchII::isAMCAS(MCID.TSFlags);
1569 MCRegister Rd = Inst.getOperand(0).getReg();
1570 MCRegister Rk = Inst.getOperand(IsAMCAS ? 2 : 1).getReg();
1571 MCRegister Rj = Inst.getOperand(IsAMCAS ? 3 : 2).getReg();
1572 if ((Rd == Rk || Rd == Rj) && Rd != LoongArch::R0)
1573 return Match_RequiresAMORdDifferRkRj;
1574 }
1575 break;
1576 case LoongArch::PseudoLA_TLS_DESC:
1577 case LoongArch::PseudoLA_TLS_DESC_LARGE: {
1578 MCRegister Rd = Inst.getOperand(0).getReg();
1579 if (Rd != LoongArch::R4)
1580 return Match_RequiresLAORdR4;
1581 break;
1582 }
1583 case LoongArch::PseudoLA_PCREL_LARGE:
1584 case LoongArch::PseudoLA_GOT_LARGE:
1585 case LoongArch::PseudoLA_TLS_IE_LARGE:
1586 case LoongArch::PseudoLA_TLS_LD_LARGE:
1587 case LoongArch::PseudoLA_TLS_GD_LARGE: {
1588 MCRegister Rd = Inst.getOperand(0).getReg();
1589 MCRegister Rj = Inst.getOperand(1).getReg();
1590 if (Rd == Rj)
1591 return Match_RequiresLAORdDifferRj;
1592 break;
1593 }
1594 case LoongArch::CSRXCHG:
1595 case LoongArch::GCSRXCHG: {
1596 MCRegister Rj = Inst.getOperand(2).getReg();
1597 if (Rj == LoongArch::R0 || Rj == LoongArch::R1)
1598 return Match_RequiresOpnd2NotR0R1;
1599 return Match_Success;
1600 }
1601 case LoongArch::BSTRINS_W:
1602 case LoongArch::BSTRINS_D:
1603 case LoongArch::BSTRPICK_W:
1604 case LoongArch::BSTRPICK_D: {
1605 unsigned Opc = Inst.getOpcode();
1606 const signed Msb =
1607 (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
1608 ? Inst.getOperand(3).getImm()
1609 : Inst.getOperand(2).getImm();
1610 const signed Lsb =
1611 (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
1612 ? Inst.getOperand(4).getImm()
1613 : Inst.getOperand(3).getImm();
1614 if (Msb < Lsb)
1615 return Match_RequiresMsbNotLessThanLsb;
1616 return Match_Success;
1617 }
1618 }
1619
1620 return Match_Success;
1621}
1622
1623unsigned
1624LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
1625 unsigned Kind) {
1626 LoongArchOperand &Op = static_cast<LoongArchOperand &>(AsmOp);
1627 if (!Op.isReg())
1628 return Match_InvalidOperand;
1629
1630 MCRegister Reg = Op.getReg();
1631 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1632 // register from FPR32 to FPR64 if necessary.
1633 if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) &&
1634 Kind == MCK_FPR64) {
1635 Op.setReg(convertFPR32ToFPR64(Reg));
1636 return Match_Success;
1637 }
1638
1639 if (Kind == MCK_GPRNoR0R1 && (Reg == LoongArch::R0 || Reg == LoongArch::R1))
1640 return Match_RequiresOpnd2NotR0R1;
1641
1642 return Match_InvalidOperand;
1643}
1644
1645bool LoongArchAsmParser::generateImmOutOfRangeError(
1646 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
1647 const Twine &Msg = "immediate must be an integer in the range") {
1648 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1649 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
1650}
1651
1652bool LoongArchAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1654 MCStreamer &Out,
1655 uint64_t &ErrorInfo,
1656 bool MatchingInlineAsm) {
1657 MCInst Inst;
1658 FeatureBitset MissingFeatures;
1659
1660 auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
1661 MatchingInlineAsm);
1662 switch (Result) {
1663 default:
1664 break;
1665 case Match_Success:
1666 return processInstruction(Inst, IDLoc, Operands, Out);
1667 case Match_MissingFeature: {
1668 assert(MissingFeatures.any() && "Unknown missing features!");
1669 bool FirstFeature = true;
1670 std::string Msg = "instruction requires the following:";
1671 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
1672 if (MissingFeatures[i]) {
1673 Msg += FirstFeature ? " " : ", ";
1674 Msg += getSubtargetFeatureName(i);
1675 FirstFeature = false;
1676 }
1677 }
1678 return Error(IDLoc, Msg);
1679 }
1680 case Match_MnemonicFail: {
1681 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1682 std::string Suggestion = LoongArchMnemonicSpellCheck(
1683 ((LoongArchOperand &)*Operands[0]).getToken(), FBS, 0);
1684 return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
1685 }
1686 case Match_InvalidOperand: {
1687 SMLoc ErrorLoc = IDLoc;
1688 if (ErrorInfo != ~0ULL) {
1689 if (ErrorInfo >= Operands.size())
1690 return Error(ErrorLoc, "too few operands for instruction");
1691
1692 ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1693 if (ErrorLoc == SMLoc())
1694 ErrorLoc = IDLoc;
1695 }
1696 return Error(ErrorLoc, "invalid operand for instruction");
1697 }
1698 }
1699
1700 // Handle the case when the error message is of specific type
1701 // other than the generic Match_InvalidOperand, and the
1702 // corresponding operand is missing.
1703 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1704 SMLoc ErrorLoc = IDLoc;
1705 if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())
1706 return Error(ErrorLoc, "too few operands for instruction");
1707 }
1708
1709 switch (Result) {
1710 default:
1711 break;
1712 case Match_RequiresMsbNotLessThanLsb: {
1713 SMLoc ErrorStart = Operands[3]->getStartLoc();
1714 return Error(ErrorStart, "msb is less than lsb",
1715 SMRange(ErrorStart, Operands[4]->getEndLoc()));
1716 }
1717 case Match_RequiresOpnd2NotR0R1:
1718 return Error(Operands[2]->getStartLoc(), "must not be $r0 or $r1");
1719 case Match_RequiresAMORdDifferRkRj:
1720 return Error(Operands[1]->getStartLoc(),
1721 "$rd must be different from both $rk and $rj");
1722 case Match_RequiresLAORdDifferRj:
1723 return Error(Operands[1]->getStartLoc(), "$rd must be different from $rj");
1724 case Match_RequiresLAORdR4:
1725 return Error(Operands[1]->getStartLoc(), "$rd must be $r4");
1726 case Match_InvalidUImm1:
1727 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1728 /*Upper=*/(1 << 1) - 1);
1729 case Match_InvalidUImm2:
1730 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1731 /*Upper=*/(1 << 2) - 1);
1732 case Match_InvalidUImm2plus1:
1733 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/1,
1734 /*Upper=*/(1 << 2));
1735 case Match_InvalidUImm3:
1736 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1737 /*Upper=*/(1 << 3) - 1);
1738 case Match_InvalidUImm4:
1739 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1740 /*Upper=*/(1 << 4) - 1);
1741 case Match_InvalidUImm5:
1742 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1743 /*Upper=*/(1 << 5) - 1);
1744 case Match_InvalidUImm6:
1745 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1746 /*Upper=*/(1 << 6) - 1);
1747 case Match_InvalidUImm7:
1748 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1749 /*Upper=*/(1 << 7) - 1);
1750 case Match_InvalidUImm8:
1751 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1752 /*Upper=*/(1 << 8) - 1);
1753 case Match_InvalidUImm12:
1754 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1755 /*Upper=*/(1 << 12) - 1);
1756 case Match_InvalidUImm12ori:
1757 return generateImmOutOfRangeError(
1758 Operands, ErrorInfo, /*Lower=*/0,
1759 /*Upper=*/(1 << 12) - 1,
1760 "operand must be a symbol with modifier (e.g. %abs_lo12) or an "
1761 "integer in the range");
1762 case Match_InvalidUImm14:
1763 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1764 /*Upper=*/(1 << 14) - 1);
1765 case Match_InvalidUImm15:
1766 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1767 /*Upper=*/(1 << 15) - 1);
1768 case Match_InvalidSImm5:
1769 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 4),
1770 /*Upper=*/(1 << 4) - 1);
1771 case Match_InvalidSImm8:
1772 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 7),
1773 /*Upper=*/(1 << 7) - 1);
1774 case Match_InvalidSImm8lsl1:
1775 return generateImmOutOfRangeError(
1776 Operands, ErrorInfo, /*Lower=*/-(1 << 8), /*Upper=*/(1 << 8) - 2,
1777 "immediate must be a multiple of 2 in the range");
1778 case Match_InvalidSImm8lsl2:
1779 return generateImmOutOfRangeError(
1780 Operands, ErrorInfo, /*Lower=*/-(1 << 9), /*Upper=*/(1 << 9) - 4,
1781 "immediate must be a multiple of 4 in the range");
1782 case Match_InvalidSImm10:
1783 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 9),
1784 /*Upper=*/(1 << 9) - 1);
1785 case Match_InvalidSImm8lsl3:
1786 return generateImmOutOfRangeError(
1787 Operands, ErrorInfo, /*Lower=*/-(1 << 10), /*Upper=*/(1 << 10) - 8,
1788 "immediate must be a multiple of 8 in the range");
1789 case Match_InvalidSImm9lsl3:
1790 return generateImmOutOfRangeError(
1791 Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 8,
1792 "immediate must be a multiple of 8 in the range");
1793 case Match_InvalidSImm10lsl2:
1794 return generateImmOutOfRangeError(
1795 Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 4,
1796 "immediate must be a multiple of 4 in the range");
1797 case Match_InvalidSImm11lsl1:
1798 return generateImmOutOfRangeError(
1799 Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 2,
1800 "immediate must be a multiple of 2 in the range");
1801 case Match_InvalidSImm12:
1802 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1803 /*Upper=*/(1 << 11) - 1);
1804 case Match_InvalidSImm12addlike:
1805 return generateImmOutOfRangeError(
1806 Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1807 /*Upper=*/(1 << 11) - 1,
1808 "operand must be a symbol with modifier (e.g. %pc_lo12) or an integer "
1809 "in the range");
1810 case Match_InvalidSImm12lu52id:
1811 return generateImmOutOfRangeError(
1812 Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1813 /*Upper=*/(1 << 11) - 1,
1814 "operand must be a symbol with modifier (e.g. %pc64_hi12) or an "
1815 "integer in the range");
1816 case Match_InvalidSImm13:
1817 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 12),
1818 /*Upper=*/(1 << 12) - 1);
1819 case Match_InvalidSImm14lsl2:
1820 return generateImmOutOfRangeError(
1821 Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4,
1822 "immediate must be a multiple of 4 in the range");
1823 case Match_InvalidSImm16:
1824 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 15),
1825 /*Upper=*/(1 << 15) - 1);
1826 case Match_InvalidSImm16lsl2:
1827 return generateImmOutOfRangeError(
1828 Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4,
1829 "operand must be a symbol with modifier (e.g. %b16) or an integer "
1830 "in the range");
1831 case Match_InvalidSImm20:
1832 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1833 /*Upper=*/(1 << 19) - 1);
1834 case Match_InvalidSImm20lu12iw:
1835 return generateImmOutOfRangeError(
1836 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1837 /*Upper=*/(1 << 19) - 1,
1838 "operand must be a symbol with modifier (e.g. %abs_hi20) or an integer "
1839 "in the range");
1840 case Match_InvalidSImm20lu32id:
1841 return generateImmOutOfRangeError(
1842 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1843 /*Upper=*/(1 << 19) - 1,
1844 "operand must be a symbol with modifier (e.g. %abs64_lo20) or an "
1845 "integer in the range");
1846 case Match_InvalidSImm20pcalau12i:
1847 return generateImmOutOfRangeError(
1848 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1849 /*Upper=*/(1 << 19) - 1,
1850 "operand must be a symbol with modifier (e.g. %pc_hi20) or an integer "
1851 "in the range");
1852 case Match_InvalidSImm20pcaddu18i:
1853 return generateImmOutOfRangeError(
1854 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1855 /*Upper=*/(1 << 19) - 1,
1856 "operand must be a symbol with modifier (e.g. %call36) or an integer "
1857 "in the range");
1858 case Match_InvalidSImm20pcaddi:
1859 return generateImmOutOfRangeError(
1860 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1861 /*Upper=*/(1 << 19) - 1,
1862 "operand must be a symbol with modifier (e.g. %pcrel_20) or an integer "
1863 "in the range");
1864 case Match_InvalidSImm21lsl2:
1865 return generateImmOutOfRangeError(
1866 Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4,
1867 "operand must be a symbol with modifier (e.g. %b21) or an integer "
1868 "in the range");
1869 case Match_InvalidSImm26Operand:
1870 return generateImmOutOfRangeError(
1871 Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4,
1872 "operand must be a bare symbol name or an immediate must be a multiple "
1873 "of 4 in the range");
1874 case Match_InvalidImm32: {
1875 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1876 return Error(ErrorLoc, "operand must be a 32 bit immediate");
1877 }
1878 case Match_InvalidImm64: {
1879 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1880 return Error(ErrorLoc, "operand must be a 64 bit immediate");
1881 }
1882 case Match_InvalidBareSymbol: {
1883 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1884 return Error(ErrorLoc, "operand must be a bare symbol name");
1885 }
1886 case Match_InvalidTPRelAddSymbol: {
1887 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1888 return Error(ErrorLoc, "operand must be a symbol with %le_add_r modifier");
1889 }
1890 }
1891 llvm_unreachable("Unknown match type detected!");
1892}
1893
1894bool LoongArchAsmParser::parseDirectiveOption() {
1895 MCAsmParser &Parser = getParser();
1896 // Get the option token.
1897 AsmToken Tok = Parser.getTok();
1898
1899 // At the moment only identifiers are supported.
1900 if (parseToken(AsmToken::Identifier, "expected identifier"))
1901 return true;
1902
1903 StringRef Option = Tok.getIdentifier();
1904
1905 if (Option == "push") {
1906 if (Parser.parseEOL())
1907 return true;
1908
1909 getTargetStreamer().emitDirectiveOptionPush();
1910 pushFeatureBits();
1911 return false;
1912 }
1913
1914 if (Option == "pop") {
1915 SMLoc StartLoc = Parser.getTok().getLoc();
1916 if (Parser.parseEOL())
1917 return true;
1918
1919 getTargetStreamer().emitDirectiveOptionPop();
1920 if (popFeatureBits())
1921 return Error(StartLoc, ".option pop with no .option push");
1922
1923 return false;
1924 }
1925
1926 if (Option == "relax") {
1927 if (Parser.parseEOL())
1928 return true;
1929
1930 getTargetStreamer().emitDirectiveOptionRelax();
1931 setFeatureBits(LoongArch::FeatureRelax, "relax");
1932 return false;
1933 }
1934
1935 if (Option == "norelax") {
1936 if (Parser.parseEOL())
1937 return true;
1938
1939 getTargetStreamer().emitDirectiveOptionNoRelax();
1940 clearFeatureBits(LoongArch::FeatureRelax, "relax");
1941 return false;
1942 }
1943
1944 // Unknown option.
1945 Warning(Parser.getTok().getLoc(),
1946 "unknown option, expected 'push', 'pop', 'relax' or 'norelax'");
1947 Parser.eatToEndOfStatement();
1948 return false;
1949}
1950
1951ParseStatus LoongArchAsmParser::parseDirective(AsmToken DirectiveID) {
1952 if (DirectiveID.getString() == ".option")
1953 return parseDirectiveOption();
1954
1955 return ParseStatus::NoMatch;
1956}
1957
1958extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
static MCRegister MatchRegisterName(StringRef Name)
static const char * getSubtargetFeatureName(uint64_t Val)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
Definition CSEInfo.cpp:27
static bool matchRegisterNameHelper(const MCSubtargetInfo &STI, MCRegister &Reg, StringRef Name)
static MCRegister convertFPR32ToFPR64(MCRegister Reg)
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
#define RegName(no)
static LVOptions Options
Definition LVOptions.cpp:25
static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name)
static MCRegister convertFPR32ToFPR64(MCRegister Reg)
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmParser()
mir Rename Register Operands
Register Reg
Promote Memory to Register
Definition Mem2Reg.cpp:110
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
#define P(N)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:480
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
bool parseImmediate(MCInst &MI, uint64_t &Size, ArrayRef< uint8_t > Bytes)
static bool is64Bit(const char *name)
Target independent representation for an assembler token.
Definition MCAsmMacro.h:22
LLVM_ABI SMLoc getLoc() const
Definition AsmLexer.cpp:32
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition MCAsmMacro.h:103
LLVM_ABI SMLoc getEndLoc() const
Definition AsmLexer.cpp:34
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
Definition MCAsmMacro.h:92
Base class for user error types.
Definition Error.h:354
constexpr size_t size() const
static const char * getRegisterName(MCRegister Reg)
static const LoongArchMCExpr * create(const MCExpr *Expr, uint16_t S, MCContext &Ctx, bool Hint=false)
void printExpr(raw_ostream &, const MCExpr &) const
virtual void eatToEndOfStatement()=0
Skip to the end of the current statement, for error recovery.
const AsmToken & getTok() const
Get the current AsmToken from the stream.
virtual void addAliasForDirective(StringRef Directive, StringRef Alias)=0
LLVM_ABI bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm) const
Try to evaluate the expression to a relocatable value, i.e.
Definition MCExpr.cpp:450
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
void setLoc(SMLoc loc)
Definition MCInst.h:207
unsigned getOpcode() const
Definition MCInst.h:202
void addOperand(const MCOperand Op)
Definition MCInst.h:215
const MCOperand & getOperand(unsigned i) const
Definition MCInst.h:210
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition MCInstrInfo.h:90
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
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
const MCExpr * getExpr() const
Definition MCInst.h:118
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:33
Streaming machine code generation interface.
Definition MCStreamer.h:220
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
MCTargetStreamer * getTargetStreamer()
Definition MCStreamer.h:324
Generic base class for all target subtargets.
const FeatureBitset & getFeatureBits() const
FeatureBitset ToggleFeature(uint64_t FB)
Toggle a feature and return the re-computed feature bits.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:214
MCTargetAsmParser - Generic interface to target specific assembly parsers.
Target specific streamer interface.
Definition MCStreamer.h:93
MCStreamer & getStreamer()
Definition MCStreamer.h:101
uint32_t getSpecifier() const
Definition MCValue.h:46
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:23
static SMLoc getFromPointer(const char *Ptr)
Definition SMLoc.h:36
constexpr const char * getPointer() const
Definition SMLoc.h:34
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
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.
static bool isAMCAS(uint64_t TSFlags)
static bool isSubjectToAMORdConstraint(uint64_t TSFlags)
InstSeq generateInstSeq(int64_t Val)
uint16_t parseSpecifier(StringRef name)
@ CE
Windows NT (Windows on ARM)
Definition MCAsmInfo.h:48
Context & getContext() const
Definition BasicBlock.h:99
This is an optimization pass for GlobalISel generic memory operations.
Target & getTheLoongArch64Target()
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:174
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:644
SmallVectorImpl< std::unique_ptr< MCParsedAsmOperand > > OperandVector
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:198
Target & getTheLoongArch32Target()
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:191
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:583
#define N
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...