49 std::unique_ptr<LanaiOperand>
parseRegister(
bool RestoreOnFailure =
false);
53 std::unique_ptr<LanaiOperand> parseIdentifier();
55 unsigned parseAluOperator(
bool PreOp,
bool PostOp);
68 SMLoc &EndLoc)
override;
73 bool MatchingInlineAsm)
override;
76#define GET_ASSEMBLER_HEADER
77#include "LanaiGenAsmMatcher.inc"
87 Lexer(Parser.getLexer()), SubtargetInfo(STI) {
89 ComputeAvailableFeatures(SubtargetInfo.getFeatureBits()));
111 SMLoc StartLoc, EndLoc;
140 explicit LanaiOperand(KindTy Kind) :
Kind(
Kind) {}
157 const MCExpr *getImm()
const {
174 return Mem.OffsetReg;
177 const MCExpr *getMemOffset()
const {
182 unsigned getMemOp()
const {
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(); }
216 return isShiftedUInt<23, 2>(
static_cast<int32_t
>(
Value));
219 bool isBrTarget() {
return isBrImm() ||
isToken(); }
229 int64_t
Value = ConstExpr->getValue();
230 return Value != 0 && isShiftedUInt<16, 16>(
Value);
234 if (
const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(
Imm.Value))
246 bool isHiImm16And() {
254 return (
Value != 0) && ((
Value & ~0xffff0000) == 0xffff);
267 return isUInt<16>(
static_cast<int32_t
>(
Value));
271 if (
const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(
Imm.Value))
283 bool isLoImm16Signed() {
291 return isInt<16>(
static_cast<int32_t
>(
Value));
295 if (
const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(
Imm.Value))
307 bool isLoImm16And() {
315 return ((
Value & ~0xffff) == 0xffff0000);
338 return isUInt<21>(
Value);
342 if (
const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(
Imm.Value))
345 dyn_cast<MCSymbolRefExpr>(
Imm.Value)) {
355 dyn_cast<MCSymbolRefExpr>(
BinaryExpr->getLHS()))
370 return isInt<10>(
Value);
391 else if (
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Expr))
398 void addRegOperands(
MCInst &Inst,
unsigned N)
const {
399 assert(
N == 1 &&
"Invalid number of operands!");
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());
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();
429 void addMemRegImmOperands(
MCInst &Inst,
unsigned N)
const {
430 assert(
N == 3 &&
"Invalid number of operands!");
432 const MCExpr *Expr = getMemOffset();
437 void addMemRegRegOperands(
MCInst &Inst,
unsigned N)
const {
438 assert(
N == 3 &&
"Invalid number of operands!");
440 assert(getMemOffsetReg() &&
"Invalid offset");
445 void addMemSplsOperands(
MCInst &Inst,
unsigned N)
const {
447 addMemRegImmOperands(Inst,
N);
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()))
467 else if (isa<LanaiMCExpr>(getImm())) {
469 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
474 }
else if (isa<MCBinaryExpr>(getImm())) {
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()))
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()))
498 else if (isa<LanaiMCExpr>(getImm())) {
500 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
505 }
else if (isa<MCBinaryExpr>(getImm())) {
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()))
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()))
529 else if (isa<LanaiMCExpr>(getImm())) {
531 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
536 }
else if (isa<MCSymbolRefExpr>(getImm())) {
539 dyn_cast<MCSymbolRefExpr>(getImm());
544 }
else if (isa<MCBinaryExpr>(getImm())) {
553 assert(
false &&
"Operand type not supported.");
559 OS <<
"Imm: " << getImm() <<
"\n";
562 OS <<
"Token: " << getToken() <<
"\n";
565 OS <<
"Reg: %r" <<
getReg() <<
"\n";
568 OS <<
"MemImm: " << *getMemOffset() <<
"\n";
571 OS <<
"MemRegImm: " << getMemBaseReg() <<
"+" << *getMemOffset() <<
"\n";
574 assert(getMemOffset() ==
nullptr);
575 OS <<
"MemRegReg: " << getMemBaseReg() <<
"+"
576 <<
"%r" << getMemOffsetReg() <<
"\n";
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;
592 auto Op = std::make_unique<LanaiOperand>(REGISTER);
593 Op->Reg.RegNum =
Reg;
594 Op->StartLoc = Start;
599 static std::unique_ptr<LanaiOperand> createImm(
const MCExpr *
Value,
601 auto Op = std::make_unique<LanaiOperand>(IMMEDIATE);
603 Op->StartLoc = Start;
608 static std::unique_ptr<LanaiOperand>
609 MorphToMemImm(std::unique_ptr<LanaiOperand>
Op) {
611 Op->Kind = MEMORY_IMM;
614 Op->Mem.OffsetReg = 0;
615 Op->Mem.Offset =
Imm;
619 static std::unique_ptr<LanaiOperand>
620 MorphToMemRegReg(
MCRegister BaseReg, std::unique_ptr<LanaiOperand>
Op,
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;
631 static std::unique_ptr<LanaiOperand>
632 MorphToMemRegImm(
MCRegister BaseReg, std::unique_ptr<LanaiOperand>
Op,
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;
646bool LanaiAsmParser::matchAndEmitInstruction(
SMLoc IdLoc,
unsigned &Opcode,
650 bool MatchingInlineAsm) {
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: {
667 return Error(IdLoc,
"Too few operands for instruction");
670 if (ErrorLoc ==
SMLoc())
673 return Error(ErrorLoc,
"Invalid operand for instruction");
686std::unique_ptr<LanaiOperand>
687LanaiAsmParser::parseRegister(
bool RestoreOnFailure) {
688 SMLoc Start = Parser.getTok().getLoc();
690 std::optional<AsmToken> PercentTok;
695 PercentTok = Parser.getTok();
701 if (PercentTok && RestoreOnFailure)
702 Lexer.UnLex(*PercentTok);
706 return LanaiOperand::createReg(Reg, Start,
End);
708 if (PercentTok && RestoreOnFailure)
709 Lexer.UnLex(*PercentTok);
715 const AsmToken &Tok = getParser().getTok();
718 std::unique_ptr<LanaiOperand>
Op = parseRegister(
false);
720 RegNum =
Op->getReg();
721 return (
Op ==
nullptr);
726 const AsmToken &Tok = getParser().getTok();
729 std::unique_ptr<LanaiOperand>
Op = parseRegister(
true);
736std::unique_ptr<LanaiOperand> LanaiAsmParser::parseIdentifier() {
737 SMLoc Start = Parser.getTok().getLoc();
746 if (Parser.parseIdentifier(Identifier))
759 Error(Lexer.getLoc(),
"Expected '('");
765 if (Parser.parseIdentifier(Identifier))
770 if (Lexer.getKind() ==
AsmToken::Plus && Parser.parseExpression(RHS))
776 Error(Lexer.getLoc(),
"Expected ')'");
783 MCSymbol *
Sym = getContext().getOrCreateSymbol(Identifier);
791 return LanaiOperand::createImm(Res, Start,
End);
794std::unique_ptr<LanaiOperand> LanaiAsmParser::parseImmediate() {
795 SMLoc Start = Parser.getTok().getLoc();
799 switch (Lexer.getKind()) {
801 return parseIdentifier();
806 if (!Parser.parseExpression(ExprVal))
807 return LanaiOperand::createImm(ExprVal, Start,
End);
822unsigned LanaiAsmParser::parseAluOperator(
bool PreOp,
bool PostOp) {
824 Parser.parseIdentifier(IdString);
827 Error(Parser.getTok().getLoc(),
"Can't parse ALU operator");
837bool LanaiAsmParser::parsePrePost(
StringRef Type,
int *OffsetValue) {
838 bool PreOrPost =
false;
839 if (Lexer.getKind() == Lexer.peekTok(
true).getKind()) {
862 if (
const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(
Op.getImm())) {
868 if (
const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(
Op.getImm()))
876 return (LHSSymbolRefExpr &&
897 Type =
static_cast<LanaiOperand *
>(
Operands[0].get())->getToken();
903 bool PostOp =
false, PreOp =
false;
906 std::unique_ptr<LanaiOperand>
Op = parseRegister();
923 std::unique_ptr<LanaiOperand>
Offset =
nullptr;
928 PreOp = parsePrePost(
Type, &OffsetValue);
930 Op = parseRegister();
939 Operands.push_back(LanaiOperand::MorphToMemImm(std::move(
Op)));
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(
952 return Error(Parser.getTok().getLoc(),
953 "Unknown operand, expected register or immediate");
955 BaseReg =
Op->getReg();
959 PostOp = parsePrePost(
Type, &OffsetValue);
965 SMLoc Start = Parser.getTok().getLoc();
970 Offset = LanaiOperand::createImm(OffsetConstExpr, Start,
End);
973 if (
Offset || OffsetValue != 0)
974 return Error(Parser.getTok().getLoc(),
"Expected ']'");
977 AluOp = parseAluOperator(PreOp, PostOp);
982 return Error(Parser.getTok().getLoc(),
"Expected ']'");
992 return Error(Parser.getTok().getLoc(),
993 "Memory address is not word aligned and larger than class RM "
998 ? LanaiOperand::MorphToMemRegImm(BaseReg, std::move(
Offset), AluOp)
999 : LanaiOperand::MorphToMemRegReg(BaseReg, std::move(
Offset), AluOp));
1015 if (
Result.isFailure()) {
1016 Parser.eatToEndOfStatement();
1021 std::unique_ptr<LanaiOperand>
Op = parseRegister();
1029 Error(Parser.getTok().getLoc(),
"Unknown operand");
1030 Parser.eatToEndOfStatement();
1044 size_t Next =
Name.find(
'.');
1051 if (Mnemonic[0] ==
'b' ||
1052 (Mnemonic[0] ==
's' && !Mnemonic.
starts_with(
"sel") &&
1059 Mnemonic = Mnemonic.
slice(0, 1);
1060 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1061 Operands->push_back(LanaiOperand::createImm(
1064 Operands->push_back(LanaiOperand::CreateToken(
".r", NameLoc));
1078 size_t Next = Mnemonic.
rfind(
'.',
Name.size());
1085 Mnemonic = Mnemonic.
substr(0, Next + 1);
1087 Mnemonic = Mnemonic.
substr(0, Next);
1089 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1090 Operands->push_back(LanaiOperand::createImm(
1096 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1098 Operands->push_back(LanaiOperand::CreateToken(
".r", NameLoc));
1110 bool Modifies =
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())
1133 dyn_cast<MCConstantExpr>(PossibleAluOp->getImm()))
1135 return Modifies &&
Operands[PossibleBaseIdx]->isReg() &&
1136 Operands[PossibleDestIdx]->isReg() &&
1137 Operands[PossibleBaseIdx]->getReg() ==
1138 Operands[PossibleDestIdx]->getReg();
1142 return static_cast<const LanaiOperand &
>(
op).
isReg();
1150 static_cast<const LanaiOperand &
>(*
Operands[0]).getToken())
1173 if (!parseOperand(&
Operands, Mnemonic).isSuccess())
1181 Operands.insert(
Operands.begin(), LanaiOperand::CreateToken(
"s", NameLoc));
1183 LanaiOperand::createImm(
1194 Operands.insert(
Operands.begin(), LanaiOperand::CreateToken(
"bt", NameLoc));
1203 if (!parseOperand(&
Operands, Mnemonic).isSuccess())
1208 Error(Parser.getTok().getLoc(),
1209 "the destination register can't equal the base register in an "
1210 "instruction that modifies the base register.");
1218 LanaiOperand::createImm(
1226#define GET_REGISTER_MATCHER
1227#define GET_MATCHER_IMPLEMENTATION
1228#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 createExpr(const MCExpr *Val)
static MCOperand createReg(MCRegister Reg)
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 parseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands)=0
Parse one assembly instruction.
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
virtual bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm)=0
Recognize a series of operands of a parsed instruction as an actual MCInst and emit it to the specifi...
void setAvailableFeatures(const FeatureBitset &Value)
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,...