LLVM 19.0.0git
HexagonAsmParser.cpp
Go to the documentation of this file.
1//===-- HexagonAsmParser.cpp - Parse Hexagon asm 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
17#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/ADT/Twine.h"
23#include "llvm/MC/MCAssembler.h"
24#include "llvm/MC/MCContext.h"
27#include "llvm/MC/MCExpr.h"
28#include "llvm/MC/MCInst.h"
36#include "llvm/MC/MCStreamer.h"
38#include "llvm/MC/MCSymbol.h"
39#include "llvm/MC/MCValue.h"
43#include "llvm/Support/Debug.h"
45#include "llvm/Support/Format.h"
48#include "llvm/Support/SMLoc.h"
51#include <algorithm>
52#include <cassert>
53#include <cctype>
54#include <cstddef>
55#include <cstdint>
56#include <memory>
57#include <string>
58#include <utility>
59
60#define DEBUG_TYPE "mcasmparser"
61
62using namespace llvm;
63
65 "mwarn-missing-parenthesis",
66 cl::desc("Warn for missing parenthesis around predicate registers"),
67 cl::init(true));
69 "merror-missing-parenthesis",
70 cl::desc("Error for missing parenthesis around predicate registers"),
71 cl::init(false));
73 "mwarn-sign-mismatch",
74 cl::desc("Warn for mismatching a signed and unsigned value"),
75 cl::init(false));
77 "mwarn-noncontigious-register",
78 cl::desc("Warn for register names that arent contigious"), cl::init(true));
80 "merror-noncontigious-register",
81 cl::desc("Error for register names that aren't contigious"),
82 cl::init(false));
83static cl::opt<bool> AddBuildAttributes("hexagon-add-build-attributes");
84namespace {
85
86struct HexagonOperand;
87
88class HexagonAsmParser : public MCTargetAsmParser {
89
90 HexagonTargetStreamer &getTargetStreamer() {
92 return static_cast<HexagonTargetStreamer &>(TS);
93 }
94
95 MCAsmParser &Parser;
96 MCInst MCB;
97 bool InBrackets;
98
99 MCAsmParser &getParser() const { return Parser; }
100 MCAssembler *getAssembler() const {
101 MCAssembler *Assembler = nullptr;
102 // FIXME: need better way to detect AsmStreamer (upstream removed getKind())
103 if (!Parser.getStreamer().hasRawTextSupport()) {
104 MCELFStreamer *MES = static_cast<MCELFStreamer *>(&Parser.getStreamer());
105 Assembler = &MES->getAssembler();
106 }
107 return Assembler;
108 }
109
110 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
111
112 bool equalIsAsmAssignment() override { return false; }
113 bool isLabel(AsmToken &Token) override;
114
115 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
116 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
117 bool ParseDirectiveFalign(unsigned Size, SMLoc L);
118
119 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
121 SMLoc &EndLoc) override;
122 bool ParseDirectiveSubsection(SMLoc L);
123 bool ParseDirectiveComm(bool IsLocal, SMLoc L);
124
125 bool parseDirectiveAttribute(SMLoc L);
126
127 bool RegisterMatchesArch(unsigned MatchNum) const;
128
129 bool matchBundleOptions();
130 bool handleNoncontigiousRegister(bool Contigious, SMLoc &Loc);
131 bool finishBundle(SMLoc IDLoc, MCStreamer &Out);
132 void canonicalizeImmediates(MCInst &MCI);
133 bool matchOneInstruction(MCInst &MCB, SMLoc IDLoc,
134 OperandVector &InstOperands, uint64_t &ErrorInfo,
135 bool MatchingInlineAsm);
136 void eatToEndOfPacket();
137 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
140 bool MatchingInlineAsm) override;
141
143 unsigned Kind) override;
144 bool OutOfRange(SMLoc IDLoc, long long Val, long long Max);
145 int processInstruction(MCInst &Inst, OperandVector const &Operands,
146 SMLoc IDLoc);
147
148 unsigned matchRegister(StringRef Name);
149
150/// @name Auto-generated Match Functions
151/// {
152
153#define GET_ASSEMBLER_HEADER
154#include "HexagonGenAsmMatcher.inc"
155
156 /// }
157
158public:
159 HexagonAsmParser(const MCSubtargetInfo &_STI, MCAsmParser &_Parser,
160 const MCInstrInfo &MII, const MCTargetOptions &Options)
161 : MCTargetAsmParser(Options, _STI, MII), Parser(_Parser),
162 InBrackets(false) {
163 MCB.setOpcode(Hexagon::BUNDLE);
164 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
165
166 Parser.addAliasForDirective(".half", ".2byte");
167 Parser.addAliasForDirective(".hword", ".2byte");
168 Parser.addAliasForDirective(".word", ".4byte");
169
171
173 getTargetStreamer().emitTargetAttributes(*STI);
174 }
175
176 bool splitIdentifier(OperandVector &Operands);
177 bool parseOperand(OperandVector &Operands);
178 bool parseInstruction(OperandVector &Operands);
179 bool implicitExpressionLocation(OperandVector &Operands);
180 bool parseExpressionOrOperand(OperandVector &Operands);
181 bool parseExpression(MCExpr const *&Expr);
182
184 SMLoc NameLoc, OperandVector &Operands) override {
185 llvm_unreachable("Unimplemented");
186 }
187
189 OperandVector &Operands) override;
190
191 bool ParseDirective(AsmToken DirectiveID) override;
192};
193
194/// HexagonOperand - Instances of this class represent a parsed Hexagon machine
195/// instruction.
196struct HexagonOperand : public MCParsedAsmOperand {
197 enum KindTy { Token, Immediate, Register } Kind;
199
200 SMLoc StartLoc, EndLoc;
201
202 struct TokTy {
203 const char *Data;
204 unsigned Length;
205 };
206
207 struct RegTy {
208 unsigned RegNum;
209 };
210
211 struct ImmTy {
212 const MCExpr *Val;
213 };
214
215 union {
216 struct TokTy Tok;
217 struct RegTy Reg;
218 struct ImmTy Imm;
219 };
220
221 HexagonOperand(KindTy K, MCContext &Context) : Kind(K), Context(Context) {}
222
223public:
224 HexagonOperand(const HexagonOperand &o)
226 Kind = o.Kind;
227 StartLoc = o.StartLoc;
228 EndLoc = o.EndLoc;
229 switch (Kind) {
230 case Register:
231 Reg = o.Reg;
232 break;
233 case Immediate:
234 Imm = o.Imm;
235 break;
236 case Token:
237 Tok = o.Tok;
238 break;
239 }
240 }
241
242 /// getStartLoc - Get the location of the first token of this operand.
243 SMLoc getStartLoc() const override { return StartLoc; }
244
245 /// getEndLoc - Get the location of the last token of this operand.
246 SMLoc getEndLoc() const override { return EndLoc; }
247
248 MCRegister getReg() const override {
249 assert(Kind == Register && "Invalid access!");
250 return Reg.RegNum;
251 }
252
253 const MCExpr *getImm() const {
254 assert(Kind == Immediate && "Invalid access!");
255 return Imm.Val;
256 }
257
258 bool isToken() const override { return Kind == Token; }
259 bool isImm() const override { return Kind == Immediate; }
260 bool isMem() const override { llvm_unreachable("No isMem"); }
261 bool isReg() const override { return Kind == Register; }
262
263 bool CheckImmRange(int immBits, int zeroBits, bool isSigned,
264 bool isRelocatable, bool Extendable) const {
265 if (Kind == Immediate) {
266 const MCExpr *myMCExpr = &HexagonMCInstrInfo::getExpr(*getImm());
267 if (HexagonMCInstrInfo::mustExtend(*Imm.Val) && !Extendable)
268 return false;
269 int64_t Res;
270 if (myMCExpr->evaluateAsAbsolute(Res)) {
271 int bits = immBits + zeroBits;
272 // Field bit range is zerobits + bits
273 // zeroBits must be 0
274 if (Res & ((1 << zeroBits) - 1))
275 return false;
276 if (isSigned) {
277 if (Res < (1LL << (bits - 1)) && Res >= -(1LL << (bits - 1)))
278 return true;
279 } else {
280 if (bits == 64)
281 return true;
282 if (Res >= 0)
283 return ((uint64_t)Res < (uint64_t)(1ULL << bits));
284 else {
285 const int64_t high_bit_set = 1ULL << 63;
286 const uint64_t mask = (high_bit_set >> (63 - bits));
287 return (((uint64_t)Res & mask) == mask);
288 }
289 }
290 } else if (myMCExpr->getKind() == MCExpr::SymbolRef && isRelocatable)
291 return true;
292 else if (myMCExpr->getKind() == MCExpr::Binary ||
293 myMCExpr->getKind() == MCExpr::Unary)
294 return true;
295 }
296 return false;
297 }
298
299 bool isa30_2Imm() const { return CheckImmRange(30, 2, true, true, true); }
300 bool isb30_2Imm() const { return CheckImmRange(30, 2, true, true, true); }
301 bool isb15_2Imm() const { return CheckImmRange(15, 2, true, true, false); }
302 bool isb13_2Imm() const { return CheckImmRange(13, 2, true, true, false); }
303
304 bool ism32_0Imm() const { return true; }
305
306 bool isf32Imm() const { return false; }
307 bool isf64Imm() const { return false; }
308 bool iss32_0Imm() const { return true; }
309 bool iss31_1Imm() const { return true; }
310 bool iss30_2Imm() const { return true; }
311 bool iss29_3Imm() const { return true; }
312 bool iss27_2Imm() const { return CheckImmRange(27, 2, true, true, false); }
313 bool iss10_0Imm() const { return CheckImmRange(10, 0, true, false, false); }
314 bool iss10_6Imm() const { return CheckImmRange(10, 6, true, false, false); }
315 bool iss9_0Imm() const { return CheckImmRange(9, 0, true, false, false); }
316 bool iss8_0Imm() const { return CheckImmRange(8, 0, true, false, false); }
317 bool iss8_0Imm64() const { return CheckImmRange(8, 0, true, true, false); }
318 bool iss7_0Imm() const { return CheckImmRange(7, 0, true, false, false); }
319 bool iss6_0Imm() const { return CheckImmRange(6, 0, true, false, false); }
320 bool iss6_3Imm() const { return CheckImmRange(6, 3, true, false, false); }
321 bool iss4_0Imm() const { return CheckImmRange(4, 0, true, false, false); }
322 bool iss4_1Imm() const { return CheckImmRange(4, 1, true, false, false); }
323 bool iss4_2Imm() const { return CheckImmRange(4, 2, true, false, false); }
324 bool iss4_3Imm() const { return CheckImmRange(4, 3, true, false, false); }
325 bool iss3_0Imm() const { return CheckImmRange(3, 0, true, false, false); }
326
327 bool isu64_0Imm() const { return CheckImmRange(64, 0, false, true, true); }
328 bool isu32_0Imm() const { return true; }
329 bool isu31_1Imm() const { return true; }
330 bool isu30_2Imm() const { return true; }
331 bool isu29_3Imm() const { return true; }
332 bool isu26_6Imm() const { return CheckImmRange(26, 6, false, true, false); }
333 bool isu16_0Imm() const { return CheckImmRange(16, 0, false, true, false); }
334 bool isu16_1Imm() const { return CheckImmRange(16, 1, false, true, false); }
335 bool isu16_2Imm() const { return CheckImmRange(16, 2, false, true, false); }
336 bool isu16_3Imm() const { return CheckImmRange(16, 3, false, true, false); }
337 bool isu11_3Imm() const { return CheckImmRange(11, 3, false, false, false); }
338 bool isu10_0Imm() const { return CheckImmRange(10, 0, false, false, false); }
339 bool isu9_0Imm() const { return CheckImmRange(9, 0, false, false, false); }
340 bool isu8_0Imm() const { return CheckImmRange(8, 0, false, false, false); }
341 bool isu7_0Imm() const { return CheckImmRange(7, 0, false, false, false); }
342 bool isu6_0Imm() const { return CheckImmRange(6, 0, false, false, false); }
343 bool isu6_1Imm() const { return CheckImmRange(6, 1, false, false, false); }
344 bool isu6_2Imm() const { return CheckImmRange(6, 2, false, false, false); }
345 bool isu6_3Imm() const { return CheckImmRange(6, 3, false, false, false); }
346 bool isu5_0Imm() const { return CheckImmRange(5, 0, false, false, false); }
347 bool isu5_2Imm() const { return CheckImmRange(5, 2, false, false, false); }
348 bool isu5_3Imm() const { return CheckImmRange(5, 3, false, false, false); }
349 bool isu4_0Imm() const { return CheckImmRange(4, 0, false, false, false); }
350 bool isu4_2Imm() const { return CheckImmRange(4, 2, false, false, false); }
351 bool isu3_0Imm() const { return CheckImmRange(3, 0, false, false, false); }
352 bool isu3_1Imm() const { return CheckImmRange(3, 1, false, false, false); }
353 bool isu2_0Imm() const { return CheckImmRange(2, 0, false, false, false); }
354 bool isu1_0Imm() const { return CheckImmRange(1, 0, false, false, false); }
355
356 bool isn1Const() const {
357 if (!isImm())
358 return false;
359 int64_t Value;
360 if (!getImm()->evaluateAsAbsolute(Value))
361 return false;
362 return Value == -1;
363 }
364 bool issgp10Const() const {
365 if (!isReg())
366 return false;
367 return getReg() == Hexagon::SGP1_0;
368 }
369 bool iss11_0Imm() const {
370 return CheckImmRange(11 + 26, 0, true, true, true);
371 }
372 bool iss11_1Imm() const {
373 return CheckImmRange(11 + 26, 1, true, true, true);
374 }
375 bool iss11_2Imm() const {
376 return CheckImmRange(11 + 26, 2, true, true, true);
377 }
378 bool iss11_3Imm() const {
379 return CheckImmRange(11 + 26, 3, true, true, true);
380 }
381 bool isu32_0MustExt() const { return isImm(); }
382
383 void addRegOperands(MCInst &Inst, unsigned N) const {
384 assert(N == 1 && "Invalid number of operands!");
386 }
387
388 void addImmOperands(MCInst &Inst, unsigned N) const {
389 assert(N == 1 && "Invalid number of operands!");
390 Inst.addOperand(MCOperand::createExpr(getImm()));
391 }
392
393 void addSignedImmOperands(MCInst &Inst, unsigned N) const {
394 assert(N == 1 && "Invalid number of operands!");
395 HexagonMCExpr *Expr =
396 const_cast<HexagonMCExpr *>(cast<HexagonMCExpr>(getImm()));
397 int64_t Value;
398 if (!Expr->evaluateAsAbsolute(Value)) {
400 return;
401 }
402 int64_t Extended = SignExtend64(Value, 32);
404 MCConstantExpr::create(Extended, Context), Context);
405 if ((Extended < 0) != (Value < 0))
406 NewExpr->setSignMismatch();
407 NewExpr->setMustExtend(Expr->mustExtend());
408 NewExpr->setMustNotExtend(Expr->mustNotExtend());
410 }
411
412 void addn1ConstOperands(MCInst &Inst, unsigned N) const {
413 addImmOperands(Inst, N);
414 }
415 void addsgp10ConstOperands(MCInst &Inst, unsigned N) const {
416 addRegOperands(Inst, N);
417 }
418
419 StringRef getToken() const {
420 assert(Kind == Token && "Invalid access!");
421 return StringRef(Tok.Data, Tok.Length);
422 }
423
424 void print(raw_ostream &OS) const override;
425
426 static std::unique_ptr<HexagonOperand> CreateToken(MCContext &Context,
427 StringRef Str, SMLoc S) {
428 HexagonOperand *Op = new HexagonOperand(Token, Context);
429 Op->Tok.Data = Str.data();
430 Op->Tok.Length = Str.size();
431 Op->StartLoc = S;
432 Op->EndLoc = S;
433 return std::unique_ptr<HexagonOperand>(Op);
434 }
435
436 static std::unique_ptr<HexagonOperand>
437 CreateReg(MCContext &Context, unsigned RegNum, SMLoc S, SMLoc E) {
438 HexagonOperand *Op = new HexagonOperand(Register, Context);
439 Op->Reg.RegNum = RegNum;
440 Op->StartLoc = S;
441 Op->EndLoc = E;
442 return std::unique_ptr<HexagonOperand>(Op);
443 }
444
445 static std::unique_ptr<HexagonOperand>
446 CreateImm(MCContext &Context, const MCExpr *Val, SMLoc S, SMLoc E) {
447 HexagonOperand *Op = new HexagonOperand(Immediate, Context);
448 Op->Imm.Val = Val;
449 Op->StartLoc = S;
450 Op->EndLoc = E;
451 return std::unique_ptr<HexagonOperand>(Op);
452 }
453};
454
455} // end anonymous namespace
456
457void HexagonOperand::print(raw_ostream &OS) const {
458 switch (Kind) {
459 case Immediate:
460 getImm()->print(OS, nullptr);
461 break;
462 case Register:
463 OS << "<register R";
464 OS << getReg() << ">";
465 break;
466 case Token:
467 OS << "'" << getToken() << "'";
468 break;
469 }
470}
471
472bool HexagonAsmParser::finishBundle(SMLoc IDLoc, MCStreamer &Out) {
473 LLVM_DEBUG(dbgs() << "Bundle:");
475 LLVM_DEBUG(dbgs() << "--\n");
476
477 MCB.setLoc(IDLoc);
478
479 // Check the bundle for errors.
480 const MCRegisterInfo *RI = getContext().getRegisterInfo();
481 MCSubtargetInfo const &STI = getSTI();
482
483 MCInst OrigBundle = MCB;
484 HexagonMCChecker Check(getContext(), MII, STI, MCB, *RI, true);
485
487 MII, STI, getContext(), MCB, &Check, true);
488
489 if (CheckOk) {
490 if (HexagonMCInstrInfo::bundleSize(MCB) == 0) {
493 // Empty packets are valid yet aren't emitted
494 return false;
495 }
496
498
499 Out.emitInstruction(MCB, STI);
500 } else
501 return true; // Error
502
503 return false; // No error
504}
505
506bool HexagonAsmParser::matchBundleOptions() {
507 MCAsmParser &Parser = getParser();
508 while (true) {
509 if (!Parser.getTok().is(AsmToken::Colon))
510 return false;
511 Lex();
512 char const *MemNoShuffMsg =
513 "invalid instruction packet: mem_noshuf specifier not "
514 "supported with this architecture";
515 StringRef Option = Parser.getTok().getString();
516 auto IDLoc = Parser.getTok().getLoc();
517 if (Option.compare_insensitive("endloop01") == 0) {
520 } else if (Option.compare_insensitive("endloop0") == 0) {
522 } else if (Option.compare_insensitive("endloop1") == 0) {
524 } else if (Option.compare_insensitive("mem_noshuf") == 0) {
525 if (getSTI().hasFeature(Hexagon::FeatureMemNoShuf))
527 else
528 return getParser().Error(IDLoc, MemNoShuffMsg);
529 } else if (Option.compare_insensitive("mem_no_order") == 0) {
530 // Nothing.
531 } else
532 return getParser().Error(IDLoc, llvm::Twine("'") + Option +
533 "' is not a valid bundle option");
534 Lex();
535 }
536}
537
538// For instruction aliases, immediates are generated rather than
539// MCConstantExpr. Convert them for uniform MCExpr.
540// Also check for signed/unsigned mismatches and warn
541void HexagonAsmParser::canonicalizeImmediates(MCInst &MCI) {
542 MCInst NewInst;
543 NewInst.setOpcode(MCI.getOpcode());
544 for (MCOperand &I : MCI)
545 if (I.isImm()) {
546 int64_t Value(I.getImm());
548 MCConstantExpr::create(Value, getContext()), getContext())));
549 } else {
550 if (I.isExpr() && cast<HexagonMCExpr>(I.getExpr())->signMismatch() &&
552 Warning(MCI.getLoc(), "Signed/Unsigned mismatch");
553 NewInst.addOperand(I);
554 }
555 MCI = NewInst;
556}
557
558bool HexagonAsmParser::matchOneInstruction(MCInst &MCI, SMLoc IDLoc,
559 OperandVector &InstOperands,
561 bool MatchingInlineAsm) {
562 // Perform matching with tablegen asmmatcher generated function
563 int result =
564 MatchInstructionImpl(InstOperands, MCI, ErrorInfo, MatchingInlineAsm);
565 if (result == Match_Success) {
566 MCI.setLoc(IDLoc);
567 canonicalizeImmediates(MCI);
568 result = processInstruction(MCI, InstOperands, IDLoc);
569
570 LLVM_DEBUG(dbgs() << "Insn:");
572 LLVM_DEBUG(dbgs() << "\n\n");
573
574 MCI.setLoc(IDLoc);
575 }
576
577 // Create instruction operand for bundle instruction
578 // Break this into a separate function Code here is less readable
579 // Think about how to get an instruction error to report correctly.
580 // SMLoc will return the "{"
581 switch (result) {
582 default:
583 break;
584 case Match_Success:
585 return false;
586 case Match_MissingFeature:
587 return Error(IDLoc, "invalid instruction");
588 case Match_MnemonicFail:
589 return Error(IDLoc, "unrecognized instruction");
590 case Match_InvalidOperand:
591 [[fallthrough]];
592 case Match_InvalidTiedOperand:
593 SMLoc ErrorLoc = IDLoc;
594 if (ErrorInfo != ~0U) {
595 if (ErrorInfo >= InstOperands.size())
596 return Error(IDLoc, "too few operands for instruction");
597
598 ErrorLoc = (static_cast<HexagonOperand *>(InstOperands[ErrorInfo].get()))
599 ->getStartLoc();
600 if (ErrorLoc == SMLoc())
601 ErrorLoc = IDLoc;
602 }
603 return Error(ErrorLoc, "invalid operand for instruction");
604 }
605 llvm_unreachable("Implement any new match types added!");
606}
607
608void HexagonAsmParser::eatToEndOfPacket() {
609 assert(InBrackets);
610 MCAsmLexer &Lexer = getLexer();
611 while (!Lexer.is(AsmToken::RCurly))
612 Lexer.Lex();
613 Lexer.Lex();
614 InBrackets = false;
615}
616
617bool HexagonAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
619 MCStreamer &Out,
621 bool MatchingInlineAsm) {
622 if (!InBrackets) {
623 MCB.clear();
625 }
626 HexagonOperand &FirstOperand = static_cast<HexagonOperand &>(*Operands[0]);
627 if (FirstOperand.isToken() && FirstOperand.getToken() == "{") {
628 assert(Operands.size() == 1 && "Brackets should be by themselves");
629 if (InBrackets) {
630 getParser().Error(IDLoc, "Already in a packet");
631 InBrackets = false;
632 return true;
633 }
634 InBrackets = true;
635 return false;
636 }
637 if (FirstOperand.isToken() && FirstOperand.getToken() == "}") {
638 assert(Operands.size() == 1 && "Brackets should be by themselves");
639 if (!InBrackets) {
640 getParser().Error(IDLoc, "Not in a packet");
641 return true;
642 }
643 InBrackets = false;
644 if (matchBundleOptions())
645 return true;
646 return finishBundle(IDLoc, Out);
647 }
648 MCInst *SubInst = getParser().getContext().createMCInst();
649 if (matchOneInstruction(*SubInst, IDLoc, Operands, ErrorInfo,
650 MatchingInlineAsm)) {
651 if (InBrackets)
652 eatToEndOfPacket();
653 return true;
654 }
656 getParser().getContext(), MII, MCB, *SubInst);
657 MCB.addOperand(MCOperand::createInst(SubInst));
658 if (!InBrackets)
659 return finishBundle(IDLoc, Out);
660 return false;
661}
662/// parseDirectiveAttribute
663/// ::= .attribute int, int
664/// ::= .attribute Tag_name, int
665bool HexagonAsmParser::parseDirectiveAttribute(SMLoc L) {
666 MCAsmParser &Parser = getParser();
667 int64_t Tag;
668 SMLoc TagLoc = Parser.getTok().getLoc();
669 if (Parser.getTok().is(AsmToken::Identifier)) {
670 StringRef Name = Parser.getTok().getIdentifier();
671 std::optional<unsigned> Ret = ELFAttrs::attrTypeFromString(
673 if (!Ret)
674 return Error(TagLoc, "attribute name not recognized: " + Name);
675 Tag = *Ret;
676 Parser.Lex();
677 } else {
678 const MCExpr *AttrExpr;
679
680 TagLoc = Parser.getTok().getLoc();
681 if (Parser.parseExpression(AttrExpr))
682 return true;
683
684 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
685 if (check(!CE, TagLoc, "expected numeric constant"))
686 return true;
687
688 Tag = CE->getValue();
689 }
690
691 if (Parser.parseComma())
692 return true;
693
694 // We currently only have integer values.
695 int64_t IntegerValue = 0;
696 SMLoc ValueExprLoc = Parser.getTok().getLoc();
697 const MCExpr *ValueExpr;
698 if (Parser.parseExpression(ValueExpr))
699 return true;
700
701 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
702 if (!CE)
703 return Error(ValueExprLoc, "expected numeric constant");
704 IntegerValue = CE->getValue();
705
706 if (Parser.parseEOL())
707 return true;
708
709 getTargetStreamer().emitAttribute(Tag, IntegerValue);
710 return false;
711}
712
713/// ParseDirective parses the Hexagon specific directives
714bool HexagonAsmParser::ParseDirective(AsmToken DirectiveID) {
715 StringRef IDVal = DirectiveID.getIdentifier();
716 if (IDVal.lower() == ".falign")
717 return ParseDirectiveFalign(256, DirectiveID.getLoc());
718 if ((IDVal.lower() == ".lcomm") || (IDVal.lower() == ".lcommon"))
719 return ParseDirectiveComm(true, DirectiveID.getLoc());
720 if ((IDVal.lower() == ".comm") || (IDVal.lower() == ".common"))
721 return ParseDirectiveComm(false, DirectiveID.getLoc());
722 if (IDVal.lower() == ".subsection")
723 return ParseDirectiveSubsection(DirectiveID.getLoc());
724 if (IDVal == ".attribute")
725 return parseDirectiveAttribute(DirectiveID.getLoc());
726
727 return true;
728}
729bool HexagonAsmParser::ParseDirectiveSubsection(SMLoc L) {
730 const MCExpr *Subsection = nullptr;
731 int64_t Res;
732
733 assert((getLexer().isNot(AsmToken::EndOfStatement)) &&
734 "Invalid subsection directive");
735 getParser().parseExpression(Subsection);
736
737 if (!Subsection->evaluateAsAbsolute(Res))
738 return Error(L, "Cannot evaluate subsection number");
739
740 if (getLexer().isNot(AsmToken::EndOfStatement))
741 return TokError("unexpected token in directive");
742
743 // 0-8192 is the hard-coded range in MCObjectStreamper.cpp, this keeps the
744 // negative subsections together and in the same order but at the opposite
745 // end of the section. Only legacy hexagon-gcc created assembly code
746 // used negative subsections.
747 if ((Res < 0) && (Res > -8193))
748 Subsection = HexagonMCExpr::create(
749 MCConstantExpr::create(8192 + Res, getContext()), getContext());
750
751 getStreamer().subSection(Subsection);
752 return false;
753}
754
755/// ::= .falign [expression]
756bool HexagonAsmParser::ParseDirectiveFalign(unsigned Size, SMLoc L) {
757
758 int64_t MaxBytesToFill = 15;
759
760 // if there is an argument
761 if (getLexer().isNot(AsmToken::EndOfStatement)) {
762 const MCExpr *Value;
763 SMLoc ExprLoc = L;
764
765 // Make sure we have a number (false is returned if expression is a number)
766 if (!getParser().parseExpression(Value)) {
767 // Make sure this is a number that is in range
768 auto *MCE = cast<MCConstantExpr>(Value);
769 uint64_t IntValue = MCE->getValue();
770 if (!isUIntN(Size, IntValue) && !isIntN(Size, IntValue))
771 return Error(ExprLoc, "literal value out of range (256) for falign");
772 MaxBytesToFill = IntValue;
773 Lex();
774 } else {
775 return Error(ExprLoc, "not a valid expression for falign directive");
776 }
777 }
778
779 getTargetStreamer().emitFAlign(16, MaxBytesToFill);
780 Lex();
781
782 return false;
783}
784
785// This is largely a copy of AsmParser's ParseDirectiveComm extended to
786// accept a 3rd argument, AccessAlignment which indicates the smallest
787// memory access made to the symbol, expressed in bytes. If no
788// AccessAlignment is specified it defaults to the Alignment Value.
789// Hexagon's .lcomm:
790// .lcomm Symbol, Length, Alignment, AccessAlignment
791bool HexagonAsmParser::ParseDirectiveComm(bool IsLocal, SMLoc Loc) {
792 // FIXME: need better way to detect if AsmStreamer (upstream removed
793 // getKind())
794 if (getStreamer().hasRawTextSupport())
795 return true; // Only object file output requires special treatment.
796
798 if (getParser().parseIdentifier(Name))
799 return TokError("expected identifier in directive");
800 // Handle the identifier as the key symbol.
801 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
802
803 if (getLexer().isNot(AsmToken::Comma))
804 return TokError("unexpected token in directive");
805 Lex();
806
807 int64_t Size;
808 SMLoc SizeLoc = getLexer().getLoc();
809 if (getParser().parseAbsoluteExpression(Size))
810 return true;
811
812 int64_t ByteAlignment = 1;
813 SMLoc ByteAlignmentLoc;
814 if (getLexer().is(AsmToken::Comma)) {
815 Lex();
816 ByteAlignmentLoc = getLexer().getLoc();
817 if (getParser().parseAbsoluteExpression(ByteAlignment))
818 return true;
819 if (!isPowerOf2_64(ByteAlignment))
820 return Error(ByteAlignmentLoc, "alignment must be a power of 2");
821 }
822
823 int64_t AccessAlignment = 0;
824 if (getLexer().is(AsmToken::Comma)) {
825 // The optional access argument specifies the size of the smallest memory
826 // access to be made to the symbol, expressed in bytes.
827 SMLoc AccessAlignmentLoc;
828 Lex();
829 AccessAlignmentLoc = getLexer().getLoc();
830 if (getParser().parseAbsoluteExpression(AccessAlignment))
831 return true;
832
833 if (!isPowerOf2_64(AccessAlignment))
834 return Error(AccessAlignmentLoc, "access alignment must be a power of 2");
835 }
836
837 if (getLexer().isNot(AsmToken::EndOfStatement))
838 return TokError("unexpected token in '.comm' or '.lcomm' directive");
839
840 Lex();
841
842 // NOTE: a size of zero for a .comm should create a undefined symbol
843 // but a size of .lcomm creates a bss symbol of size zero.
844 if (Size < 0)
845 return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
846 "be less than zero");
847
848 // NOTE: The alignment in the directive is a power of 2 value, the assembler
849 // may internally end up wanting an alignment in bytes.
850 // FIXME: Diagnose overflow.
851 if (ByteAlignment < 0)
852 return Error(ByteAlignmentLoc, "invalid '.comm' or '.lcomm' directive "
853 "alignment, can't be less than zero");
854
855 if (!Sym->isUndefined())
856 return Error(Loc, "invalid symbol redefinition");
857
858 HexagonMCELFStreamer &HexagonELFStreamer =
859 static_cast<HexagonMCELFStreamer &>(getStreamer());
860 if (IsLocal) {
861 HexagonELFStreamer.HexagonMCEmitLocalCommonSymbol(
862 Sym, Size, Align(ByteAlignment), AccessAlignment);
863 return false;
864 }
865
866 HexagonELFStreamer.HexagonMCEmitCommonSymbol(Sym, Size, Align(ByteAlignment),
867 AccessAlignment);
868 return false;
869}
870
871// validate register against architecture
872bool HexagonAsmParser::RegisterMatchesArch(unsigned MatchNum) const {
873 if (HexagonMCRegisterClasses[Hexagon::V62RegsRegClassID].contains(MatchNum))
874 if (!getSTI().hasFeature(Hexagon::ArchV62))
875 return false;
876 return true;
877}
878
879// extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeHexagonAsmLexer();
880
881/// Force static initialization.
884}
885
886#define GET_MATCHER_IMPLEMENTATION
887#define GET_REGISTER_MATCHER
888#include "HexagonGenAsmMatcher.inc"
889
892 if (Index >= Operands.size())
893 return false;
894 MCParsedAsmOperand &Operand = *Operands[Operands.size() - Index - 1];
895 if (!Operand.isToken())
896 return false;
897 return static_cast<HexagonOperand &>(Operand).getToken().equals_insensitive(
898 String);
899}
900
902 return previousEqual(Operands, Index, "loop0") ||
903 previousEqual(Operands, Index, "loop1") ||
904 previousEqual(Operands, Index, "sp1loop0") ||
905 previousEqual(Operands, Index, "sp2loop0") ||
906 previousEqual(Operands, Index, "sp3loop0");
907}
908
909bool HexagonAsmParser::splitIdentifier(OperandVector &Operands) {
910 AsmToken const &Token = getParser().getTok();
911 StringRef String = Token.getString();
912 SMLoc Loc = Token.getLoc();
913 Lex();
914 do {
915 std::pair<StringRef, StringRef> HeadTail = String.split('.');
916 if (!HeadTail.first.empty())
917 Operands.push_back(
918 HexagonOperand::CreateToken(getContext(), HeadTail.first, Loc));
919 if (!HeadTail.second.empty())
920 Operands.push_back(HexagonOperand::CreateToken(
921 getContext(), String.substr(HeadTail.first.size(), 1), Loc));
922 String = HeadTail.second;
923 } while (!String.empty());
924 return false;
925}
926
927bool HexagonAsmParser::parseOperand(OperandVector &Operands) {
929 SMLoc Begin;
930 SMLoc End;
931 MCAsmLexer &Lexer = getLexer();
932 if (!parseRegister(Register, Begin, End)) {
934 switch (Register) {
935 default:
936 break;
937 case Hexagon::P0:
938 case Hexagon::P1:
939 case Hexagon::P2:
940 case Hexagon::P3:
941 if (previousEqual(Operands, 0, "if")) {
943 Warning(Begin, "Missing parenthesis around predicate register");
944 static char const *LParen = "(";
945 static char const *RParen = ")";
946 Operands.push_back(
947 HexagonOperand::CreateToken(getContext(), LParen, Begin));
948 Operands.push_back(
949 HexagonOperand::CreateReg(getContext(), Register, Begin, End));
950 const AsmToken &MaybeDotNew = Lexer.getTok();
951 if (MaybeDotNew.is(AsmToken::TokenKind::Identifier) &&
952 MaybeDotNew.getString().equals_insensitive(".new"))
953 splitIdentifier(Operands);
954 Operands.push_back(
955 HexagonOperand::CreateToken(getContext(), RParen, Begin));
956 return false;
957 }
958 if (previousEqual(Operands, 0, "!") &&
959 previousEqual(Operands, 1, "if")) {
961 Warning(Begin, "Missing parenthesis around predicate register");
962 static char const *LParen = "(";
963 static char const *RParen = ")";
964 Operands.insert(Operands.end() - 1, HexagonOperand::CreateToken(
965 getContext(), LParen, Begin));
966 Operands.push_back(
967 HexagonOperand::CreateReg(getContext(), Register, Begin, End));
968 const AsmToken &MaybeDotNew = Lexer.getTok();
969 if (MaybeDotNew.is(AsmToken::TokenKind::Identifier) &&
970 MaybeDotNew.getString().equals_insensitive(".new"))
971 splitIdentifier(Operands);
972 Operands.push_back(
973 HexagonOperand::CreateToken(getContext(), RParen, Begin));
974 return false;
975 }
976 break;
977 }
978 Operands.push_back(
979 HexagonOperand::CreateReg(getContext(), Register, Begin, End));
980 return false;
981 }
982 return splitIdentifier(Operands);
983}
984
985bool HexagonAsmParser::isLabel(AsmToken &Token) {
986 MCAsmLexer &Lexer = getLexer();
987 AsmToken const &Second = Lexer.getTok();
988 AsmToken Third = Lexer.peekTok();
989 StringRef String = Token.getString();
990 if (Token.is(AsmToken::TokenKind::LCurly) ||
991 Token.is(AsmToken::TokenKind::RCurly))
992 return false;
993 // special case for parsing vwhist256:sat
994 if (String.lower() == "vwhist256" && Second.is(AsmToken::Colon) &&
995 Third.getString().lower() == "sat")
996 return false;
997 if (!Token.is(AsmToken::TokenKind::Identifier))
998 return true;
999 if (!matchRegister(String.lower()))
1000 return true;
1001 assert(Second.is(AsmToken::Colon));
1002 StringRef Raw(String.data(), Third.getString().data() - String.data() +
1003 Third.getString().size());
1004 std::string Collapsed = std::string(Raw);
1005 llvm::erase_if(Collapsed, isSpace);
1006 StringRef Whole = Collapsed;
1007 std::pair<StringRef, StringRef> DotSplit = Whole.split('.');
1008 if (!matchRegister(DotSplit.first.lower()))
1009 return true;
1010 return false;
1011}
1012
1013bool HexagonAsmParser::handleNoncontigiousRegister(bool Contigious,
1014 SMLoc &Loc) {
1015 if (!Contigious && ErrorNoncontigiousRegister) {
1016 Error(Loc, "Register name is not contigious");
1017 return true;
1018 }
1019 if (!Contigious && WarnNoncontigiousRegister)
1020 Warning(Loc, "Register name is not contigious");
1021 return false;
1022}
1023
1024bool HexagonAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
1025 SMLoc &EndLoc) {
1026 return !tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
1027}
1028
1029ParseStatus HexagonAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1030 SMLoc &EndLoc) {
1031 MCAsmLexer &Lexer = getLexer();
1032 StartLoc = getLexer().getLoc();
1033 SmallVector<AsmToken, 5> Lookahead;
1034 StringRef RawString(Lexer.getTok().getString().data(), 0);
1035 bool Again = Lexer.is(AsmToken::Identifier);
1036 bool NeededWorkaround = false;
1037 while (Again) {
1038 AsmToken const &Token = Lexer.getTok();
1039 RawString = StringRef(RawString.data(), Token.getString().data() -
1040 RawString.data() +
1041 Token.getString().size());
1042 Lookahead.push_back(Token);
1043 Lexer.Lex();
1044 bool Contigious = Lexer.getTok().getString().data() ==
1045 Lookahead.back().getString().data() +
1046 Lookahead.back().getString().size();
1047 bool Type = Lexer.is(AsmToken::Identifier) || Lexer.is(AsmToken::Dot) ||
1048 Lexer.is(AsmToken::Integer) || Lexer.is(AsmToken::Real) ||
1049 Lexer.is(AsmToken::Colon);
1050 bool Workaround =
1051 Lexer.is(AsmToken::Colon) || Lookahead.back().is(AsmToken::Colon);
1052 Again = (Contigious && Type) || (Workaround && Type);
1053 NeededWorkaround = NeededWorkaround || (Again && !(Contigious && Type));
1054 }
1055 std::string Collapsed = std::string(RawString);
1056 llvm::erase_if(Collapsed, isSpace);
1057 StringRef FullString = Collapsed;
1058 std::pair<StringRef, StringRef> DotSplit = FullString.split('.');
1059 unsigned DotReg = matchRegister(DotSplit.first.lower());
1060 if (DotReg != Hexagon::NoRegister && RegisterMatchesArch(DotReg)) {
1061 if (DotSplit.second.empty()) {
1062 Reg = DotReg;
1063 EndLoc = Lexer.getLoc();
1064 if (handleNoncontigiousRegister(!NeededWorkaround, StartLoc))
1065 return ParseStatus::NoMatch;
1066 return ParseStatus::Success;
1067 } else {
1068 Reg = DotReg;
1069 size_t First = RawString.find('.');
1070 StringRef DotString (RawString.data() + First, RawString.size() - First);
1071 Lexer.UnLex(AsmToken(AsmToken::Identifier, DotString));
1072 EndLoc = Lexer.getLoc();
1073 if (handleNoncontigiousRegister(!NeededWorkaround, StartLoc))
1074 return ParseStatus::NoMatch;
1075 return ParseStatus::Success;
1076 }
1077 }
1078 std::pair<StringRef, StringRef> ColonSplit = StringRef(FullString).split(':');
1079 unsigned ColonReg = matchRegister(ColonSplit.first.lower());
1080 if (ColonReg != Hexagon::NoRegister && RegisterMatchesArch(DotReg)) {
1081 do {
1082 Lexer.UnLex(Lookahead.pop_back_val());
1083 } while (!Lookahead.empty() && !Lexer.is(AsmToken::Colon));
1084 Reg = ColonReg;
1085 EndLoc = Lexer.getLoc();
1086 if (handleNoncontigiousRegister(!NeededWorkaround, StartLoc))
1087 return ParseStatus::NoMatch;
1088 return ParseStatus::Success;
1089 }
1090 while (!Lookahead.empty()) {
1091 Lexer.UnLex(Lookahead.pop_back_val());
1092 }
1093 return ParseStatus::NoMatch;
1094}
1095
1096bool HexagonAsmParser::implicitExpressionLocation(OperandVector &Operands) {
1097 if (previousEqual(Operands, 0, "call"))
1098 return true;
1099 if (previousEqual(Operands, 0, "jump"))
1100 if (!getLexer().getTok().is(AsmToken::Colon))
1101 return true;
1102 if (previousEqual(Operands, 0, "(") && previousIsLoop(Operands, 1))
1103 return true;
1104 if (previousEqual(Operands, 1, ":") && previousEqual(Operands, 2, "jump") &&
1105 (previousEqual(Operands, 0, "nt") || previousEqual(Operands, 0, "t")))
1106 return true;
1107 return false;
1108}
1109
1110bool HexagonAsmParser::parseExpression(MCExpr const *&Expr) {
1112 MCAsmLexer &Lexer = getLexer();
1113 bool Done = false;
1114 static char const *Comma = ",";
1115 do {
1116 Tokens.emplace_back(Lexer.getTok());
1117 Lex();
1118 switch (Tokens.back().getKind()) {
1119 case AsmToken::TokenKind::Hash:
1120 if (Tokens.size() > 1)
1121 if ((Tokens.end() - 2)->getKind() == AsmToken::TokenKind::Plus) {
1122 Tokens.insert(Tokens.end() - 2,
1123 AsmToken(AsmToken::TokenKind::Comma, Comma));
1124 Done = true;
1125 }
1126 break;
1127 case AsmToken::TokenKind::RCurly:
1128 case AsmToken::TokenKind::EndOfStatement:
1129 case AsmToken::TokenKind::Eof:
1130 Done = true;
1131 break;
1132 default:
1133 break;
1134 }
1135 } while (!Done);
1136 while (!Tokens.empty()) {
1137 Lexer.UnLex(Tokens.back());
1138 Tokens.pop_back();
1139 }
1140 SMLoc Loc = Lexer.getLoc();
1141 return getParser().parseExpression(Expr, Loc);
1142}
1143
1144bool HexagonAsmParser::parseExpressionOrOperand(OperandVector &Operands) {
1145 if (implicitExpressionLocation(Operands)) {
1146 MCAsmParser &Parser = getParser();
1147 SMLoc Loc = Parser.getLexer().getLoc();
1148 MCExpr const *Expr = nullptr;
1149 bool Error = parseExpression(Expr);
1150 Expr = HexagonMCExpr::create(Expr, getContext());
1151 if (!Error)
1152 Operands.push_back(
1153 HexagonOperand::CreateImm(getContext(), Expr, Loc, Loc));
1154 return Error;
1155 }
1156 return parseOperand(Operands);
1157}
1158
1159/// Parse an instruction.
1160bool HexagonAsmParser::parseInstruction(OperandVector &Operands) {
1161 MCAsmParser &Parser = getParser();
1162 MCAsmLexer &Lexer = getLexer();
1163 while (true) {
1164 AsmToken const &Token = Parser.getTok();
1165 switch (Token.getKind()) {
1166 case AsmToken::Eof:
1168 Lex();
1169 return false;
1170 }
1171 case AsmToken::LCurly: {
1172 if (!Operands.empty())
1173 return true;
1174 Operands.push_back(HexagonOperand::CreateToken(
1175 getContext(), Token.getString(), Token.getLoc()));
1176 Lex();
1177 return false;
1178 }
1179 case AsmToken::RCurly: {
1180 if (Operands.empty()) {
1181 Operands.push_back(HexagonOperand::CreateToken(
1182 getContext(), Token.getString(), Token.getLoc()));
1183 Lex();
1184 }
1185 return false;
1186 }
1187 case AsmToken::Comma: {
1188 Lex();
1189 continue;
1190 }
1196 case AsmToken::LessLess: {
1197 Operands.push_back(HexagonOperand::CreateToken(
1198 getContext(), Token.getString().substr(0, 1), Token.getLoc()));
1199 Operands.push_back(HexagonOperand::CreateToken(
1200 getContext(), Token.getString().substr(1, 1), Token.getLoc()));
1201 Lex();
1202 continue;
1203 }
1204 case AsmToken::Hash: {
1205 bool MustNotExtend = false;
1206 bool ImplicitExpression = implicitExpressionLocation(Operands);
1207 SMLoc ExprLoc = Lexer.getLoc();
1208 if (!ImplicitExpression)
1209 Operands.push_back(HexagonOperand::CreateToken(
1210 getContext(), Token.getString(), Token.getLoc()));
1211 Lex();
1212 bool MustExtend = false;
1213 bool HiOnly = false;
1214 bool LoOnly = false;
1215 if (Lexer.is(AsmToken::Hash)) {
1216 Lex();
1217 MustExtend = true;
1218 } else if (ImplicitExpression)
1219 MustNotExtend = true;
1220 AsmToken const &Token = Parser.getTok();
1221 if (Token.is(AsmToken::Identifier)) {
1222 StringRef String = Token.getString();
1223 if (String.lower() == "hi") {
1224 HiOnly = true;
1225 } else if (String.lower() == "lo") {
1226 LoOnly = true;
1227 }
1228 if (HiOnly || LoOnly) {
1229 AsmToken LParen = Lexer.peekTok();
1230 if (!LParen.is(AsmToken::LParen)) {
1231 HiOnly = false;
1232 LoOnly = false;
1233 } else {
1234 Lex();
1235 }
1236 }
1237 }
1238 MCExpr const *Expr = nullptr;
1239 if (parseExpression(Expr))
1240 return true;
1241 int64_t Value;
1242 MCContext &Context = Parser.getContext();
1243 assert(Expr != nullptr);
1244 if (Expr->evaluateAsAbsolute(Value)) {
1245 if (HiOnly)
1247 Expr, MCConstantExpr::create(16, Context), Context);
1248 if (HiOnly || LoOnly)
1250 Expr, MCConstantExpr::create(0xffff, Context), Context);
1251 } else {
1252 MCValue Value;
1253 if (Expr->evaluateAsRelocatable(Value, nullptr, nullptr)) {
1254 if (!Value.isAbsolute()) {
1255 switch (Value.getAccessVariant()) {
1256 case MCSymbolRefExpr::VariantKind::VK_TPREL:
1257 case MCSymbolRefExpr::VariantKind::VK_DTPREL:
1258 // Don't lazy extend these expression variants
1259 MustNotExtend = !MustExtend;
1260 break;
1261 default:
1262 break;
1263 }
1264 }
1265 }
1266 }
1267 Expr = HexagonMCExpr::create(Expr, Context);
1268 HexagonMCInstrInfo::setMustNotExtend(*Expr, MustNotExtend);
1269 HexagonMCInstrInfo::setMustExtend(*Expr, MustExtend);
1270 std::unique_ptr<HexagonOperand> Operand =
1271 HexagonOperand::CreateImm(getContext(), Expr, ExprLoc, ExprLoc);
1272 Operands.push_back(std::move(Operand));
1273 continue;
1274 }
1275 default:
1276 break;
1277 }
1278 if (parseExpressionOrOperand(Operands))
1279 return true;
1280 }
1281}
1282
1283bool HexagonAsmParser::ParseInstruction(ParseInstructionInfo &Info,
1286 getLexer().UnLex(ID);
1287 return parseInstruction(Operands);
1288}
1289
1290static MCInst makeCombineInst(int opCode, MCOperand &Rdd, MCOperand &MO1,
1291 MCOperand &MO2) {
1292 MCInst TmpInst;
1293 TmpInst.setOpcode(opCode);
1294 TmpInst.addOperand(Rdd);
1295 TmpInst.addOperand(MO1);
1296 TmpInst.addOperand(MO2);
1297
1298 return TmpInst;
1299}
1300
1301// Define this matcher function after the auto-generated include so we
1302// have the match class enum definitions.
1303unsigned HexagonAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
1304 unsigned Kind) {
1305 HexagonOperand *Op = static_cast<HexagonOperand *>(&AsmOp);
1306
1307 switch (Kind) {
1308 case MCK_0: {
1309 int64_t Value;
1310 return Op->isImm() && Op->Imm.Val->evaluateAsAbsolute(Value) && Value == 0
1311 ? Match_Success
1312 : Match_InvalidOperand;
1313 }
1314 case MCK_1: {
1315 int64_t Value;
1316 return Op->isImm() && Op->Imm.Val->evaluateAsAbsolute(Value) && Value == 1
1317 ? Match_Success
1318 : Match_InvalidOperand;
1319 }
1320 }
1321 if (Op->Kind == HexagonOperand::Token && Kind != InvalidMatchClass) {
1322 StringRef myStringRef = StringRef(Op->Tok.Data, Op->Tok.Length);
1323 if (matchTokenString(myStringRef.lower()) == (MatchClassKind)Kind)
1324 return Match_Success;
1325 if (matchTokenString(myStringRef.upper()) == (MatchClassKind)Kind)
1326 return Match_Success;
1327 }
1328
1329 LLVM_DEBUG(dbgs() << "Unmatched Operand:");
1330 LLVM_DEBUG(Op->dump());
1331 LLVM_DEBUG(dbgs() << "\n");
1332
1333 return Match_InvalidOperand;
1334}
1335
1336// FIXME: Calls to OutOfRange shoudl propagate failure up to parseStatement.
1337bool HexagonAsmParser::OutOfRange(SMLoc IDLoc, long long Val, long long Max) {
1338 std::string errStr;
1339 raw_string_ostream ES(errStr);
1340 ES << "value " << Val << "(" << format_hex(Val, 0) << ") out of range: ";
1341 if (Max >= 0)
1342 ES << "0-" << Max;
1343 else
1344 ES << Max << "-" << (-Max - 1);
1345 return Parser.printError(IDLoc, ES.str());
1346}
1347
1348int HexagonAsmParser::processInstruction(MCInst &Inst,
1349 OperandVector const &Operands,
1350 SMLoc IDLoc) {
1351 MCContext &Context = getParser().getContext();
1352 const MCRegisterInfo *RI = getContext().getRegisterInfo();
1353 const std::string r = "r";
1354 const std::string v = "v";
1355 const std::string Colon = ":";
1356 using RegPairVals = std::pair<unsigned, unsigned>;
1357 auto GetRegPair = [this, r](RegPairVals RegPair) {
1358 const std::string R1 = r + utostr(RegPair.first);
1359 const std::string R2 = r + utostr(RegPair.second);
1360
1361 return std::make_pair(matchRegister(R1), matchRegister(R2));
1362 };
1363 auto GetScalarRegs = [RI, GetRegPair](unsigned RegPair) {
1364 const unsigned Lower = RI->getEncodingValue(RegPair);
1365 const RegPairVals RegPair_ = std::make_pair(Lower + 1, Lower);
1366
1367 return GetRegPair(RegPair_);
1368 };
1369 auto GetVecRegs = [GetRegPair](unsigned VecRegPair) {
1370 const RegPairVals RegPair =
1372
1373 return GetRegPair(RegPair);
1374 };
1375
1376 bool is32bit = false; // used to distinguish between CONST32 and CONST64
1377 switch (Inst.getOpcode()) {
1378 default:
1379 if (HexagonMCInstrInfo::getDesc(MII, Inst).isPseudo()) {
1380 SMDiagnostic Diag = getSourceManager().GetMessage(
1381 IDLoc, SourceMgr::DK_Error,
1382 "Found pseudo instruction with no expansion");
1383 Diag.print("", errs());
1384 report_fatal_error("Invalid pseudo instruction");
1385 }
1386 break;
1387
1388 case Hexagon::J2_trap1:
1389 if (!getSTI().hasFeature(Hexagon::ArchV65)) {
1390 MCOperand &Rx = Inst.getOperand(0);
1391 MCOperand &Ry = Inst.getOperand(1);
1392 if (Rx.getReg() != Hexagon::R0 || Ry.getReg() != Hexagon::R0) {
1393 Error(IDLoc, "trap1 can only have register r0 as operand");
1394 return Match_InvalidOperand;
1395 }
1396 }
1397 break;
1398
1399 case Hexagon::A2_iconst: {
1400 Inst.setOpcode(Hexagon::A2_addi);
1401 MCOperand Reg = Inst.getOperand(0);
1402 MCOperand S27 = Inst.getOperand(1);
1405 Inst.clear();
1406 Inst.addOperand(Reg);
1407 Inst.addOperand(MCOperand::createReg(Hexagon::R0));
1408 Inst.addOperand(S27);
1409 break;
1410 }
1411 case Hexagon::M4_mpyrr_addr:
1412 case Hexagon::S4_addi_asl_ri:
1413 case Hexagon::S4_addi_lsr_ri:
1414 case Hexagon::S4_andi_asl_ri:
1415 case Hexagon::S4_andi_lsr_ri:
1416 case Hexagon::S4_ori_asl_ri:
1417 case Hexagon::S4_ori_lsr_ri:
1418 case Hexagon::S4_or_andix:
1419 case Hexagon::S4_subi_asl_ri:
1420 case Hexagon::S4_subi_lsr_ri: {
1421 MCOperand &Ry = Inst.getOperand(0);
1422 MCOperand &src = Inst.getOperand(2);
1423 if (RI->getEncodingValue(Ry.getReg()) != RI->getEncodingValue(src.getReg()))
1424 return Match_InvalidOperand;
1425 break;
1426 }
1427
1428 case Hexagon::C2_cmpgei: {
1429 MCOperand &MO = Inst.getOperand(2);
1432 MCConstantExpr::create(1, Context), Context),
1433 Context));
1434 Inst.setOpcode(Hexagon::C2_cmpgti);
1435 break;
1436 }
1437
1438 case Hexagon::C2_cmpgeui: {
1439 MCOperand &MO = Inst.getOperand(2);
1440 int64_t Value;
1441 bool Success = MO.getExpr()->evaluateAsAbsolute(Value);
1442 (void)Success;
1443 assert(Success && "Assured by matcher");
1444 if (Value == 0) {
1445 MCInst TmpInst;
1446 MCOperand &Pd = Inst.getOperand(0);
1447 MCOperand &Rt = Inst.getOperand(1);
1448 TmpInst.setOpcode(Hexagon::C2_cmpeq);
1449 TmpInst.addOperand(Pd);
1450 TmpInst.addOperand(Rt);
1451 TmpInst.addOperand(Rt);
1452 Inst = TmpInst;
1453 } else {
1456 MCConstantExpr::create(1, Context), Context),
1457 Context));
1458 Inst.setOpcode(Hexagon::C2_cmpgtui);
1459 }
1460 break;
1461 }
1462
1463 // Translate a "$Rdd = $Rss" to "$Rdd = combine($Rs, $Rt)"
1464 case Hexagon::A2_tfrp: {
1465 MCOperand &MO = Inst.getOperand(1);
1466 const std::pair<unsigned, unsigned> RegPair = GetScalarRegs(MO.getReg());
1467 MO.setReg(RegPair.first);
1468 Inst.addOperand(MCOperand::createReg(RegPair.second));
1469 Inst.setOpcode(Hexagon::A2_combinew);
1470 break;
1471 }
1472
1473 case Hexagon::A2_tfrpt:
1474 case Hexagon::A2_tfrpf: {
1475 MCOperand &MO = Inst.getOperand(2);
1476 const std::pair<unsigned, unsigned> RegPair = GetScalarRegs(MO.getReg());
1477 MO.setReg(RegPair.first);
1478 Inst.addOperand(MCOperand::createReg(RegPair.second));
1479 Inst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrpt)
1480 ? Hexagon::C2_ccombinewt
1481 : Hexagon::C2_ccombinewf);
1482 break;
1483 }
1484 case Hexagon::A2_tfrptnew:
1485 case Hexagon::A2_tfrpfnew: {
1486 MCOperand &MO = Inst.getOperand(2);
1487 const std::pair<unsigned, unsigned> RegPair = GetScalarRegs(MO.getReg());
1488 MO.setReg(RegPair.first);
1489 Inst.addOperand(MCOperand::createReg(RegPair.second));
1490 Inst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrptnew)
1491 ? Hexagon::C2_ccombinewnewt
1492 : Hexagon::C2_ccombinewnewf);
1493 break;
1494 }
1495
1496 // Translate a "$Vdd = $Vss" to "$Vdd = vcombine($Vs, $Vt)"
1497 case Hexagon::V6_vassignp: {
1498 MCOperand &MO = Inst.getOperand(1);
1499 const std::pair<unsigned, unsigned> RegPair = GetVecRegs(MO.getReg());
1500 MO.setReg(RegPair.first);
1501 Inst.addOperand(MCOperand::createReg(RegPair.second));
1502 Inst.setOpcode(Hexagon::V6_vcombine);
1503 break;
1504 }
1505
1506 // Translate a "$Rx = CONST32(#imm)" to "$Rx = memw(gp+#LABEL) "
1507 case Hexagon::CONST32:
1508 is32bit = true;
1509 [[fallthrough]];
1510 // Translate a "$Rx:y = CONST64(#imm)" to "$Rx:y = memd(gp+#LABEL) "
1511 case Hexagon::CONST64:
1512 // FIXME: need better way to detect AsmStreamer (upstream removed getKind())
1513 if (!Parser.getStreamer().hasRawTextSupport()) {
1514 MCELFStreamer *MES = static_cast<MCELFStreamer *>(&Parser.getStreamer());
1515 MCOperand &MO_1 = Inst.getOperand(1);
1516 MCOperand &MO_0 = Inst.getOperand(0);
1517
1518 // push section onto section stack
1519 MES->pushSection();
1520
1521 std::string myCharStr;
1522 MCSectionELF *mySection;
1523
1524 // check if this as an immediate or a symbol
1525 int64_t Value;
1526 bool Absolute = MO_1.getExpr()->evaluateAsAbsolute(Value);
1527 if (Absolute) {
1528 // Create a new section - one for each constant
1529 // Some or all of the zeros are replaced with the given immediate.
1530 if (is32bit) {
1531 std::string myImmStr = utohexstr(static_cast<uint32_t>(Value));
1532 myCharStr = StringRef(".gnu.linkonce.l4.CONST_00000000")
1533 .drop_back(myImmStr.size())
1534 .str() +
1535 myImmStr;
1536 } else {
1537 std::string myImmStr = utohexstr(Value);
1538 myCharStr = StringRef(".gnu.linkonce.l8.CONST_0000000000000000")
1539 .drop_back(myImmStr.size())
1540 .str() +
1541 myImmStr;
1542 }
1543
1544 mySection = getContext().getELFSection(myCharStr, ELF::SHT_PROGBITS,
1546 } else if (MO_1.isExpr()) {
1547 // .lita - for expressions
1548 myCharStr = ".lita";
1549 mySection = getContext().getELFSection(myCharStr, ELF::SHT_PROGBITS,
1551 } else
1552 llvm_unreachable("unexpected type of machine operand!");
1553
1554 MES->switchSection(mySection);
1555 unsigned byteSize = is32bit ? 4 : 8;
1556 getStreamer().emitCodeAlignment(Align(byteSize), &getSTI(), byteSize);
1557
1558 MCSymbol *Sym;
1559
1560 // for symbols, get rid of prepended ".gnu.linkonce.lx."
1561
1562 // emit symbol if needed
1563 if (Absolute) {
1564 Sym = getContext().getOrCreateSymbol(StringRef(myCharStr.c_str() + 16));
1565 if (Sym->isUndefined()) {
1566 getStreamer().emitLabel(Sym);
1567 getStreamer().emitSymbolAttribute(Sym, MCSA_Global);
1568 getStreamer().emitIntValue(Value, byteSize);
1569 }
1570 } else if (MO_1.isExpr()) {
1571 const char *StringStart = nullptr;
1572 const char *StringEnd = nullptr;
1573 if (*Operands[4]->getStartLoc().getPointer() == '#') {
1574 StringStart = Operands[5]->getStartLoc().getPointer();
1575 StringEnd = Operands[6]->getStartLoc().getPointer();
1576 } else { // no pound
1577 StringStart = Operands[4]->getStartLoc().getPointer();
1578 StringEnd = Operands[5]->getStartLoc().getPointer();
1579 }
1580
1581 unsigned size = StringEnd - StringStart;
1582 std::string DotConst = ".CONST_";
1583 Sym = getContext().getOrCreateSymbol(DotConst +
1584 StringRef(StringStart, size));
1585
1586 if (Sym->isUndefined()) {
1587 // case where symbol is not yet defined: emit symbol
1588 getStreamer().emitLabel(Sym);
1589 getStreamer().emitSymbolAttribute(Sym, MCSA_Local);
1590 getStreamer().emitValue(MO_1.getExpr(), 4);
1591 }
1592 } else
1593 llvm_unreachable("unexpected type of machine operand!");
1594
1595 MES->popSection();
1596
1597 if (Sym) {
1598 MCInst TmpInst;
1599 if (is32bit) // 32 bit
1600 TmpInst.setOpcode(Hexagon::L2_loadrigp);
1601 else // 64 bit
1602 TmpInst.setOpcode(Hexagon::L2_loadrdgp);
1603
1604 TmpInst.addOperand(MO_0);
1606 MCSymbolRefExpr::create(Sym, getContext()), getContext())));
1607 Inst = TmpInst;
1608 }
1609 }
1610 break;
1611
1612 // Translate a "$Rdd = #-imm" to "$Rdd = combine(#[-1,0], #-imm)"
1613 case Hexagon::A2_tfrpi: {
1614 MCOperand &Rdd = Inst.getOperand(0);
1615 MCOperand &MO = Inst.getOperand(1);
1616 int64_t Value;
1617 int sVal = (MO.getExpr()->evaluateAsAbsolute(Value) && Value < 0) ? -1 : 0;
1619 HexagonMCExpr::create(MCConstantExpr::create(sVal, Context), Context)));
1620 Inst = makeCombineInst(Hexagon::A2_combineii, Rdd, imm, MO);
1621 break;
1622 }
1623
1624 // Translate a "$Rdd = [#]#imm" to "$Rdd = combine(#, [#]#imm)"
1625 case Hexagon::TFRI64_V4: {
1626 MCOperand &Rdd = Inst.getOperand(0);
1627 MCOperand &MO = Inst.getOperand(1);
1628 int64_t Value;
1629 if (MO.getExpr()->evaluateAsAbsolute(Value)) {
1630 int s8 = Hi_32(Value);
1631 if (!isInt<8>(s8))
1632 OutOfRange(IDLoc, s8, -128);
1634 MCConstantExpr::create(s8, Context), Context))); // upper 32
1635 auto Expr = HexagonMCExpr::create(
1636 MCConstantExpr::create(Lo_32(Value), Context), Context);
1639 MCOperand imm2(MCOperand::createExpr(Expr)); // lower 32
1640 Inst = makeCombineInst(Hexagon::A4_combineii, Rdd, imm, imm2);
1641 } else {
1643 MCConstantExpr::create(0, Context), Context))); // upper 32
1644 Inst = makeCombineInst(Hexagon::A4_combineii, Rdd, imm, MO);
1645 }
1646 break;
1647 }
1648
1649 // Handle $Rdd = combine(##imm, #imm)"
1650 case Hexagon::TFRI64_V2_ext: {
1651 MCOperand &Rdd = Inst.getOperand(0);
1652 MCOperand &MO1 = Inst.getOperand(1);
1653 MCOperand &MO2 = Inst.getOperand(2);
1654 int64_t Value;
1655 if (MO2.getExpr()->evaluateAsAbsolute(Value)) {
1656 int s8 = Value;
1657 if (s8 < -128 || s8 > 127)
1658 OutOfRange(IDLoc, s8, -128);
1659 }
1660 Inst = makeCombineInst(Hexagon::A2_combineii, Rdd, MO1, MO2);
1661 break;
1662 }
1663
1664 // Handle $Rdd = combine(#imm, ##imm)"
1665 case Hexagon::A4_combineii: {
1666 MCOperand &Rdd = Inst.getOperand(0);
1667 MCOperand &MO1 = Inst.getOperand(1);
1668 int64_t Value;
1669 if (MO1.getExpr()->evaluateAsAbsolute(Value)) {
1670 int s8 = Value;
1671 if (s8 < -128 || s8 > 127)
1672 OutOfRange(IDLoc, s8, -128);
1673 }
1674 MCOperand &MO2 = Inst.getOperand(2);
1675 Inst = makeCombineInst(Hexagon::A4_combineii, Rdd, MO1, MO2);
1676 break;
1677 }
1678
1679 case Hexagon::S2_tableidxb_goodsyntax:
1680 Inst.setOpcode(Hexagon::S2_tableidxb);
1681 break;
1682
1683 case Hexagon::S2_tableidxh_goodsyntax: {
1684 MCInst TmpInst;
1685 MCOperand &Rx = Inst.getOperand(0);
1686 MCOperand &Rs = Inst.getOperand(2);
1687 MCOperand &Imm4 = Inst.getOperand(3);
1688 MCOperand &Imm6 = Inst.getOperand(4);
1691 MCConstantExpr::create(1, Context), Context),
1692 Context));
1693 TmpInst.setOpcode(Hexagon::S2_tableidxh);
1694 TmpInst.addOperand(Rx);
1695 TmpInst.addOperand(Rx);
1696 TmpInst.addOperand(Rs);
1697 TmpInst.addOperand(Imm4);
1698 TmpInst.addOperand(Imm6);
1699 Inst = TmpInst;
1700 break;
1701 }
1702
1703 case Hexagon::S2_tableidxw_goodsyntax: {
1704 MCInst TmpInst;
1705 MCOperand &Rx = Inst.getOperand(0);
1706 MCOperand &Rs = Inst.getOperand(2);
1707 MCOperand &Imm4 = Inst.getOperand(3);
1708 MCOperand &Imm6 = Inst.getOperand(4);
1711 MCConstantExpr::create(2, Context), Context),
1712 Context));
1713 TmpInst.setOpcode(Hexagon::S2_tableidxw);
1714 TmpInst.addOperand(Rx);
1715 TmpInst.addOperand(Rx);
1716 TmpInst.addOperand(Rs);
1717 TmpInst.addOperand(Imm4);
1718 TmpInst.addOperand(Imm6);
1719 Inst = TmpInst;
1720 break;
1721 }
1722
1723 case Hexagon::S2_tableidxd_goodsyntax: {
1724 MCInst TmpInst;
1725 MCOperand &Rx = Inst.getOperand(0);
1726 MCOperand &Rs = Inst.getOperand(2);
1727 MCOperand &Imm4 = Inst.getOperand(3);
1728 MCOperand &Imm6 = Inst.getOperand(4);
1731 MCConstantExpr::create(3, Context), Context),
1732 Context));
1733 TmpInst.setOpcode(Hexagon::S2_tableidxd);
1734 TmpInst.addOperand(Rx);
1735 TmpInst.addOperand(Rx);
1736 TmpInst.addOperand(Rs);
1737 TmpInst.addOperand(Imm4);
1738 TmpInst.addOperand(Imm6);
1739 Inst = TmpInst;
1740 break;
1741 }
1742
1743 case Hexagon::M2_mpyui:
1744 Inst.setOpcode(Hexagon::M2_mpyi);
1745 break;
1746 case Hexagon::M2_mpysmi: {
1747 MCInst TmpInst;
1748 MCOperand &Rd = Inst.getOperand(0);
1749 MCOperand &Rs = Inst.getOperand(1);
1750 MCOperand &Imm = Inst.getOperand(2);
1751 int64_t Value;
1752 MCExpr const &Expr = *Imm.getExpr();
1753 bool Absolute = Expr.evaluateAsAbsolute(Value);
1754 if (!Absolute)
1755 return Match_InvalidOperand;
1756 if (!HexagonMCInstrInfo::mustExtend(Expr) &&
1757 ((Value <= -256) || Value >= 256))
1758 return Match_InvalidOperand;
1759 if (Value < 0 && Value > -256) {
1760 Imm.setExpr(HexagonMCExpr::create(
1761 MCConstantExpr::create(Value * -1, Context), Context));
1762 TmpInst.setOpcode(Hexagon::M2_mpysin);
1763 } else
1764 TmpInst.setOpcode(Hexagon::M2_mpysip);
1765 TmpInst.addOperand(Rd);
1766 TmpInst.addOperand(Rs);
1767 TmpInst.addOperand(Imm);
1768 Inst = TmpInst;
1769 break;
1770 }
1771
1772 case Hexagon::S2_asr_i_r_rnd_goodsyntax: {
1773 MCOperand &Imm = Inst.getOperand(2);
1774 MCInst TmpInst;
1775 int64_t Value;
1776 bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Value);
1777 if (!Absolute)
1778 return Match_InvalidOperand;
1779 if (Value == 0) { // convert to $Rd = $Rs
1780 TmpInst.setOpcode(Hexagon::A2_tfr);
1781 MCOperand &Rd = Inst.getOperand(0);
1782 MCOperand &Rs = Inst.getOperand(1);
1783 TmpInst.addOperand(Rd);
1784 TmpInst.addOperand(Rs);
1785 } else {
1786 Imm.setExpr(HexagonMCExpr::create(
1787 MCBinaryExpr::createSub(Imm.getExpr(),
1788 MCConstantExpr::create(1, Context), Context),
1789 Context));
1790 TmpInst.setOpcode(Hexagon::S2_asr_i_r_rnd);
1791 MCOperand &Rd = Inst.getOperand(0);
1792 MCOperand &Rs = Inst.getOperand(1);
1793 TmpInst.addOperand(Rd);
1794 TmpInst.addOperand(Rs);
1795 TmpInst.addOperand(Imm);
1796 }
1797 Inst = TmpInst;
1798 break;
1799 }
1800
1801 case Hexagon::S2_asr_i_p_rnd_goodsyntax: {
1802 MCOperand &Rdd = Inst.getOperand(0);
1803 MCOperand &Rss = Inst.getOperand(1);
1804 MCOperand &Imm = Inst.getOperand(2);
1805 int64_t Value;
1806 bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Value);
1807 if (!Absolute)
1808 return Match_InvalidOperand;
1809 if (Value == 0) { // convert to $Rdd = combine ($Rs[0], $Rs[1])
1810 MCInst TmpInst;
1811 unsigned int RegPairNum = RI->getEncodingValue(Rss.getReg());
1812 std::string R1 = r + utostr(RegPairNum + 1);
1813 StringRef Reg1(R1);
1814 Rss.setReg(matchRegister(Reg1));
1815 // Add a new operand for the second register in the pair.
1816 std::string R2 = r + utostr(RegPairNum);
1817 StringRef Reg2(R2);
1818 TmpInst.setOpcode(Hexagon::A2_combinew);
1819 TmpInst.addOperand(Rdd);
1820 TmpInst.addOperand(Rss);
1821 TmpInst.addOperand(MCOperand::createReg(matchRegister(Reg2)));
1822 Inst = TmpInst;
1823 } else {
1824 Imm.setExpr(HexagonMCExpr::create(
1825 MCBinaryExpr::createSub(Imm.getExpr(),
1826 MCConstantExpr::create(1, Context), Context),
1827 Context));
1828 Inst.setOpcode(Hexagon::S2_asr_i_p_rnd);
1829 }
1830 break;
1831 }
1832
1833 case Hexagon::A4_boundscheck: {
1834 MCOperand &Rs = Inst.getOperand(1);
1835 unsigned int RegNum = RI->getEncodingValue(Rs.getReg());
1836 if (RegNum & 1) { // Odd mapped to raw:hi, regpair is rodd:odd-1, like r3:2
1837 Inst.setOpcode(Hexagon::A4_boundscheck_hi);
1838 std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
1839 StringRef RegPair = Name;
1840 Rs.setReg(matchRegister(RegPair));
1841 } else { // raw:lo
1842 Inst.setOpcode(Hexagon::A4_boundscheck_lo);
1843 std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
1844 StringRef RegPair = Name;
1845 Rs.setReg(matchRegister(RegPair));
1846 }
1847 break;
1848 }
1849
1850 case Hexagon::A2_addsp: {
1851 MCOperand &Rs = Inst.getOperand(1);
1852 unsigned int RegNum = RI->getEncodingValue(Rs.getReg());
1853 if (RegNum & 1) { // Odd mapped to raw:hi
1854 Inst.setOpcode(Hexagon::A2_addsph);
1855 std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
1856 StringRef RegPair = Name;
1857 Rs.setReg(matchRegister(RegPair));
1858 } else { // Even mapped raw:lo
1859 Inst.setOpcode(Hexagon::A2_addspl);
1860 std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
1861 StringRef RegPair = Name;
1862 Rs.setReg(matchRegister(RegPair));
1863 }
1864 break;
1865 }
1866
1867 case Hexagon::M2_vrcmpys_s1: {
1868 MCOperand &Rt = Inst.getOperand(2);
1869 unsigned int RegNum = RI->getEncodingValue(Rt.getReg());
1870 if (RegNum & 1) { // Odd mapped to sat:raw:hi
1871 Inst.setOpcode(Hexagon::M2_vrcmpys_s1_h);
1872 std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
1873 StringRef RegPair = Name;
1874 Rt.setReg(matchRegister(RegPair));
1875 } else { // Even mapped sat:raw:lo
1876 Inst.setOpcode(Hexagon::M2_vrcmpys_s1_l);
1877 std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
1878 StringRef RegPair = Name;
1879 Rt.setReg(matchRegister(RegPair));
1880 }
1881 break;
1882 }
1883
1884 case Hexagon::M2_vrcmpys_acc_s1: {
1885 MCInst TmpInst;
1886 MCOperand &Rxx = Inst.getOperand(0);
1887 MCOperand &Rss = Inst.getOperand(2);
1888 MCOperand &Rt = Inst.getOperand(3);
1889 unsigned int RegNum = RI->getEncodingValue(Rt.getReg());
1890 if (RegNum & 1) { // Odd mapped to sat:raw:hi
1891 TmpInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_h);
1892 std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
1893 StringRef RegPair = Name;
1894 Rt.setReg(matchRegister(RegPair));
1895 } else { // Even mapped sat:raw:lo
1896 TmpInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_l);
1897 std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
1898 StringRef RegPair = Name;
1899 Rt.setReg(matchRegister(RegPair));
1900 }
1901 // Registers are in different positions
1902 TmpInst.addOperand(Rxx);
1903 TmpInst.addOperand(Rxx);
1904 TmpInst.addOperand(Rss);
1905 TmpInst.addOperand(Rt);
1906 Inst = TmpInst;
1907 break;
1908 }
1909
1910 case Hexagon::M2_vrcmpys_s1rp: {
1911 MCOperand &Rt = Inst.getOperand(2);
1912 unsigned int RegNum = RI->getEncodingValue(Rt.getReg());
1913 if (RegNum & 1) { // Odd mapped to rnd:sat:raw:hi
1914 Inst.setOpcode(Hexagon::M2_vrcmpys_s1rp_h);
1915 std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
1916 StringRef RegPair = Name;
1917 Rt.setReg(matchRegister(RegPair));
1918 } else { // Even mapped rnd:sat:raw:lo
1919 Inst.setOpcode(Hexagon::M2_vrcmpys_s1rp_l);
1920 std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
1921 StringRef RegPair = Name;
1922 Rt.setReg(matchRegister(RegPair));
1923 }
1924 break;
1925 }
1926
1927 case Hexagon::S5_asrhub_rnd_sat_goodsyntax: {
1928 MCOperand &Imm = Inst.getOperand(2);
1929 int64_t Value;
1930 bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Value);
1931 if (!Absolute)
1932 return Match_InvalidOperand;
1933 if (Value == 0)
1934 Inst.setOpcode(Hexagon::S2_vsathub);
1935 else {
1936 Imm.setExpr(HexagonMCExpr::create(
1937 MCBinaryExpr::createSub(Imm.getExpr(),
1938 MCConstantExpr::create(1, Context), Context),
1939 Context));
1940 Inst.setOpcode(Hexagon::S5_asrhub_rnd_sat);
1941 }
1942 break;
1943 }
1944
1945 case Hexagon::S5_vasrhrnd_goodsyntax: {
1946 MCOperand &Rdd = Inst.getOperand(0);
1947 MCOperand &Rss = Inst.getOperand(1);
1948 MCOperand &Imm = Inst.getOperand(2);
1949 int64_t Value;
1950 bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Value);
1951 if (!Absolute)
1952 return Match_InvalidOperand;
1953 if (Value == 0) {
1954 MCInst TmpInst;
1955 unsigned int RegPairNum = RI->getEncodingValue(Rss.getReg());
1956 std::string R1 = r + utostr(RegPairNum + 1);
1957 StringRef Reg1(R1);
1958 Rss.setReg(matchRegister(Reg1));
1959 // Add a new operand for the second register in the pair.
1960 std::string R2 = r + utostr(RegPairNum);
1961 StringRef Reg2(R2);
1962 TmpInst.setOpcode(Hexagon::A2_combinew);
1963 TmpInst.addOperand(Rdd);
1964 TmpInst.addOperand(Rss);
1965 TmpInst.addOperand(MCOperand::createReg(matchRegister(Reg2)));
1966 Inst = TmpInst;
1967 } else {
1968 Imm.setExpr(HexagonMCExpr::create(
1969 MCBinaryExpr::createSub(Imm.getExpr(),
1970 MCConstantExpr::create(1, Context), Context),
1971 Context));
1972 Inst.setOpcode(Hexagon::S5_vasrhrnd);
1973 }
1974 break;
1975 }
1976
1977 case Hexagon::A2_not: {
1978 MCInst TmpInst;
1979 MCOperand &Rd = Inst.getOperand(0);
1980 MCOperand &Rs = Inst.getOperand(1);
1981 TmpInst.setOpcode(Hexagon::A2_subri);
1982 TmpInst.addOperand(Rd);
1984 HexagonMCExpr::create(MCConstantExpr::create(-1, Context), Context)));
1985 TmpInst.addOperand(Rs);
1986 Inst = TmpInst;
1987 break;
1988 }
1989 case Hexagon::PS_loadrubabs:
1991 Inst.setOpcode(Hexagon::L2_loadrubgp);
1992 break;
1993 case Hexagon::PS_loadrbabs:
1995 Inst.setOpcode(Hexagon::L2_loadrbgp);
1996 break;
1997 case Hexagon::PS_loadruhabs:
1999 Inst.setOpcode(Hexagon::L2_loadruhgp);
2000 break;
2001 case Hexagon::PS_loadrhabs:
2003 Inst.setOpcode(Hexagon::L2_loadrhgp);
2004 break;
2005 case Hexagon::PS_loadriabs:
2007 Inst.setOpcode(Hexagon::L2_loadrigp);
2008 break;
2009 case Hexagon::PS_loadrdabs:
2011 Inst.setOpcode(Hexagon::L2_loadrdgp);
2012 break;
2013 case Hexagon::PS_storerbabs:
2015 Inst.setOpcode(Hexagon::S2_storerbgp);
2016 break;
2017 case Hexagon::PS_storerhabs:
2019 Inst.setOpcode(Hexagon::S2_storerhgp);
2020 break;
2021 case Hexagon::PS_storerfabs:
2023 Inst.setOpcode(Hexagon::S2_storerfgp);
2024 break;
2025 case Hexagon::PS_storeriabs:
2027 Inst.setOpcode(Hexagon::S2_storerigp);
2028 break;
2029 case Hexagon::PS_storerdabs:
2031 Inst.setOpcode(Hexagon::S2_storerdgp);
2032 break;
2033 case Hexagon::PS_storerbnewabs:
2035 Inst.setOpcode(Hexagon::S2_storerbnewgp);
2036 break;
2037 case Hexagon::PS_storerhnewabs:
2039 Inst.setOpcode(Hexagon::S2_storerhnewgp);
2040 break;
2041 case Hexagon::PS_storerinewabs:
2043 Inst.setOpcode(Hexagon::S2_storerinewgp);
2044 break;
2045 case Hexagon::A2_zxtb: {
2046 Inst.setOpcode(Hexagon::A2_andir);
2047 Inst.addOperand(
2049 break;
2050 }
2051 } // switch
2052
2053 return Match_Success;
2054}
2055
2056unsigned HexagonAsmParser::matchRegister(StringRef Name) {
2057 if (unsigned Reg = MatchRegisterName(Name))
2058 return Reg;
2059 return MatchRegisterAltName(Name);
2060}
static MCRegister MatchRegisterName(StringRef Name)
#define Success
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static size_t byteSize(BTF::CommonType *Type)
Definition: BTFParser.cpp:154
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:135
#define LLVM_DEBUG(X)
Definition: Debug.h:101
std::string Name
uint64_t Size
bool End
Definition: ELF_riscv.cpp:480
Symbol * Sym
Definition: ELF_riscv.cpp:479
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
static bool isSigned(unsigned int Opcode)
#define Check(C,...)
#define check(cond)
static cl::opt< bool > WarnSignedMismatch("mwarn-sign-mismatch", cl::desc("Warn for mismatching a signed and unsigned value"), cl::init(false))
static cl::opt< bool > WarnNoncontigiousRegister("mwarn-noncontigious-register", cl::desc("Warn for register names that arent contigious"), cl::init(true))
static cl::opt< bool > ErrorMissingParenthesis("merror-missing-parenthesis", cl::desc("Error for missing parenthesis around predicate registers"), cl::init(false))
static cl::opt< bool > ErrorNoncontigiousRegister("merror-noncontigious-register", cl::desc("Error for register names that aren't contigious"), cl::init(false))
static bool previousEqual(OperandVector &Operands, size_t Index, StringRef String)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeHexagonAsmParser()
Force static initialization.
static MCInst makeCombineInst(int opCode, MCOperand &Rdd, MCOperand &MO1, MCOperand &MO2)
static bool previousIsLoop(OperandVector &Operands, size_t Index)
static cl::opt< bool > WarnMissingParenthesis("mwarn-missing-parenthesis", cl::desc("Warn for missing parenthesis around predicate registers"), cl::init(true))
static cl::opt< bool > AddBuildAttributes("hexagon-add-build-attributes")
static LVOptions Options
Definition: LVOptions.cpp:25
#define I(x, y, z)
Definition: MD5.cpp:58
mir Rename Register Operands
unsigned Reg
#define R2(n)
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
LLVMContext & Context
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isImm(const MachineOperand &MO, MachineRegisterInfo *MRI)
This file contains some templates that are useful if you are working with the STL at all.
raw_pwrite_stream & OS
This file defines the SmallVector class.
This file contains some functions that are useful when dealing with strings.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:469
Target independent representation for an assembler token.
Definition: MCAsmMacro.h:21
SMLoc getLoc() const
Definition: MCAsmLexer.cpp:26
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition: MCAsmMacro.h:110
bool is(TokenKind K) const
Definition: MCAsmMacro.h:82
TokenKind getKind() const
Definition: MCAsmMacro.h:81
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
Definition: MCAsmMacro.h:99
This class represents an Operation in the Expression.
Base class for user error types.
Definition: Error.h:352
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
Check for a valid bundle.
void HexagonMCEmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, Align ByteAlignment, unsigned AccessSize)
void HexagonMCEmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, Align ByteAlignment, unsigned AccessSize)
bool mustNotExtend() const
bool mustExtend() const
static HexagonMCExpr * create(MCExpr const *Expr, MCContext &Ctx)
Generic assembler lexer interface, for use by target specific assembly lexers.
Definition: MCAsmLexer.h:37
void UnLex(AsmToken const &Token)
Definition: MCAsmLexer.h:93
const AsmToken peekTok(bool ShouldSkipSpace=true)
Look ahead at the next token to be lexed.
Definition: MCAsmLexer.h:111
SMLoc getLoc() const
Get the current source location.
Definition: MCAsmLexer.cpp:22
const AsmToken & getTok() const
Get the current (last) lexed token.
Definition: MCAsmLexer.h:106
const AsmToken & Lex()
Consume the next token from the input stream and return it.
Definition: MCAsmLexer.h:79
bool is(AsmToken::TokenKind K) const
Check if the current token has kind K.
Definition: MCAsmLexer.h:141
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.
Definition: MCAsmParser.h:123
virtual bool printError(SMLoc L, const Twine &Msg, SMRange Range=std::nullopt)=0
Emit an error at the location L, with the message Msg.
virtual MCStreamer & getStreamer()=0
Return the output streamer for the assembler.
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression.
const AsmToken & getTok() const
Get the current AsmToken from the stream.
Definition: MCAsmParser.cpp:40
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
virtual MCAsmLexer & getLexer()=0
virtual bool Warning(SMLoc L, const Twine &Msg, SMRange Range=std::nullopt)=0
Emit a warning at the location L, with the message Msg.
virtual void addAliasForDirective(StringRef Directive, StringRef Alias)=0
virtual MCContext & getContext()=0
bool Error(SMLoc L, const Twine &Msg, SMRange Range=std::nullopt)
Return an error at the location L, with the message Msg.
static const MCBinaryExpr * createLShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:616
static const MCBinaryExpr * createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:541
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:621
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
Context object for machine code objects.
Definition: MCContext.h:81
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
bool evaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout, const SectionAddrMap &Addrs) const
Try to evaluate the expression to an absolute value.
Definition: MCExpr.cpp:556
@ Unary
Unary expressions.
Definition: MCExpr.h:41
@ SymbolRef
References to labels and assigned expressions.
Definition: MCExpr.h:40
@ Binary
Binary expressions.
Definition: MCExpr.h:38
bool evaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const
Try to evaluate the expression to a relocatable value, i.e.
Definition: MCExpr.cpp:814
ExprKind getKind() const
Definition: MCExpr.h:81
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
void dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer=nullptr, StringRef Separator=" ", const MCRegisterInfo *RegInfo=nullptr) const
Dump the MCInst as prettily as possible using the additional MC structures, if given.
Definition: MCInst.cpp:84
void setLoc(SMLoc loc)
Definition: MCInst.h:203
unsigned getOpcode() const
Definition: MCInst.h:198
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
void setOpcode(unsigned Op)
Definition: MCInst.h:197
void clear()
Definition: MCInst.h:215
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:206
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
MCAssembler & getAssembler()
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:134
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:162
void setReg(unsigned Reg)
Set the register number.
Definition: MCInst.h:75
void setExpr(const MCExpr *Val)
Definition: MCInst.h:119
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:141
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:69
const MCExpr * getExpr() const
Definition: MCInst.h:114
bool isExpr() const
Definition: MCInst.h:65
static MCOperand createInst(const MCInst *Val)
Definition: MCInst.h:169
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
virtual bool isToken() const =0
isToken - Is this a token operand?
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
uint16_t getEncodingValue(MCRegister RegNo) const
Returns the encoding for RegNo.
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
This represents a section on linux, lots of unix variants and some bare metal systems.
Definition: MCSectionELF.h:26
Streaming machine code generation interface.
Definition: MCStreamer.h:212
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
virtual bool hasRawTextSupport() const
Return true if this asm streamer supports emitting unformatted text to the .s file with EmitRawText.
Definition: MCStreamer.h:342
bool popSection()
Restore the current and previous section from the section stack.
Definition: MCStreamer.h:426
MCTargetStreamer * getTargetStreamer()
Definition: MCStreamer.h:306
void pushSection()
Save the current and previous section on the section stack.
Definition: MCStreamer.h:417
virtual void switchSection(MCSection *Section, const MCExpr *Subsection=nullptr)
Set the current section where code is being emitted to Section.
Generic base class for all target subtargets.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:397
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:40
MCTargetAsmParser - Generic interface to target specific assembly parsers.
virtual bool equalIsAsmAssignment()
virtual bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
virtual bool ParseDirective(AsmToken DirectiveID)
ParseDirective - Parse a target specific assembler directive This method is deprecated,...
virtual ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
tryParseRegister - parse one register if possible
virtual bool isLabel(AsmToken &Token)
void setAvailableFeatures(const FeatureBitset &Value)
const MCSubtargetInfo & getSTI() const
virtual unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, unsigned Kind)
Allow a target to add special case operand matching for things that tblgen doesn't/can't handle effec...
virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands)=0
ParseInstruction - Parse one assembly instruction.
virtual bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm)=0
MatchAndEmitInstruction - Recognize a series of operands of a parsed instruction as an actual MCInst ...
Target specific streamer interface.
Definition: MCStreamer.h:93
MCStreamer & getStreamer()
Definition: MCStreamer.h:101
This represents an "assembler immediate".
Definition: MCValue.h:36
Ternary parse status returned by various parse* methods.
static constexpr StatusTy Success
static constexpr StatusTy NoMatch
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
Instances of this class encapsulate one diagnostic report, allowing printing to a raw_ostream as a ca...
Definition: SourceMgr.h:281
void print(const char *ProgName, raw_ostream &S, bool ShowColors=true, bool ShowKindLabel=true, bool ShowLocation=true) const
Definition: SourceMgr.cpp:484
Represents a location in source code.
Definition: SMLoc.h:23
bool empty() const
Definition: SmallVector.h:94
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:950
iterator insert(iterator I, T &&Elt)
Definition: SmallVector.h:818
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:693
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:223
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:564
std::string upper() const
Convert the given ASCII string to uppercase.
Definition: StringRef.cpp:116
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:131
std::string lower() const
Definition: StringRef.cpp:111
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Definition: StringRef.h:609
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
Definition: StringRef.h:171
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVM Value Representation.
Definition: Value.h:74
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:660
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::optional< unsigned > attrTypeFromString(StringRef tag, TagNameMap tagNameMap)
@ SHF_ALLOC
Definition: ELF.h:1159
@ SHF_WRITE
Definition: ELF.h:1156
@ SHT_PROGBITS
Definition: ELF.h:1065
const TagNameMap & getHexagonAttributeTags()
bool isOuterLoop(MCInst const &MCI)
size_t bundleSize(MCInst const &MCI)
void setS27_2_reloc(MCExpr const &Expr, bool Val=true)
std::pair< unsigned, unsigned > GetVecRegPairIndices(unsigned VecRegPair)
Returns an ordered pair of the constituent register ordinals for each of the elements of VecRegPair.
MCInstrDesc const & getDesc(MCInstrInfo const &MCII, MCInst const &MCI)
void setMemReorderDisabled(MCInst &MCI)
bool isBundle(MCInst const &MCI)
MCExpr const & getExpr(MCExpr const &Expr)
bool isInnerLoop(MCInst const &MCI)
bool canonicalizePacket(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCContext &Context, MCInst &MCB, HexagonMCChecker *Checker, bool AttemptCompatibility=false)
void setMustNotExtend(MCExpr const &Expr, bool Val=true)
void extendIfNeeded(MCContext &Context, MCInstrInfo const &MCII, MCInst &MCB, MCInst const &MCI)
bool mustExtend(MCExpr const &Expr)
void setMustExtend(MCExpr const &Expr, bool Val=true)
@ ByteAlignment
Definition: MCAsmInfo.h:50
@ CE
Windows NT (Windows on ARM)
bool isPseudo(uint64_t TSFlags)
Definition: X86BaseInfo.h:898
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:450
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Length
Definition: DWP.cpp:456
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition: STLExtras.h:1680
bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:239
static bool isMem(const MachineInstr &MI, unsigned Op)
Definition: X86InstrInfo.h:161
@ Done
Definition: Threading.h:61
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition: MathExtras.h:280
Target & getTheHexagonTarget()
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition: MathExtras.h:138
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:156
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition: MathExtras.h:143
FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)
format_hex - Output N as a fixed width hexadecimal.
Definition: Format.h:187
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:244
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition: STLExtras.h:2051
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition: MathExtras.h:465
@ MCSA_Local
.local (ELF)
Definition: MCDirectives.h:38
@ MCSA_Global
.type _foo, @gnu_unique_object
Definition: MCDirectives.h:30
auto mask(ShuffFunc S, unsigned Length, OptArgs... args) -> MaskT
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...