51 std::unique_ptr<LanaiOperand>
parseRegister(
bool RestoreOnFailure =
false);
55 std::unique_ptr<LanaiOperand> parseIdentifier();
57 unsigned parseAluOperator(
bool PreOp,
bool PostOp);
71 SMLoc &EndLoc)
override;
73 SMLoc &EndLoc)
override;
78 bool MatchingInlineAsm)
override;
81#define GET_ASSEMBLER_HEADER
82#include "LanaiGenAsmMatcher.inc"
93 Lexer(Parser.getLexer()), SubtargetInfo(STI) {
95 ComputeAvailableFeatures(SubtargetInfo.getFeatureBits()));
117 SMLoc StartLoc, EndLoc;
146 explicit LanaiOperand(KindTy Kind) :
Kind(
Kind) {}
158 unsigned getReg()
const override {
163 const MCExpr *getImm()
const {
173 unsigned getMemBaseReg()
const {
178 unsigned getMemOffsetReg()
const {
180 return Mem.OffsetReg;
183 const MCExpr *getMemOffset()
const {
188 unsigned getMemOp()
const {
194 bool isReg()
const override {
return Kind == REGISTER; }
196 bool isImm()
const override {
return Kind == IMMEDIATE; }
198 bool isMem()
const override {
199 return isMemImm() || isMemRegImm() || isMemRegReg();
202 bool isMemImm()
const {
return Kind == MEMORY_IMM; }
204 bool isMemRegImm()
const {
return Kind == MEMORY_REG_IMM; }
206 bool isMemRegReg()
const {
return Kind == MEMORY_REG_REG; }
208 bool isMemSpls()
const {
return isMemRegImm() || isMemRegReg(); }
222 return isShiftedUInt<23, 2>(
static_cast<int32_t
>(
Value));
225 bool isBrTarget() {
return isBrImm() ||
isToken(); }
235 int64_t
Value = ConstExpr->getValue();
236 return Value != 0 && isShiftedUInt<16, 16>(
Value);
240 if (
const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(
Imm.Value))
252 bool isHiImm16And() {
260 return (
Value != 0) && ((
Value & ~0xffff0000) == 0xffff);
273 return isUInt<16>(
static_cast<int32_t
>(
Value));
277 if (
const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(
Imm.Value))
289 bool isLoImm16Signed() {
297 return isInt<16>(
static_cast<int32_t
>(
Value));
301 if (
const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(
Imm.Value))
313 bool isLoImm16And() {
321 return ((
Value & ~0xffff) == 0xffff0000);
344 return isUInt<21>(
Value);
348 if (
const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(
Imm.Value))
351 dyn_cast<MCSymbolRefExpr>(
Imm.Value)) {
361 dyn_cast<MCSymbolRefExpr>(
BinaryExpr->getLHS()))
376 return isInt<10>(
Value);
397 else if (
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Expr))
404 void addRegOperands(
MCInst &Inst,
unsigned N)
const {
405 assert(
N == 1 &&
"Invalid number of operands!");
409 void addImmOperands(
MCInst &Inst,
unsigned N)
const {
410 assert(
N == 1 &&
"Invalid number of operands!");
411 addExpr(Inst, getImm());
414 void addBrTargetOperands(
MCInst &Inst,
unsigned N)
const {
415 assert(
N == 1 &&
"Invalid number of operands!");
416 addExpr(Inst, getImm());
420 assert(
N == 1 &&
"Invalid number of operands!");
421 addExpr(Inst, getImm());
424 void addCondCodeOperands(
MCInst &Inst,
unsigned N)
const {
425 assert(
N == 1 &&
"Invalid number of operands!");
426 addExpr(Inst, getImm());
429 void addMemImmOperands(
MCInst &Inst,
unsigned N)
const {
430 assert(
N == 1 &&
"Invalid number of operands!");
431 const MCExpr *Expr = getMemOffset();
435 void addMemRegImmOperands(
MCInst &Inst,
unsigned N)
const {
436 assert(
N == 3 &&
"Invalid number of operands!");
438 const MCExpr *Expr = getMemOffset();
443 void addMemRegRegOperands(
MCInst &Inst,
unsigned N)
const {
444 assert(
N == 3 &&
"Invalid number of operands!");
446 assert(getMemOffsetReg() != 0 &&
"Invalid offset");
451 void addMemSplsOperands(
MCInst &Inst,
unsigned N)
const {
453 addMemRegImmOperands(Inst,
N);
455 addMemRegRegOperands(Inst,
N);
458 void addImmShiftOperands(
MCInst &Inst,
unsigned N)
const {
459 assert(
N == 1 &&
"Invalid number of operands!");
460 addExpr(Inst, getImm());
463 void addImm10Operands(
MCInst &Inst,
unsigned N)
const {
464 assert(
N == 1 &&
"Invalid number of operands!");
465 addExpr(Inst, getImm());
468 void addLoImm16Operands(
MCInst &Inst,
unsigned N)
const {
469 assert(
N == 1 &&
"Invalid number of operands!");
470 if (
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
473 else if (isa<LanaiMCExpr>(getImm())) {
475 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
480 }
else if (isa<MCBinaryExpr>(getImm())) {
489 assert(
false &&
"Operand type not supported.");
492 void addLoImm16AndOperands(
MCInst &Inst,
unsigned N)
const {
493 assert(
N == 1 &&
"Invalid number of operands!");
494 if (
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
497 assert(
false &&
"Operand type not supported.");
500 void addHiImm16Operands(
MCInst &Inst,
unsigned N)
const {
501 assert(
N == 1 &&
"Invalid number of operands!");
502 if (
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
504 else if (isa<LanaiMCExpr>(getImm())) {
506 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
511 }
else if (isa<MCBinaryExpr>(getImm())) {
520 assert(
false &&
"Operand type not supported.");
523 void addHiImm16AndOperands(
MCInst &Inst,
unsigned N)
const {
524 assert(
N == 1 &&
"Invalid number of operands!");
525 if (
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
528 assert(
false &&
"Operand type not supported.");
531 void addLoImm21Operands(
MCInst &Inst,
unsigned N)
const {
532 assert(
N == 1 &&
"Invalid number of operands!");
533 if (
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
535 else if (isa<LanaiMCExpr>(getImm())) {
537 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
542 }
else if (isa<MCSymbolRefExpr>(getImm())) {
545 dyn_cast<MCSymbolRefExpr>(getImm());
550 }
else if (isa<MCBinaryExpr>(getImm())) {
559 assert(
false &&
"Operand type not supported.");
565 OS <<
"Imm: " << getImm() <<
"\n";
568 OS <<
"Token: " << getToken() <<
"\n";
571 OS <<
"Reg: %r" <<
getReg() <<
"\n";
574 OS <<
"MemImm: " << *getMemOffset() <<
"\n";
577 OS <<
"MemRegImm: " << getMemBaseReg() <<
"+" << *getMemOffset() <<
"\n";
580 assert(getMemOffset() ==
nullptr);
581 OS <<
"MemRegReg: " << getMemBaseReg() <<
"+"
582 <<
"%r" << getMemOffsetReg() <<
"\n";
587 static std::unique_ptr<LanaiOperand> CreateToken(
StringRef Str,
SMLoc Start) {
588 auto Op = std::make_unique<LanaiOperand>(
TOKEN);
589 Op->Tok.Data = Str.data();
590 Op->Tok.Length = Str.size();
591 Op->StartLoc = Start;
596 static std::unique_ptr<LanaiOperand> createReg(
unsigned RegNum,
SMLoc Start,
598 auto Op = std::make_unique<LanaiOperand>(REGISTER);
599 Op->Reg.RegNum = RegNum;
600 Op->StartLoc = Start;
605 static std::unique_ptr<LanaiOperand> createImm(
const MCExpr *
Value,
607 auto Op = std::make_unique<LanaiOperand>(IMMEDIATE);
609 Op->StartLoc = Start;
614 static std::unique_ptr<LanaiOperand>
615 MorphToMemImm(std::unique_ptr<LanaiOperand> Op) {
617 Op->Kind = MEMORY_IMM;
620 Op->Mem.OffsetReg = 0;
621 Op->Mem.Offset =
Imm;
625 static std::unique_ptr<LanaiOperand>
626 MorphToMemRegReg(
unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
628 unsigned OffsetReg =
Op->getReg();
629 Op->Kind = MEMORY_REG_REG;
630 Op->Mem.BaseReg = BaseReg;
631 Op->Mem.AluOp = AluOp;
632 Op->Mem.OffsetReg = OffsetReg;
633 Op->Mem.Offset =
nullptr;
637 static std::unique_ptr<LanaiOperand>
638 MorphToMemRegImm(
unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
641 Op->Kind = MEMORY_REG_IMM;
642 Op->Mem.BaseReg = BaseReg;
643 Op->Mem.AluOp = AluOp;
644 Op->Mem.OffsetReg = 0;
645 Op->Mem.Offset =
Imm;
652bool LanaiAsmParser::ParseDirective(
AsmToken ) {
return true; }
654bool LanaiAsmParser::MatchAndEmitInstruction(
SMLoc IdLoc,
unsigned &Opcode,
658 bool MatchingInlineAsm) {
667 case Match_MissingFeature:
668 return Error(IdLoc,
"Instruction use requires option to be enabled");
669 case Match_MnemonicFail:
670 return Error(IdLoc,
"Unrecognized instruction mnemonic");
671 case Match_InvalidOperand: {
675 return Error(IdLoc,
"Too few operands for instruction");
678 if (ErrorLoc ==
SMLoc())
681 return Error(ErrorLoc,
"Invalid operand for instruction");
694std::unique_ptr<LanaiOperand>
695LanaiAsmParser::parseRegister(
bool RestoreOnFailure) {
696 SMLoc Start = Parser.getTok().getLoc();
698 std::optional<AsmToken> PercentTok;
703 PercentTok = Parser.getTok();
709 if (PercentTok && RestoreOnFailure)
710 Lexer.UnLex(*PercentTok);
714 return LanaiOperand::createReg(RegNum, Start, End);
716 if (PercentTok && RestoreOnFailure)
717 Lexer.UnLex(*PercentTok);
723 const AsmToken &Tok = getParser().getTok();
726 std::unique_ptr<LanaiOperand>
Op = parseRegister(
false);
728 RegNum =
Op->getReg();
729 return (Op ==
nullptr);
735 const AsmToken &Tok = getParser().getTok();
738 std::unique_ptr<LanaiOperand>
Op = parseRegister(
true);
741 RegNum =
Op->getReg();
745std::unique_ptr<LanaiOperand> LanaiAsmParser::parseIdentifier() {
746 SMLoc Start = Parser.getTok().getLoc();
755 if (Parser.parseIdentifier(Identifier))
768 Error(Lexer.getLoc(),
"Expected '('");
774 if (Parser.parseIdentifier(Identifier))
779 if (Lexer.getKind() ==
AsmToken::Plus && Parser.parseExpression(RHS))
785 Error(Lexer.getLoc(),
"Expected ')'");
792 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
800 return LanaiOperand::createImm(Res, Start, End);
803std::unique_ptr<LanaiOperand> LanaiAsmParser::parseImmediate() {
804 SMLoc Start = Parser.getTok().getLoc();
808 switch (Lexer.getKind()) {
810 return parseIdentifier();
815 if (!Parser.parseExpression(ExprVal))
816 return LanaiOperand::createImm(ExprVal, Start, End);
831unsigned LanaiAsmParser::parseAluOperator(
bool PreOp,
bool PostOp) {
833 Parser.parseIdentifier(IdString);
836 Error(Parser.getTok().getLoc(),
"Can't parse ALU operator");
846bool LanaiAsmParser::parsePrePost(
StringRef Type,
int *OffsetValue) {
847 bool PreOrPost =
false;
848 if (Lexer.getKind() == Lexer.peekTok(
true).getKind()) {
871 if (
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Op.getImm())) {
877 if (
const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Op.getImm()))
885 return (LHSSymbolRefExpr &&
907 Type =
static_cast<LanaiOperand *
>(
Operands[0].get())->getToken();
911 unsigned BaseReg = 0;
913 bool PostOp =
false, PreOp =
false;
916 std::unique_ptr<LanaiOperand>
Op = parseRegister();
933 std::unique_ptr<LanaiOperand>
Offset =
nullptr;
938 PreOp = parsePrePost(
Type, &OffsetValue);
940 Op = parseRegister();
949 Operands.push_back(LanaiOperand::MorphToMemImm(std::move(Op)));
951 if (!
Op->isLoImm16Signed()) {
952 Error(Parser.getTok().getLoc(),
953 "Memory address is not word "
954 "aligned and larger than class RM can handle");
957 Operands.push_back(LanaiOperand::MorphToMemRegImm(
964 Error(Parser.getTok().getLoc(),
965 "Unknown operand, expected register or immediate");
968 BaseReg =
Op->getReg();
972 PostOp = parsePrePost(
Type, &OffsetValue);
978 SMLoc Start = Parser.getTok().getLoc();
983 Offset = LanaiOperand::createImm(OffsetConstExpr, Start, End);
986 if (
Offset || OffsetValue != 0) {
987 Error(Parser.getTok().getLoc(),
"Expected ']'");
992 AluOp = parseAluOperator(PreOp, PostOp);
997 Error(Parser.getTok().getLoc(),
"Expected ']'");
1009 Error(Parser.getTok().getLoc(),
1010 "Memory address is not word "
1011 "aligned and larger than class RM can handle");
1017 ? LanaiOperand::MorphToMemRegImm(BaseReg, std::move(
Offset), AluOp)
1018 : LanaiOperand::MorphToMemRegReg(BaseReg, std::move(
Offset), AluOp));
1035 Parser.eatToEndOfStatement();
1040 std::unique_ptr<LanaiOperand>
Op = parseRegister();
1048 Error(Parser.getTok().getLoc(),
"Unknown operand");
1049 Parser.eatToEndOfStatement();
1054 Operands->push_back(std::move(Op));
1063 size_t Next =
Name.find(
'.');
1068 if (
Name.endswith(
".r")) {
1069 Mnemonic =
Name.substr(0,
Name.size() - 2);
1074 if (Mnemonic[0] ==
'b' ||
1075 (Mnemonic[0] ==
's' && !Mnemonic.
startswith(
"sel") &&
1082 Mnemonic = Mnemonic.
slice(0, 1);
1083 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1084 Operands->push_back(LanaiOperand::createImm(
1087 Operands->push_back(LanaiOperand::CreateToken(
".r", NameLoc));
1101 size_t Next = Mnemonic.
rfind(
'.',
Name.size());
1108 Mnemonic = Mnemonic.
substr(0, Next + 1);
1110 Mnemonic = Mnemonic.
substr(0, Next);
1112 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1113 Operands->push_back(LanaiOperand::createImm(
1119 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1121 Operands->push_back(LanaiOperand::CreateToken(
".r", NameLoc));
1133 bool Modifies =
false;
1149 int PossibleAluOpIdx =
Offset + 3;
1150 int PossibleBaseIdx =
Offset + 1;
1151 int PossibleDestIdx =
Offset + 4;
1152 if (LanaiOperand *PossibleAluOp =
1153 static_cast<LanaiOperand *
>(
Operands[PossibleAluOpIdx].
get()))
1154 if (PossibleAluOp->isImm())
1156 dyn_cast<MCConstantExpr>(PossibleAluOp->getImm()))
1158 return Modifies &&
Operands[PossibleBaseIdx]->isReg() &&
1159 Operands[PossibleDestIdx]->isReg() &&
1160 Operands[PossibleBaseIdx]->getReg() ==
1161 Operands[PossibleDestIdx]->getReg();
1165 return static_cast<const LanaiOperand &
>(
op).
isReg();
1173 static_cast<const LanaiOperand &
>(*
Operands[0]).getToken())
1204 Operands.insert(
Operands.begin(), LanaiOperand::CreateToken(
"s", NameLoc));
1206 LanaiOperand::createImm(
1217 Operands.insert(
Operands.begin(), LanaiOperand::CreateToken(
"bt", NameLoc));
1231 Error(Parser.getTok().getLoc(),
1232 "the destination register can't equal the base register in an "
1233 "instruction that modifies the base register.");
1241 LanaiOperand::createImm(
1249#define GET_REGISTER_MATCHER
1250#define GET_MATCHER_IMPLEMENTATION
1251#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 bool MaybePredicatedInst(const OperandVector &Operands)
static unsigned MatchRegisterName(StringRef Name)
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.
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 unsigned getReg() const =0
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 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 ParseDirective(AsmToken DirectiveID)=0
ParseDirective - Parse a target specific assembler directive.
virtual bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
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 ...
virtual OperandMatchResultTy tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
tryParseRegister - parse one register if possible
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.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
bool startswith(StringRef Prefix) const
size_t rfind(char C, size_t From=npos) const
Search for the last character C in the string.
bool endswith(StringRef Suffix) const
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)
This is an optimization pass for GlobalISel generic memory operations.
Target & getTheLanaiTarget()
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...