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 (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() {

372

373 if (Reg)

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 (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

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 (Reg)

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,...