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
36 using namespace llvm;
37
38 namespace {
39 /// Parses AVR assembly from a stream.
40 class 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
toDREG(MCRegister Reg,unsigned From=AVR::sub_lo)81 MCRegister toDREG(MCRegister Reg, unsigned From = AVR::sub_lo) {
82 MCRegisterClass const *Class = &AVRMCRegisterClasses[AVR::DREGSRegClassID];
83 return MRI->getMatchingSuperReg(Reg, From, 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
93 public:
AVRAsmParser(const MCSubtargetInfo & STI,MCAsmParser & Parser,const MCInstrInfo & MII,const MCTargetOptions & Options)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(STI.getFeatureBits()));
101 }
102
getParser() const103 MCAsmParser &getParser() const { return Parser; }
getLexer() const104 AsmLexer &getLexer() const { return Parser.getLexer(); }
105 };
106
107 /// An parsed AVR assembly operand.
108 class AVROperand : public MCParsedAsmOperand {
109 typedef MCParsedAsmOperand Base;
110 enum KindTy { k_Immediate, k_Register, k_Token, k_Memri } Kind;
111
112 public:
AVROperand(StringRef Tok,SMLoc const & S)113 AVROperand(StringRef Tok, SMLoc const &S)
114 : Kind(k_Token), Tok(Tok), Start(S), End(S) {}
AVROperand(MCRegister Reg,SMLoc const & S,SMLoc const & E)115 AVROperand(MCRegister Reg, SMLoc const &S, SMLoc const &E)
116 : Kind(k_Register), RegImm({Reg, nullptr}), Start(S), End(E) {}
AVROperand(MCExpr const * Imm,SMLoc const & S,SMLoc const & E)117 AVROperand(MCExpr const *Imm, SMLoc const &S, SMLoc const &E)
118 : Kind(k_Immediate), RegImm({0, Imm}), Start(S), End(E) {}
AVROperand(MCRegister Reg,MCExpr const * Imm,SMLoc const & S,SMLoc const & E)119 AVROperand(MCRegister Reg, MCExpr const *Imm, SMLoc const &S, SMLoc const &E)
120 : Kind(k_Memri), RegImm({Reg, 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
133 public:
addRegOperands(MCInst & Inst,unsigned N) const134 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(MCOperand::createReg(getReg()));
139 }
140
addExpr(MCInst & Inst,const MCExpr * Expr) const141 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
142 // Add as immediate when possible
143 if (!Expr)
144 Inst.addOperand(MCOperand::createImm(0));
145 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
146 Inst.addOperand(MCOperand::createImm(CE->getValue()));
147 else
148 Inst.addOperand(MCOperand::createExpr(Expr));
149 }
150
addImmOperands(MCInst & Inst,unsigned N) const151 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.
addMemriOperands(MCInst & Inst,unsigned N) const160 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(MCOperand::createReg(getReg()));
165 addExpr(Inst, getImm());
166 }
167
addImmCom8Operands(MCInst & Inst,unsigned N) const168 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>(getImm());
173 Inst.addOperand(MCOperand::createImm(~(uint8_t)CE->getValue()));
174 }
175
isImmCom8() const176 bool isImmCom8() const {
177 if (!isImm())
178 return false;
179 const auto *CE = dyn_cast<MCConstantExpr>(getImm());
180 if (!CE)
181 return false;
182 int64_t Value = CE->getValue();
183 return isUInt<8>(Value);
184 }
185
isReg() const186 bool isReg() const override { return Kind == k_Register; }
isImm() const187 bool isImm() const override { return Kind == k_Immediate; }
isToken() const188 bool isToken() const override { return Kind == k_Token; }
isMem() const189 bool isMem() const override { return Kind == k_Memri; }
isMemri() const190 bool isMemri() const { return Kind == k_Memri; }
191
getToken() const192 StringRef getToken() const {
193 assert(Kind == k_Token && "Invalid access!");
194 return Tok;
195 }
196
getReg() const197 MCRegister getReg() const override {
198 assert((Kind == k_Register || Kind == k_Memri) && "Invalid access!");
199
200 return RegImm.Reg;
201 }
202
getImm() const203 const MCExpr *getImm() const {
204 assert((Kind == k_Immediate || Kind == k_Memri) && "Invalid access!");
205 return RegImm.Imm;
206 }
207
CreateToken(StringRef Str,SMLoc S)208 static std::unique_ptr<AVROperand> CreateToken(StringRef Str, SMLoc S) {
209 return std::make_unique<AVROperand>(Str, S);
210 }
211
CreateReg(MCRegister Reg,SMLoc S,SMLoc E)212 static std::unique_ptr<AVROperand> CreateReg(MCRegister Reg, SMLoc S,
213 SMLoc E) {
214 return std::make_unique<AVROperand>(Reg, S, E);
215 }
216
CreateImm(const MCExpr * Val,SMLoc S,SMLoc E)217 static std::unique_ptr<AVROperand> CreateImm(const MCExpr *Val, SMLoc S,
218 SMLoc E) {
219 return std::make_unique<AVROperand>(Val, S, E);
220 }
221
222 static std::unique_ptr<AVROperand>
CreateMemri(MCRegister Reg,const MCExpr * Val,SMLoc S,SMLoc E)223 CreateMemri(MCRegister Reg, const MCExpr *Val, SMLoc S, SMLoc E) {
224 return std::make_unique<AVROperand>(Reg, Val, S, E);
225 }
226
makeToken(StringRef Token)227 void makeToken(StringRef Token) {
228 Kind = k_Token;
229 Tok = Token;
230 }
231
makeReg(MCRegister Reg)232 void makeReg(MCRegister Reg) {
233 Kind = k_Register;
234 RegImm = {Reg, nullptr};
235 }
236
makeImm(MCExpr const * Ex)237 void makeImm(MCExpr const *Ex) {
238 Kind = k_Immediate;
239 RegImm = {0, Ex};
240 }
241
makeMemri(MCRegister Reg,MCExpr const * Imm)242 void makeMemri(MCRegister Reg, MCExpr const *Imm) {
243 Kind = k_Memri;
244 RegImm = {Reg, Imm};
245 }
246
getStartLoc() const247 SMLoc getStartLoc() const override { return Start; }
getEndLoc() const248 SMLoc getEndLoc() const override { return End; }
249
print(raw_ostream & O,const MCAsmInfo & MAI) const250 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.
282 static MCRegister MatchRegisterName(StringRef Name);
283
284 /// Maps from the set of all alternative registernames to a register number.
285 /// \note Generated by TableGen.
286 static MCRegister MatchRegisterAltName(StringRef Name);
287
invalidOperand(SMLoc const & Loc,OperandVector const & Operands,uint64_t const & ErrorInfo)288 bool 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(ErrorLoc, Diag);
312 }
313
missingFeature(llvm::SMLoc const & Loc,uint64_t const & ErrorInfo)314 bool AVRAsmParser::missingFeature(llvm::SMLoc const &Loc,
315 uint64_t const &ErrorInfo) {
316 return Error(Loc, "instruction requires a CPU feature not currently enabled");
317 }
318
emit(MCInst & Inst,SMLoc const & Loc,MCStreamer & Out) const319 bool 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
matchAndEmitInstruction(SMLoc Loc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)326 bool 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);
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(Loc, "invalid instruction");
343 case Match_InvalidRegisterOnTiny:
344 return Error(Loc, "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.
parseRegisterName(MCRegister (* matchFn)(StringRef))352 MCRegister 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
parseRegisterName()371 MCRegister AVRAsmParser::parseRegisterName() {
372 MCRegister Reg = parseRegisterName(&MatchRegisterName);
373
374 if (!Reg)
375 Reg = parseRegisterName(&MatchRegisterAltName);
376
377 return Reg;
378 }
379
parseRegister(bool RestoreOnFailure)380 MCRegister AVRAsmParser::parseRegister(bool RestoreOnFailure) {
381 MCRegister Reg;
382
383 if (Parser.getTok().is(AsmToken::Identifier)) {
384 // Check for register pair syntax
385 if (Parser.getLexer().peekTok().is(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(AsmToken::Identifier)) {
392 // Convert lower (even) register to DREG
393 Reg = toDREG(parseRegisterName());
394 }
395 if (!Reg && RestoreOnFailure) {
396 getLexer().UnLex(std::move(ColonTok));
397 getLexer().UnLex(std::move(HighTok));
398 }
399 } else {
400 Reg = parseRegisterName();
401 }
402 }
403 return Reg;
404 }
405
tryParseRegisterOperand(OperandVector & Operands)406 bool 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(AVR::FeatureTinyEncoding))
415 return Error(Parser.getTok().getLoc(), "invalid register on avrtiny");
416
417 AsmToken const &T = Parser.getTok();
418 Operands.push_back(AVROperand::CreateReg(Reg, T.getLoc(), T.getEndLoc()));
419 Parser.Lex(); // Eat register token.
420
421 return false;
422 }
423
tryParseExpression(OperandVector & Operands,int64_t offset)424 bool 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(Expression))
441 return true;
442
443 if (offset) {
444 Expression = MCBinaryExpr::createAdd(
445 Expression, MCConstantExpr::create(offset, getContext()), getContext());
446 }
447
448 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
449 Operands.push_back(AVROperand::CreateImm(Expression, S, E));
450 return false;
451 }
452
tryParseRelocExpression(OperandVector & Operands)453 bool 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(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(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(GSModName);
488 if (ModifierKind != AVR::S_AVR_NONE)
489 Parser.Lex(); // Eat gs modifier name
490 }
491 } else {
492 return Error(Parser.getTok().getLoc(), "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(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(ModifierKind, InnerExpression, isNegated, getContext());
518
519 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
520 Operands.push_back(AVROperand::CreateImm(Expression, S, E));
521
522 return false;
523 }
524
parseOperand(OperandVector & Operands,bool maybeReg)525 bool AVRAsmParser::parseOperand(OperandVector &Operands, bool maybeReg) {
526 LLVM_DEBUG(dbgs() << "parseOperand\n");
527
528 switch (getLexer().getKind()) {
529 default:
530 return Error(Parser.getTok().getLoc(), "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, 0);
541 case AsmToken::Dot:
542 return tryParseExpression(Operands, 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, 0))
553 return false;
554 break;
555 default:
556 break;
557 }
558 // Treat the token as an independent token.
559 Operands.push_back(AVROperand::CreateToken(Parser.getTok().getString(),
560 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
parseMemriOperand(OperandVector & Operands)570 ParseStatus 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(Parser.getTok().getLoc().getPointer() - 1);
585 Parser.Lex(); // Eat register token.
586 }
587
588 // Parse immediate;
589 {
590 if (getParser().parseExpression(Expression))
591 return ParseStatus::Failure;
592
593 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
594 }
595
596 Operands.push_back(AVROperand::CreateMemri(Reg, Expression, S, E));
597
598 return ParseStatus::Success;
599 }
600
parseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)601 bool 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
tryParseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)610 ParseStatus 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
eatComma()621 void AVRAsmParser::eatComma() {
622 if (getLexer().is(AsmToken::Comma)) {
623 Parser.Lex();
624 } else {
625 // GCC allows commas to be omitted.
626 }
627 }
628
parseInstruction(ParseInstructionInfo & Info,StringRef Mnemonic,SMLoc NameLoc,OperandVector & Operands)629 bool AVRAsmParser::parseInstruction(ParseInstructionInfo &Info,
630 StringRef Mnemonic, SMLoc NameLoc,
631 OperandVector &Operands) {
632 Operands.push_back(AVROperand::CreateToken(Mnemonic, NameLoc));
633
634 int OperandNum = -1;
635 while (getLexer().isNot(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(Loc, "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(Loc, "unexpected token in argument list");
678 }
679 }
680 Parser.Lex(); // Consume the EndOfStatement
681 return false;
682 }
683
parseDirective(llvm::AsmToken DirectiveID)684 ParseStatus AVRAsmParser::parseDirective(llvm::AsmToken DirectiveID) {
685 StringRef IDVal = DirectiveID.getIdentifier();
686 if (IDVal.lower() == ".long")
687 return parseLiteralValues(SIZE_LONG, DirectiveID.getLoc());
688 if (IDVal.lower() == ".word" || IDVal.lower() == ".short")
689 return parseLiteralValues(SIZE_WORD, DirectiveID.getLoc());
690 if (IDVal.lower() == ".byte")
691 return parseLiteralValues(1, DirectiveID.getLoc());
692 return ParseStatus::NoMatch;
693 }
694
parseLiteralValues(unsigned SizeInBytes,SMLoc L)695 ParseStatus 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(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(".text");
705 AVRStreamer.emitValueForModiferKind(Symbol, SizeInBytes, L,
706 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(ModifierName);
714 if (Spec != AVR::S_AVR_NONE) {
715 Parser.Lex();
716 Parser.Lex(); // Eat the modifier and parenthesis
717 } else {
718 return Error(Parser.getTok().getLoc(), "unknown modifier");
719 }
720 MCSymbol *Symbol =
721 getContext().getOrCreateSymbol(Parser.getTok().getString());
722 AVRStreamer.emitValueForModiferKind(Symbol, SizeInBytes, L, Spec);
723 Lex(); // Eat the symbol name.
724 if (parseToken(AsmToken::RParen))
725 return ParseStatus::Failure;
726 return parseEOL();
727 }
728
729 auto parseOne = [&]() -> bool {
730 const MCExpr *Value;
731 if (Parser.parseExpression(Value))
732 return true;
733 Parser.getStreamer().emitValue(Value, SizeInBytes, L);
734 return false;
735 };
736 return (parseMany(parseOne));
737 }
738
LLVMInitializeAVRAsmParser()739 extern "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
validateTargetOperandClass(MCParsedAsmOperand & AsmOp,unsigned ExpectedKind)748 unsigned 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>(Op.getImm())) {
757 int64_t RegNum = Const->getValue();
758
759 // Reject R0~R15 on avrtiny.
760 if (0 <= RegNum && RegNum <= 15 &&
761 STI.hasFeature(AVR::FeatureTinyEncoding))
762 return Match_InvalidRegisterOnTiny;
763
764 std::ostringstream RegName;
765 RegName << "r" << RegNum;
766 if (MCRegister Reg = MatchRegisterName(RegName.str())) {
767 Op.makeReg(Reg);
768 if (validateOperandClass(Op, 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(Expected, MCK_DREGS)) {
780 MCRegister correspondingDREG = toDREG(Op.getReg());
781
782 if (correspondingDREG) {
783 Op.makeReg(correspondingDREG);
784 return validateOperandClass(Op, Expected);
785 }
786 }
787 }
788 return Match_InvalidOperand;
789 }
790