35#define DEBUG_TYPE "avr-asm-parser"
45 const std::string GENERATE_STUBS =
"gs";
47 enum AVRMatchResultTy {
48 Match_InvalidRegisterOnTiny = FIRST_TARGET_MATCH_RESULT_TY + 1,
51#define GET_ASSEMBLER_HEADER
52#include "AVRGenAsmMatcher.inc"
57 bool MatchingInlineAsm)
override;
61 SMLoc &EndLoc)
override;
72 int parseRegisterName();
80 unsigned Kind)
override;
82 unsigned toDREG(
unsigned Reg,
unsigned From = AVR::sub_lo) {
83 MCRegisterClass const *Class = &AVRMCRegisterClasses[AVR::DREGSRegClassID];
84 return MRI->getMatchingSuperReg(Reg,
From, Class);
111 enum KindTy { k_Immediate, k_Register, k_Token, k_Memri }
Kind;
115 :
Kind(k_Token), Tok(Tok), Start(S),
End(S) {}
116 AVROperand(
unsigned Reg,
SMLoc const &S,
SMLoc const &E)
123 struct RegisterImmediate {
135 void addRegOperands(
MCInst &Inst,
unsigned N)
const {
136 assert(Kind == k_Register &&
"Unexpected operand kind");
137 assert(
N == 1 &&
"Invalid number of operands!");
146 else if (
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
152 void addImmOperands(
MCInst &Inst,
unsigned N)
const {
153 assert(Kind == k_Immediate &&
"Unexpected operand kind");
154 assert(
N == 1 &&
"Invalid number of operands!");
156 const MCExpr *Expr = getImm();
161 void addMemriOperands(
MCInst &Inst,
unsigned N)
const {
162 assert(Kind == k_Memri &&
"Unexpected operand kind");
163 assert(
N == 2 &&
"Invalid number of operands");
166 addExpr(Inst, getImm());
169 void addImmCom8Operands(
MCInst &Inst,
unsigned N)
const {
170 assert(
N == 1 &&
"Invalid number of operands!");
173 const auto *
CE = cast<MCConstantExpr>(getImm());
177 bool isImmCom8()
const {
180 const auto *
CE = dyn_cast<MCConstantExpr>(getImm());
183 int64_t
Value =
CE->getValue();
184 return isUInt<8>(
Value);
187 bool isReg()
const override {
return Kind == k_Register; }
188 bool isImm()
const override {
return Kind == k_Immediate; }
189 bool isToken()
const override {
return Kind == k_Token; }
190 bool isMem()
const override {
return Kind == k_Memri; }
191 bool isMemri()
const {
return Kind == k_Memri; }
194 assert(Kind == k_Token &&
"Invalid access!");
199 assert((Kind == k_Register || Kind == k_Memri) &&
"Invalid access!");
204 const MCExpr *getImm()
const {
205 assert((Kind == k_Immediate || Kind == k_Memri) &&
"Invalid access!");
209 static std::unique_ptr<AVROperand> CreateToken(
StringRef Str,
SMLoc S) {
210 return std::make_unique<AVROperand>(Str, S);
213 static std::unique_ptr<AVROperand> CreateReg(
unsigned RegNum,
SMLoc S,
215 return std::make_unique<AVROperand>(RegNum, S, E);
218 static std::unique_ptr<AVROperand> CreateImm(
const MCExpr *Val,
SMLoc S,
220 return std::make_unique<AVROperand>(Val, S, E);
223 static std::unique_ptr<AVROperand>
225 return std::make_unique<AVROperand>(RegNum, Val, S, E);
233 void makeReg(
unsigned RegNo) {
235 RegImm = {RegNo,
nullptr};
238 void makeImm(
MCExpr const *Ex) {
243 void makeMemri(
unsigned RegNo,
MCExpr const *Imm) {
254 O <<
"Token: \"" << getToken() <<
"\"";
260 O <<
"Immediate: \"" << *getImm() <<
"\"";
265 O <<
"Memri: \"" <<
getReg() <<
'+' << *getImm() <<
"\"";
285bool AVRAsmParser::invalidOperand(
SMLoc const &Loc,
288 SMLoc ErrorLoc = Loc;
289 char const *Diag =
nullptr;
293 Diag =
"too few operands for instruction.";
298 if (
Op.getStartLoc() !=
SMLoc()) {
299 ErrorLoc =
Op.getStartLoc();
305 Diag =
"invalid operand for instruction";
308 return Error(ErrorLoc, Diag);
311bool AVRAsmParser::missingFeature(
llvm::SMLoc const &Loc,
313 return Error(Loc,
"instruction requires a CPU feature not currently enabled");
323bool AVRAsmParser::MatchAndEmitInstruction(
SMLoc Loc,
unsigned &Opcode,
326 bool MatchingInlineAsm) {
328 unsigned MatchResult =
331 switch (MatchResult) {
333 return emit(Inst, Loc, Out);
334 case Match_MissingFeature:
336 case Match_InvalidOperand:
338 case Match_MnemonicFail:
339 return Error(Loc,
"invalid instruction");
340 case Match_InvalidRegisterOnTiny:
341 return Error(Loc,
"invalid register on avrtiny");
352 int RegNum = matchFn(
Name);
358 if (RegNum == AVR::NoRegister) {
359 RegNum = matchFn(
Name.lower());
361 if (RegNum == AVR::NoRegister) {
362 RegNum = matchFn(
Name.upper());
368int AVRAsmParser::parseRegisterName() {
371 if (RegNum == AVR::NoRegister)
377int AVRAsmParser::parseRegister(
bool RestoreOnFailure) {
378 int RegNum = AVR::NoRegister;
390 RegNum = toDREG(parseRegisterName());
392 if (RegNum == AVR::NoRegister && RestoreOnFailure) {
393 getLexer().UnLex(std::move(ColonTok));
394 getLexer().UnLex(std::move(HighTok));
397 RegNum = parseRegisterName();
404 int RegNo = parseRegister();
406 if (RegNo == AVR::NoRegister)
410 if (AVR::R0 <= RegNo && RegNo <= AVR::R15 &&
415 Operands.push_back(AVROperand::CreateReg(RegNo,
T.getLoc(),
T.getEndLoc()));
424 if (!tryParseRelocExpression(
Operands))
446 bool isNegated =
false;
478 std::string GSModName = ModifierName.
str() +
"_" + GENERATE_STUBS;
494 MCExpr const *InnerExpression;
495 if (getParser().parseExpression(InnerExpression))
520 switch (getLexer().getKind()) {
526 if (maybeReg && !tryParseRegisterOperand(
Operands)) {
533 return tryParseExpression(
Operands);
538 switch (getLexer().peekTok().getKind()) {
570 RegNo = parseRegister();
572 if (RegNo == AVR::NoRegister)
595 Reg = parseRegister(
false);
598 return Reg == AVR::NoRegister;
604 Reg = parseRegister(
true);
607 if (Reg == AVR::NoRegister)
612void AVRAsmParser::eatComma() {
623 Operands.push_back(AVROperand::CreateToken(Mnemonic, NameLoc));
637 SMLoc Loc = getLexer().getLoc();
640 return Error(Loc,
"failed to parse register and immediate pair");
645 bool maybeReg =
true;
646 if (OperandNum == 1) {
647 std::array<StringRef, 8> Insts = {
"lds",
"adiw",
"sbiw",
"ldi"};
648 for (
auto Inst : Insts) {
649 if (Inst == Mnemonic) {
654 }
else if (OperandNum == 0) {
655 std::array<StringRef, 8> Insts = {
"sts",
"call",
"rcall",
"rjmp",
"jmp"};
656 for (
auto Inst : Insts) {
657 if (Inst == Mnemonic) {
664 if (parseOperand(
Operands, maybeReg)) {
665 SMLoc Loc = getLexer().getLoc();
667 return Error(Loc,
"unexpected token in argument list");
676 if (IDVal.
lower() ==
".long")
678 if (IDVal.
lower() ==
".word" || IDVal.
lower() ==
".short")
680 if (IDVal.
lower() ==
".byte")
681 return parseLiteralValues(1, DirectiveID.
getLoc());
685ParseStatus AVRAsmParser::parseLiteralValues(
unsigned SizeInBytes,
SMLoc L) {
720 auto parseOne = [&]() ->
bool {
727 return (parseMany(parseOne));
734#define GET_REGISTER_MATCHER
735#define GET_MATCHER_IMPLEMENTATION
736#include "AVRGenAsmMatcher.inc"
740 unsigned ExpectedKind) {
741 AVROperand &
Op =
static_cast<AVROperand &
>(AsmOp);
742 MatchClassKind
Expected =
static_cast<MatchClassKind
>(ExpectedKind);
748 int64_t RegNum = Const->getValue();
751 if (0 <= RegNum && RegNum <= 15 &&
753 return Match_InvalidRegisterOnTiny;
758 if (RegNum != AVR::NoRegister) {
760 if (validateOperandClass(
Op,
Expected) == Match_Success) {
761 return Match_Success;
771 if (isSubclass(
Expected, MCK_DREGS)) {
772 unsigned correspondingDREG = toDREG(
Op.getReg());
774 if (correspondingDREG != AVR::NoRegister) {
775 Op.makeReg(correspondingDREG);
780 return Match_InvalidOperand;
unsigned const MachineRegisterInfo * MRI
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
This file implements a class to represent arbitrary precision integral constant values and operations...
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
static MCRegister MatchRegisterName(StringRef Name)
Maps from the set of all register names to a register number.
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRAsmParser()
BlockVerifier::State From
#define LLVM_EXTERNAL_VISIBILITY
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
mir Rename Register Operands
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void emitValueForModiferKind(const MCSymbol *Sym, unsigned SizeInBytes, SMLoc Loc=SMLoc(), AVRMCExpr::VariantKind ModifierKind=AVRMCExpr::VK_AVR_None)
static const AVRMCExpr * create(VariantKind Kind, const MCExpr *Expr, bool isNegated, MCContext &Ctx)
Creates an AVR machine code expression.
static VariantKind getKindByName(StringRef Name)
VariantKind
Specifies the type of an expression.
Target independent representation for an assembler token.
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
bool is(TokenKind K) const
TokenKind getKind() const
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
This class represents an Operation in the Expression.
Base class for user error types.
Lightweight error class with error context and mandatory checking.
Tagged union holding either a T or a Error.
Class representing an expression and its matching format.
Generic assembler lexer interface, for use by target specific assembly lexers.
const AsmToken peekTok(bool ShouldSkipSpace=true)
Look ahead at the next token to be lexed.
AsmToken::TokenKind getKind() const
Get the kind of current token.
virtual size_t peekTokens(MutableArrayRef< AsmToken > Buf, bool ShouldSkipSpace=true)=0
Look ahead an arbitrary number of tokens.
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
MCAsmParser & getParser()
Generic assembler parser interface, for use by target specific assembly parsers.
virtual void eatToEndOfStatement()=0
Skip to the end of the current statement, for error recovery.
virtual MCStreamer & getStreamer()=0
Return the output streamer for the assembler.
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression.
const AsmToken & getTok() const
Get the current AsmToken from the stream.
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
virtual MCAsmLexer & getLexer()=0
const MCRegisterInfo * getRegisterInfo() const
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.
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.
MCRegisterClass - Base class of TargetRegisterClass.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
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.
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
const FeatureBitset & getFeatureBits() 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 ParseStatus parseDirective(AsmToken DirectiveID)
Parses a target-specific assembler directive.
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 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, unsigned Kind)
Allow a target to add special case operand matching for things that tblgen doesn't/can't handle effec...
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 ...
const MCSubtargetInfo * STI
Current STI.
Ternary parse status returned by various parse* methods.
constexpr bool isFailure() const
static constexpr StatusTy Failure
constexpr bool isSuccess() const
static constexpr StatusTy Success
static constexpr StatusTy NoMatch
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
constexpr const char * getPointer() const
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.
std::string str() const
str - Get the contents as an std::string.
std::string lower() const
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
@ CE
Windows NT (Windows on ARM)
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Target & getTheAVRTarget()
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...