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