1//===---- AVRAsmParser.cpp - Parse AVR assembly to MCInst instructions ----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "AVRRegisterInfo.h"
10#include "MCTargetDesc/AVRMCAsmInfo.h"
11#include "MCTargetDesc/AVRMCELFStreamer.h"
12#include "MCTargetDesc/AVRMCTargetDesc.h"
13#include "TargetInfo/AVRTargetInfo.h"
14
15#include "llvm/ADT/APInt.h"
16#include "llvm/MC/MCContext.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCInst.h"
19#include "llvm/MC/MCParser/AsmLexer.h"
20#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21#include "llvm/MC/MCParser/MCTargetAsmParser.h"
22#include "llvm/MC/MCStreamer.h"
23#include "llvm/MC/MCSubtargetInfo.h"
24#include "llvm/MC/MCSymbol.h"
25#include "llvm/MC/MCValue.h"
26#include "llvm/MC/TargetRegistry.h"
27#include "llvm/Support/Compiler.h"
28#include "llvm/Support/Debug.h"
29#include "llvm/Support/MathExtras.h"
30
31#include <array>
32#include <sstream>
33
34#define DEBUG_TYPE "avr-asm-parser"
35
36using namespace llvm;
37
38namespace {
39/// Parses AVR assembly from a stream.
40class AVRAsmParser : public MCTargetAsmParser {
41 const MCSubtargetInfo &STI;
42 MCAsmParser &Parser;
43 const MCRegisterInfo *MRI;
44 const std::string GENERATE_STUBS = "gs";
45
46 enum AVRMatchResultTy {
47 Match_InvalidRegisterOnTiny = FIRST_TARGET_MATCH_RESULT_TY + 1,
48 };
49
50#define GET_ASSEMBLER_HEADER
51#include "AVRGenAsmMatcher.inc"
52
53 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
54 OperandVector &Operands, MCStreamer &Out,
55 uint64_t &ErrorInfo,
56 bool MatchingInlineAsm) override;
57
58 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
59 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
60 SMLoc &EndLoc) override;
61
62 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
63 SMLoc NameLoc, OperandVector &Operands) override;
64
65 ParseStatus parseDirective(AsmToken DirectiveID) override;
66
67 ParseStatus parseMemriOperand(OperandVector &Operands);
68
69 bool parseOperand(OperandVector &Operands, bool maybeReg);
70 MCRegister parseRegisterName(MCRegister (*matchFn)(StringRef));
71 MCRegister parseRegisterName();
72 MCRegister parseRegister(bool RestoreOnFailure = false);
73 bool tryParseRegisterOperand(OperandVector &Operands);
74 bool tryParseExpression(OperandVector &Operands, int64_t offset);
75 bool tryParseRelocExpression(OperandVector &Operands);
76 void eatComma();
77
78 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
79 unsigned Kind) override;
80
81 MCRegister toDREG(MCRegister Reg, unsigned From = AVR::sub_lo) {
82 MCRegisterClass const *Class = &AVRMCRegisterClasses[AVR::DREGSRegClassID];
83 return MRI->getMatchingSuperReg(Reg, SubIdx: From, RC: Class);
84 }
85
86 bool emit(MCInst &Instruction, SMLoc const &Loc, MCStreamer &Out) const;
87 bool invalidOperand(SMLoc const &Loc, OperandVector const &Operands,
88 uint64_t const &ErrorInfo);
89 bool missingFeature(SMLoc const &Loc, uint64_t const &ErrorInfo);
90
91 ParseStatus parseLiteralValues(unsigned SizeInBytes, SMLoc L);
92
93public:
94 AVRAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
95 const MCInstrInfo &MII, const MCTargetOptions &Options)
96 : MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) {
97 MCAsmParserExtension::Initialize(Parser);
98 MRI = getContext().getRegisterInfo();
99
100 setAvailableFeatures(ComputeAvailableFeatures(FB: STI.getFeatureBits()));
101 }
102
103 MCAsmParser &getParser() const { return Parser; }
104 AsmLexer &getLexer() const { return Parser.getLexer(); }
105};
106
107/// An parsed AVR assembly operand.
108class AVROperand : public MCParsedAsmOperand {
109 typedef MCParsedAsmOperand Base;
110 enum KindTy { k_Immediate, k_Register, k_Token, k_Memri } Kind;
111
112public:
113 AVROperand(StringRef Tok, SMLoc const &S)
114 : Kind(k_Token), Tok(Tok), Start(S), End(S) {}
115 AVROperand(MCRegister Reg, SMLoc const &S, SMLoc const &E)
116 : Kind(k_Register), RegImm({.Reg: Reg, .Imm: nullptr}), Start(S), End(E) {}
117 AVROperand(MCExpr const *Imm, SMLoc const &S, SMLoc const &E)
118 : Kind(k_Immediate), RegImm({.Reg: 0, .Imm: Imm}), Start(S), End(E) {}
119 AVROperand(MCRegister Reg, MCExpr const *Imm, SMLoc const &S, SMLoc const &E)
120 : Kind(k_Memri), RegImm({.Reg: Reg, .Imm: Imm}), Start(S), End(E) {}
121
122 struct RegisterImmediate {
123 MCRegister Reg;
124 MCExpr const *Imm;
125 };
126 union {
127 StringRef Tok;
128 RegisterImmediate RegImm;
129 };
130
131 SMLoc Start, End;
132
133public:
134 void addRegOperands(MCInst &Inst, unsigned N) const {
135 assert(Kind == k_Register && "Unexpected operand kind");
136 assert(N == 1 && "Invalid number of operands!");
137
138 Inst.addOperand(Op: MCOperand::createReg(Reg: getReg()));
139 }
140
141 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
142 // Add as immediate when possible
143 if (!Expr)
144 Inst.addOperand(Op: MCOperand::createImm(Val: 0));
145 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: Expr))
146 Inst.addOperand(Op: MCOperand::createImm(Val: CE->getValue()));
147 else
148 Inst.addOperand(Op: MCOperand::createExpr(Val: Expr));
149 }
150
151 void addImmOperands(MCInst &Inst, unsigned N) const {
152 assert(Kind == k_Immediate && "Unexpected operand kind");
153 assert(N == 1 && "Invalid number of operands!");
154
155 const MCExpr *Expr = getImm();
156 addExpr(Inst, Expr);
157 }
158
159 /// Adds the contained reg+imm operand to an instruction.
160 void addMemriOperands(MCInst &Inst, unsigned N) const {
161 assert(Kind == k_Memri && "Unexpected operand kind");
162 assert(N == 2 && "Invalid number of operands");
163
164 Inst.addOperand(Op: MCOperand::createReg(Reg: getReg()));
165 addExpr(Inst, Expr: getImm());
166 }
167
168 void addImmCom8Operands(MCInst &Inst, unsigned N) const {
169 assert(N == 1 && "Invalid number of operands!");
170 // The operand is actually a imm8, but we have its bitwise
171 // negation in the assembly source, so twiddle it here.
172 const auto *CE = cast<MCConstantExpr>(Val: getImm());
173 Inst.addOperand(Op: MCOperand::createImm(Val: ~(uint8_t)CE->getValue()));
174 }
175
176 bool isImmCom8() const {
177 if (!isImm())
178 return false;
179 const auto *CE = dyn_cast<MCConstantExpr>(Val: getImm());
180 if (!CE)
181 return false;
182 int64_t Value = CE->getValue();
183 return isUInt<8>(x: Value);
184 }
185
186 bool isReg() const override { return Kind == k_Register; }
187 bool isImm() const override { return Kind == k_Immediate; }
188 bool isToken() const override { return Kind == k_Token; }
189 bool isMem() const override { return Kind == k_Memri; }
190 bool isMemri() const { return Kind == k_Memri; }
191
192 StringRef getToken() const {
193 assert(Kind == k_Token && "Invalid access!");
194 return Tok;
195 }
196
197 MCRegister getReg() const override {
198 assert((Kind == k_Register || Kind == k_Memri) && "Invalid access!");
199
200 return RegImm.Reg;
201 }
202
203 const MCExpr *getImm() const {
204 assert((Kind == k_Immediate || Kind == k_Memri) && "Invalid access!");
205 return RegImm.Imm;
206 }
207
208 static std::unique_ptr<AVROperand> CreateToken(StringRef Str, SMLoc S) {
209 return std::make_unique<AVROperand>(args&: Str, args&: S);
210 }
211
212 static std::unique_ptr<AVROperand> CreateReg(MCRegister Reg, SMLoc S,
213 SMLoc E) {
214 return std::make_unique<AVROperand>(args&: Reg, args&: S, args&: E);
215 }
216
217 static std::unique_ptr<AVROperand> CreateImm(const MCExpr *Val, SMLoc S,
218 SMLoc E) {
219 return std::make_unique<AVROperand>(args&: Val, args&: S, args&: E);
220 }
221
222 static std::unique_ptr<AVROperand>
223 CreateMemri(MCRegister Reg, const MCExpr *Val, SMLoc S, SMLoc E) {
224 return std::make_unique<AVROperand>(args&: Reg, args&: Val, args&: S, args&: E);
225 }
226
227 void makeToken(StringRef Token) {
228 Kind = k_Token;
229 Tok = Token;
230 }
231
232 void makeReg(MCRegister Reg) {
233 Kind = k_Register;
234 RegImm = {.Reg: Reg, .Imm: nullptr};
235 }
236
237 void makeImm(MCExpr const *Ex) {
238 Kind = k_Immediate;
239 RegImm = {.Reg: 0, .Imm: Ex};
240 }
241
242 void makeMemri(MCRegister Reg, MCExpr const *Imm) {
243 Kind = k_Memri;
244 RegImm = {.Reg: Reg, .Imm: Imm};
245 }
246
247 SMLoc getStartLoc() const override { return Start; }
248 SMLoc getEndLoc() const override { return End; }
249
250 void print(raw_ostream &O, const MCAsmInfo &MAI) const override {
251 switch (Kind) {
252 case k_Token:
253 O << "Token: \"" << getToken() << "\"";
254 break;
255 case k_Register:
256 O << "Register: " << getReg();
257 break;
258 case k_Immediate:
259 O << "Immediate: \"";
260 MAI.printExpr(O, *getImm());
261 O << "\"";
262 break;
263 case k_Memri: {
264 // only manually print the size for non-negative values,
265 // as the sign is inserted automatically.
266 O << "Memri: \"" << getReg() << '+';
267 MAI.printExpr(O, *getImm());
268 O << "\"";
269 break;
270 }
271 }
272 O << "\n";
273 }
274};
275
276} // end anonymous namespace.
277
278// Auto-generated Match Functions
279
280/// Maps from the set of all register names to a register number.
281/// \note Generated by TableGen.
282static MCRegister MatchRegisterName(StringRef Name);
283
284/// Maps from the set of all alternative registernames to a register number.
285/// \note Generated by TableGen.
286static MCRegister MatchRegisterAltName(StringRef Name);
287
288bool AVRAsmParser::invalidOperand(SMLoc const &Loc,
289 OperandVector const &Operands,
290 uint64_t const &ErrorInfo) {
291 SMLoc ErrorLoc = Loc;
292 char const *Diag = nullptr;
293
294 if (ErrorInfo != ~0U) {
295 if (ErrorInfo >= Operands.size()) {
296 Diag = "too few operands for instruction.";
297 } else {
298 AVROperand const &Op = (AVROperand const &)*Operands[ErrorInfo];
299
300 // TODO: See if we can do a better error than just "invalid ...".
301 if (Op.getStartLoc() != SMLoc()) {
302 ErrorLoc = Op.getStartLoc();
303 }
304 }
305 }
306
307 if (!Diag) {
308 Diag = "invalid operand for instruction";
309 }
310
311 return Error(L: ErrorLoc, Msg: Diag);
312}
313
314bool AVRAsmParser::missingFeature(llvm::SMLoc const &Loc,
315 uint64_t const &ErrorInfo) {
316 return Error(L: Loc, Msg: "instruction requires a CPU feature not currently enabled");
317}
318
319bool AVRAsmParser::emit(MCInst &Inst, SMLoc const &Loc, MCStreamer &Out) const {
320 Inst.setLoc(Loc);
321 Out.emitInstruction(Inst, STI);
322
323 return false;
324}
325
326bool AVRAsmParser::matchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,
327 OperandVector &Operands,
328 MCStreamer &Out, uint64_t &ErrorInfo,
329 bool MatchingInlineAsm) {
330 MCInst Inst;
331 unsigned MatchResult =
332 MatchInstructionImpl(Operands, Inst, ErrorInfo, matchingInlineAsm: MatchingInlineAsm);
333
334 switch (MatchResult) {
335 case Match_Success:
336 return emit(Inst, Loc, Out);
337 case Match_MissingFeature:
338 return missingFeature(Loc, ErrorInfo);
339 case Match_InvalidOperand:
340 return invalidOperand(Loc, Operands, ErrorInfo);
341 case Match_MnemonicFail:
342 return Error(L: Loc, Msg: "invalid instruction");
343 case Match_InvalidRegisterOnTiny:
344 return Error(L: Loc, Msg: "invalid register on avrtiny");
345 default:
346 return true;
347 }
348}
349
350/// Parses a register name using a given matching function.
351/// Checks for lowercase or uppercase if necessary.
352MCRegister AVRAsmParser::parseRegisterName(MCRegister (*matchFn)(StringRef)) {
353 StringRef Name = Parser.getTok().getString();
354
355 MCRegister Reg = matchFn(Name);
356
357 // GCC supports case insensitive register names. Some of the AVR registers
358 // are all lower case, some are all upper case but non are mixed. We prefer
359 // to use the original names in the register definitions. That is why we
360 // have to test both upper and lower case here.
361 if (!Reg) {
362 Reg = matchFn(Name.lower());
363 }
364 if (!Reg) {
365 Reg = matchFn(Name.upper());
366 }
367
368 return Reg;
369}
370
371MCRegister AVRAsmParser::parseRegisterName() {
372 MCRegister Reg = parseRegisterName(matchFn: &MatchRegisterName);
373
374 if (!Reg)
375 Reg = parseRegisterName(matchFn: &MatchRegisterAltName);
376
377 return Reg;
378}
379
380MCRegister AVRAsmParser::parseRegister(bool RestoreOnFailure) {
381 MCRegister Reg;
382
383 if (Parser.getTok().is(K: AsmToken::Identifier)) {
384 // Check for register pair syntax
385 if (Parser.getLexer().peekTok().is(K: AsmToken::Colon)) {
386 AsmToken HighTok = Parser.getTok();
387 Parser.Lex();
388 AsmToken ColonTok = Parser.getTok();
389 Parser.Lex(); // Eat high (odd) register and colon
390
391 if (Parser.getTok().is(K: AsmToken::Identifier)) {
392 // Convert lower (even) register to DREG
393 Reg = toDREG(Reg: parseRegisterName());
394 }
395 if (!Reg && RestoreOnFailure) {
396 getLexer().UnLex(Token: std::move(ColonTok));
397 getLexer().UnLex(Token: std::move(HighTok));
398 }
399 } else {
400 Reg = parseRegisterName();
401 }
402 }
403 return Reg;
404}
405
406bool AVRAsmParser::tryParseRegisterOperand(OperandVector &Operands) {
407 MCRegister Reg = parseRegister();
408
409 if (!Reg)
410 return true;
411
412 // Reject R0~R15 on avrtiny.
413 if (AVR::R0 <= Reg && Reg <= AVR::R15 &&
414 STI.hasFeature(Feature: AVR::FeatureTinyEncoding))
415 return Error(L: Parser.getTok().getLoc(), Msg: "invalid register on avrtiny");
416
417 AsmToken const &T = Parser.getTok();
418 Operands.push_back(Elt: AVROperand::CreateReg(Reg, S: T.getLoc(), E: T.getEndLoc()));
419 Parser.Lex(); // Eat register token.
420
421 return false;
422}
423
424bool AVRAsmParser::tryParseExpression(OperandVector &Operands, int64_t offset) {
425 SMLoc S = Parser.getTok().getLoc();
426
427 if (!tryParseRelocExpression(Operands))
428 return false;
429
430 if ((Parser.getTok().getKind() == AsmToken::Plus ||
431 Parser.getTok().getKind() == AsmToken::Minus) &&
432 Parser.getLexer().peekTok().getKind() == AsmToken::Identifier) {
433 // Don't handle this case - it should be split into two
434 // separate tokens.
435 return true;
436 }
437
438 // Parse (potentially inner) expression
439 MCExpr const *Expression;
440 if (getParser().parseExpression(Res&: Expression))
441 return true;
442
443 if (offset) {
444 Expression = MCBinaryExpr::createAdd(
445 LHS: Expression, RHS: MCConstantExpr::create(Value: offset, Ctx&: getContext()), Ctx&: getContext());
446 }
447
448 SMLoc E = SMLoc::getFromPointer(Ptr: Parser.getTok().getLoc().getPointer() - 1);
449 Operands.push_back(Elt: AVROperand::CreateImm(Val: Expression, S, E));
450 return false;
451}
452
453bool AVRAsmParser::tryParseRelocExpression(OperandVector &Operands) {
454 bool isNegated = false;
455 AVR::Specifier ModifierKind = AVR::S_AVR_NONE;
456
457 SMLoc S = Parser.getTok().getLoc();
458
459 // Reject the form in which sign comes first. This behaviour is
460 // in accordance with avr-gcc.
461 AsmToken::TokenKind CurTok = Parser.getLexer().getKind();
462 if (CurTok == AsmToken::Minus || CurTok == AsmToken::Plus)
463 return true;
464
465 // Check for sign.
466 AsmToken tokens[2];
467 if (Parser.getLexer().peekTokens(Buf: tokens) == 2)
468 if (tokens[0].getKind() == AsmToken::LParen &&
469 tokens[1].getKind() == AsmToken::Minus)
470 isNegated = true;
471
472 // Check if we have a target specific modifier (lo8, hi8, &c)
473 if (CurTok != AsmToken::Identifier ||
474 Parser.getLexer().peekTok().getKind() != AsmToken::LParen) {
475 // Not a reloc expr
476 return true;
477 }
478 StringRef ModifierName = Parser.getTok().getString();
479 ModifierKind = AVRMCExpr::parseSpecifier(Name: ModifierName);
480
481 if (ModifierKind != AVR::S_AVR_NONE) {
482 Parser.Lex();
483 Parser.Lex(); // Eat modifier name and parenthesis
484 if (Parser.getTok().getString() == GENERATE_STUBS &&
485 Parser.getTok().getKind() == AsmToken::Identifier) {
486 std::string GSModName = ModifierName.str() + "_" + GENERATE_STUBS;
487 ModifierKind = AVRMCExpr::parseSpecifier(Name: GSModName);
488 if (ModifierKind != AVR::S_AVR_NONE)
489 Parser.Lex(); // Eat gs modifier name
490 }
491 } else {
492 return Error(L: Parser.getTok().getLoc(), Msg: "unknown modifier");
493 }
494
495 if (tokens[1].getKind() == AsmToken::Minus ||
496 tokens[1].getKind() == AsmToken::Plus) {
497 Parser.Lex();
498 assert(Parser.getTok().getKind() == AsmToken::LParen);
499 Parser.Lex(); // Eat the sign and parenthesis
500 }
501
502 MCExpr const *InnerExpression;
503 if (getParser().parseExpression(Res&: InnerExpression))
504 return true;
505
506 if (tokens[1].getKind() == AsmToken::Minus ||
507 tokens[1].getKind() == AsmToken::Plus) {
508 assert(Parser.getTok().getKind() == AsmToken::RParen);
509 Parser.Lex(); // Eat closing parenthesis
510 }
511
512 // If we have a modifier wrap the inner expression
513 assert(Parser.getTok().getKind() == AsmToken::RParen);
514 Parser.Lex(); // Eat closing parenthesis
515
516 MCExpr const *Expression =
517 AVRMCExpr::create(S: ModifierKind, Expr: InnerExpression, isNegated, Ctx&: getContext());
518
519 SMLoc E = SMLoc::getFromPointer(Ptr: Parser.getTok().getLoc().getPointer() - 1);
520 Operands.push_back(Elt: AVROperand::CreateImm(Val: Expression, S, E));
521
522 return false;
523}
524
525bool AVRAsmParser::parseOperand(OperandVector &Operands, bool maybeReg) {
526 LLVM_DEBUG(dbgs() << "parseOperand\n");
527
528 switch (getLexer().getKind()) {
529 default:
530 return Error(L: Parser.getTok().getLoc(), Msg: "unexpected token in operand");
531
532 case AsmToken::Identifier:
533 // Try to parse a register, fall through to the next case if it fails.
534 if (maybeReg && !tryParseRegisterOperand(Operands)) {
535 return false;
536 }
537 [[fallthrough]];
538 case AsmToken::LParen:
539 case AsmToken::Integer:
540 return tryParseExpression(Operands, offset: 0);
541 case AsmToken::Dot:
542 return tryParseExpression(Operands, offset: 2);
543 case AsmToken::Plus:
544 case AsmToken::Minus: {
545 // If the sign preceeds a number, parse the number,
546 // otherwise treat the sign a an independent token.
547 switch (getLexer().peekTok().getKind()) {
548 case AsmToken::Integer:
549 case AsmToken::BigNum:
550 case AsmToken::Identifier:
551 case AsmToken::Real:
552 if (!tryParseExpression(Operands, offset: 0))
553 return false;
554 break;
555 default:
556 break;
557 }
558 // Treat the token as an independent token.
559 Operands.push_back(Elt: AVROperand::CreateToken(Str: Parser.getTok().getString(),
560 S: Parser.getTok().getLoc()));
561 Parser.Lex(); // Eat the token.
562 return false;
563 }
564 }
565
566 // Could not parse operand
567 return true;
568}
569
570ParseStatus AVRAsmParser::parseMemriOperand(OperandVector &Operands) {
571 LLVM_DEBUG(dbgs() << "parseMemriOperand()\n");
572
573 SMLoc E, S;
574 MCExpr const *Expression;
575 MCRegister Reg;
576
577 // Parse register.
578 {
579 Reg = parseRegister();
580
581 if (!Reg)
582 return ParseStatus::Failure;
583
584 S = SMLoc::getFromPointer(Ptr: Parser.getTok().getLoc().getPointer() - 1);
585 Parser.Lex(); // Eat register token.
586 }
587
588 // Parse immediate;
589 {
590 if (getParser().parseExpression(Res&: Expression))
591 return ParseStatus::Failure;
592
593 E = SMLoc::getFromPointer(Ptr: Parser.getTok().getLoc().getPointer() - 1);
594 }
595
596 Operands.push_back(Elt: AVROperand::CreateMemri(Reg, Val: Expression, S, E));
597
598 return ParseStatus::Success;
599}
600
601bool AVRAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
602 SMLoc &EndLoc) {
603 StartLoc = Parser.getTok().getLoc();
604 Reg = parseRegister(/*RestoreOnFailure=*/false);
605 EndLoc = Parser.getTok().getLoc();
606
607 return Reg == AVR::NoRegister;
608}
609
610ParseStatus AVRAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
611 SMLoc &EndLoc) {
612 StartLoc = Parser.getTok().getLoc();
613 Reg = parseRegister(/*RestoreOnFailure=*/true);
614 EndLoc = Parser.getTok().getLoc();
615
616 if (Reg == AVR::NoRegister)
617 return ParseStatus::NoMatch;
618 return ParseStatus::Success;
619}
620
621void AVRAsmParser::eatComma() {
622 if (getLexer().is(K: AsmToken::Comma)) {
623 Parser.Lex();
624 } else {
625 // GCC allows commas to be omitted.
626 }
627}
628
629bool AVRAsmParser::parseInstruction(ParseInstructionInfo &Info,
630 StringRef Mnemonic, SMLoc NameLoc,
631 OperandVector &Operands) {
632 Operands.push_back(Elt: AVROperand::CreateToken(Str: Mnemonic, S: NameLoc));
633
634 int OperandNum = -1;
635 while (getLexer().isNot(K: AsmToken::EndOfStatement)) {
636 OperandNum++;
637 if (OperandNum > 0)
638 eatComma();
639
640 ParseStatus ParseRes = MatchOperandParserImpl(Operands, Mnemonic);
641
642 if (ParseRes.isSuccess())
643 continue;
644
645 if (ParseRes.isFailure()) {
646 SMLoc Loc = getLexer().getLoc();
647 Parser.eatToEndOfStatement();
648
649 return Error(L: Loc, Msg: "failed to parse register and immediate pair");
650 }
651
652 // These specific operands should be treated as addresses/symbols/labels,
653 // other than registers.
654 bool maybeReg = true;
655
656 if (OperandNum == 1) {
657 std::array<StringRef, 8> Insts = {"lds", "adiw", "sbiw", "ldi"};
658 for (auto Inst : Insts) {
659 if (Inst == Mnemonic) {
660 maybeReg = false;
661 break;
662 }
663 }
664 } else if (OperandNum == 0) {
665 std::array<StringRef, 8> Insts = {"sts", "call", "rcall", "rjmp", "jmp"};
666 for (auto Inst : Insts) {
667 if (Inst == Mnemonic) {
668 maybeReg = false;
669 break;
670 }
671 }
672 }
673
674 if (parseOperand(Operands, maybeReg)) {
675 SMLoc Loc = getLexer().getLoc();
676 Parser.eatToEndOfStatement();
677 return Error(L: Loc, Msg: "unexpected token in argument list");
678 }
679 }
680 Parser.Lex(); // Consume the EndOfStatement
681 return false;
682}
683
684ParseStatus AVRAsmParser::parseDirective(llvm::AsmToken DirectiveID) {
685 StringRef IDVal = DirectiveID.getIdentifier();
686 if (IDVal.lower() == ".long")
687 return parseLiteralValues(SizeInBytes: SIZE_LONG, L: DirectiveID.getLoc());
688 if (IDVal.lower() == ".word" || IDVal.lower() == ".short")
689 return parseLiteralValues(SizeInBytes: SIZE_WORD, L: DirectiveID.getLoc());
690 if (IDVal.lower() == ".byte")
691 return parseLiteralValues(SizeInBytes: 1, L: DirectiveID.getLoc());
692 return ParseStatus::NoMatch;
693}
694
695ParseStatus AVRAsmParser::parseLiteralValues(unsigned SizeInBytes, SMLoc L) {
696 MCAsmParser &Parser = getParser();
697 AVRMCELFStreamer &AVRStreamer =
698 static_cast<AVRMCELFStreamer &>(Parser.getStreamer());
699 AsmToken Tokens[2];
700 size_t ReadCount = Parser.getLexer().peekTokens(Buf: Tokens);
701 if (ReadCount == 2 && Parser.getTok().getKind() == AsmToken::Identifier &&
702 Tokens[0].getKind() == AsmToken::Minus &&
703 Tokens[1].getKind() == AsmToken::Identifier) {
704 MCSymbol *Symbol = getContext().getOrCreateSymbol(Name: ".text");
705 AVRStreamer.emitValueForModiferKind(Sym: Symbol, SizeInBytes, Loc: L,
706 ModifierKind: AVR::S_AVR_NONE);
707 return ParseStatus::NoMatch;
708 }
709
710 if (Parser.getTok().getKind() == AsmToken::Identifier &&
711 Parser.getLexer().peekTok().getKind() == AsmToken::LParen) {
712 StringRef ModifierName = Parser.getTok().getString();
713 AVR::Specifier Spec = AVRMCExpr::parseSpecifier(Name: ModifierName);
714 if (Spec != AVR::S_AVR_NONE) {
715 Parser.Lex();
716 Parser.Lex(); // Eat the modifier and parenthesis
717 } else {
718 return Error(L: Parser.getTok().getLoc(), Msg: "unknown modifier");
719 }
720 MCSymbol *Symbol =
721 getContext().getOrCreateSymbol(Name: Parser.getTok().getString());
722 AVRStreamer.emitValueForModiferKind(Sym: Symbol, SizeInBytes, Loc: L, ModifierKind: Spec);
723 Lex(); // Eat the symbol name.
724 if (parseToken(T: AsmToken::RParen))
725 return ParseStatus::Failure;
726 return parseEOL();
727 }
728
729 auto parseOne = [&]() -> bool {
730 const MCExpr *Value;
731 if (Parser.parseExpression(Res&: Value))
732 return true;
733 Parser.getStreamer().emitValue(Value, Size: SizeInBytes, Loc: L);
734 return false;
735 };
736 return (parseMany(parseOne));
737}
738
739extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRAsmParser() {
740 RegisterMCAsmParser<AVRAsmParser> X(getTheAVRTarget());
741}
742
743#define GET_REGISTER_MATCHER
744#define GET_MATCHER_IMPLEMENTATION
745#include "AVRGenAsmMatcher.inc"
746
747// Uses enums defined in AVRGenAsmMatcher.inc
748unsigned AVRAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
749 unsigned ExpectedKind) {
750 AVROperand &Op = static_cast<AVROperand &>(AsmOp);
751 MatchClassKind Expected = static_cast<MatchClassKind>(ExpectedKind);
752
753 // If need be, GCC converts bare numbers to register names
754 // It's ugly, but GCC supports it.
755 if (Op.isImm()) {
756 if (MCConstantExpr const *Const = dyn_cast<MCConstantExpr>(Val: Op.getImm())) {
757 int64_t RegNum = Const->getValue();
758
759 // Reject R0~R15 on avrtiny.
760 if (0 <= RegNum && RegNum <= 15 &&
761 STI.hasFeature(Feature: AVR::FeatureTinyEncoding))
762 return Match_InvalidRegisterOnTiny;
763
764 std::ostringstream RegName;
765 RegName << "r" << RegNum;
766 if (MCRegister Reg = MatchRegisterName(Name: RegName.str())) {
767 Op.makeReg(Reg);
768 if (validateOperandClass(GOp&: Op, Kind: Expected) == Match_Success) {
769 return Match_Success;
770 }
771 }
772 // Let the other quirks try their magic.
773 }
774 }
775
776 if (Op.isReg()) {
777 // If the instruction uses a register pair but we got a single, lower
778 // register we perform a "class cast".
779 if (isSubclass(A: Expected, B: MCK_DREGS)) {
780 MCRegister correspondingDREG = toDREG(Reg: Op.getReg());
781
782 if (correspondingDREG) {
783 Op.makeReg(Reg: correspondingDREG);
784 return validateOperandClass(GOp&: Op, Kind: Expected);
785 }
786 }
787 }
788 return Match_InvalidOperand;
789}
790