Revert "[asan] Enable wait4 test on Android" (#125011)
[llvm-project.git] / llvm / lib / Target / Lanai / AsmParser / LanaiAsmParser.cpp
blob2c930774c5f46c424579508b71a327610ed44222
1 //===-- LanaiAsmParser.cpp - Parse Lanai 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 //===----------------------------------------------------------------------===//
9 #include "LanaiAluCode.h"
10 #include "LanaiCondCode.h"
11 #include "LanaiInstrInfo.h"
12 #include "MCTargetDesc/LanaiMCExpr.h"
13 #include "TargetInfo/LanaiTargetInfo.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/ADT/StringSwitch.h"
16 #include "llvm/MC/MCContext.h"
17 #include "llvm/MC/MCExpr.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/MC/MCParser/MCAsmLexer.h"
20 #include "llvm/MC/MCParser/MCAsmParser.h"
21 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
22 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
23 #include "llvm/MC/MCStreamer.h"
24 #include "llvm/MC/MCSubtargetInfo.h"
25 #include "llvm/MC/MCSymbol.h"
26 #include "llvm/MC/TargetRegistry.h"
27 #include "llvm/Support/Casting.h"
28 #include "llvm/Support/ErrorHandling.h"
29 #include "llvm/Support/MathExtras.h"
30 #include "llvm/Support/SMLoc.h"
31 #include "llvm/Support/raw_ostream.h"
32 #include <cassert>
33 #include <cstddef>
34 #include <cstdint>
35 #include <memory>
36 #include <optional>
38 using namespace llvm;
40 // Auto-generated by TableGen
41 static MCRegister MatchRegisterName(StringRef Name);
43 namespace {
45 struct LanaiOperand;
47 class LanaiAsmParser : public MCTargetAsmParser {
48 // Parse operands
49 std::unique_ptr<LanaiOperand> parseRegister(bool RestoreOnFailure = false);
51 std::unique_ptr<LanaiOperand> parseImmediate();
53 std::unique_ptr<LanaiOperand> parseIdentifier();
55 unsigned parseAluOperator(bool PreOp, bool PostOp);
57 // Split the mnemonic stripping conditional code and quantifiers
58 StringRef splitMnemonic(StringRef Name, SMLoc NameLoc,
59 OperandVector *Operands);
61 bool parsePrePost(StringRef Type, int *OffsetValue);
63 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
64 SMLoc NameLoc, OperandVector &Operands) override;
66 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
67 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
68 SMLoc &EndLoc) override;
70 bool matchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
71 OperandVector &Operands, MCStreamer &Out,
72 uint64_t &ErrorInfo,
73 bool MatchingInlineAsm) override;
75 // Auto-generated instruction matching functions
76 #define GET_ASSEMBLER_HEADER
77 #include "LanaiGenAsmMatcher.inc"
79 ParseStatus parseOperand(OperandVector *Operands, StringRef Mnemonic);
81 ParseStatus parseMemoryOperand(OperandVector &Operands);
83 public:
84 LanaiAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
85 const MCInstrInfo &MII, const MCTargetOptions &Options)
86 : MCTargetAsmParser(Options, STI, MII), Parser(Parser),
87 Lexer(Parser.getLexer()), SubtargetInfo(STI) {
88 setAvailableFeatures(
89 ComputeAvailableFeatures(SubtargetInfo.getFeatureBits()));
92 private:
93 MCAsmParser &Parser;
94 MCAsmLexer &Lexer;
96 const MCSubtargetInfo &SubtargetInfo;
99 // LanaiOperand - Instances of this class represented a parsed machine
100 // instruction
101 struct LanaiOperand : public MCParsedAsmOperand {
102 enum KindTy {
103 TOKEN,
104 REGISTER,
105 IMMEDIATE,
106 MEMORY_IMM,
107 MEMORY_REG_IMM,
108 MEMORY_REG_REG,
109 } Kind;
111 SMLoc StartLoc, EndLoc;
113 struct Token {
114 const char *Data;
115 unsigned Length;
118 struct RegOp {
119 MCRegister RegNum;
122 struct ImmOp {
123 const MCExpr *Value;
126 struct MemOp {
127 MCRegister BaseReg;
128 MCRegister OffsetReg;
129 unsigned AluOp;
130 const MCExpr *Offset;
133 union {
134 struct Token Tok;
135 struct RegOp Reg;
136 struct ImmOp Imm;
137 struct MemOp Mem;
140 explicit LanaiOperand(KindTy Kind) : Kind(Kind) {}
142 public:
143 // The functions below are used by the autogenerated ASM matcher and hence to
144 // be of the form expected.
146 // getStartLoc - Gets location of the first token of this operand
147 SMLoc getStartLoc() const override { return StartLoc; }
149 // getEndLoc - Gets location of the last token of this operand
150 SMLoc getEndLoc() const override { return EndLoc; }
152 MCRegister getReg() const override {
153 assert(isReg() && "Invalid type access!");
154 return Reg.RegNum;
157 const MCExpr *getImm() const {
158 assert(isImm() && "Invalid type access!");
159 return Imm.Value;
162 StringRef getToken() const {
163 assert(isToken() && "Invalid type access!");
164 return StringRef(Tok.Data, Tok.Length);
167 MCRegister getMemBaseReg() const {
168 assert(isMem() && "Invalid type access!");
169 return Mem.BaseReg;
172 MCRegister getMemOffsetReg() const {
173 assert(isMem() && "Invalid type access!");
174 return Mem.OffsetReg;
177 const MCExpr *getMemOffset() const {
178 assert(isMem() && "Invalid type access!");
179 return Mem.Offset;
182 unsigned getMemOp() const {
183 assert(isMem() && "Invalid type access!");
184 return Mem.AluOp;
187 // Functions for testing operand type
188 bool isReg() const override { return Kind == REGISTER; }
190 bool isImm() const override { return Kind == IMMEDIATE; }
192 bool isMem() const override {
193 return isMemImm() || isMemRegImm() || isMemRegReg();
196 bool isMemImm() const { return Kind == MEMORY_IMM; }
198 bool isMemRegImm() const { return Kind == MEMORY_REG_IMM; }
200 bool isMemRegReg() const { return Kind == MEMORY_REG_REG; }
202 bool isMemSpls() const { return isMemRegImm() || isMemRegReg(); }
204 bool isToken() const override { return Kind == TOKEN; }
206 bool isBrImm() {
207 if (!isImm())
208 return false;
210 // Constant case
211 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm.Value);
212 if (!MCE)
213 return true;
214 int64_t Value = MCE->getValue();
215 // Check if value fits in 25 bits with 2 least significant bits 0.
216 return isShiftedUInt<23, 2>(static_cast<int32_t>(Value));
219 bool isBrTarget() { return isBrImm() || isToken(); }
221 bool isCallTarget() { return isImm() || isToken(); }
223 bool isHiImm16() {
224 if (!isImm())
225 return false;
227 // Constant case
228 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
229 int64_t Value = ConstExpr->getValue();
230 return Value != 0 && isShiftedUInt<16, 16>(Value);
233 // Symbolic reference expression
234 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
235 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
237 // Binary expression
238 if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
239 if (const LanaiMCExpr *SymbolRefExpr =
240 dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
241 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
243 return false;
246 bool isHiImm16And() {
247 if (!isImm())
248 return false;
250 const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
251 if (ConstExpr) {
252 int64_t Value = ConstExpr->getValue();
253 // Check if in the form 0xXYZWffff
254 return (Value != 0) && ((Value & ~0xffff0000) == 0xffff);
256 return false;
259 bool isLoImm16() {
260 if (!isImm())
261 return false;
263 // Constant case
264 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
265 int64_t Value = ConstExpr->getValue();
266 // Check if value fits in 16 bits
267 return isUInt<16>(static_cast<int32_t>(Value));
270 // Symbolic reference expression
271 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
272 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
274 // Binary expression
275 if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
276 if (const LanaiMCExpr *SymbolRefExpr =
277 dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
278 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
280 return false;
283 bool isLoImm16Signed() {
284 if (!isImm())
285 return false;
287 // Constant case
288 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
289 int64_t Value = ConstExpr->getValue();
290 // Check if value fits in 16 bits or value of the form 0xffffxyzw
291 return isInt<16>(static_cast<int32_t>(Value));
294 // Symbolic reference expression
295 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
296 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
298 // Binary expression
299 if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
300 if (const LanaiMCExpr *SymbolRefExpr =
301 dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
302 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
304 return false;
307 bool isLoImm16And() {
308 if (!isImm())
309 return false;
311 const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
312 if (ConstExpr) {
313 int64_t Value = ConstExpr->getValue();
314 // Check if in the form 0xffffXYZW
315 return ((Value & ~0xffff) == 0xffff0000);
317 return false;
320 bool isImmShift() {
321 if (!isImm())
322 return false;
324 const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
325 if (!ConstExpr)
326 return false;
327 int64_t Value = ConstExpr->getValue();
328 return (Value >= -31) && (Value <= 31);
331 bool isLoImm21() {
332 if (!isImm())
333 return false;
335 // Constant case
336 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
337 int64_t Value = ConstExpr->getValue();
338 return isUInt<21>(Value);
341 // Symbolic reference expression
342 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
343 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
344 if (const MCSymbolRefExpr *SymbolRefExpr =
345 dyn_cast<MCSymbolRefExpr>(Imm.Value)) {
346 return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
349 // Binary expression
350 if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value)) {
351 if (const LanaiMCExpr *SymbolRefExpr =
352 dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
353 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
354 if (const MCSymbolRefExpr *SymbolRefExpr =
355 dyn_cast<MCSymbolRefExpr>(BinaryExpr->getLHS()))
356 return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
359 return false;
362 bool isImm10() {
363 if (!isImm())
364 return false;
366 const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
367 if (!ConstExpr)
368 return false;
369 int64_t Value = ConstExpr->getValue();
370 return isInt<10>(Value);
373 bool isCondCode() {
374 if (!isImm())
375 return false;
377 const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
378 if (!ConstExpr)
379 return false;
380 uint64_t Value = ConstExpr->getValue();
381 // The condition codes are between 0 (ICC_T) and 15 (ICC_LE). If the
382 // unsigned value of the immediate is less than LPCC::UNKNOWN (16) then
383 // value corresponds to a valid condition code.
384 return Value < LPCC::UNKNOWN;
387 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
388 // Add as immediates where possible. Null MCExpr = 0
389 if (Expr == nullptr)
390 Inst.addOperand(MCOperand::createImm(0));
391 else if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Expr))
392 Inst.addOperand(
393 MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));
394 else
395 Inst.addOperand(MCOperand::createExpr(Expr));
398 void addRegOperands(MCInst &Inst, unsigned N) const {
399 assert(N == 1 && "Invalid number of operands!");
400 Inst.addOperand(MCOperand::createReg(getReg()));
403 void addImmOperands(MCInst &Inst, unsigned N) const {
404 assert(N == 1 && "Invalid number of operands!");
405 addExpr(Inst, getImm());
408 void addBrTargetOperands(MCInst &Inst, unsigned N) const {
409 assert(N == 1 && "Invalid number of operands!");
410 addExpr(Inst, getImm());
413 void addCallTargetOperands(MCInst &Inst, unsigned N) const {
414 assert(N == 1 && "Invalid number of operands!");
415 addExpr(Inst, getImm());
418 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
419 assert(N == 1 && "Invalid number of operands!");
420 addExpr(Inst, getImm());
423 void addMemImmOperands(MCInst &Inst, unsigned N) const {
424 assert(N == 1 && "Invalid number of operands!");
425 const MCExpr *Expr = getMemOffset();
426 addExpr(Inst, Expr);
429 void addMemRegImmOperands(MCInst &Inst, unsigned N) const {
430 assert(N == 3 && "Invalid number of operands!");
431 Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
432 const MCExpr *Expr = getMemOffset();
433 addExpr(Inst, Expr);
434 Inst.addOperand(MCOperand::createImm(getMemOp()));
437 void addMemRegRegOperands(MCInst &Inst, unsigned N) const {
438 assert(N == 3 && "Invalid number of operands!");
439 Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
440 assert(getMemOffsetReg() && "Invalid offset");
441 Inst.addOperand(MCOperand::createReg(getMemOffsetReg()));
442 Inst.addOperand(MCOperand::createImm(getMemOp()));
445 void addMemSplsOperands(MCInst &Inst, unsigned N) const {
446 if (isMemRegImm())
447 addMemRegImmOperands(Inst, N);
448 if (isMemRegReg())
449 addMemRegRegOperands(Inst, N);
452 void addImmShiftOperands(MCInst &Inst, unsigned N) const {
453 assert(N == 1 && "Invalid number of operands!");
454 addExpr(Inst, getImm());
457 void addImm10Operands(MCInst &Inst, unsigned N) const {
458 assert(N == 1 && "Invalid number of operands!");
459 addExpr(Inst, getImm());
462 void addLoImm16Operands(MCInst &Inst, unsigned N) const {
463 assert(N == 1 && "Invalid number of operands!");
464 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
465 Inst.addOperand(
466 MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));
467 else if (isa<LanaiMCExpr>(getImm())) {
468 #ifndef NDEBUG
469 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
470 assert(SymbolRefExpr &&
471 SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO);
472 #endif
473 Inst.addOperand(MCOperand::createExpr(getImm()));
474 } else if (isa<MCBinaryExpr>(getImm())) {
475 #ifndef NDEBUG
476 const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
477 assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
478 cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
479 LanaiMCExpr::VK_Lanai_ABS_LO);
480 #endif
481 Inst.addOperand(MCOperand::createExpr(getImm()));
482 } else
483 assert(false && "Operand type not supported.");
486 void addLoImm16AndOperands(MCInst &Inst, unsigned N) const {
487 assert(N == 1 && "Invalid number of operands!");
488 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
489 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0xffff));
490 else
491 assert(false && "Operand type not supported.");
494 void addHiImm16Operands(MCInst &Inst, unsigned N) const {
495 assert(N == 1 && "Invalid number of operands!");
496 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
497 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
498 else if (isa<LanaiMCExpr>(getImm())) {
499 #ifndef NDEBUG
500 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
501 assert(SymbolRefExpr &&
502 SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI);
503 #endif
504 Inst.addOperand(MCOperand::createExpr(getImm()));
505 } else if (isa<MCBinaryExpr>(getImm())) {
506 #ifndef NDEBUG
507 const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
508 assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
509 cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
510 LanaiMCExpr::VK_Lanai_ABS_HI);
511 #endif
512 Inst.addOperand(MCOperand::createExpr(getImm()));
513 } else
514 assert(false && "Operand type not supported.");
517 void addHiImm16AndOperands(MCInst &Inst, unsigned N) const {
518 assert(N == 1 && "Invalid number of operands!");
519 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
520 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
521 else
522 assert(false && "Operand type not supported.");
525 void addLoImm21Operands(MCInst &Inst, unsigned N) const {
526 assert(N == 1 && "Invalid number of operands!");
527 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
528 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0x1fffff));
529 else if (isa<LanaiMCExpr>(getImm())) {
530 #ifndef NDEBUG
531 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
532 assert(SymbolRefExpr &&
533 SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
534 #endif
535 Inst.addOperand(MCOperand::createExpr(getImm()));
536 } else if (isa<MCSymbolRefExpr>(getImm())) {
537 #ifndef NDEBUG
538 const MCSymbolRefExpr *SymbolRefExpr =
539 dyn_cast<MCSymbolRefExpr>(getImm());
540 assert(SymbolRefExpr &&
541 SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None);
542 #endif
543 Inst.addOperand(MCOperand::createExpr(getImm()));
544 } else if (isa<MCBinaryExpr>(getImm())) {
545 #ifndef NDEBUG
546 const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
547 assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
548 cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
549 LanaiMCExpr::VK_Lanai_None);
550 #endif
551 Inst.addOperand(MCOperand::createExpr(getImm()));
552 } else
553 assert(false && "Operand type not supported.");
556 void print(raw_ostream &OS) const override {
557 switch (Kind) {
558 case IMMEDIATE:
559 OS << "Imm: " << getImm() << "\n";
560 break;
561 case TOKEN:
562 OS << "Token: " << getToken() << "\n";
563 break;
564 case REGISTER:
565 OS << "Reg: %r" << getReg() << "\n";
566 break;
567 case MEMORY_IMM:
568 OS << "MemImm: " << *getMemOffset() << "\n";
569 break;
570 case MEMORY_REG_IMM:
571 OS << "MemRegImm: " << getMemBaseReg() << "+" << *getMemOffset() << "\n";
572 break;
573 case MEMORY_REG_REG:
574 assert(getMemOffset() == nullptr);
575 OS << "MemRegReg: " << getMemBaseReg() << "+"
576 << "%r" << getMemOffsetReg() << "\n";
577 break;
581 static std::unique_ptr<LanaiOperand> CreateToken(StringRef Str, SMLoc Start) {
582 auto Op = std::make_unique<LanaiOperand>(TOKEN);
583 Op->Tok.Data = Str.data();
584 Op->Tok.Length = Str.size();
585 Op->StartLoc = Start;
586 Op->EndLoc = Start;
587 return Op;
590 static std::unique_ptr<LanaiOperand> createReg(MCRegister Reg, SMLoc Start,
591 SMLoc End) {
592 auto Op = std::make_unique<LanaiOperand>(REGISTER);
593 Op->Reg.RegNum = Reg;
594 Op->StartLoc = Start;
595 Op->EndLoc = End;
596 return Op;
599 static std::unique_ptr<LanaiOperand> createImm(const MCExpr *Value,
600 SMLoc Start, SMLoc End) {
601 auto Op = std::make_unique<LanaiOperand>(IMMEDIATE);
602 Op->Imm.Value = Value;
603 Op->StartLoc = Start;
604 Op->EndLoc = End;
605 return Op;
608 static std::unique_ptr<LanaiOperand>
609 MorphToMemImm(std::unique_ptr<LanaiOperand> Op) {
610 const MCExpr *Imm = Op->getImm();
611 Op->Kind = MEMORY_IMM;
612 Op->Mem.BaseReg = MCRegister();
613 Op->Mem.AluOp = LPAC::ADD;
614 Op->Mem.OffsetReg = 0;
615 Op->Mem.Offset = Imm;
616 return Op;
619 static std::unique_ptr<LanaiOperand>
620 MorphToMemRegReg(MCRegister BaseReg, std::unique_ptr<LanaiOperand> Op,
621 unsigned AluOp) {
622 MCRegister OffsetReg = Op->getReg();
623 Op->Kind = MEMORY_REG_REG;
624 Op->Mem.BaseReg = BaseReg;
625 Op->Mem.AluOp = AluOp;
626 Op->Mem.OffsetReg = OffsetReg;
627 Op->Mem.Offset = nullptr;
628 return Op;
631 static std::unique_ptr<LanaiOperand>
632 MorphToMemRegImm(MCRegister BaseReg, std::unique_ptr<LanaiOperand> Op,
633 unsigned AluOp) {
634 const MCExpr *Imm = Op->getImm();
635 Op->Kind = MEMORY_REG_IMM;
636 Op->Mem.BaseReg = BaseReg;
637 Op->Mem.AluOp = AluOp;
638 Op->Mem.OffsetReg = 0;
639 Op->Mem.Offset = Imm;
640 return Op;
644 } // end anonymous namespace
646 bool LanaiAsmParser::matchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
647 OperandVector &Operands,
648 MCStreamer &Out,
649 uint64_t &ErrorInfo,
650 bool MatchingInlineAsm) {
651 MCInst Inst;
652 SMLoc ErrorLoc;
654 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
655 case Match_Success:
656 Out.emitInstruction(Inst, SubtargetInfo);
657 Opcode = Inst.getOpcode();
658 return false;
659 case Match_MissingFeature:
660 return Error(IdLoc, "Instruction use requires option to be enabled");
661 case Match_MnemonicFail:
662 return Error(IdLoc, "Unrecognized instruction mnemonic");
663 case Match_InvalidOperand: {
664 ErrorLoc = IdLoc;
665 if (ErrorInfo != ~0U) {
666 if (ErrorInfo >= Operands.size())
667 return Error(IdLoc, "Too few operands for instruction");
669 ErrorLoc = ((LanaiOperand &)*Operands[ErrorInfo]).getStartLoc();
670 if (ErrorLoc == SMLoc())
671 ErrorLoc = IdLoc;
673 return Error(ErrorLoc, "Invalid operand for instruction");
675 default:
676 break;
679 llvm_unreachable("Unknown match type detected!");
682 // Both '%rN' and 'rN' are parsed as valid registers. This was done to remain
683 // backwards compatible with GCC and the different ways inline assembly is
684 // handled.
685 // TODO: see if there isn't a better way to do this.
686 std::unique_ptr<LanaiOperand>
687 LanaiAsmParser::parseRegister(bool RestoreOnFailure) {
688 SMLoc Start = Parser.getTok().getLoc();
689 SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
690 std::optional<AsmToken> PercentTok;
692 MCRegister Reg;
693 // Eat the '%'.
694 if (Lexer.getKind() == AsmToken::Percent) {
695 PercentTok = Parser.getTok();
696 Parser.Lex();
698 if (Lexer.getKind() == AsmToken::Identifier) {
699 Reg = MatchRegisterName(Lexer.getTok().getIdentifier());
700 if (!Reg) {
701 if (PercentTok && RestoreOnFailure)
702 Lexer.UnLex(*PercentTok);
703 return nullptr;
705 Parser.Lex(); // Eat identifier token
706 return LanaiOperand::createReg(Reg, Start, End);
708 if (PercentTok && RestoreOnFailure)
709 Lexer.UnLex(*PercentTok);
710 return nullptr;
713 bool LanaiAsmParser::parseRegister(MCRegister &RegNum, SMLoc &StartLoc,
714 SMLoc &EndLoc) {
715 const AsmToken &Tok = getParser().getTok();
716 StartLoc = Tok.getLoc();
717 EndLoc = Tok.getEndLoc();
718 std::unique_ptr<LanaiOperand> Op = parseRegister(/*RestoreOnFailure=*/false);
719 if (Op != nullptr)
720 RegNum = Op->getReg();
721 return (Op == nullptr);
724 ParseStatus LanaiAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
725 SMLoc &EndLoc) {
726 const AsmToken &Tok = getParser().getTok();
727 StartLoc = Tok.getLoc();
728 EndLoc = Tok.getEndLoc();
729 std::unique_ptr<LanaiOperand> Op = parseRegister(/*RestoreOnFailure=*/true);
730 if (Op == nullptr)
731 return ParseStatus::NoMatch;
732 Reg = Op->getReg();
733 return ParseStatus::Success;
736 std::unique_ptr<LanaiOperand> LanaiAsmParser::parseIdentifier() {
737 SMLoc Start = Parser.getTok().getLoc();
738 SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
739 const MCExpr *Res, *RHS = nullptr;
740 LanaiMCExpr::VariantKind Kind = LanaiMCExpr::VK_Lanai_None;
742 if (Lexer.getKind() != AsmToken::Identifier)
743 return nullptr;
745 StringRef Identifier;
746 if (Parser.parseIdentifier(Identifier))
747 return nullptr;
749 // Check if identifier has a modifier
750 if (Identifier.equals_insensitive("hi"))
751 Kind = LanaiMCExpr::VK_Lanai_ABS_HI;
752 else if (Identifier.equals_insensitive("lo"))
753 Kind = LanaiMCExpr::VK_Lanai_ABS_LO;
755 // If the identifier corresponds to a variant then extract the real
756 // identifier.
757 if (Kind != LanaiMCExpr::VK_Lanai_None) {
758 if (Lexer.getKind() != AsmToken::LParen) {
759 Error(Lexer.getLoc(), "Expected '('");
760 return nullptr;
762 Lexer.Lex(); // lex '('
764 // Parse identifier
765 if (Parser.parseIdentifier(Identifier))
766 return nullptr;
769 // If addition parse the RHS.
770 if (Lexer.getKind() == AsmToken::Plus && Parser.parseExpression(RHS))
771 return nullptr;
773 // For variants parse the final ')'
774 if (Kind != LanaiMCExpr::VK_Lanai_None) {
775 if (Lexer.getKind() != AsmToken::RParen) {
776 Error(Lexer.getLoc(), "Expected ')'");
777 return nullptr;
779 Lexer.Lex(); // lex ')'
782 End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
783 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
784 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
785 Res = LanaiMCExpr::create(Kind, Expr, getContext());
787 // Nest if this was an addition
788 if (RHS)
789 Res = MCBinaryExpr::createAdd(Res, RHS, getContext());
791 return LanaiOperand::createImm(Res, Start, End);
794 std::unique_ptr<LanaiOperand> LanaiAsmParser::parseImmediate() {
795 SMLoc Start = Parser.getTok().getLoc();
796 SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
798 const MCExpr *ExprVal;
799 switch (Lexer.getKind()) {
800 case AsmToken::Identifier:
801 return parseIdentifier();
802 case AsmToken::Plus:
803 case AsmToken::Minus:
804 case AsmToken::Integer:
805 case AsmToken::Dot:
806 if (!Parser.parseExpression(ExprVal))
807 return LanaiOperand::createImm(ExprVal, Start, End);
808 [[fallthrough]];
809 default:
810 return nullptr;
814 static unsigned AluWithPrePost(unsigned AluCode, bool PreOp, bool PostOp) {
815 if (PreOp)
816 return LPAC::makePreOp(AluCode);
817 if (PostOp)
818 return LPAC::makePostOp(AluCode);
819 return AluCode;
822 unsigned LanaiAsmParser::parseAluOperator(bool PreOp, bool PostOp) {
823 StringRef IdString;
824 Parser.parseIdentifier(IdString);
825 unsigned AluCode = LPAC::stringToLanaiAluCode(IdString);
826 if (AluCode == LPAC::UNKNOWN) {
827 Error(Parser.getTok().getLoc(), "Can't parse ALU operator");
828 return 0;
830 return AluCode;
833 static int SizeForSuffix(StringRef T) {
834 return StringSwitch<int>(T).EndsWith(".h", 2).EndsWith(".b", 1).Default(4);
837 bool LanaiAsmParser::parsePrePost(StringRef Type, int *OffsetValue) {
838 bool PreOrPost = false;
839 if (Lexer.getKind() == Lexer.peekTok(true).getKind()) {
840 PreOrPost = true;
841 if (Lexer.is(AsmToken::Minus))
842 *OffsetValue = -SizeForSuffix(Type);
843 else if (Lexer.is(AsmToken::Plus))
844 *OffsetValue = SizeForSuffix(Type);
845 else
846 return false;
848 // Eat the '-' '-' or '+' '+'
849 Parser.Lex();
850 Parser.Lex();
851 } else if (Lexer.is(AsmToken::Star)) {
852 Parser.Lex(); // Eat the '*'
853 PreOrPost = true;
856 return PreOrPost;
859 bool shouldBeSls(const LanaiOperand &Op) {
860 // The instruction should be encoded as an SLS if the constant is word
861 // aligned and will fit in 21 bits
862 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Op.getImm())) {
863 int64_t Value = ConstExpr->getValue();
864 return (Value % 4 == 0) && (Value >= 0) && (Value <= 0x1fffff);
866 // The instruction should be encoded as an SLS if the operand is a symbolic
867 // reference with no variant.
868 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Op.getImm()))
869 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
870 // The instruction should be encoded as an SLS if the operand is a binary
871 // expression with the left-hand side being a symbolic reference with no
872 // variant.
873 if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Op.getImm())) {
874 const LanaiMCExpr *LHSSymbolRefExpr =
875 dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS());
876 return (LHSSymbolRefExpr &&
877 LHSSymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
879 return false;
882 // Matches memory operand. Returns true if error encountered.
883 ParseStatus LanaiAsmParser::parseMemoryOperand(OperandVector &Operands) {
884 // Try to match a memory operand.
885 // The memory operands are of the form:
886 // (1) Register|Immediate|'' '[' '*'? Register '*'? ']' or
887 // ^
888 // (2) '[' '*'? Register '*'? AluOperator Register ']'
889 // ^
890 // (3) '[' '--'|'++' Register '--'|'++' ']'
892 // (4) '[' Immediate ']' (for SLS)
894 // Store the type for use in parsing pre/post increment/decrement operators
895 StringRef Type;
896 if (Operands[0]->isToken())
897 Type = static_cast<LanaiOperand *>(Operands[0].get())->getToken();
899 // Use 0 if no offset given
900 int OffsetValue = 0;
901 MCRegister BaseReg;
902 unsigned AluOp = LPAC::ADD;
903 bool PostOp = false, PreOp = false;
905 // Try to parse the offset
906 std::unique_ptr<LanaiOperand> Op = parseRegister();
907 if (!Op)
908 Op = parseImmediate();
910 // Only continue if next token is '['
911 if (Lexer.isNot(AsmToken::LBrac)) {
912 if (!Op)
913 return ParseStatus::NoMatch;
915 // The start of this custom parsing overlaps with register/immediate so
916 // consider this as a successful match of an operand of that type as the
917 // token stream can't be rewound to allow them to match separately.
918 Operands.push_back(std::move(Op));
919 return ParseStatus::Success;
922 Parser.Lex(); // Eat the '['.
923 std::unique_ptr<LanaiOperand> Offset = nullptr;
924 if (Op)
925 Offset.swap(Op);
927 // Determine if a pre operation
928 PreOp = parsePrePost(Type, &OffsetValue);
930 Op = parseRegister();
931 if (!Op) {
932 if (!Offset) {
933 if ((Op = parseImmediate()) && Lexer.is(AsmToken::RBrac)) {
934 Parser.Lex(); // Eat the ']'
936 // Memory address operations aligned to word boundary are encoded as
937 // SLS, the rest as RM.
938 if (shouldBeSls(*Op)) {
939 Operands.push_back(LanaiOperand::MorphToMemImm(std::move(Op)));
940 } else {
941 if (!Op->isLoImm16Signed())
942 return Error(Parser.getTok().getLoc(),
943 "Memory address is not word aligned and larger than "
944 "class RM can handle");
945 Operands.push_back(LanaiOperand::MorphToMemRegImm(
946 Lanai::R0, std::move(Op), LPAC::ADD));
948 return ParseStatus::Success;
952 return Error(Parser.getTok().getLoc(),
953 "Unknown operand, expected register or immediate");
955 BaseReg = Op->getReg();
957 // Determine if a post operation
958 if (!PreOp)
959 PostOp = parsePrePost(Type, &OffsetValue);
961 // If ] match form (1) else match form (2)
962 if (Lexer.is(AsmToken::RBrac)) {
963 Parser.Lex(); // Eat the ']'.
964 if (!Offset) {
965 SMLoc Start = Parser.getTok().getLoc();
966 SMLoc End =
967 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
968 const MCConstantExpr *OffsetConstExpr =
969 MCConstantExpr::create(OffsetValue, getContext());
970 Offset = LanaiOperand::createImm(OffsetConstExpr, Start, End);
972 } else {
973 if (Offset || OffsetValue != 0)
974 return Error(Parser.getTok().getLoc(), "Expected ']'");
976 // Parse operator
977 AluOp = parseAluOperator(PreOp, PostOp);
979 // Second form requires offset register
980 Offset = parseRegister();
981 if (!BaseReg || Lexer.isNot(AsmToken::RBrac))
982 return Error(Parser.getTok().getLoc(), "Expected ']'");
983 Parser.Lex(); // Eat the ']'.
986 // First form has addition as operator. Add pre- or post-op indicator as
987 // needed.
988 AluOp = AluWithPrePost(AluOp, PreOp, PostOp);
990 // Ensure immediate offset is not too large
991 if (Offset->isImm() && !Offset->isLoImm16Signed())
992 return Error(Parser.getTok().getLoc(),
993 "Memory address is not word aligned and larger than class RM "
994 "can handle");
996 Operands.push_back(
997 Offset->isImm()
998 ? LanaiOperand::MorphToMemRegImm(BaseReg, std::move(Offset), AluOp)
999 : LanaiOperand::MorphToMemRegReg(BaseReg, std::move(Offset), AluOp));
1001 return ParseStatus::Success;
1004 // Looks at a token type and creates the relevant operand from this
1005 // information, adding to operands.
1006 // If operand was parsed, returns false, else true.
1007 ParseStatus LanaiAsmParser::parseOperand(OperandVector *Operands,
1008 StringRef Mnemonic) {
1009 // Check if the current operand has a custom associated parser, if so, try to
1010 // custom parse the operand, or fallback to the general approach.
1011 ParseStatus Result = MatchOperandParserImpl(*Operands, Mnemonic);
1013 if (Result.isSuccess())
1014 return Result;
1015 if (Result.isFailure()) {
1016 Parser.eatToEndOfStatement();
1017 return Result;
1020 // Attempt to parse token as register
1021 std::unique_ptr<LanaiOperand> Op = parseRegister();
1023 // Attempt to parse token as immediate
1024 if (!Op)
1025 Op = parseImmediate();
1027 // If the token could not be parsed then fail
1028 if (!Op) {
1029 Error(Parser.getTok().getLoc(), "Unknown operand");
1030 Parser.eatToEndOfStatement();
1031 return ParseStatus::Failure;
1034 // Push back parsed operand into list of operands
1035 Operands->push_back(std::move(Op));
1037 return ParseStatus::Success;
1040 // Split the mnemonic into ASM operand, conditional code and instruction
1041 // qualifier (half-word, byte).
1042 StringRef LanaiAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc,
1043 OperandVector *Operands) {
1044 size_t Next = Name.find('.');
1046 StringRef Mnemonic = Name;
1048 bool IsBRR = Mnemonic.consume_back(".r");
1050 // Match b?? and s?? (BR, BRR, and SCC instruction classes).
1051 if (Mnemonic[0] == 'b' ||
1052 (Mnemonic[0] == 's' && !Mnemonic.starts_with("sel") &&
1053 !Mnemonic.starts_with("st"))) {
1054 // Parse instructions with a conditional code. For example, 'bne' is
1055 // converted into two operands 'b' and 'ne'.
1056 LPCC::CondCode CondCode =
1057 LPCC::suffixToLanaiCondCode(Mnemonic.substr(1, Next));
1058 if (CondCode != LPCC::UNKNOWN) {
1059 Mnemonic = Mnemonic.slice(0, 1);
1060 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1061 Operands->push_back(LanaiOperand::createImm(
1062 MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1063 if (IsBRR) {
1064 Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1066 return Mnemonic;
1070 // Parse other instructions with condition codes (RR instructions).
1071 // We ignore .f here and assume they are flag-setting operations, not
1072 // conditional codes (except for select instructions where flag-setting
1073 // variants are not yet implemented).
1074 if (Mnemonic.starts_with("sel") ||
1075 (!Mnemonic.ends_with(".f") && !Mnemonic.starts_with("st"))) {
1076 LPCC::CondCode CondCode = LPCC::suffixToLanaiCondCode(Mnemonic);
1077 if (CondCode != LPCC::UNKNOWN) {
1078 size_t Next = Mnemonic.rfind('.', Name.size());
1079 // 'sel' doesn't use a predicate operand whose printer adds the period,
1080 // but instead has the period as part of the identifier (i.e., 'sel.' is
1081 // expected by the generated matcher). If the mnemonic starts with 'sel'
1082 // then include the period as part of the mnemonic, else don't include it
1083 // as part of the mnemonic.
1084 if (Mnemonic.starts_with("sel")) {
1085 Mnemonic = Mnemonic.substr(0, Next + 1);
1086 } else {
1087 Mnemonic = Mnemonic.substr(0, Next);
1089 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1090 Operands->push_back(LanaiOperand::createImm(
1091 MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1092 return Mnemonic;
1096 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1097 if (IsBRR) {
1098 Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1101 return Mnemonic;
1104 static bool IsMemoryAssignmentError(const OperandVector &Operands) {
1105 // Detects if a memory operation has an erroneous base register modification.
1106 // Memory operations are detected by matching the types of operands.
1108 // TODO: This test is focussed on one specific instance (ld/st).
1109 // Extend it to handle more cases or be more robust.
1110 bool Modifies = false;
1112 int Offset = 0;
1114 if (Operands.size() < 5)
1115 return false;
1116 else if (Operands[0]->isToken() && Operands[1]->isReg() &&
1117 Operands[2]->isImm() && Operands[3]->isImm() && Operands[4]->isReg())
1118 Offset = 0;
1119 else if (Operands[0]->isToken() && Operands[1]->isToken() &&
1120 Operands[2]->isReg() && Operands[3]->isImm() &&
1121 Operands[4]->isImm() && Operands[5]->isReg())
1122 Offset = 1;
1123 else
1124 return false;
1126 int PossibleAluOpIdx = Offset + 3;
1127 int PossibleBaseIdx = Offset + 1;
1128 int PossibleDestIdx = Offset + 4;
1129 if (LanaiOperand *PossibleAluOp =
1130 static_cast<LanaiOperand *>(Operands[PossibleAluOpIdx].get()))
1131 if (PossibleAluOp->isImm())
1132 if (const MCConstantExpr *ConstExpr =
1133 dyn_cast<MCConstantExpr>(PossibleAluOp->getImm()))
1134 Modifies = LPAC::modifiesOp(ConstExpr->getValue());
1135 return Modifies && Operands[PossibleBaseIdx]->isReg() &&
1136 Operands[PossibleDestIdx]->isReg() &&
1137 Operands[PossibleBaseIdx]->getReg() ==
1138 Operands[PossibleDestIdx]->getReg();
1141 static bool IsRegister(const MCParsedAsmOperand &op) {
1142 return static_cast<const LanaiOperand &>(op).isReg();
1145 static bool MaybePredicatedInst(const OperandVector &Operands) {
1146 if (Operands.size() < 4 || !IsRegister(*Operands[1]) ||
1147 !IsRegister(*Operands[2]))
1148 return false;
1149 return StringSwitch<bool>(
1150 static_cast<const LanaiOperand &>(*Operands[0]).getToken())
1151 .StartsWith("addc", true)
1152 .StartsWith("add", true)
1153 .StartsWith("and", true)
1154 .StartsWith("sh", true)
1155 .StartsWith("subb", true)
1156 .StartsWith("sub", true)
1157 .StartsWith("or", true)
1158 .StartsWith("xor", true)
1159 .Default(false);
1162 bool LanaiAsmParser::parseInstruction(ParseInstructionInfo & /*Info*/,
1163 StringRef Name, SMLoc NameLoc,
1164 OperandVector &Operands) {
1165 // First operand is token for instruction
1166 StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands);
1168 // If there are no more operands, then finish
1169 if (Lexer.is(AsmToken::EndOfStatement))
1170 return false;
1172 // Parse first operand
1173 if (!parseOperand(&Operands, Mnemonic).isSuccess())
1174 return true;
1176 // If it is a st instruction with one 1 operand then it is a "store true".
1177 // Transform <"st"> to <"s">, <LPCC:ICC_T>
1178 if (Lexer.is(AsmToken::EndOfStatement) && Name == "st" &&
1179 Operands.size() == 2) {
1180 Operands.erase(Operands.begin(), Operands.begin() + 1);
1181 Operands.insert(Operands.begin(), LanaiOperand::CreateToken("s", NameLoc));
1182 Operands.insert(Operands.begin() + 1,
1183 LanaiOperand::createImm(
1184 MCConstantExpr::create(LPCC::ICC_T, getContext()),
1185 NameLoc, NameLoc));
1188 // If the instruction is a bt instruction with 1 operand (in assembly) then it
1189 // is an unconditional branch instruction and the first two elements of
1190 // operands need to be merged.
1191 if (Lexer.is(AsmToken::EndOfStatement) && Name.starts_with("bt") &&
1192 Operands.size() == 3) {
1193 Operands.erase(Operands.begin(), Operands.begin() + 2);
1194 Operands.insert(Operands.begin(), LanaiOperand::CreateToken("bt", NameLoc));
1197 // Parse until end of statement, consuming commas between operands
1198 while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.is(AsmToken::Comma)) {
1199 // Consume comma token
1200 Lex();
1202 // Parse next operand
1203 if (!parseOperand(&Operands, Mnemonic).isSuccess())
1204 return true;
1207 if (IsMemoryAssignmentError(Operands)) {
1208 Error(Parser.getTok().getLoc(),
1209 "the destination register can't equal the base register in an "
1210 "instruction that modifies the base register.");
1211 return true;
1214 // Insert always true operand for instruction that may be predicated but
1215 // are not. Currently the autogenerated parser always expects a predicate.
1216 if (MaybePredicatedInst(Operands)) {
1217 Operands.insert(Operands.begin() + 1,
1218 LanaiOperand::createImm(
1219 MCConstantExpr::create(LPCC::ICC_T, getContext()),
1220 NameLoc, NameLoc));
1223 return false;
1226 #define GET_REGISTER_MATCHER
1227 #define GET_MATCHER_IMPLEMENTATION
1228 #include "LanaiGenAsmMatcher.inc"
1230 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLanaiAsmParser() {
1231 RegisterMCAsmParser<LanaiAsmParser> x(getTheLanaiTarget());