51 std::unique_ptr<LanaiOperand>
parseRegister(
bool RestoreOnFailure =
false);
55 std::unique_ptr<LanaiOperand> parseIdentifier();
57 unsigned parseAluOperator(
bool PreOp,
bool PostOp);
70 SMLoc &EndLoc)
override;
75 bool MatchingInlineAsm)
override;
78#define GET_ASSEMBLER_HEADER
79#include "LanaiGenAsmMatcher.inc"
89 Lexer(Parser.getLexer()), SubtargetInfo(STI) {
91 ComputeAvailableFeatures(SubtargetInfo.getFeatureBits()));
113 SMLoc StartLoc, EndLoc;
142 explicit LanaiOperand(KindTy Kind) :
Kind(
Kind) {}
159 const MCExpr *getImm()
const {
169 unsigned getMemBaseReg()
const {
174 unsigned getMemOffsetReg()
const {
176 return Mem.OffsetReg;
179 const MCExpr *getMemOffset()
const {
184 unsigned getMemOp()
const {
190 bool isReg()
const override {
return Kind == REGISTER; }
192 bool isImm()
const override {
return Kind == IMMEDIATE; }
194 bool isMem()
const override {
195 return isMemImm() || isMemRegImm() || isMemRegReg();
198 bool isMemImm()
const {
return Kind == MEMORY_IMM; }
200 bool isMemRegImm()
const {
return Kind == MEMORY_REG_IMM; }
202 bool isMemRegReg()
const {
return Kind == MEMORY_REG_REG; }
204 bool isMemSpls()
const {
return isMemRegImm() || isMemRegReg(); }
218 return isShiftedUInt<23, 2>(
static_cast<int32_t
>(
Value));
221 bool isBrTarget() {
return isBrImm() ||
isToken(); }
231 int64_t
Value = ConstExpr->getValue();
232 return Value != 0 && isShiftedUInt<16, 16>(
Value);
236 if (
const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(
Imm.Value))
248 bool isHiImm16And() {
256 return (
Value != 0) && ((
Value & ~0xffff0000) == 0xffff);
269 return isUInt<16>(
static_cast<int32_t
>(
Value));
273 if (
const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(
Imm.Value))
285 bool isLoImm16Signed() {
293 return isInt<16>(
static_cast<int32_t
>(
Value));
297 if (
const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(
Imm.Value))
309 bool isLoImm16And() {
317 return ((
Value & ~0xffff) == 0xffff0000);
340 return isUInt<21>(
Value);
344 if (
const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(
Imm.Value))
347 dyn_cast<MCSymbolRefExpr>(
Imm.Value)) {
357 dyn_cast<MCSymbolRefExpr>(
BinaryExpr->getLHS()))
372 return isInt<10>(
Value);
393 else if (
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Expr))
400 void addRegOperands(
MCInst &Inst,
unsigned N)
const {
401 assert(
N == 1 &&
"Invalid number of operands!");
405 void addImmOperands(
MCInst &Inst,
unsigned N)
const {
406 assert(
N == 1 &&
"Invalid number of operands!");
407 addExpr(Inst, getImm());
410 void addBrTargetOperands(
MCInst &Inst,
unsigned N)
const {
411 assert(
N == 1 &&
"Invalid number of operands!");
412 addExpr(Inst, getImm());
416 assert(
N == 1 &&
"Invalid number of operands!");
417 addExpr(Inst, getImm());
420 void addCondCodeOperands(
MCInst &Inst,
unsigned N)
const {
421 assert(
N == 1 &&
"Invalid number of operands!");
422 addExpr(Inst, getImm());
425 void addMemImmOperands(
MCInst &Inst,
unsigned N)
const {
426 assert(
N == 1 &&
"Invalid number of operands!");
427 const MCExpr *Expr = getMemOffset();
431 void addMemRegImmOperands(
MCInst &Inst,
unsigned N)
const {
432 assert(
N == 3 &&
"Invalid number of operands!");
434 const MCExpr *Expr = getMemOffset();
439 void addMemRegRegOperands(
MCInst &Inst,
unsigned N)
const {
440 assert(
N == 3 &&
"Invalid number of operands!");
442 assert(getMemOffsetReg() != 0 &&
"Invalid offset");
447 void addMemSplsOperands(
MCInst &Inst,
unsigned N)
const {
449 addMemRegImmOperands(Inst,
N);
451 addMemRegRegOperands(Inst,
N);
454 void addImmShiftOperands(
MCInst &Inst,
unsigned N)
const {
455 assert(
N == 1 &&
"Invalid number of operands!");
456 addExpr(Inst, getImm());
459 void addImm10Operands(
MCInst &Inst,
unsigned N)
const {
460 assert(
N == 1 &&
"Invalid number of operands!");
461 addExpr(Inst, getImm());
464 void addLoImm16Operands(
MCInst &Inst,
unsigned N)
const {
465 assert(
N == 1 &&
"Invalid number of operands!");
466 if (
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
469 else if (isa<LanaiMCExpr>(getImm())) {
471 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
476 }
else if (isa<MCBinaryExpr>(getImm())) {
485 assert(
false &&
"Operand type not supported.");
488 void addLoImm16AndOperands(
MCInst &Inst,
unsigned N)
const {
489 assert(
N == 1 &&
"Invalid number of operands!");
490 if (
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
493 assert(
false &&
"Operand type not supported.");
496 void addHiImm16Operands(
MCInst &Inst,
unsigned N)
const {
497 assert(
N == 1 &&
"Invalid number of operands!");
498 if (
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
500 else if (isa<LanaiMCExpr>(getImm())) {
502 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
507 }
else if (isa<MCBinaryExpr>(getImm())) {
516 assert(
false &&
"Operand type not supported.");
519 void addHiImm16AndOperands(
MCInst &Inst,
unsigned N)
const {
520 assert(
N == 1 &&
"Invalid number of operands!");
521 if (
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
524 assert(
false &&
"Operand type not supported.");
527 void addLoImm21Operands(
MCInst &Inst,
unsigned N)
const {
528 assert(
N == 1 &&
"Invalid number of operands!");
529 if (
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
531 else if (isa<LanaiMCExpr>(getImm())) {
533 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
538 }
else if (isa<MCSymbolRefExpr>(getImm())) {
541 dyn_cast<MCSymbolRefExpr>(getImm());
546 }
else if (isa<MCBinaryExpr>(getImm())) {
555 assert(
false &&
"Operand type not supported.");
561 OS <<
"Imm: " << getImm() <<
"\n";
564 OS <<
"Token: " << getToken() <<
"\n";
567 OS <<
"Reg: %r" <<
getReg() <<
"\n";
570 OS <<
"MemImm: " << *getMemOffset() <<
"\n";
573 OS <<
"MemRegImm: " << getMemBaseReg() <<
"+" << *getMemOffset() <<
"\n";
576 assert(getMemOffset() ==
nullptr);
577 OS <<
"MemRegReg: " << getMemBaseReg() <<
"+"
578 <<
"%r" << getMemOffsetReg() <<
"\n";
583 static std::unique_ptr<LanaiOperand> CreateToken(
StringRef Str,
SMLoc Start) {
584 auto Op = std::make_unique<LanaiOperand>(
TOKEN);
585 Op->Tok.Data = Str.data();
586 Op->Tok.Length = Str.size();
587 Op->StartLoc = Start;
592 static std::unique_ptr<LanaiOperand> createReg(
unsigned RegNum,
SMLoc Start,
594 auto Op = std::make_unique<LanaiOperand>(REGISTER);
595 Op->Reg.RegNum = RegNum;
596 Op->StartLoc = Start;
601 static std::unique_ptr<LanaiOperand> createImm(
const MCExpr *
Value,
603 auto Op = std::make_unique<LanaiOperand>(IMMEDIATE);
605 Op->StartLoc = Start;
610 static std::unique_ptr<LanaiOperand>
611 MorphToMemImm(std::unique_ptr<LanaiOperand>
Op) {
613 Op->Kind = MEMORY_IMM;
616 Op->Mem.OffsetReg = 0;
617 Op->Mem.Offset =
Imm;
621 static std::unique_ptr<LanaiOperand>
622 MorphToMemRegReg(
unsigned BaseReg, std::unique_ptr<LanaiOperand>
Op,
624 unsigned OffsetReg =
Op->getReg();
625 Op->Kind = MEMORY_REG_REG;
626 Op->Mem.BaseReg = BaseReg;
627 Op->Mem.AluOp = AluOp;
628 Op->Mem.OffsetReg = OffsetReg;
629 Op->Mem.Offset =
nullptr;
633 static std::unique_ptr<LanaiOperand>
634 MorphToMemRegImm(
unsigned BaseReg, std::unique_ptr<LanaiOperand>
Op,
637 Op->Kind = MEMORY_REG_IMM;
638 Op->Mem.BaseReg = BaseReg;
639 Op->Mem.AluOp = AluOp;
640 Op->Mem.OffsetReg = 0;
641 Op->Mem.Offset =
Imm;
648bool LanaiAsmParser::MatchAndEmitInstruction(
SMLoc IdLoc,
unsigned &Opcode,
652 bool MatchingInlineAsm) {
661 case Match_MissingFeature:
662 return Error(IdLoc,
"Instruction use requires option to be enabled");
663 case Match_MnemonicFail:
664 return Error(IdLoc,
"Unrecognized instruction mnemonic");
665 case Match_InvalidOperand: {
669 return Error(IdLoc,
"Too few operands for instruction");
672 if (ErrorLoc ==
SMLoc())
675 return Error(ErrorLoc,
"Invalid operand for instruction");
688std::unique_ptr<LanaiOperand>
689LanaiAsmParser::parseRegister(
bool RestoreOnFailure) {
690 SMLoc Start = Parser.getTok().getLoc();
692 std::optional<AsmToken> PercentTok;
697 PercentTok = Parser.getTok();
703 if (PercentTok && RestoreOnFailure)
704 Lexer.UnLex(*PercentTok);
708 return LanaiOperand::createReg(RegNum, Start,
End);
710 if (PercentTok && RestoreOnFailure)
711 Lexer.UnLex(*PercentTok);
717 const AsmToken &Tok = getParser().getTok();
720 std::unique_ptr<LanaiOperand>
Op = parseRegister(
false);
722 RegNum =
Op->getReg();
723 return (
Op ==
nullptr);
728 const AsmToken &Tok = getParser().getTok();
731 std::unique_ptr<LanaiOperand>
Op = parseRegister(
true);
738std::unique_ptr<LanaiOperand> LanaiAsmParser::parseIdentifier() {
739 SMLoc Start = Parser.getTok().getLoc();
748 if (Parser.parseIdentifier(Identifier))
761 Error(Lexer.getLoc(),
"Expected '('");
767 if (Parser.parseIdentifier(Identifier))
772 if (Lexer.getKind() ==
AsmToken::Plus && Parser.parseExpression(RHS))
778 Error(Lexer.getLoc(),
"Expected ')'");
785 MCSymbol *
Sym = getContext().getOrCreateSymbol(Identifier);
793 return LanaiOperand::createImm(Res, Start,
End);
796std::unique_ptr<LanaiOperand> LanaiAsmParser::parseImmediate() {
797 SMLoc Start = Parser.getTok().getLoc();
801 switch (Lexer.getKind()) {
803 return parseIdentifier();
808 if (!Parser.parseExpression(ExprVal))
809 return LanaiOperand::createImm(ExprVal, Start,
End);
824unsigned LanaiAsmParser::parseAluOperator(
bool PreOp,
bool PostOp) {
826 Parser.parseIdentifier(IdString);
829 Error(Parser.getTok().getLoc(),
"Can't parse ALU operator");
839bool LanaiAsmParser::parsePrePost(
StringRef Type,
int *OffsetValue) {
840 bool PreOrPost =
false;
841 if (Lexer.getKind() == Lexer.peekTok(
true).getKind()) {
864 if (
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(
Op.getImm())) {
870 if (
const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(
Op.getImm()))
878 return (LHSSymbolRefExpr &&
899 Type =
static_cast<LanaiOperand *
>(
Operands[0].get())->getToken();
903 unsigned BaseReg = 0;
905 bool PostOp =
false, PreOp =
false;
908 std::unique_ptr<LanaiOperand>
Op = parseRegister();
925 std::unique_ptr<LanaiOperand>
Offset =
nullptr;
930 PreOp = parsePrePost(
Type, &OffsetValue);
932 Op = parseRegister();
941 Operands.push_back(LanaiOperand::MorphToMemImm(std::move(
Op)));
943 if (!
Op->isLoImm16Signed())
944 return Error(Parser.getTok().getLoc(),
945 "Memory address is not word aligned and larger than "
946 "class RM can handle");
947 Operands.push_back(LanaiOperand::MorphToMemRegImm(
954 return Error(Parser.getTok().getLoc(),
955 "Unknown operand, expected register or immediate");
957 BaseReg =
Op->getReg();
961 PostOp = parsePrePost(
Type, &OffsetValue);
967 SMLoc Start = Parser.getTok().getLoc();
972 Offset = LanaiOperand::createImm(OffsetConstExpr, Start,
End);
975 if (
Offset || OffsetValue != 0)
976 return Error(Parser.getTok().getLoc(),
"Expected ']'");
979 AluOp = parseAluOperator(PreOp, PostOp);
984 return Error(Parser.getTok().getLoc(),
"Expected ']'");
994 return Error(Parser.getTok().getLoc(),
995 "Memory address is not word aligned and larger than class RM "
1000 ? LanaiOperand::MorphToMemRegImm(BaseReg, std::move(
Offset), AluOp)
1001 : LanaiOperand::MorphToMemRegReg(BaseReg, std::move(
Offset), AluOp));
1017 if (
Result.isFailure()) {
1018 Parser.eatToEndOfStatement();
1023 std::unique_ptr<LanaiOperand>
Op = parseRegister();
1031 Error(Parser.getTok().getLoc(),
"Unknown operand");
1032 Parser.eatToEndOfStatement();
1046 size_t Next =
Name.find(
'.');
1053 if (Mnemonic[0] ==
'b' ||
1054 (Mnemonic[0] ==
's' && !Mnemonic.
starts_with(
"sel") &&
1061 Mnemonic = Mnemonic.
slice(0, 1);
1062 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1063 Operands->push_back(LanaiOperand::createImm(
1066 Operands->push_back(LanaiOperand::CreateToken(
".r", NameLoc));
1080 size_t Next = Mnemonic.
rfind(
'.',
Name.size());
1087 Mnemonic = Mnemonic.
substr(0, Next + 1);
1089 Mnemonic = Mnemonic.
substr(0, Next);
1091 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1092 Operands->push_back(LanaiOperand::createImm(
1098 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1100 Operands->push_back(LanaiOperand::CreateToken(
".r", NameLoc));
1112 bool Modifies =
false;
1128 int PossibleAluOpIdx =
Offset + 3;
1129 int PossibleBaseIdx =
Offset + 1;
1130 int PossibleDestIdx =
Offset + 4;
1131 if (LanaiOperand *PossibleAluOp =
1132 static_cast<LanaiOperand *
>(
Operands[PossibleAluOpIdx].
get()))
1133 if (PossibleAluOp->isImm())
1135 dyn_cast<MCConstantExpr>(PossibleAluOp->getImm()))
1137 return Modifies &&
Operands[PossibleBaseIdx]->isReg() &&
1138 Operands[PossibleDestIdx]->isReg() &&
1139 Operands[PossibleBaseIdx]->getReg() ==
1140 Operands[PossibleDestIdx]->getReg();
1144 return static_cast<const LanaiOperand &
>(
op).
isReg();
1152 static_cast<const LanaiOperand &
>(*
Operands[0]).getToken())
1175 if (!parseOperand(&
Operands, Mnemonic).isSuccess())
1183 Operands.insert(
Operands.begin(), LanaiOperand::CreateToken(
"s", NameLoc));
1185 LanaiOperand::createImm(
1196 Operands.insert(
Operands.begin(), LanaiOperand::CreateToken(
"bt", NameLoc));
1205 if (!parseOperand(&
Operands, Mnemonic).isSuccess())
1210 Error(Parser.getTok().getLoc(),
1211 "the destination register can't equal the base register in an "
1212 "instruction that modifies the base register.");
1220 LanaiOperand::createImm(
1228#define GET_REGISTER_MATCHER
1229#define GET_MATCHER_IMPLEMENTATION
1230#include "LanaiGenAsmMatcher.inc"
static bool addCallTargetOperands(MachineInstrBuilder &CallInst, MachineIRBuilder &MIRBuilder, AMDGPUCallLowering::CallLoweringInfo &Info)
#define LLVM_EXTERNAL_VISIBILITY
static int SizeForSuffix(StringRef T)
static bool IsMemoryAssignmentError(const OperandVector &Operands)
bool shouldBeSls(const LanaiOperand &Op)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLanaiAsmParser()
static MCRegister MatchRegisterName(StringRef Name)
static bool MaybePredicatedInst(const OperandVector &Operands)
static unsigned AluWithPrePost(unsigned AluCode, bool PreOp, bool PostOp)
static bool IsRegister(const MCParsedAsmOperand &op)
mir Rename Register Operands
static bool isReg(const MCInst &MI, unsigned OpNo)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isImm(const MachineOperand &MO, MachineRegisterInfo *MRI)
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
bool parseImmediate(MCInst &MI, uint64_t &Size, ArrayRef< uint8_t > Bytes)
Target independent representation for an assembler token.
This class represents an Operation in the Expression.
Base class for user error types.
Lightweight error class with error context and mandatory checking.
VariantKind getKind() const
static const LanaiMCExpr * create(VariantKind Kind, const MCExpr *Expr, MCContext &Ctx)
Generic assembler lexer interface, for use by target specific assembly lexers.
Generic assembler parser interface, for use by target specific assembly parsers.
Binary assembler expressions.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Base class for the full range of assembler expressions which are needed for parsing.
Instances of this class represent a single low-level machine instruction.
unsigned getOpcode() const
void addOperand(const MCOperand Op)
Interface to description of machine instruction set.
static MCOperand createReg(unsigned Reg)
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createImm(int64_t Val)
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
virtual SMLoc getStartLoc() const =0
getStartLoc - Get the location of the first token of this operand.
virtual bool isReg() const =0
isReg - Is this a register operand?
virtual bool isMem() const =0
isMem - Is this a memory operand?
virtual MCRegister getReg() const =0
virtual void print(raw_ostream &OS) const =0
print - Print a debug representation of the operand to the given stream.
virtual bool isToken() const =0
isToken - Is this a token operand?
virtual bool isImm() const =0
isImm - Is this an immediate operand?
virtual SMLoc getEndLoc() const =0
getEndLoc - Get the location of the last token of this operand.
Wrapper class representing physical registers. Should be passed by value.
Streaming machine code generation interface.
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
Generic base class for all target subtargets.
Represent a reference to a symbol from inside an expression.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
VariantKind getKind() const
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
MCTargetAsmParser - Generic interface to target specific assembly parsers.
virtual bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
virtual ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
tryParseRegister - parse one register if possible
void setAvailableFeatures(const FeatureBitset &Value)
virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands)=0
ParseInstruction - Parse one assembly instruction.
virtual bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm)=0
MatchAndEmitInstruction - Recognize a series of operands of a parsed instruction as an actual MCInst ...
Ternary parse status returned by various parse* methods.
static constexpr StatusTy Failure
static constexpr StatusTy Success
static constexpr StatusTy NoMatch
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
StringRef - Represent a constant reference to a string, i.e.
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
size_t rfind(char C, size_t From=npos) const
Search for the last character C in the string.
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
A switch()-like statement whose cases are string literals.
StringSwitch & StartsWith(StringLiteral S, T Value)
StringSwitch & EndsWith(StringLiteral S, T Value)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
static unsigned makePostOp(unsigned AluOp)
static unsigned makePreOp(unsigned AluOp)
static AluCode stringToLanaiAluCode(StringRef S)
static bool modifiesOp(unsigned AluOp)
static CondCode suffixToLanaiCondCode(StringRef S)
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Target & getTheLanaiTarget()
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
DWARFExpression::Operation Op
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...