LLVM: lib/Target/AVR/AsmParser/AVRAsmParser.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
14
30
31#include
32#include
33
34#define DEBUG_TYPE "avr-asm-parser"
35
36using namespace llvm;
37
38namespace {
39
43 const std::string GENERATE_STUBS = "gs";
44
45 enum AVRMatchResultTy {
46 Match_InvalidRegisterOnTiny = FIRST_TARGET_MATCH_RESULT_TY + 1,
47 };
48
49#define GET_ASSEMBLER_HEADER
50#include "AVRGenAsmMatcher.inc"
51
52 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
55 bool MatchingInlineAsm) override;
56
59 SMLoc &EndLoc) override;
60
63
65
67
68 bool parseOperand(OperandVector &Operands, bool maybeReg);
71 MCRegister parseRegister(bool RestoreOnFailure = false);
72 bool tryParseRegisterOperand(OperandVector &Operands);
73 bool tryParseExpression(OperandVector &Operands, int64_t offset);
74 bool tryParseRelocExpression(OperandVector &Operands);
75 void eatComma();
76
78 unsigned Kind) override;
79
81 MCRegisterClass const *Class = &AVRMCRegisterClasses[AVR::DREGSRegClassID];
82 return MRI->getMatchingSuperReg(Reg, From, Class);
83 }
84
85 bool emit(MCInst &Instruction, SMLoc const &Loc, MCStreamer &Out) const;
86 bool invalidOperand(SMLoc const &Loc, OperandVector const &Operands,
87 uint64_t const &ErrorInfo);
88 bool missingFeature(SMLoc const &Loc, uint64_t const &ErrorInfo);
89
90 ParseStatus parseLiteralValues(unsigned SizeInBytes, SMLoc L);
91
92public:
93 AVRAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
94 const MCInstrInfo &MII, const MCTargetOptions &Options)
95 : MCTargetAsmParser(Options, STI, MII), Parser(Parser) {
98
99 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
100 }
101
102 MCAsmParser &getParser() const { return Parser; }
103 AsmLexer &getLexer() const { return Parser.getLexer(); }
104};
105
106
108 typedef MCParsedAsmOperand Base;
109 enum KindTy { k_Immediate, k_Register, k_Token, k_Memri } Kind;
110
111public:
112 AVROperand(StringRef Tok, SMLoc const &S)
113 : Kind(k_Token), Tok(Tok), Start(S), End(S) {}
114 AVROperand(MCRegister Reg, SMLoc const &S, SMLoc const &E)
115 : Kind(k_Register), RegImm({Reg, nullptr}), Start(S), End(E) {}
116 AVROperand(MCExpr const *Imm, SMLoc const &S, SMLoc const &E)
117 : Kind(k_Immediate), RegImm({0, Imm}), Start(S), End(E) {}
118 AVROperand(MCRegister Reg, MCExpr const *Imm, SMLoc const &S, SMLoc const &E)
119 : Kind(k_Memri), RegImm({Reg, Imm}), Start(S), End(E) {}
120
121 struct RegisterImmediate {
122 MCRegister Reg;
123 MCExpr const *Imm;
124 };
125 union {
126 StringRef Tok;
127 RegisterImmediate RegImm;
128 };
129
130 SMLoc Start, End;
131
132public:
133 void addRegOperands(MCInst &Inst, unsigned N) const {
134 assert(Kind == k_Register && "Unexpected operand kind");
135 assert(N == 1 && "Invalid number of operands!");
136
138 }
139
140 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
141
142 if (!Expr)
146 else
148 }
149
150 void addImmOperands(MCInst &Inst, unsigned N) const {
151 assert(Kind == k_Immediate && "Unexpected operand kind");
152 assert(N == 1 && "Invalid number of operands!");
153
154 const MCExpr *Expr = getImm();
155 addExpr(Inst, Expr);
156 }
157
158
159 void addMemriOperands(MCInst &Inst, unsigned N) const {
160 assert(Kind == k_Memri && "Unexpected operand kind");
161 assert(N == 2 && "Invalid number of operands");
162
164 addExpr(Inst, getImm());
165 }
166
167 void addImmCom8Operands(MCInst &Inst, unsigned N) const {
168 assert(N == 1 && "Invalid number of operands!");
169
170
173 }
174
175 bool isImmCom8() const {
176 if (!isImm())
177 return false;
179 if (!CE)
180 return false;
181 int64_t Value = CE->getValue();
183 }
184
185 bool isReg() const override { return Kind == k_Register; }
186 bool isImm() const override { return Kind == k_Immediate; }
187 bool isToken() const override { return Kind == k_Token; }
188 bool isMem() const override { return Kind == k_Memri; }
189 bool isMemri() const { return Kind == k_Memri; }
190
192 assert(Kind == k_Token && "Invalid access!");
193 return Tok;
194 }
195
196 MCRegister getReg() const override {
197 assert((Kind == k_Register || Kind == k_Memri) && "Invalid access!");
198
200 }
201
202 const MCExpr *getImm() const {
203 assert((Kind == k_Immediate || Kind == k_Memri) && "Invalid access!");
205 }
206
207 static std::unique_ptr CreateToken(StringRef Str, SMLoc S) {
208 return std::make_unique(Str, S);
209 }
210
211 static std::unique_ptr CreateReg(MCRegister Reg, SMLoc S,
212 SMLoc E) {
213 return std::make_unique(Reg, S, E);
214 }
215
216 static std::unique_ptr CreateImm(const MCExpr *Val, SMLoc S,
217 SMLoc E) {
218 return std::make_unique(Val, S, E);
219 }
220
221 static std::unique_ptr
222 CreateMemri(MCRegister Reg, const MCExpr *Val, SMLoc S, SMLoc E) {
223 return std::make_unique(Reg, Val, S, E);
224 }
225
226 void makeToken(StringRef Token) {
227 Kind = k_Token;
228 Tok = Token;
229 }
230
231 void makeReg(MCRegister Reg) {
232 Kind = k_Register;
234 }
235
236 void makeImm(MCExpr const *Ex) {
237 Kind = k_Immediate;
239 }
240
241 void makeMemri(MCRegister Reg, MCExpr const *Imm) {
242 Kind = k_Memri;
244 }
245
246 SMLoc getStartLoc() const override { return Start; }
247 SMLoc getEndLoc() const override { return End; }
248
249 void print(raw_ostream &O, const MCAsmInfo &MAI) const override {
250 switch (Kind) {
251 case k_Token:
252 O << "Token: \"" << getToken() << "\"";
253 break;
254 case k_Register:
255 O << "Register: " << getReg().id();
256 break;
257 case k_Immediate:
258 O << "Immediate: \"";
260 O << "\"";
261 break;
262 case k_Memri: {
263
264
265 O << "Memri: \"" << getReg().id() << '+';
267 O << "\"";
268 break;
269 }
270 }
271 O << "\n";
272 }
273};
274
275}
276
277
278
279
280
282
283
284
286
287bool AVRAsmParser::invalidOperand(SMLoc const &Loc,
291 char const *Diag = nullptr;
292
295 Diag = "too few operands for instruction.";
296 } else {
297 AVROperand const &Op = (AVROperand const &)*Operands[ErrorInfo];
298
299
300 if (Op.getStartLoc() != SMLoc()) {
301 ErrorLoc = Op.getStartLoc();
302 }
303 }
304 }
305
306 if (!Diag) {
307 Diag = "invalid operand for instruction";
308 }
309
310 return Error(ErrorLoc, Diag);
311}
312
313bool AVRAsmParser::missingFeature(llvm::SMLoc const &Loc,
314 uint64_t const &ErrorInfo) {
315 return Error(Loc, "instruction requires a CPU feature not currently enabled");
316}
317
318bool AVRAsmParser::emit(MCInst &Inst, SMLoc const &Loc, MCStreamer &Out) const {
321
322 return false;
323}
324
325bool AVRAsmParser::matchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,
327 MCStreamer &Out, uint64_t &ErrorInfo,
328 bool MatchingInlineAsm) {
329 MCInst Inst;
330 unsigned MatchResult =
331 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
332
333 switch (MatchResult) {
334 case Match_Success:
335 return emit(Inst, Loc, Out);
336 case Match_MissingFeature:
337 return missingFeature(Loc, ErrorInfo);
338 case Match_InvalidOperand:
339 return invalidOperand(Loc, Operands, ErrorInfo);
340 case Match_MnemonicFail:
341 return Error(Loc, "invalid instruction");
342 case Match_InvalidRegisterOnTiny:
343 return Error(Loc, "invalid register on avrtiny");
344 default:
345 return true;
346 }
347}
348
349
350
351MCRegister AVRAsmParser::parseRegisterName(MCRegister (*matchFn)(StringRef)) {
353
354 MCRegister Reg = matchFn(Name);
355
356
357
358
359
360 if () {
361 Reg = matchFn(Name.lower());
362 }
363 if () {
364 Reg = matchFn(Name.upper());
365 }
366
367 return Reg;
368}
369
370MCRegister AVRAsmParser::parseRegisterName() {
372
373 if ()
375
376 return Reg;
377}
378
379MCRegister AVRAsmParser::parseRegister(bool RestoreOnFailure) {
380 MCRegister Reg;
381
383
385 AsmToken HighTok = Parser.getTok();
386 Parser.Lex();
387 AsmToken ColonTok = Parser.getTok();
388 Parser.Lex();
389
391
392 Reg = toDREG(parseRegisterName());
393 }
394 if ( && RestoreOnFailure) {
395 getLexer().UnLex(std::move(ColonTok));
396 getLexer().UnLex(std::move(HighTok));
397 }
398 } else {
399 Reg = parseRegisterName();
400 }
401 }
402 return Reg;
403}
404
405bool AVRAsmParser::tryParseRegisterOperand(OperandVector &Operands) {
406 MCRegister Reg = parseRegister();
407
408 if ()
409 return true;
410
411
412 if (AVR::R0 <= Reg && Reg <= AVR::R15 &&
413 STI->hasFeature(AVR::FeatureTinyEncoding))
414 return Error(Parser.getTok().getLoc(), "invalid register on avrtiny");
415
416 AsmToken const &T = Parser.getTok();
417 Operands.push_back(AVROperand::CreateReg(Reg, T.getLoc(), T.getEndLoc()));
418 Parser.Lex();
419
420 return false;
421}
422
423bool AVRAsmParser::tryParseExpression(OperandVector &Operands, int64_t offset) {
425
426 if (!tryParseRelocExpression(Operands))
427 return false;
428
432
433
434 return true;
435 }
436
437
438 MCExpr const *Expression;
439 if (getParser().parseExpression(Expression))
440 return true;
441
442 if (offset) {
445 }
446
448 Operands.push_back(AVROperand::CreateImm(Expression, S, E));
449 return false;
450}
451
452bool AVRAsmParser::tryParseRelocExpression(OperandVector &Operands) {
453 bool isNegated = false;
455
457
458
459
462 return true;
463
464
465 AsmToken tokens[2];
469 isNegated = true;
470
471
474
475 return true;
476 }
479
481 Parser.Lex();
482 Parser.Lex();
485 std::string GSModName = ModifierName.str() + "_" + GENERATE_STUBS;
488 Parser.Lex();
489 }
490 } else {
492 }
493
496 Parser.Lex();
498 Parser.Lex();
499 }
500
501 MCExpr const *InnerExpression;
502 if (getParser().parseExpression(InnerExpression))
503 return true;
504
508 Parser.Lex();
509 }
510
511
513 Parser.Lex();
514
515 MCExpr const *Expression =
517
519 Operands.push_back(AVROperand::CreateImm(Expression, S, E));
520
521 return false;
522}
523
524bool AVRAsmParser::parseOperand(OperandVector &Operands, bool maybeReg) {
526
527 switch (getLexer().getKind()) {
528 default:
529 return Error(Parser.getTok().getLoc(), "unexpected token in operand");
530
532
533 if (maybeReg && !tryParseRegisterOperand(Operands)) {
534 return false;
535 }
536 [[fallthrough]];
539 return tryParseExpression(Operands, 0);
541 return tryParseExpression(Operands, 2);
544
545
546 switch (getLexer().peekTok().getKind()) {
551 if (!tryParseExpression(Operands, 0))
552 return false;
553 break;
554 default:
555 break;
556 }
557
560 Parser.Lex();
561 return false;
562 }
563 }
564
565
566 return true;
567}
568
569ParseStatus AVRAsmParser::parseMemriOperand(OperandVector &Operands) {
571
572 SMLoc E, S;
573 MCExpr const *Expression;
574 MCRegister Reg;
575
576
577 {
578 Reg = parseRegister();
579
580 if ()
582
584 Parser.Lex();
585 }
586
587
588 {
589 if (getParser().parseExpression(Expression))
591
593 }
594
595 Operands.push_back(AVROperand::CreateMemri(Reg, Expression, S, E));
596
598}
599
600bool AVRAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
601 SMLoc &EndLoc) {
603 Reg = parseRegister(false);
605
606 return Reg == AVR::NoRegister;
607}
608
609ParseStatus AVRAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
610 SMLoc &EndLoc) {
612 Reg = parseRegister(true);
614
615 if (Reg == AVR::NoRegister)
618}
619
620void AVRAsmParser::eatComma() {
622 Parser.Lex();
623 } else {
624
625 }
626}
627
628bool AVRAsmParser::parseInstruction(ParseInstructionInfo &Info,
629 StringRef Mnemonic, SMLoc NameLoc,
631 Operands.push_back(AVROperand::CreateToken(Mnemonic, NameLoc));
632
633 int OperandNum = -1;
635 OperandNum++;
636 if (OperandNum > 0)
637 eatComma();
638
639 ParseStatus ParseRes = MatchOperandParserImpl(Operands, Mnemonic);
640
642 continue;
643
645 SMLoc Loc = getLexer().getLoc();
647
648 return Error(Loc, "failed to parse register and immediate pair");
649 }
650
651
652
653 bool maybeReg = true;
654
655 if (OperandNum == 1) {
656 std::array<StringRef, 8> Insts = {"lds", "adiw", "sbiw", "ldi"};
657 for (auto Inst : Insts) {
658 if (Inst == Mnemonic) {
659 maybeReg = false;
660 break;
661 }
662 }
663 } else if (OperandNum == 0) {
664 std::array<StringRef, 8> Insts = {"sts", "call", "rcall", "rjmp", "jmp"};
665 for (auto Inst : Insts) {
666 if (Inst == Mnemonic) {
667 maybeReg = false;
668 break;
669 }
670 }
671 }
672
673 if (parseOperand(Operands, maybeReg)) {
674 SMLoc Loc = getLexer().getLoc();
676 return Error(Loc, "unexpected token in argument list");
677 }
678 }
679 Parser.Lex();
680 return false;
681}
682
683ParseStatus AVRAsmParser::parseDirective(llvm::AsmToken DirectiveID) {
685 if (IDVal.lower() == ".long")
686 return parseLiteralValues(SIZE_LONG, DirectiveID.getLoc());
687 if (IDVal.lower() == ".word" || IDVal.lower() == ".short")
688 return parseLiteralValues(SIZE_WORD, DirectiveID.getLoc());
689 if (IDVal.lower() == ".byte")
690 return parseLiteralValues(1, DirectiveID.getLoc());
692}
693
694ParseStatus AVRAsmParser::parseLiteralValues(unsigned SizeInBytes, SMLoc L) {
695 MCAsmParser &Parser = getParser();
696 AVRMCELFStreamer &AVRStreamer =
697 static_cast<AVRMCELFStreamer &>(Parser.getStreamer());
698 AsmToken Tokens[2];
707 }
708
714 Parser.Lex();
715 Parser.Lex();
716 } else {
718 }
722 Lex();
725 return parseEOL();
726 }
727
728 auto parseOne = [&]() -> bool {
729 const MCExpr *Value;
731 return true;
733 return false;
734 };
735 return (parseMany(parseOne));
736}
737
741
742#define GET_REGISTER_MATCHER
743#define GET_MATCHER_IMPLEMENTATION
744#include "AVRGenAsmMatcher.inc"
745
746
747unsigned AVRAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
748 unsigned ExpectedKind) {
749 AVROperand &Op = static_cast<AVROperand &>(AsmOp);
750 MatchClassKind Expected = static_cast<MatchClassKind>(ExpectedKind);
751
752
753
754 if (Op.isImm()) {
756 int64_t RegNum = Const->getValue();
757
758
759 if (0 <= RegNum && RegNum <= 15 &&
760 STI->hasFeature(AVR::FeatureTinyEncoding))
761 return Match_InvalidRegisterOnTiny;
762
763 std::ostringstream RegName;
764 RegName << "r" << RegNum;
767 if (validateOperandClass(Op, Expected, *STI) == Match_Success) {
768 return Match_Success;
769 }
770 }
771
772 }
773 }
774
775 if (Op.isReg()) {
776
777
778 if (isSubclass(Expected, MCK_DREGS)) {
779 MCRegister correspondingDREG = toDREG(Op.getReg());
780
781 if (correspondingDREG) {
782 Op.makeReg(correspondingDREG);
783 return validateOperandClass(Op, Expected, *STI);
784 }
785 }
786 }
787 return Match_InvalidOperand;
788}
unsigned const MachineRegisterInfo * MRI
static MCRegister MatchRegisterName(StringRef Name)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRAsmParser()
Definition AVRAsmParser.cpp:738
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
#define LLVM_EXTERNAL_VISIBILITY
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
void emitValueForModiferKind(const MCSymbol *Sym, unsigned SizeInBytes, SMLoc Loc=SMLoc(), AVRMCExpr::Specifier ModifierKind=AVR::S_AVR_NONE)
static const AVRMCExpr * create(Specifier S, const MCExpr *Expr, bool isNegated, MCContext &Ctx)
Specifies the type of an expression.
static Specifier parseSpecifier(StringRef Name)
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.
LLVM_ABI size_t peekTokens(MutableArrayRef< AsmToken > Buf, bool ShouldSkipSpace=true)
Look ahead an arbitrary number of tokens.
Target independent representation for an assembler token.
LLVM_ABI SMLoc getLoc() const
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.
Base class for user error types.
Tagged union holding either a T or a Error.
void printExpr(raw_ostream &, const MCExpr &) const
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
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 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.
MCStreamer & getStreamer()
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
void addOperand(const MCOperand Op)
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.
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.
constexpr unsigned id() const
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())
bool hasFeature(unsigned Feature) const
const FeatureBitset & getFeatureBits() const
MCTargetAsmParser - Generic interface to target specific assembly parsers.
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
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
LLVM_ABI std::string lower() const
@ CE
Windows NT (Windows on ARM)
Context & getContext() const
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
static bool isMem(const MachineInstr &MI, unsigned Op)
LLVM_ABI std::pair< StringRef, StringRef > getToken(StringRef Source, StringRef Delimiters=" \t\n\v\f\r")
getToken - This function extracts one token from source, ignoring any leading characters that appear ...
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
Target & getTheAVRTarget()
SmallVectorImpl< std::unique_ptr< MCParsedAsmOperand > > OperandVector
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...