789 lines · cpp
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-exception6//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 MCAsmParser &Parser;42 const MCRegisterInfo *MRI;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_HEADER50#include "AVRGenAsmMatcher.inc"51 52 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,53 OperandVector &Operands, MCStreamer &Out,54 uint64_t &ErrorInfo,55 bool MatchingInlineAsm) override;56 57 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;58 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,59 SMLoc &EndLoc) override;60 61 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,62 SMLoc NameLoc, OperandVector &Operands) override;63 64 ParseStatus parseDirective(AsmToken DirectiveID) override;65 66 ParseStatus parseMemriOperand(OperandVector &Operands);67 68 bool parseOperand(OperandVector &Operands, bool maybeReg);69 MCRegister parseRegisterName(MCRegister (*matchFn)(StringRef));70 MCRegister parseRegisterName();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 77 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,78 unsigned Kind) override;79 80 MCRegister toDREG(MCRegister Reg, unsigned From = AVR::sub_lo) {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) {96 MCAsmParserExtension::Initialize(Parser);97 MRI = getContext().getRegisterInfo();98 99 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));100 }101 102 MCAsmParser &getParser() const { return Parser; }103 AsmLexer &getLexer() const { return Parser.getLexer(); }104};105 106/// An parsed AVR assembly operand.107class AVROperand : public MCParsedAsmOperand {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 137 Inst.addOperand(MCOperand::createReg(getReg()));138 }139 140 void addExpr(MCInst &Inst, const MCExpr *Expr) const {141 // Add as immediate when possible142 if (!Expr)143 Inst.addOperand(MCOperand::createImm(0));144 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))145 Inst.addOperand(MCOperand::createImm(CE->getValue()));146 else147 Inst.addOperand(MCOperand::createExpr(Expr));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 /// Adds the contained reg+imm operand to an instruction.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 163 Inst.addOperand(MCOperand::createReg(getReg()));164 addExpr(Inst, getImm());165 }166 167 void addImmCom8Operands(MCInst &Inst, unsigned N) const {168 assert(N == 1 && "Invalid number of operands!");169 // The operand is actually a imm8, but we have its bitwise170 // negation in the assembly source, so twiddle it here.171 const auto *CE = cast<MCConstantExpr>(getImm());172 Inst.addOperand(MCOperand::createImm(~(uint8_t)CE->getValue()));173 }174 175 bool isImmCom8() const {176 if (!isImm())177 return false;178 const auto *CE = dyn_cast<MCConstantExpr>(getImm());179 if (!CE)180 return false;181 int64_t Value = CE->getValue();182 return isUInt<8>(Value);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 191 StringRef getToken() const {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 199 return RegImm.Reg;200 }201 202 const MCExpr *getImm() const {203 assert((Kind == k_Immediate || Kind == k_Memri) && "Invalid access!");204 return RegImm.Imm;205 }206 207 static std::unique_ptr<AVROperand> CreateToken(StringRef Str, SMLoc S) {208 return std::make_unique<AVROperand>(Str, S);209 }210 211 static std::unique_ptr<AVROperand> CreateReg(MCRegister Reg, SMLoc S,212 SMLoc E) {213 return std::make_unique<AVROperand>(Reg, S, E);214 }215 216 static std::unique_ptr<AVROperand> CreateImm(const MCExpr *Val, SMLoc S,217 SMLoc E) {218 return std::make_unique<AVROperand>(Val, S, E);219 }220 221 static std::unique_ptr<AVROperand>222 CreateMemri(MCRegister Reg, const MCExpr *Val, SMLoc S, SMLoc E) {223 return std::make_unique<AVROperand>(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;233 RegImm = {Reg, nullptr};234 }235 236 void makeImm(MCExpr const *Ex) {237 Kind = k_Immediate;238 RegImm = {0, Ex};239 }240 241 void makeMemri(MCRegister Reg, MCExpr const *Imm) {242 Kind = k_Memri;243 RegImm = {Reg, Imm};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: \"";259 MAI.printExpr(O, *getImm());260 O << "\"";261 break;262 case k_Memri: {263 // only manually print the size for non-negative values,264 // as the sign is inserted automatically.265 O << "Memri: \"" << getReg().id() << '+';266 MAI.printExpr(O, *getImm());267 O << "\"";268 break;269 }270 }271 O << "\n";272 }273};274 275} // end anonymous namespace.276 277// Auto-generated Match Functions278 279/// Maps from the set of all register names to a register number.280/// \note Generated by TableGen.281static MCRegister MatchRegisterName(StringRef Name);282 283/// Maps from the set of all alternative registernames to a register number.284/// \note Generated by TableGen.285static MCRegister MatchRegisterAltName(StringRef Name);286 287bool AVRAsmParser::invalidOperand(SMLoc const &Loc,288 OperandVector const &Operands,289 uint64_t const &ErrorInfo) {290 SMLoc ErrorLoc = Loc;291 char const *Diag = nullptr;292 293 if (ErrorInfo != ~0U) {294 if (ErrorInfo >= Operands.size()) {295 Diag = "too few operands for instruction.";296 } else {297 AVROperand const &Op = (AVROperand const &)*Operands[ErrorInfo];298 299 // TODO: See if we can do a better error than just "invalid ...".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 {319 Inst.setLoc(Loc);320 Out.emitInstruction(Inst, *STI);321 322 return false;323}324 325bool AVRAsmParser::matchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,326 OperandVector &Operands,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/// Parses a register name using a given matching function.350/// Checks for lowercase or uppercase if necessary.351MCRegister AVRAsmParser::parseRegisterName(MCRegister (*matchFn)(StringRef)) {352 StringRef Name = Parser.getTok().getString();353 354 MCRegister Reg = matchFn(Name);355 356 // GCC supports case insensitive register names. Some of the AVR registers357 // are all lower case, some are all upper case but non are mixed. We prefer358 // to use the original names in the register definitions. That is why we359 // have to test both upper and lower case here.360 if (!Reg) {361 Reg = matchFn(Name.lower());362 }363 if (!Reg) {364 Reg = matchFn(Name.upper());365 }366 367 return Reg;368}369 370MCRegister AVRAsmParser::parseRegisterName() {371 MCRegister Reg = parseRegisterName(&MatchRegisterName);372 373 if (!Reg)374 Reg = parseRegisterName(&MatchRegisterAltName);375 376 return Reg;377}378 379MCRegister AVRAsmParser::parseRegister(bool RestoreOnFailure) {380 MCRegister Reg;381 382 if (Parser.getTok().is(AsmToken::Identifier)) {383 // Check for register pair syntax384 if (Parser.getLexer().peekTok().is(AsmToken::Colon)) {385 AsmToken HighTok = Parser.getTok();386 Parser.Lex();387 AsmToken ColonTok = Parser.getTok();388 Parser.Lex(); // Eat high (odd) register and colon389 390 if (Parser.getTok().is(AsmToken::Identifier)) {391 // Convert lower (even) register to DREG392 Reg = toDREG(parseRegisterName());393 }394 if (!Reg && 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 (!Reg)409 return true;410 411 // Reject R0~R15 on avrtiny.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(); // Eat register token.419 420 return false;421}422 423bool AVRAsmParser::tryParseExpression(OperandVector &Operands, int64_t offset) {424 SMLoc S = Parser.getTok().getLoc();425 426 if (!tryParseRelocExpression(Operands))427 return false;428 429 if ((Parser.getTok().getKind() == AsmToken::Plus ||430 Parser.getTok().getKind() == AsmToken::Minus) &&431 Parser.getLexer().peekTok().getKind() == AsmToken::Identifier) {432 // Don't handle this case - it should be split into two433 // separate tokens.434 return true;435 }436 437 // Parse (potentially inner) expression438 MCExpr const *Expression;439 if (getParser().parseExpression(Expression))440 return true;441 442 if (offset) {443 Expression = MCBinaryExpr::createAdd(444 Expression, MCConstantExpr::create(offset, getContext()), getContext());445 }446 447 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);448 Operands.push_back(AVROperand::CreateImm(Expression, S, E));449 return false;450}451 452bool AVRAsmParser::tryParseRelocExpression(OperandVector &Operands) {453 bool isNegated = false;454 AVR::Specifier ModifierKind = AVR::S_AVR_NONE;455 456 SMLoc S = Parser.getTok().getLoc();457 458 // Reject the form in which sign comes first. This behaviour is459 // in accordance with avr-gcc.460 AsmToken::TokenKind CurTok = Parser.getLexer().getKind();461 if (CurTok == AsmToken::Minus || CurTok == AsmToken::Plus)462 return true;463 464 // Check for sign.465 AsmToken tokens[2];466 if (Parser.getLexer().peekTokens(tokens) == 2)467 if (tokens[0].getKind() == AsmToken::LParen &&468 tokens[1].getKind() == AsmToken::Minus)469 isNegated = true;470 471 // Check if we have a target specific modifier (lo8, hi8, &c)472 if (CurTok != AsmToken::Identifier ||473 Parser.getLexer().peekTok().getKind() != AsmToken::LParen) {474 // Not a reloc expr475 return true;476 }477 StringRef ModifierName = Parser.getTok().getString();478 ModifierKind = AVRMCExpr::parseSpecifier(ModifierName);479 480 if (ModifierKind != AVR::S_AVR_NONE) {481 Parser.Lex();482 Parser.Lex(); // Eat modifier name and parenthesis483 if (Parser.getTok().getString() == GENERATE_STUBS &&484 Parser.getTok().getKind() == AsmToken::Identifier) {485 std::string GSModName = ModifierName.str() + "_" + GENERATE_STUBS;486 ModifierKind = AVRMCExpr::parseSpecifier(GSModName);487 if (ModifierKind != AVR::S_AVR_NONE)488 Parser.Lex(); // Eat gs modifier name489 }490 } else {491 return Error(Parser.getTok().getLoc(), "unknown modifier");492 }493 494 if (tokens[1].getKind() == AsmToken::Minus ||495 tokens[1].getKind() == AsmToken::Plus) {496 Parser.Lex();497 assert(Parser.getTok().getKind() == AsmToken::LParen);498 Parser.Lex(); // Eat the sign and parenthesis499 }500 501 MCExpr const *InnerExpression;502 if (getParser().parseExpression(InnerExpression))503 return true;504 505 if (tokens[1].getKind() == AsmToken::Minus ||506 tokens[1].getKind() == AsmToken::Plus) {507 assert(Parser.getTok().getKind() == AsmToken::RParen);508 Parser.Lex(); // Eat closing parenthesis509 }510 511 // If we have a modifier wrap the inner expression512 assert(Parser.getTok().getKind() == AsmToken::RParen);513 Parser.Lex(); // Eat closing parenthesis514 515 MCExpr const *Expression =516 AVRMCExpr::create(ModifierKind, InnerExpression, isNegated, getContext());517 518 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);519 Operands.push_back(AVROperand::CreateImm(Expression, S, E));520 521 return false;522}523 524bool AVRAsmParser::parseOperand(OperandVector &Operands, bool maybeReg) {525 LLVM_DEBUG(dbgs() << "parseOperand\n");526 527 switch (getLexer().getKind()) {528 default:529 return Error(Parser.getTok().getLoc(), "unexpected token in operand");530 531 case AsmToken::Identifier:532 // Try to parse a register, fall through to the next case if it fails.533 if (maybeReg && !tryParseRegisterOperand(Operands)) {534 return false;535 }536 [[fallthrough]];537 case AsmToken::LParen:538 case AsmToken::Integer:539 return tryParseExpression(Operands, 0);540 case AsmToken::Dot:541 return tryParseExpression(Operands, 2);542 case AsmToken::Plus:543 case AsmToken::Minus: {544 // If the sign preceeds a number, parse the number,545 // otherwise treat the sign a an independent token.546 switch (getLexer().peekTok().getKind()) {547 case AsmToken::Integer:548 case AsmToken::BigNum:549 case AsmToken::Identifier:550 case AsmToken::Real:551 if (!tryParseExpression(Operands, 0))552 return false;553 break;554 default:555 break;556 }557 // Treat the token as an independent token.558 Operands.push_back(AVROperand::CreateToken(Parser.getTok().getString(),559 Parser.getTok().getLoc()));560 Parser.Lex(); // Eat the token.561 return false;562 }563 }564 565 // Could not parse operand566 return true;567}568 569ParseStatus AVRAsmParser::parseMemriOperand(OperandVector &Operands) {570 LLVM_DEBUG(dbgs() << "parseMemriOperand()\n");571 572 SMLoc E, S;573 MCExpr const *Expression;574 MCRegister Reg;575 576 // Parse register.577 {578 Reg = parseRegister();579 580 if (!Reg)581 return ParseStatus::Failure;582 583 S = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);584 Parser.Lex(); // Eat register token.585 }586 587 // Parse immediate;588 {589 if (getParser().parseExpression(Expression))590 return ParseStatus::Failure;591 592 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);593 }594 595 Operands.push_back(AVROperand::CreateMemri(Reg, Expression, S, E));596 597 return ParseStatus::Success;598}599 600bool AVRAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,601 SMLoc &EndLoc) {602 StartLoc = Parser.getTok().getLoc();603 Reg = parseRegister(/*RestoreOnFailure=*/false);604 EndLoc = Parser.getTok().getLoc();605 606 return Reg == AVR::NoRegister;607}608 609ParseStatus AVRAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,610 SMLoc &EndLoc) {611 StartLoc = Parser.getTok().getLoc();612 Reg = parseRegister(/*RestoreOnFailure=*/true);613 EndLoc = Parser.getTok().getLoc();614 615 if (Reg == AVR::NoRegister)616 return ParseStatus::NoMatch;617 return ParseStatus::Success;618}619 620void AVRAsmParser::eatComma() {621 if (getLexer().is(AsmToken::Comma)) {622 Parser.Lex();623 } else {624 // GCC allows commas to be omitted.625 }626}627 628bool AVRAsmParser::parseInstruction(ParseInstructionInfo &Info,629 StringRef Mnemonic, SMLoc NameLoc,630 OperandVector &Operands) {631 Operands.push_back(AVROperand::CreateToken(Mnemonic, NameLoc));632 633 int OperandNum = -1;634 while (getLexer().isNot(AsmToken::EndOfStatement)) {635 OperandNum++;636 if (OperandNum > 0)637 eatComma();638 639 ParseStatus ParseRes = MatchOperandParserImpl(Operands, Mnemonic);640 641 if (ParseRes.isSuccess())642 continue;643 644 if (ParseRes.isFailure()) {645 SMLoc Loc = getLexer().getLoc();646 Parser.eatToEndOfStatement();647 648 return Error(Loc, "failed to parse register and immediate pair");649 }650 651 // These specific operands should be treated as addresses/symbols/labels,652 // other than registers.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();675 Parser.eatToEndOfStatement();676 return Error(Loc, "unexpected token in argument list");677 }678 }679 Parser.Lex(); // Consume the EndOfStatement680 return false;681}682 683ParseStatus AVRAsmParser::parseDirective(llvm::AsmToken DirectiveID) {684 StringRef IDVal = DirectiveID.getIdentifier();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());691 return ParseStatus::NoMatch;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];699 size_t ReadCount = Parser.getLexer().peekTokens(Tokens);700 if (ReadCount == 2 && Parser.getTok().getKind() == AsmToken::Identifier &&701 Tokens[0].getKind() == AsmToken::Minus &&702 Tokens[1].getKind() == AsmToken::Identifier) {703 MCSymbol *Symbol = getContext().getOrCreateSymbol(".text");704 AVRStreamer.emitValueForModiferKind(Symbol, SizeInBytes, L,705 AVR::S_AVR_NONE);706 return ParseStatus::NoMatch;707 }708 709 if (Parser.getTok().getKind() == AsmToken::Identifier &&710 Parser.getLexer().peekTok().getKind() == AsmToken::LParen) {711 StringRef ModifierName = Parser.getTok().getString();712 AVR::Specifier Spec = AVRMCExpr::parseSpecifier(ModifierName);713 if (Spec != AVR::S_AVR_NONE) {714 Parser.Lex();715 Parser.Lex(); // Eat the modifier and parenthesis716 } else {717 return Error(Parser.getTok().getLoc(), "unknown modifier");718 }719 MCSymbol *Symbol =720 getContext().getOrCreateSymbol(Parser.getTok().getString());721 AVRStreamer.emitValueForModiferKind(Symbol, SizeInBytes, L, Spec);722 Lex(); // Eat the symbol name.723 if (parseToken(AsmToken::RParen))724 return ParseStatus::Failure;725 return parseEOL();726 }727 728 auto parseOne = [&]() -> bool {729 const MCExpr *Value;730 if (Parser.parseExpression(Value))731 return true;732 Parser.getStreamer().emitValue(Value, SizeInBytes, L);733 return false;734 };735 return (parseMany(parseOne));736}737 738extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRAsmParser() {739 RegisterMCAsmParser<AVRAsmParser> X(getTheAVRTarget());740}741 742#define GET_REGISTER_MATCHER743#define GET_MATCHER_IMPLEMENTATION744#include "AVRGenAsmMatcher.inc"745 746// Uses enums defined in AVRGenAsmMatcher.inc747unsigned AVRAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,748 unsigned ExpectedKind) {749 AVROperand &Op = static_cast<AVROperand &>(AsmOp);750 MatchClassKind Expected = static_cast<MatchClassKind>(ExpectedKind);751 752 // If need be, GCC converts bare numbers to register names753 // It's ugly, but GCC supports it.754 if (Op.isImm()) {755 if (MCConstantExpr const *Const = dyn_cast<MCConstantExpr>(Op.getImm())) {756 int64_t RegNum = Const->getValue();757 758 // Reject R0~R15 on avrtiny.759 if (0 <= RegNum && RegNum <= 15 &&760 STI->hasFeature(AVR::FeatureTinyEncoding))761 return Match_InvalidRegisterOnTiny;762 763 std::ostringstream RegName;764 RegName << "r" << RegNum;765 if (MCRegister Reg = MatchRegisterName(RegName.str())) {766 Op.makeReg(Reg);767 if (validateOperandClass(Op, Expected, *STI) == Match_Success) {768 return Match_Success;769 }770 }771 // Let the other quirks try their magic.772 }773 }774 775 if (Op.isReg()) {776 // If the instruction uses a register pair but we got a single, lower777 // register we perform a "class cast".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}789