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