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
9#include "MCTargetDesc/LoongArchBaseInfo.h"
10#include "MCTargetDesc/LoongArchInstPrinter.h"
11#include "MCTargetDesc/LoongArchMCAsmInfo.h"
12#include "MCTargetDesc/LoongArchMCTargetDesc.h"
13#include "MCTargetDesc/LoongArchMatInt.h"
14#include "MCTargetDesc/LoongArchTargetStreamer.h"
15#include "TargetInfo/LoongArchTargetInfo.h"
16#include "llvm/BinaryFormat/ELF.h"
17#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCInstBuilder.h"
19#include "llvm/MC/MCInstrInfo.h"
20#include "llvm/MC/MCParser/AsmLexer.h"
21#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
22#include "llvm/MC/MCParser/MCTargetAsmParser.h"
23#include "llvm/MC/MCRegisterInfo.h"
24#include "llvm/MC/MCStreamer.h"
25#include "llvm/MC/MCSubtargetInfo.h"
26#include "llvm/MC/MCValue.h"
27#include "llvm/MC/TargetRegistry.h"
28#include "llvm/Support/Casting.h"
29#include "llvm/Support/Compiler.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(Feature: 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,
64 OperandVector &Operands, MCStreamer &Out,
65 uint64_t &ErrorInfo,
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);
89 ParseStatus parseImmediate(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(FB: STI.ToggleFeature(FS: 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(FB: STI.ToggleFeature(FS: FeatureString)));
111 }
112 }
113
114 void pushFeatureBits() {
115 FeatureBitStack.push_back(Elt: 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(FB: 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,
192 LoongArchMCExpr::Specifier &Kind);
193
194 LoongArchAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
195 const MCInstrInfo &MII, const MCTargetOptions &Options)
196 : MCTargetAsmParser(Options, STI, MII) {
197 Parser.addAliasForDirective(Directive: ".half", Alias: ".2byte");
198 Parser.addAliasForDirective(Directive: ".hword", Alias: ".2byte");
199 Parser.addAliasForDirective(Directive: ".word", Alias: ".4byte");
200 Parser.addAliasForDirective(Directive: ".dword", Alias: ".8byte");
201
202 // Initialize the set of available features.
203 setAvailableFeatures(ComputeAvailableFeatures(FB: 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: Reg.RegNum);
242 }
243
244 static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
245 LoongArchMCExpr::Specifier &VK) {
246 if (auto *LE = dyn_cast<LoongArchMCExpr>(Val: Expr)) {
247 VK = LE->getSpecifier();
248 return false;
249 }
250
251 if (auto CE = dyn_cast<MCConstantExpr>(Val: 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;
264 LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;
265 bool IsConstantImm = evaluateConstantImm(Expr: getImm(), Imm, VK);
266 return IsConstantImm && isUInt<N>(Imm - P) &&
267 VK == LoongArchMCExpr::VK_None;
268 }
269
270 template <unsigned N, unsigned S = 0> bool isSImm() const {
271 if (!isImm())
272 return false;
273
274 int64_t Imm;
275 LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;
276 bool IsConstantImm = evaluateConstantImm(Expr: getImm(), Imm, VK);
277 return IsConstantImm && isShiftedInt<N, S>(Imm) &&
278 VK == LoongArchMCExpr::VK_None;
279 }
280
281 bool isBareSymbol() const {
282 int64_t Imm;
283 LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;
284 // Must be of 'immediate' type but not a constant.
285 if (!isImm() || evaluateConstantImm(Expr: getImm(), Imm, VK))
286 return false;
287 return LoongArchAsmParser::classifySymbolRef(Expr: getImm(), Kind&: VK) &&
288 VK == LoongArchMCExpr::VK_None;
289 }
290
291 bool isTPRelAddSymbol() const {
292 int64_t Imm;
293 LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;
294 // Must be of 'immediate' type but not a constant.
295 if (!isImm() || evaluateConstantImm(Expr: getImm(), Imm, VK))
296 return false;
297 return LoongArchAsmParser::classifySymbolRef(Expr: getImm(), Kind&: 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;
326 LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;
327 bool IsConstantImm = evaluateConstantImm(Expr: 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>(x: Imm) && IsValidKind
335 : LoongArchAsmParser::classifySymbolRef(Expr: getImm(), Kind&: VK) &&
336 IsValidKind;
337 }
338
339 bool isSImm12lu52id() const {
340 if (!isImm())
341 return false;
342
343 int64_t Imm;
344 LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;
345 bool IsConstantImm = evaluateConstantImm(Expr: 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>(x: Imm) && IsValidKind
356 : LoongArchAsmParser::classifySymbolRef(Expr: getImm(), Kind&: 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;
367 LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;
368 bool IsConstantImm = evaluateConstantImm(Expr: 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>(x: Imm) && IsValidKind
377 : LoongArchAsmParser::classifySymbolRef(Expr: getImm(), Kind&: 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;
393 LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;
394 bool IsConstantImm = evaluateConstantImm(Expr: 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>(x: Imm) && IsValidKind
400 : LoongArchAsmParser::classifySymbolRef(Expr: getImm(), Kind&: 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;
411 LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;
412 bool IsConstantImm = evaluateConstantImm(Expr: 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>(x: Imm) && IsValidKind
421 : LoongArchAsmParser::classifySymbolRef(Expr: getImm(), Kind&: VK) &&
422 IsValidKind;
423 }
424
425 bool isSImm20lu12iw() const {
426 if (!isImm())
427 return false;
428
429 int64_t Imm;
430 LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;
431 bool IsConstantImm = evaluateConstantImm(Expr: 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>(x: Imm) && IsValidKind
440 : LoongArchAsmParser::classifySymbolRef(Expr: getImm(), Kind&: VK) &&
441 IsValidKind;
442 }
443
444 bool isSImm20lu32id() const {
445 if (!isImm())
446 return false;
447
448 int64_t Imm;
449 LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;
450 bool IsConstantImm = evaluateConstantImm(Expr: 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>(x: Imm) && IsValidKind
462 : LoongArchAsmParser::classifySymbolRef(Expr: getImm(), Kind&: VK) &&
463 IsValidKind;
464 }
465
466 bool isSImm20pcaddu18i() const {
467 if (!isImm())
468 return false;
469
470 int64_t Imm;
471 LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;
472 bool IsConstantImm = evaluateConstantImm(Expr: getImm(), Imm, VK);
473 bool IsValidKind =
474 VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_CALL36;
475
476 return IsConstantImm
477 ? isInt<20>(x: Imm) && IsValidKind
478 : LoongArchAsmParser::classifySymbolRef(Expr: getImm(), Kind&: VK) &&
479 IsValidKind;
480 }
481
482 bool isSImm20pcaddi() const {
483 if (!isImm())
484 return false;
485
486 int64_t Imm;
487 LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;
488 bool IsConstantImm = evaluateConstantImm(Expr: 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>(x: Imm) && IsValidKind
496 : LoongArchAsmParser::classifySymbolRef(Expr: getImm(), Kind&: VK) &&
497 IsValidKind;
498 }
499
500 bool isSImm21lsl2() const {
501 if (!isImm())
502 return false;
503
504 int64_t Imm;
505 LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;
506 bool IsConstantImm = evaluateConstantImm(Expr: getImm(), Imm, VK);
507 bool IsValidKind = VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_B21;
508 return IsConstantImm
509 ? isShiftedInt<21, 2>(x: Imm) && IsValidKind
510 : LoongArchAsmParser::classifySymbolRef(Expr: getImm(), Kind&: VK) &&
511 IsValidKind;
512 }
513
514 bool isSImm26Operand() const {
515 if (!isImm())
516 return false;
517
518 int64_t Imm;
519 LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;
520 bool IsConstantImm = evaluateConstantImm(Expr: getImm(), Imm, VK);
521 bool IsValidKind = VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_B26;
522 return IsConstantImm
523 ? isShiftedInt<26, 2>(x: Imm) && IsValidKind
524 : LoongArchAsmParser::classifySymbolRef(Expr: getImm(), Kind&: 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;
533 LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;
534 bool IsConstantImm = evaluateConstantImm(Expr: 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)
561 return LoongArchInstPrinter::getRegisterName(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>(args: 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>(args: 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>(args: 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>(Val: Expr))
607 Inst.addOperand(Op: MCOperand::createImm(Val: CE->getValue()));
608 else
609 Inst.addOperand(Op: MCOperand::createExpr(Val: Expr));
610 }
611
612 // Used by the TableGen Code.
613 void addRegOperands(MCInst &Inst, unsigned N) const {
614 assert(N == 1 && "Invalid number of operands!");
615 Inst.addOperand(Op: MCOperand::createReg(Reg: getReg()));
616 }
617 void addImmOperands(MCInst &Inst, unsigned N) const {
618 assert(N == 1 && "Invalid number of operands!");
619 addExpr(Inst, Expr: 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
630static MCRegister convertFPR32ToFPR64(MCRegister Reg) {
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.
638static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) {
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(L: getLoc(), Msg: "invalid register name");
656
657 if (!LoongArchMCRegisterClasses[LoongArch::GPRRegClassID].contains(Reg) &&
658 !LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg))
659 return Error(L: getLoc(), Msg: "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(T: AsmToken::Dollar);
672 if (getLexer().getKind() != AsmToken::Identifier)
673 return ParseStatus::NoMatch;
674
675 StringRef Name = Tok.getIdentifier();
676 if (matchRegisterNameHelper(RegNo&: Reg, Name))
677 return ParseStatus::NoMatch;
678
679 getParser().Lex(); // Eat identifier token.
680 return ParseStatus::Success;
681}
682
683bool LoongArchAsmParser::classifySymbolRef(const MCExpr *Expr,
684 LoongArchMCExpr::Specifier &Kind) {
685 Kind = LoongArchMCExpr::VK_None;
686
687 if (const LoongArchMCExpr *RE = dyn_cast<LoongArchMCExpr>(Val: Expr)) {
688 Kind = RE->getSpecifier();
689 Expr = RE->getSubExpr();
690 }
691
692 MCValue Res;
693 if (Expr->evaluateAsRelocatable(Res, Asm: nullptr))
694 return Res.getSpecifier() == LoongArchMCExpr::VK_None;
695 return false;
696}
697
698ParseStatus LoongArchAsmParser::parseRegister(OperandVector &Operands) {
699 if (!parseOptionalToken(T: AsmToken::Dollar))
700 return ParseStatus::NoMatch;
701 if (getLexer().getKind() != AsmToken::Identifier)
702 return ParseStatus::NoMatch;
703
704 StringRef Name = getLexer().getTok().getIdentifier();
705 MCRegister RegNo;
706 matchRegisterNameHelper(RegNo, Name);
707 if (RegNo == LoongArch::NoRegister)
708 return ParseStatus::NoMatch;
709
710 SMLoc S = getLoc();
711 SMLoc E = SMLoc::getFromPointer(Ptr: S.getPointer() + Name.size());
712 getLexer().Lex();
713 Operands.push_back(Elt: LoongArchOperand::createReg(Reg: RegNo, S, E));
714
715 return ParseStatus::Success;
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:
725 return ParseStatus::NoMatch;
726 case AsmToken::LParen:
727 case AsmToken::Dot:
728 case AsmToken::Minus:
729 case AsmToken::Plus:
730 case AsmToken::Exclaim:
731 case AsmToken::Tilde:
732 case AsmToken::Integer:
733 case AsmToken::String:
734 case AsmToken::Identifier:
735 if (getParser().parseExpression(Res, EndLoc&: E))
736 return ParseStatus::Failure;
737 break;
738 case AsmToken::Percent:
739 return parseOperandWithModifier(Operands);
740 }
741
742 Operands.push_back(Elt: LoongArchOperand::createImm(Val: Res, S, E));
743 return ParseStatus::Success;
744}
745
746ParseStatus
747LoongArchAsmParser::parseOperandWithModifier(OperandVector &Operands) {
748 SMLoc S = getLoc();
749 SMLoc E;
750
751 if (getLexer().getKind() != AsmToken::Percent)
752 return Error(L: getLoc(), Msg: "expected '%' for operand modifier");
753
754 getParser().Lex(); // Eat '%'
755
756 if (getLexer().getKind() != AsmToken::Identifier)
757 return Error(L: getLoc(), Msg: "expected valid identifier for operand modifier");
758 StringRef Identifier = getParser().getTok().getIdentifier();
759 auto VK = LoongArch::parseSpecifier(name: Identifier);
760 if (VK == LoongArchMCExpr::VK_None)
761 return Error(L: getLoc(), Msg: "invalid relocation specifier");
762
763 getParser().Lex(); // Eat the identifier
764 if (getLexer().getKind() != AsmToken::LParen)
765 return Error(L: getLoc(), Msg: "expected '('");
766 getParser().Lex(); // Eat '('
767
768 const MCExpr *SubExpr;
769 if (getParser().parseParenExpression(Res&: SubExpr, EndLoc&: E))
770 return ParseStatus::Failure;
771
772 const MCExpr *ModExpr = LoongArchMCExpr::create(Expr: SubExpr, S: VK, Ctx&: getContext());
773 Operands.push_back(Elt: LoongArchOperand::createImm(Val: ModExpr, S, E));
774 return ParseStatus::Success;
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)
785 return ParseStatus::NoMatch;
786
787 StringRef Identifier;
788 if (getParser().parseIdentifier(Res&: Identifier))
789 return ParseStatus::Failure;
790
791 SMLoc E = SMLoc::getFromPointer(Ptr: S.getPointer() + Identifier.size());
792
793 MCSymbol *Sym = getContext().getOrCreateSymbol(Name: Identifier);
794 Res = MCSymbolRefExpr::create(Symbol: Sym, Ctx&: getContext());
795 Operands.push_back(Elt: LoongArchOperand::createImm(Val: Res, S, E));
796 return ParseStatus::Success;
797}
798
799ParseStatus LoongArchAsmParser::parseAtomicMemOp(OperandVector &Operands) {
800 // Parse "$r*".
801 if (!parseRegister(Operands).isSuccess())
802 return ParseStatus::NoMatch;
803
804 // If there is a next operand and it is 0, ignore it. Otherwise print a
805 // diagnostic message.
806 if (parseOptionalToken(T: AsmToken::Comma)) {
807 int64_t ImmVal;
808 SMLoc ImmStart = getLoc();
809 if (getParser().parseIntToken(V&: ImmVal, ErrMsg: "expected optional integer offset"))
810 return ParseStatus::Failure;
811 if (ImmVal)
812 return Error(L: ImmStart, Msg: "optional integer offset must be 0");
813 }
814
815 return ParseStatus::Success;
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(L: getLoc(), Msg: "unknown operand");
836}
837
838bool LoongArchAsmParser::parseInstruction(ParseInstructionInfo &Info,
839 StringRef Name, SMLoc NameLoc,
840 OperandVector &Operands) {
841 // First operand in MCInst is instruction mnemonic.
842 Operands.push_back(Elt: LoongArchOperand::createToken(Str: Name, S: NameLoc));
843
844 // If there are no more operands, then finish.
845 if (parseOptionalToken(T: AsmToken::EndOfStatement))
846 return false;
847
848 // Parse first operand.
849 if (parseOperand(Operands, Mnemonic: Name))
850 return true;
851
852 // Parse until end of statement, consuming commas between operands.
853 while (parseOptionalToken(T: AsmToken::Comma))
854 if (parseOperand(Operands, Mnemonic: Name))
855 return true;
856
857 // Parse end of statement and return successfully.
858 if (parseOptionalToken(T: AsmToken::EndOfStatement))
859 return false;
860
861 SMLoc Loc = getLexer().getLoc();
862 getParser().eatToEndOfStatement();
863 return Error(L: Loc, Msg: "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(Expr: Symbol, S: VK, Ctx, Hint: RelaxHint);
877 switch (Opc) {
878 default:
879 llvm_unreachable("unexpected opcode");
880 case LoongArch::PCALAU12I:
881 case LoongArch::LU12I_W:
882 Out.emitInstruction(Inst: MCInstBuilder(Opc).addReg(Reg: DestReg).addExpr(Val: LE),
883 STI: 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 Inst: MCInstBuilder(Opc).addReg(Reg: DestReg).addReg(Reg: DestReg).addImm(Val: 0),
892 STI: getSTI());
893 continue;
894 } else if (VK == ELF::R_LARCH_TLS_DESC_LD) {
895 Out.emitInstruction(Inst: MCInstBuilder(Opc)
896 .addReg(Reg: LoongArch::R1)
897 .addReg(Reg: DestReg)
898 .addExpr(Val: LE),
899 STI: getSTI());
900 continue;
901 }
902 Out.emitInstruction(
903 Inst: MCInstBuilder(Opc).addReg(Reg: DestReg).addReg(Reg: DestReg).addExpr(Val: LE),
904 STI: getSTI());
905 break;
906 }
907 case LoongArch::LU32I_D:
908 Out.emitInstruction(Inst: MCInstBuilder(Opc)
909 .addReg(Reg: DestReg == TmpReg ? DestReg : TmpReg)
910 .addReg(Reg: DestReg == TmpReg ? DestReg : TmpReg)
911 .addExpr(Val: LE),
912 STI: getSTI());
913 break;
914 case LoongArch::LU52I_D:
915 Out.emitInstruction(
916 Inst: MCInstBuilder(Opc).addReg(Reg: TmpReg).addReg(Reg: TmpReg).addExpr(Val: LE),
917 STI: getSTI());
918 break;
919 case LoongArch::ADDI_D:
920 Out.emitInstruction(
921 Inst: MCInstBuilder(Opc)
922 .addReg(Reg: TmpReg)
923 .addReg(Reg: DestReg == TmpReg ? TmpReg : LoongArch::R0)
924 .addExpr(Val: LE),
925 STI: getSTI());
926 break;
927 case LoongArch::ADD_D:
928 case LoongArch::LDX_D:
929 Out.emitInstruction(
930 Inst: MCInstBuilder(Opc).addReg(Reg: DestReg).addReg(Reg: DestReg).addReg(Reg: TmpReg),
931 STI: getSTI());
932 break;
933 case LoongArch::JIRL:
934 Out.emitInstruction(Inst: MCInstBuilder(Opc)
935 .addReg(Reg: LoongArch::R1)
936 .addReg(Reg: LoongArch::R1)
937 .addExpr(Val: LE),
938 STI: 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(i: 0).getReg();
955 const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_ABS
956 ? Inst.getOperand(i: 1).getExpr()
957 : Inst.getOperand(i: 2).getExpr();
958 InstSeq Insts;
959
960 Insts.push_back(
961 Elt: LoongArchAsmParser::Inst(LoongArch::LU12I_W, ELF::R_LARCH_ABS_HI20));
962 Insts.push_back(
963 Elt: LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_ABS_LO12));
964
965 if (is64Bit()) {
966 Insts.push_back(
967 Elt: LoongArchAsmParser::Inst(LoongArch::LU32I_D, ELF::R_LARCH_ABS64_LO20));
968 Insts.push_back(
969 Elt: LoongArchAsmParser::Inst(LoongArch::LU52I_D, ELF::R_LARCH_ABS64_HI12));
970 }
971
972 emitLAInstSeq(DestReg, TmpReg: DestReg, Symbol, Insts, IDLoc, Out);
973}
974
975void LoongArchAsmParser::emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc,
976 MCStreamer &Out) {
977 // la.pcrel $rd, sym
978 // expands to:
979 // pcalau12i $rd, %pc_hi20(sym)
980 // addi.w/d $rd, rd, %pc_lo12(sym)
981 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
982 const MCExpr *Symbol = Inst.getOperand(i: 1).getExpr();
983 InstSeq Insts;
984 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
985
986 Insts.push_back(
987 Elt: LoongArchAsmParser::Inst(LoongArch::PCALAU12I, ELF::R_LARCH_PCALA_HI20));
988 Insts.push_back(Elt: LoongArchAsmParser::Inst(ADDI, ELF::R_LARCH_PCALA_LO12));
989
990 emitLAInstSeq(DestReg, TmpReg: DestReg, Symbol, Insts, IDLoc, Out,
991 /*RelaxHint=*/true);
992}
993
994void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc,
995 MCStreamer &Out) {
996 // la.pcrel $rd, $rj, sym
997 // expands to:
998 // pcalau12i $rd, %pc_hi20(sym)
999 // addi.d $rj, $r0, %pc_lo12(sym)
1000 // lu32i.d $rj, %pc64_lo20(sym)
1001 // lu52i.d $rj, $rj, %pc64_hi12(sym)
1002 // add.d $rd, $rd, $rj
1003 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
1004 MCRegister TmpReg = Inst.getOperand(i: 1).getReg();
1005 const MCExpr *Symbol = Inst.getOperand(i: 2).getExpr();
1006 InstSeq Insts;
1007
1008 Insts.push_back(
1009 Elt: LoongArchAsmParser::Inst(LoongArch::PCALAU12I, ELF::R_LARCH_PCALA_HI20));
1010 Insts.push_back(
1011 Elt: LoongArchAsmParser::Inst(LoongArch::ADDI_D, ELF::R_LARCH_PCALA_LO12));
1012 Insts.push_back(
1013 Elt: LoongArchAsmParser::Inst(LoongArch::LU32I_D, ELF::R_LARCH_PCALA64_LO20));
1014 Insts.push_back(
1015 Elt: LoongArchAsmParser::Inst(LoongArch::LU52I_D, ELF::R_LARCH_PCALA64_HI12));
1016 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::ADD_D));
1017
1018 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1019}
1020
1021void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc,
1022 MCStreamer &Out) {
1023 // la.got $rd, sym
1024 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
1025 const MCExpr *Symbol = Inst.getOperand(i: 1).getExpr();
1026 InstSeq Insts;
1027 unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
1028
1029 if (getSTI().hasFeature(Feature: LoongArch::LaGlobalWithAbs)) {
1030 // with feature: +la-glabal-with-abs
1031 // for 32bit:
1032 // lu12i.w $rd, %got_hi20(sym)
1033 // ori $rd, $rd, %got_lo12(sym)
1034 // ld.w $rd, $rd, 0
1035 //
1036 // for 64bit:
1037 // lu12i.w $rd, %got_hi20(sym)
1038 // ori $rd, $rd, %got_lo12(sym)
1039 // lu32i.d $rd, %got64_lo20(sym)
1040 // lu52i.d $rd, $rd, %got64_hi12(sym)
1041 // ld.d $rd, $rd, 0
1042 Insts.push_back(
1043 Elt: LoongArchAsmParser::Inst(LoongArch::LU12I_W, ELF::R_LARCH_GOT_HI20));
1044 Insts.push_back(
1045 Elt: LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_GOT_LO12));
1046
1047 if (is64Bit()) {
1048 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::LU32I_D,
1049 ELF::R_LARCH_GOT64_LO20));
1050 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::LU52I_D,
1051 ELF::R_LARCH_GOT64_HI12));
1052 }
1053 Insts.push_back(Elt: LoongArchAsmParser::Inst(LD));
1054 emitLAInstSeq(DestReg, TmpReg: DestReg, Symbol, Insts, IDLoc, Out);
1055 return;
1056 }
1057 // expands to:
1058 // pcalau12i $rd, %got_pc_hi20(sym)
1059 // ld.w/d $rd, $rd, %got_pc_lo12(sym)
1060 Insts.push_back(
1061 Elt: LoongArchAsmParser::Inst(LoongArch::PCALAU12I, ELF::R_LARCH_GOT_PC_HI20));
1062 Insts.push_back(Elt: LoongArchAsmParser::Inst(LD, ELF::R_LARCH_GOT_PC_LO12));
1063
1064 emitLAInstSeq(DestReg, TmpReg: DestReg, Symbol, Insts, IDLoc, Out,
1065 /*RelaxHint=*/true);
1066}
1067
1068void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc,
1069 MCStreamer &Out) {
1070 // la.got $rd, $rj, sym
1071 // expands to:
1072 // pcalau12i $rd, %got_pc_hi20(sym)
1073 // addi.d $rj, $r0, %got_pc_lo12(sym)
1074 // lu32i.d $rj, %got64_pc_lo20(sym)
1075 // lu52i.d $rj, $rj, %got64_pc_hi12(sym)
1076 // ldx.d $rd, $rd, $rj
1077 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
1078 MCRegister TmpReg = Inst.getOperand(i: 1).getReg();
1079 const MCExpr *Symbol = Inst.getOperand(i: 2).getExpr();
1080 InstSeq Insts;
1081
1082 Insts.push_back(
1083 Elt: LoongArchAsmParser::Inst(LoongArch::PCALAU12I, ELF::R_LARCH_GOT_PC_HI20));
1084 Insts.push_back(
1085 Elt: LoongArchAsmParser::Inst(LoongArch::ADDI_D, ELF::R_LARCH_GOT_PC_LO12));
1086 Insts.push_back(
1087 Elt: LoongArchAsmParser::Inst(LoongArch::LU32I_D, ELF::R_LARCH_GOT64_PC_LO20));
1088 Insts.push_back(
1089 Elt: LoongArchAsmParser::Inst(LoongArch::LU52I_D, ELF::R_LARCH_GOT64_PC_HI12));
1090 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::LDX_D));
1091
1092 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1093}
1094
1095void LoongArchAsmParser::emitLoadAddressTLSLE(MCInst &Inst, SMLoc IDLoc,
1096 MCStreamer &Out) {
1097 // la.tls.le $rd, sym
1098 // expands to:
1099 // lu12i.w $rd, %le_hi20(sym)
1100 // ori $rd, $rd, %le_lo12(sym)
1101 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
1102 const MCExpr *Symbol = Inst.getOperand(i: 1).getExpr();
1103 InstSeq Insts;
1104
1105 Insts.push_back(
1106 Elt: LoongArchAsmParser::Inst(LoongArch::LU12I_W, ELF::R_LARCH_TLS_LE_HI20));
1107 Insts.push_back(
1108 Elt: LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_TLS_LE_LO12));
1109
1110 emitLAInstSeq(DestReg, TmpReg: DestReg, Symbol, Insts, IDLoc, Out);
1111}
1112
1113void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc,
1114 MCStreamer &Out) {
1115 // la.tls.ie $rd, sym
1116 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
1117 const MCExpr *Symbol = Inst.getOperand(i: 1).getExpr();
1118 InstSeq Insts;
1119 unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
1120
1121 if (getSTI().hasFeature(Feature: LoongArch::LaGlobalWithAbs)) {
1122 // with feature: +la-glabal-with-abs
1123 // for 32bit:
1124 // lu12i.w $rd, %ie_hi20(sym)
1125 // ori $rd, $rd, %ie_lo12(sym)
1126 // ld.w $rd, $rd, 0
1127 //
1128 // for 64bit:
1129 // lu12i.w $rd, %ie_hi20(sym)
1130 // ori $rd, $rd, %ie_lo12(sym)
1131 // lu32i.d $rd, %ie64_lo20(sym)
1132 // lu52i.d $rd, $rd, %ie64_hi12(sym)
1133 // ld.d $rd, $rd, 0
1134 Insts.push_back(
1135 Elt: LoongArchAsmParser::Inst(LoongArch::LU12I_W, ELF::R_LARCH_TLS_IE_HI20));
1136 Insts.push_back(
1137 Elt: LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_TLS_IE_LO12));
1138
1139 if (is64Bit()) {
1140 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::LU32I_D,
1141 ELF::R_LARCH_TLS_IE64_LO20));
1142 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::LU52I_D,
1143 ELF::R_LARCH_TLS_IE64_HI12));
1144 }
1145 Insts.push_back(Elt: LoongArchAsmParser::Inst(LD));
1146 emitLAInstSeq(DestReg, TmpReg: DestReg, Symbol, Insts, IDLoc, Out);
1147 return;
1148 }
1149
1150 // expands to:
1151 // pcalau12i $rd, %ie_pc_hi20(sym)
1152 // ld.w/d $rd, $rd, %ie_pc_lo12(sym)
1153 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
1154 ELF::R_LARCH_TLS_IE_PC_HI20));
1155 Insts.push_back(Elt: LoongArchAsmParser::Inst(LD, ELF::R_LARCH_TLS_IE_PC_LO12));
1156
1157 emitLAInstSeq(DestReg, TmpReg: DestReg, Symbol, Insts, IDLoc, Out,
1158 /*RelaxHint=*/true);
1159}
1160
1161void LoongArchAsmParser::emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc,
1162 MCStreamer &Out) {
1163 // la.tls.ie $rd, $rj, sym
1164 // expands to:
1165 // pcalau12i $rd, %ie_pc_hi20(sym)
1166 // addi.d $rj, $r0, %ie_pc_lo12(sym)
1167 // lu32i.d $rj, %ie64_pc_lo20(sym)
1168 // lu52i.d $rj, $rj, %ie64_pc_hi12(sym)
1169 // ldx.d $rd, $rd, $rj
1170 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
1171 MCRegister TmpReg = Inst.getOperand(i: 1).getReg();
1172 const MCExpr *Symbol = Inst.getOperand(i: 2).getExpr();
1173 InstSeq Insts;
1174
1175 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
1176 ELF::R_LARCH_TLS_IE_PC_HI20));
1177 Insts.push_back(
1178 Elt: LoongArchAsmParser::Inst(LoongArch::ADDI_D, ELF::R_LARCH_TLS_IE_PC_LO12));
1179 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::LU32I_D,
1180 ELF::R_LARCH_TLS_IE64_PC_LO20));
1181 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::LU52I_D,
1182 ELF::R_LARCH_TLS_IE64_PC_HI12));
1183 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::LDX_D));
1184
1185 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1186}
1187
1188void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc,
1189 MCStreamer &Out) {
1190 // la.tls.ld $rd, sym
1191 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
1192 const MCExpr *Symbol = Inst.getOperand(i: 1).getExpr();
1193 InstSeq Insts;
1194 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1195
1196 if (getSTI().hasFeature(Feature: LoongArch::LaGlobalWithAbs)) {
1197 // with feature: +la-glabal-with-abs
1198 // for 32bit:
1199 // lu12i.w $rd, %ld_hi20(sym)
1200 // ori $rd, $rd, %got_lo12(sym)
1201 //
1202 // for 64bit:
1203 // lu12i.w $rd, %ld_hi20(sym)
1204 // ori $rd, $rd, %got_lo12(sym)
1205 // lu32i.d $rd, %got64_lo20(sym)
1206 // lu52i.d $rd, $rd, %got64_hi12(sym)
1207 Insts.push_back(
1208 Elt: LoongArchAsmParser::Inst(LoongArch::LU12I_W, ELF::R_LARCH_TLS_LD_HI20));
1209 Insts.push_back(
1210 Elt: LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_GOT_LO12));
1211
1212 if (is64Bit()) {
1213 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::LU32I_D,
1214 ELF::R_LARCH_GOT64_LO20));
1215 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::LU52I_D,
1216 ELF::R_LARCH_GOT64_HI12));
1217 }
1218 emitLAInstSeq(DestReg, TmpReg: DestReg, Symbol, Insts, IDLoc, Out);
1219 return;
1220 }
1221
1222 // expands to:
1223 // pcalau12i $rd, %ld_pc_hi20(sym)
1224 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
1225 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
1226 ELF::R_LARCH_TLS_LD_PC_HI20));
1227 Insts.push_back(Elt: LoongArchAsmParser::Inst(ADDI, ELF::R_LARCH_GOT_PC_LO12));
1228
1229 emitLAInstSeq(DestReg, TmpReg: DestReg, Symbol, Insts, IDLoc, Out,
1230 /*RelaxHint=*/true);
1231}
1232
1233void LoongArchAsmParser::emitLoadAddressTLSLDLarge(MCInst &Inst, SMLoc IDLoc,
1234 MCStreamer &Out) {
1235 // la.tls.ld $rd, $rj, sym
1236 // expands to:
1237 // pcalau12i $rd, %ld_pc_hi20(sym)
1238 // addi.d $rj, $r0, %got_pc_lo12(sym)
1239 // lu32i.d $rj, %got64_pc_lo20(sym)
1240 // lu52i.d $rj, $rj, %got64_pc_hi12(sym)
1241 // add.d $rd, $rd, $rj
1242 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
1243 MCRegister TmpReg = Inst.getOperand(i: 1).getReg();
1244 const MCExpr *Symbol = Inst.getOperand(i: 2).getExpr();
1245 InstSeq Insts;
1246
1247 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
1248 ELF::R_LARCH_TLS_LD_PC_HI20));
1249 Insts.push_back(
1250 Elt: LoongArchAsmParser::Inst(LoongArch::ADDI_D, ELF::R_LARCH_GOT_PC_LO12));
1251 Insts.push_back(
1252 Elt: LoongArchAsmParser::Inst(LoongArch::LU32I_D, ELF::R_LARCH_GOT64_PC_LO20));
1253 Insts.push_back(
1254 Elt: LoongArchAsmParser::Inst(LoongArch::LU52I_D, ELF::R_LARCH_GOT64_PC_HI12));
1255 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::ADD_D));
1256
1257 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1258}
1259
1260void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc,
1261 MCStreamer &Out) {
1262 // la.tls.gd $rd, sym
1263 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
1264 const MCExpr *Symbol = Inst.getOperand(i: 1).getExpr();
1265 InstSeq Insts;
1266 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1267
1268 if (getSTI().hasFeature(Feature: LoongArch::LaGlobalWithAbs)) {
1269 // with feature: +la-glabal-with-abs
1270 // for 32bit:
1271 // lu12i.w $rd, %gd_hi20(sym)
1272 // ori $rd, $rd, %got_lo12(sym)
1273 //
1274 // for 64bit:
1275 // lu12i.w $rd, %gd_hi20(sym)
1276 // ori $rd, $rd, %got_lo12(sym)
1277 // lu32i.d $rd, %got64_lo20(sym)
1278 // lu52i.d $rd, $rd, %got64_hi12(sym)
1279 Insts.push_back(
1280 Elt: LoongArchAsmParser::Inst(LoongArch::LU12I_W, ELF::R_LARCH_TLS_GD_HI20));
1281 Insts.push_back(
1282 Elt: LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_GOT_LO12));
1283
1284 if (is64Bit()) {
1285 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::LU32I_D,
1286 ELF::R_LARCH_GOT64_LO20));
1287 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::LU52I_D,
1288 ELF::R_LARCH_GOT64_HI12));
1289 }
1290 emitLAInstSeq(DestReg, TmpReg: DestReg, Symbol, Insts, IDLoc, Out);
1291 return;
1292 }
1293
1294 // expands to:
1295 // pcalau12i $rd, %gd_pc_hi20(sym)
1296 // addi.w/d $rd, $rd, %got_pc_lo12(sym)
1297 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
1298 ELF::R_LARCH_TLS_GD_PC_HI20));
1299 Insts.push_back(Elt: LoongArchAsmParser::Inst(ADDI, ELF::R_LARCH_GOT_PC_LO12));
1300
1301 emitLAInstSeq(DestReg, TmpReg: DestReg, Symbol, Insts, IDLoc, Out,
1302 /*RelaxHint=*/true);
1303}
1304
1305void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc,
1306 MCStreamer &Out) {
1307 // la.tls.gd $rd, $rj, sym
1308 // expands to:
1309 // pcalau12i $rd, %gd_pc_hi20(sym)
1310 // addi.d $rj, $r0, %got_pc_lo12(sym)
1311 // lu32i.d $rj, %got64_pc_lo20(sym)
1312 // lu52i.d $rj, $rj, %got64_pc_hi12(sym)
1313 // add.d $rd, $rd, $rj
1314 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
1315 MCRegister TmpReg = Inst.getOperand(i: 1).getReg();
1316 const MCExpr *Symbol = Inst.getOperand(i: 2).getExpr();
1317 InstSeq Insts;
1318
1319 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
1320 ELF::R_LARCH_TLS_GD_PC_HI20));
1321 Insts.push_back(
1322 Elt: LoongArchAsmParser::Inst(LoongArch::ADDI_D, ELF::R_LARCH_GOT_PC_LO12));
1323 Insts.push_back(
1324 Elt: LoongArchAsmParser::Inst(LoongArch::LU32I_D, ELF::R_LARCH_GOT64_PC_LO20));
1325 Insts.push_back(
1326 Elt: LoongArchAsmParser::Inst(LoongArch::LU52I_D, ELF::R_LARCH_GOT64_PC_HI12));
1327 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::ADD_D));
1328
1329 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1330}
1331
1332void LoongArchAsmParser::emitLoadAddressTLSDesc(MCInst &Inst, SMLoc IDLoc,
1333 MCStreamer &Out) {
1334 // la.tls.desc $rd, sym
1335 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
1336 const MCExpr *Symbol = Inst.getOperand(i: 1).getExpr();
1337 unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
1338 unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
1339 InstSeq Insts;
1340
1341 if (getSTI().hasFeature(Feature: LoongArch::LaGlobalWithAbs)) {
1342 // with feature: +la-glabal-with-abs
1343 // for la32 expands to:
1344 // lu12i.w $rd, %desc_hi20(sym)
1345 // ori $rd, $rd, %desc_lo12(sym)
1346 // ld.w $ra, $rd, %desc_ld(sym)
1347 // jirl $ra, $ra, %desc_call(sym)
1348 //
1349 // for la64 expands to:
1350 // lu12i.w $rd, %desc_hi20(sym)
1351 // ori $rd, $rd, %desc_lo12(sym)
1352 // lu32i.d $rd, %desc64_lo20(sym)
1353 // lu52i.d $rd, $rd, %desc64_hi12(sym)
1354 // ld.d $ra, $rd, %desc_ld(sym)
1355 // jirl $ra, $ra, %desc_call(sym)
1356 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::LU12I_W,
1357 ELF::R_LARCH_TLS_DESC_HI20));
1358 Insts.push_back(
1359 Elt: LoongArchAsmParser::Inst(LoongArch::ORI, ELF::R_LARCH_TLS_DESC_LO12));
1360
1361 if (is64Bit()) {
1362 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::LU32I_D,
1363 ELF::R_LARCH_TLS_DESC64_LO20));
1364 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::LU52I_D,
1365 ELF::R_LARCH_TLS_DESC64_HI12));
1366 }
1367
1368 Insts.push_back(Elt: LoongArchAsmParser::Inst(LD, ELF::R_LARCH_TLS_DESC_LD));
1369 Insts.push_back(
1370 Elt: LoongArchAsmParser::Inst(LoongArch::JIRL, ELF::R_LARCH_TLS_DESC_CALL));
1371
1372 emitLAInstSeq(DestReg, TmpReg: DestReg, Symbol, Insts, IDLoc, Out);
1373 return;
1374 }
1375
1376 // expands to:
1377 // pcalau12i $rd, %desc_pc_hi20(sym)
1378 // addi.w/d $rd, $rd, %desc_pc_lo12(sym)
1379 // ld.w/d $ra, $rd, %desc_ld(sym)
1380 // jirl $ra, $ra, %desc_call(sym)
1381 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
1382 ELF::R_LARCH_TLS_DESC_PC_HI20));
1383 Insts.push_back(
1384 Elt: LoongArchAsmParser::Inst(ADDI, ELF::R_LARCH_TLS_DESC_PC_LO12));
1385 Insts.push_back(Elt: LoongArchAsmParser::Inst(LD, ELF::R_LARCH_TLS_DESC_LD));
1386 Insts.push_back(
1387 Elt: LoongArchAsmParser::Inst(LoongArch::JIRL, ELF::R_LARCH_TLS_DESC_CALL));
1388
1389 emitLAInstSeq(DestReg, TmpReg: DestReg, Symbol, Insts, IDLoc, Out,
1390 /*RelaxHint=*/true);
1391}
1392
1393void LoongArchAsmParser::emitLoadAddressTLSDescLarge(MCInst &Inst, SMLoc IDLoc,
1394 MCStreamer &Out) {
1395 // la.tls.desc $rd, $rj, sym
1396 // expands to:
1397 // pcalau12i $rd, %desc_pc_hi20(sym)
1398 // addi.d $rj, $r0, %desc_pc_lo12(sym)
1399 // lu32i.d $rj, %desc64_pc_lo20(sym)
1400 // lu52i.d $rj, $rj, %desc64_pc_hi12(sym)
1401 // add.d $rd, $rd, $rj
1402 // ld.w/d $ra, $rd, %desc_ld(sym)
1403 // jirl $ra, $ra, %desc_call(sym)
1404 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
1405 MCRegister TmpReg = Inst.getOperand(i: 1).getReg();
1406 const MCExpr *Symbol = Inst.getOperand(i: 2).getExpr();
1407 InstSeq Insts;
1408
1409 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
1410 ELF::R_LARCH_TLS_DESC_PC_HI20));
1411 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::ADDI_D,
1412 ELF::R_LARCH_TLS_DESC_PC_LO12));
1413 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::LU32I_D,
1414 ELF::R_LARCH_TLS_DESC64_PC_LO20));
1415 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::LU52I_D,
1416 ELF::R_LARCH_TLS_DESC64_PC_HI12));
1417 Insts.push_back(Elt: LoongArchAsmParser::Inst(LoongArch::ADD_D));
1418 Insts.push_back(
1419 Elt: LoongArchAsmParser::Inst(LoongArch::LD_D, ELF::R_LARCH_TLS_DESC_LD));
1420 Insts.push_back(
1421 Elt: LoongArchAsmParser::Inst(LoongArch::JIRL, ELF::R_LARCH_TLS_DESC_CALL));
1422
1423 emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
1424}
1425
1426void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc,
1427 MCStreamer &Out) {
1428 MCRegister DestReg = Inst.getOperand(i: 0).getReg();
1429 int64_t Imm = Inst.getOperand(i: 1).getImm();
1430 MCRegister SrcReg = LoongArch::R0;
1431
1432 if (Inst.getOpcode() == LoongArch::PseudoLI_W)
1433 Imm = SignExtend64<32>(x: Imm);
1434
1435 for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Val: Imm)) {
1436 switch (Inst.Opc) {
1437 case LoongArch::LU12I_W:
1438 Out.emitInstruction(
1439 Inst: MCInstBuilder(Inst.Opc).addReg(Reg: DestReg).addImm(Val: Inst.Imm), STI: getSTI());
1440 break;
1441 case LoongArch::ADDI_W:
1442 case LoongArch::ORI:
1443 case LoongArch::LU32I_D:
1444 case LoongArch::LU52I_D:
1445 Out.emitInstruction(
1446 Inst: MCInstBuilder(Inst.Opc).addReg(Reg: DestReg).addReg(Reg: SrcReg).addImm(
1447 Val: Inst.Imm),
1448 STI: getSTI());
1449 break;
1450 case LoongArch::BSTRINS_D:
1451 Out.emitInstruction(Inst: MCInstBuilder(Inst.Opc)
1452 .addReg(Reg: DestReg)
1453 .addReg(Reg: SrcReg)
1454 .addReg(Reg: SrcReg)
1455 .addImm(Val: Inst.Imm >> 32)
1456 .addImm(Val: Inst.Imm & 0xFF),
1457 STI: getSTI());
1458 break;
1459 default:
1460 llvm_unreachable("unexpected opcode generated by LoongArchMatInt");
1461 }
1462 SrcReg = DestReg;
1463 }
1464}
1465
1466void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc,
1467 MCStreamer &Out, bool IsTailCall) {
1468 // call36 sym
1469 // expands to:
1470 // pcaddu18i $ra, %call36(sym)
1471 // jirl $ra, $ra, 0
1472 //
1473 // tail36 $rj, sym
1474 // expands to:
1475 // pcaddu18i $rj, %call36(sym)
1476 // jirl $r0, $rj, 0
1477 MCRegister ScratchReg =
1478 IsTailCall ? Inst.getOperand(i: 0).getReg() : MCRegister(LoongArch::R1);
1479 const MCExpr *Sym =
1480 IsTailCall ? Inst.getOperand(i: 1).getExpr() : Inst.getOperand(i: 0).getExpr();
1481 const LoongArchMCExpr *LE = LoongArchMCExpr::create(
1482 Expr: Sym, S: ELF::R_LARCH_CALL36, Ctx&: getContext(), /*RelaxHint=*/Hint: true);
1483
1484 Out.emitInstruction(
1485 Inst: MCInstBuilder(LoongArch::PCADDU18I).addReg(Reg: ScratchReg).addExpr(Val: LE),
1486 STI: getSTI());
1487 Out.emitInstruction(
1488 Inst: MCInstBuilder(LoongArch::JIRL)
1489 .addReg(Reg: IsTailCall ? MCRegister(LoongArch::R0) : ScratchReg)
1490 .addReg(Reg: ScratchReg)
1491 .addImm(Val: 0),
1492 STI: getSTI());
1493}
1494
1495bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
1496 OperandVector &Operands,
1497 MCStreamer &Out) {
1498 Inst.setLoc(IDLoc);
1499 switch (Inst.getOpcode()) {
1500 default:
1501 break;
1502 case LoongArch::PseudoLA_ABS:
1503 case LoongArch::PseudoLA_ABS_LARGE:
1504 emitLoadAddressAbs(Inst, IDLoc, Out);
1505 return false;
1506 case LoongArch::PseudoLA_PCREL:
1507 emitLoadAddressPcrel(Inst, IDLoc, Out);
1508 return false;
1509 case LoongArch::PseudoLA_PCREL_LARGE:
1510 emitLoadAddressPcrelLarge(Inst, IDLoc, Out);
1511 return false;
1512 case LoongArch::PseudoLA_GOT:
1513 emitLoadAddressGot(Inst, IDLoc, Out);
1514 return false;
1515 case LoongArch::PseudoLA_GOT_LARGE:
1516 emitLoadAddressGotLarge(Inst, IDLoc, Out);
1517 return false;
1518 case LoongArch::PseudoLA_TLS_LE:
1519 emitLoadAddressTLSLE(Inst, IDLoc, Out);
1520 return false;
1521 case LoongArch::PseudoLA_TLS_IE:
1522 emitLoadAddressTLSIE(Inst, IDLoc, Out);
1523 return false;
1524 case LoongArch::PseudoLA_TLS_IE_LARGE:
1525 emitLoadAddressTLSIELarge(Inst, IDLoc, Out);
1526 return false;
1527 case LoongArch::PseudoLA_TLS_LD:
1528 emitLoadAddressTLSLD(Inst, IDLoc, Out);
1529 return false;
1530 case LoongArch::PseudoLA_TLS_LD_LARGE:
1531 emitLoadAddressTLSLDLarge(Inst, IDLoc, Out);
1532 return false;
1533 case LoongArch::PseudoLA_TLS_GD:
1534 emitLoadAddressTLSGD(Inst, IDLoc, Out);
1535 return false;
1536 case LoongArch::PseudoLA_TLS_GD_LARGE:
1537 emitLoadAddressTLSGDLarge(Inst, IDLoc, Out);
1538 return false;
1539 case LoongArch::PseudoLA_TLS_DESC:
1540 emitLoadAddressTLSDesc(Inst, IDLoc, Out);
1541 return false;
1542 case LoongArch::PseudoLA_TLS_DESC_LARGE:
1543 emitLoadAddressTLSDescLarge(Inst, IDLoc, Out);
1544 return false;
1545 case LoongArch::PseudoLI_W:
1546 case LoongArch::PseudoLI_D:
1547 emitLoadImm(Inst, IDLoc, Out);
1548 return false;
1549 case LoongArch::PseudoCALL36:
1550 emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/false);
1551 return false;
1552 case LoongArch::PseudoTAIL36:
1553 emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/true);
1554 return false;
1555 }
1556 Out.emitInstruction(Inst, STI: getSTI());
1557 return false;
1558}
1559
1560unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1561 unsigned Opc = Inst.getOpcode();
1562 const MCInstrDesc &MCID = MII.get(Opcode: Opc);
1563 switch (Opc) {
1564 default:
1565 if (LoongArchII::isSubjectToAMORdConstraint(TSFlags: MCID.TSFlags)) {
1566 const bool IsAMCAS = LoongArchII::isAMCAS(TSFlags: MCID.TSFlags);
1567 MCRegister Rd = Inst.getOperand(i: 0).getReg();
1568 MCRegister Rk = Inst.getOperand(i: IsAMCAS ? 2 : 1).getReg();
1569 MCRegister Rj = Inst.getOperand(i: IsAMCAS ? 3 : 2).getReg();
1570 if ((Rd == Rk || Rd == Rj) && Rd != LoongArch::R0)
1571 return Match_RequiresAMORdDifferRkRj;
1572 }
1573 break;
1574 case LoongArch::PseudoLA_TLS_DESC:
1575 case LoongArch::PseudoLA_TLS_DESC_LARGE: {
1576 MCRegister Rd = Inst.getOperand(i: 0).getReg();
1577 if (Rd != LoongArch::R4)
1578 return Match_RequiresLAORdR4;
1579 break;
1580 }
1581 case LoongArch::PseudoLA_PCREL_LARGE:
1582 case LoongArch::PseudoLA_GOT_LARGE:
1583 case LoongArch::PseudoLA_TLS_IE_LARGE:
1584 case LoongArch::PseudoLA_TLS_LD_LARGE:
1585 case LoongArch::PseudoLA_TLS_GD_LARGE: {
1586 MCRegister Rd = Inst.getOperand(i: 0).getReg();
1587 MCRegister Rj = Inst.getOperand(i: 1).getReg();
1588 if (Rd == Rj)
1589 return Match_RequiresLAORdDifferRj;
1590 break;
1591 }
1592 case LoongArch::CSRXCHG:
1593 case LoongArch::GCSRXCHG: {
1594 MCRegister Rj = Inst.getOperand(i: 2).getReg();
1595 if (Rj == LoongArch::R0 || Rj == LoongArch::R1)
1596 return Match_RequiresOpnd2NotR0R1;
1597 return Match_Success;
1598 }
1599 case LoongArch::BSTRINS_W:
1600 case LoongArch::BSTRINS_D:
1601 case LoongArch::BSTRPICK_W:
1602 case LoongArch::BSTRPICK_D: {
1603 unsigned Opc = Inst.getOpcode();
1604 const signed Msb =
1605 (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
1606 ? Inst.getOperand(i: 3).getImm()
1607 : Inst.getOperand(i: 2).getImm();
1608 const signed Lsb =
1609 (Opc == LoongArch::BSTRINS_W || Opc == LoongArch::BSTRINS_D)
1610 ? Inst.getOperand(i: 4).getImm()
1611 : Inst.getOperand(i: 3).getImm();
1612 if (Msb < Lsb)
1613 return Match_RequiresMsbNotLessThanLsb;
1614 return Match_Success;
1615 }
1616 }
1617
1618 return Match_Success;
1619}
1620
1621unsigned
1622LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
1623 unsigned Kind) {
1624 LoongArchOperand &Op = static_cast<LoongArchOperand &>(AsmOp);
1625 if (!Op.isReg())
1626 return Match_InvalidOperand;
1627
1628 MCRegister Reg = Op.getReg();
1629 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1630 // register from FPR32 to FPR64 if necessary.
1631 if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) &&
1632 Kind == MCK_FPR64) {
1633 Op.setReg(convertFPR32ToFPR64(Reg));
1634 return Match_Success;
1635 }
1636
1637 if (Kind == MCK_GPRNoR0R1 && (Reg == LoongArch::R0 || Reg == LoongArch::R1))
1638 return Match_RequiresOpnd2NotR0R1;
1639
1640 return Match_InvalidOperand;
1641}
1642
1643bool LoongArchAsmParser::generateImmOutOfRangeError(
1644 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
1645 const Twine &Msg = "immediate must be an integer in the range") {
1646 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1647 return Error(L: ErrorLoc, Msg: Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
1648}
1649
1650bool LoongArchAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1651 OperandVector &Operands,
1652 MCStreamer &Out,
1653 uint64_t &ErrorInfo,
1654 bool MatchingInlineAsm) {
1655 MCInst Inst;
1656 FeatureBitset MissingFeatures;
1657
1658 auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
1659 matchingInlineAsm: MatchingInlineAsm);
1660 switch (Result) {
1661 default:
1662 break;
1663 case Match_Success:
1664 return processInstruction(Inst, IDLoc, Operands, Out);
1665 case Match_MissingFeature: {
1666 assert(MissingFeatures.any() && "Unknown missing features!");
1667 bool FirstFeature = true;
1668 std::string Msg = "instruction requires the following:";
1669 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
1670 if (MissingFeatures[i]) {
1671 Msg += FirstFeature ? " " : ", ";
1672 Msg += getSubtargetFeatureName(Val: i);
1673 FirstFeature = false;
1674 }
1675 }
1676 return Error(L: IDLoc, Msg);
1677 }
1678 case Match_MnemonicFail: {
1679 FeatureBitset FBS = ComputeAvailableFeatures(FB: getSTI().getFeatureBits());
1680 std::string Suggestion = LoongArchMnemonicSpellCheck(
1681 S: ((LoongArchOperand &)*Operands[0]).getToken(), FBS, VariantID: 0);
1682 return Error(L: IDLoc, Msg: "unrecognized instruction mnemonic" + Suggestion);
1683 }
1684 case Match_InvalidOperand: {
1685 SMLoc ErrorLoc = IDLoc;
1686 if (ErrorInfo != ~0ULL) {
1687 if (ErrorInfo >= Operands.size())
1688 return Error(L: ErrorLoc, Msg: "too few operands for instruction");
1689
1690 ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1691 if (ErrorLoc == SMLoc())
1692 ErrorLoc = IDLoc;
1693 }
1694 return Error(L: ErrorLoc, Msg: "invalid operand for instruction");
1695 }
1696 }
1697
1698 // Handle the case when the error message is of specific type
1699 // other than the generic Match_InvalidOperand, and the
1700 // corresponding operand is missing.
1701 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1702 SMLoc ErrorLoc = IDLoc;
1703 if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())
1704 return Error(L: ErrorLoc, Msg: "too few operands for instruction");
1705 }
1706
1707 switch (Result) {
1708 default:
1709 break;
1710 case Match_RequiresMsbNotLessThanLsb: {
1711 SMLoc ErrorStart = Operands[3]->getStartLoc();
1712 return Error(L: ErrorStart, Msg: "msb is less than lsb",
1713 Range: SMRange(ErrorStart, Operands[4]->getEndLoc()));
1714 }
1715 case Match_RequiresOpnd2NotR0R1:
1716 return Error(L: Operands[2]->getStartLoc(), Msg: "must not be $r0 or $r1");
1717 case Match_RequiresAMORdDifferRkRj:
1718 return Error(L: Operands[1]->getStartLoc(),
1719 Msg: "$rd must be different from both $rk and $rj");
1720 case Match_RequiresLAORdDifferRj:
1721 return Error(L: Operands[1]->getStartLoc(), Msg: "$rd must be different from $rj");
1722 case Match_RequiresLAORdR4:
1723 return Error(L: Operands[1]->getStartLoc(), Msg: "$rd must be $r4");
1724 case Match_InvalidUImm1:
1725 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1726 /*Upper=*/(1 << 1) - 1);
1727 case Match_InvalidUImm2:
1728 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1729 /*Upper=*/(1 << 2) - 1);
1730 case Match_InvalidUImm2plus1:
1731 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/1,
1732 /*Upper=*/(1 << 2));
1733 case Match_InvalidUImm3:
1734 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1735 /*Upper=*/(1 << 3) - 1);
1736 case Match_InvalidUImm4:
1737 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1738 /*Upper=*/(1 << 4) - 1);
1739 case Match_InvalidUImm5:
1740 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1741 /*Upper=*/(1 << 5) - 1);
1742 case Match_InvalidUImm6:
1743 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1744 /*Upper=*/(1 << 6) - 1);
1745 case Match_InvalidUImm7:
1746 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1747 /*Upper=*/(1 << 7) - 1);
1748 case Match_InvalidUImm8:
1749 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1750 /*Upper=*/(1 << 8) - 1);
1751 case Match_InvalidUImm12:
1752 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1753 /*Upper=*/(1 << 12) - 1);
1754 case Match_InvalidUImm12ori:
1755 return generateImmOutOfRangeError(
1756 Operands, ErrorInfo, /*Lower=*/0,
1757 /*Upper=*/(1 << 12) - 1,
1758 Msg: "operand must be a symbol with modifier (e.g. %abs_lo12) or an "
1759 "integer in the range");
1760 case Match_InvalidUImm14:
1761 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1762 /*Upper=*/(1 << 14) - 1);
1763 case Match_InvalidUImm15:
1764 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
1765 /*Upper=*/(1 << 15) - 1);
1766 case Match_InvalidSImm5:
1767 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 4),
1768 /*Upper=*/(1 << 4) - 1);
1769 case Match_InvalidSImm8:
1770 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 7),
1771 /*Upper=*/(1 << 7) - 1);
1772 case Match_InvalidSImm8lsl1:
1773 return generateImmOutOfRangeError(
1774 Operands, ErrorInfo, /*Lower=*/-(1 << 8), /*Upper=*/(1 << 8) - 2,
1775 Msg: "immediate must be a multiple of 2 in the range");
1776 case Match_InvalidSImm8lsl2:
1777 return generateImmOutOfRangeError(
1778 Operands, ErrorInfo, /*Lower=*/-(1 << 9), /*Upper=*/(1 << 9) - 4,
1779 Msg: "immediate must be a multiple of 4 in the range");
1780 case Match_InvalidSImm10:
1781 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 9),
1782 /*Upper=*/(1 << 9) - 1);
1783 case Match_InvalidSImm8lsl3:
1784 return generateImmOutOfRangeError(
1785 Operands, ErrorInfo, /*Lower=*/-(1 << 10), /*Upper=*/(1 << 10) - 8,
1786 Msg: "immediate must be a multiple of 8 in the range");
1787 case Match_InvalidSImm9lsl3:
1788 return generateImmOutOfRangeError(
1789 Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 8,
1790 Msg: "immediate must be a multiple of 8 in the range");
1791 case Match_InvalidSImm10lsl2:
1792 return generateImmOutOfRangeError(
1793 Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 4,
1794 Msg: "immediate must be a multiple of 4 in the range");
1795 case Match_InvalidSImm11lsl1:
1796 return generateImmOutOfRangeError(
1797 Operands, ErrorInfo, /*Lower=*/-(1 << 11), /*Upper=*/(1 << 11) - 2,
1798 Msg: "immediate must be a multiple of 2 in the range");
1799 case Match_InvalidSImm12:
1800 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1801 /*Upper=*/(1 << 11) - 1);
1802 case Match_InvalidSImm12addlike:
1803 return generateImmOutOfRangeError(
1804 Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1805 /*Upper=*/(1 << 11) - 1,
1806 Msg: "operand must be a symbol with modifier (e.g. %pc_lo12) or an integer "
1807 "in the range");
1808 case Match_InvalidSImm12lu52id:
1809 return generateImmOutOfRangeError(
1810 Operands, ErrorInfo, /*Lower=*/-(1 << 11),
1811 /*Upper=*/(1 << 11) - 1,
1812 Msg: "operand must be a symbol with modifier (e.g. %pc64_hi12) or an "
1813 "integer in the range");
1814 case Match_InvalidSImm13:
1815 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 12),
1816 /*Upper=*/(1 << 12) - 1);
1817 case Match_InvalidSImm14lsl2:
1818 return generateImmOutOfRangeError(
1819 Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4,
1820 Msg: "immediate must be a multiple of 4 in the range");
1821 case Match_InvalidSImm16:
1822 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 15),
1823 /*Upper=*/(1 << 15) - 1);
1824 case Match_InvalidSImm16lsl2:
1825 return generateImmOutOfRangeError(
1826 Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4,
1827 Msg: "operand must be a symbol with modifier (e.g. %b16) or an integer "
1828 "in the range");
1829 case Match_InvalidSImm20:
1830 return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1831 /*Upper=*/(1 << 19) - 1);
1832 case Match_InvalidSImm20lu12iw:
1833 return generateImmOutOfRangeError(
1834 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1835 /*Upper=*/(1 << 19) - 1,
1836 Msg: "operand must be a symbol with modifier (e.g. %abs_hi20) or an integer "
1837 "in the range");
1838 case Match_InvalidSImm20lu32id:
1839 return generateImmOutOfRangeError(
1840 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1841 /*Upper=*/(1 << 19) - 1,
1842 Msg: "operand must be a symbol with modifier (e.g. %abs64_lo20) or an "
1843 "integer in the range");
1844 case Match_InvalidSImm20pcalau12i:
1845 return generateImmOutOfRangeError(
1846 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1847 /*Upper=*/(1 << 19) - 1,
1848 Msg: "operand must be a symbol with modifier (e.g. %pc_hi20) or an integer "
1849 "in the range");
1850 case Match_InvalidSImm20pcaddu18i:
1851 return generateImmOutOfRangeError(
1852 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1853 /*Upper=*/(1 << 19) - 1,
1854 Msg: "operand must be a symbol with modifier (e.g. %call36) or an integer "
1855 "in the range");
1856 case Match_InvalidSImm20pcaddi:
1857 return generateImmOutOfRangeError(
1858 Operands, ErrorInfo, /*Lower=*/-(1 << 19),
1859 /*Upper=*/(1 << 19) - 1,
1860 Msg: "operand must be a symbol with modifier (e.g. %pcrel_20) or an integer "
1861 "in the range");
1862 case Match_InvalidSImm21lsl2:
1863 return generateImmOutOfRangeError(
1864 Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4,
1865 Msg: "operand must be a symbol with modifier (e.g. %b21) or an integer "
1866 "in the range");
1867 case Match_InvalidSImm26Operand:
1868 return generateImmOutOfRangeError(
1869 Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4,
1870 Msg: "operand must be a bare symbol name or an immediate must be a multiple "
1871 "of 4 in the range");
1872 case Match_InvalidImm32: {
1873 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1874 return Error(L: ErrorLoc, Msg: "operand must be a 32 bit immediate");
1875 }
1876 case Match_InvalidImm64: {
1877 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1878 return Error(L: ErrorLoc, Msg: "operand must be a 64 bit immediate");
1879 }
1880 case Match_InvalidBareSymbol: {
1881 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1882 return Error(L: ErrorLoc, Msg: "operand must be a bare symbol name");
1883 }
1884 case Match_InvalidTPRelAddSymbol: {
1885 SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1886 return Error(L: ErrorLoc, Msg: "operand must be a symbol with %le_add_r modifier");
1887 }
1888 }
1889 llvm_unreachable("Unknown match type detected!");
1890}
1891
1892bool LoongArchAsmParser::parseDirectiveOption() {
1893 MCAsmParser &Parser = getParser();
1894 // Get the option token.
1895 AsmToken Tok = Parser.getTok();
1896
1897 // At the moment only identifiers are supported.
1898 if (parseToken(T: AsmToken::Identifier, Msg: "expected identifier"))
1899 return true;
1900
1901 StringRef Option = Tok.getIdentifier();
1902
1903 if (Option == "push") {
1904 if (Parser.parseEOL())
1905 return true;
1906
1907 getTargetStreamer().emitDirectiveOptionPush();
1908 pushFeatureBits();
1909 return false;
1910 }
1911
1912 if (Option == "pop") {
1913 SMLoc StartLoc = Parser.getTok().getLoc();
1914 if (Parser.parseEOL())
1915 return true;
1916
1917 getTargetStreamer().emitDirectiveOptionPop();
1918 if (popFeatureBits())
1919 return Error(L: StartLoc, Msg: ".option pop with no .option push");
1920
1921 return false;
1922 }
1923
1924 if (Option == "relax") {
1925 if (Parser.parseEOL())
1926 return true;
1927
1928 getTargetStreamer().emitDirectiveOptionRelax();
1929 setFeatureBits(Feature: LoongArch::FeatureRelax, FeatureString: "relax");
1930 return false;
1931 }
1932
1933 if (Option == "norelax") {
1934 if (Parser.parseEOL())
1935 return true;
1936
1937 getTargetStreamer().emitDirectiveOptionNoRelax();
1938 clearFeatureBits(Feature: LoongArch::FeatureRelax, FeatureString: "relax");
1939 return false;
1940 }
1941
1942 // Unknown option.
1943 Warning(L: Parser.getTok().getLoc(),
1944 Msg: "unknown option, expected 'push', 'pop', 'relax' or 'norelax'");
1945 Parser.eatToEndOfStatement();
1946 return false;
1947}
1948
1949ParseStatus LoongArchAsmParser::parseDirective(AsmToken DirectiveID) {
1950 if (DirectiveID.getString() == ".option")
1951 return parseDirectiveOption();
1952
1953 return ParseStatus::NoMatch;
1954}
1955
1956extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
1957LLVMInitializeLoongArchAsmParser() {
1958 RegisterMCAsmParser<LoongArchAsmParser> X(getTheLoongArch32Target());
1959 RegisterMCAsmParser<LoongArchAsmParser> Y(getTheLoongArch64Target());
1960}
1961