59#define DEBUG_TYPE "mcasmparser"
64 "mwarn-missing-parenthesis",
65 cl::desc(
"Warn for missing parenthesis around predicate registers"),
68 "merror-missing-parenthesis",
69 cl::desc(
"Error for missing parenthesis around predicate registers"),
72 "mwarn-sign-mismatch",
73 cl::desc(
"Warn for mismatching a signed and unsigned value"),
76 "mwarn-noncontigious-register",
79 "merror-noncontigious-register",
80 cl::desc(
"Error for register names that aren't contigious"),
116 bool ParseDirectiveFalign(
unsigned Size,
SMLoc L);
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;
126 bool matchBundleOptions();
127 bool handleNoncontigiousRegister(
bool Contigious,
SMLoc &Loc);
129 void canonicalizeImmediates(
MCInst &MCI);
132 bool MatchingInlineAsm);
133 void eatToEndOfPacket();
137 bool MatchingInlineAsm)
override;
140 unsigned Kind)
override;
141 bool OutOfRange(
SMLoc IDLoc,
long long Val,
long long Max);
150#define GET_ASSEMBLER_HEADER
151#include "HexagonGenAsmMatcher.inc"
175 bool parseExpression(
MCExpr const *&Expr);
194 SMLoc StartLoc, EndLoc;
218 HexagonOperand(
const HexagonOperand &o)
221 StartLoc =
o.StartLoc;
237 SMLoc getStartLoc()
const override {
return StartLoc; }
240 SMLoc getEndLoc()
const override {
return EndLoc; }
242 unsigned getReg()
const override {
247 const MCExpr *getImm()
const {
248 assert(Kind == Immediate &&
"Invalid access!");
252 bool isToken()
const override {
return Kind == Token; }
253 bool isImm()
const override {
return Kind == Immediate; }
257 bool CheckImmRange(
int immBits,
int zeroBits,
bool isSigned,
258 bool isRelocatable,
bool Extendable)
const {
259 if (Kind == Immediate) {
264 if (myMCExpr->evaluateAsAbsolute(Res)) {
265 int bits = immBits + zeroBits;
268 if (Res & ((1 << zeroBits) - 1))
271 if (Res < (1LL << (bits - 1)) && Res >= -(1LL << (bits - 1)))
279 const int64_t high_bit_set = 1ULL << 63;
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); }
298 bool ism32_0Imm()
const {
return true; }
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); }
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); }
350 bool isn1Const()
const {
354 if (!getImm()->evaluateAsAbsolute(
Value))
358 bool issgp10Const()
const {
361 return getReg() == Hexagon::SGP1_0;
363 bool iss11_0Imm()
const {
364 return CheckImmRange(11 + 26, 0,
true,
true,
true);
366 bool iss11_1Imm()
const {
367 return CheckImmRange(11 + 26, 1,
true,
true,
true);
369 bool iss11_2Imm()
const {
370 return CheckImmRange(11 + 26, 2,
true,
true,
true);
372 bool iss11_3Imm()
const {
373 return CheckImmRange(11 + 26, 3,
true,
true,
true);
375 bool isu32_0MustExt()
const {
return isImm(); }
377 void addRegOperands(
MCInst &Inst,
unsigned N)
const {
378 assert(
N == 1 &&
"Invalid number of operands!");
382 void addImmOperands(
MCInst &Inst,
unsigned N)
const {
383 assert(
N == 1 &&
"Invalid number of operands!");
387 void addSignedImmOperands(
MCInst &Inst,
unsigned N)
const {
388 assert(
N == 1 &&
"Invalid number of operands!");
399 if ((Extended < 0) != (
Value < 0))
406 void addn1ConstOperands(
MCInst &Inst,
unsigned N)
const {
407 addImmOperands(Inst,
N);
409 void addsgp10ConstOperands(
MCInst &Inst,
unsigned N)
const {
410 addRegOperands(Inst,
N);
414 assert(Kind == Token &&
"Invalid access!");
420 static std::unique_ptr<HexagonOperand> CreateToken(
MCContext &Context,
422 HexagonOperand *
Op =
new HexagonOperand(Token, Context);
423 Op->Tok.Data = Str.data();
424 Op->Tok.Length = Str.size();
427 return std::unique_ptr<HexagonOperand>(Op);
430 static std::unique_ptr<HexagonOperand>
432 HexagonOperand *
Op =
new HexagonOperand(
Register, Context);
433 Op->Reg.RegNum = RegNum;
436 return std::unique_ptr<HexagonOperand>(Op);
439 static std::unique_ptr<HexagonOperand>
441 HexagonOperand *
Op =
new HexagonOperand(Immediate, Context);
445 return std::unique_ptr<HexagonOperand>(Op);
454 getImm()->print(
OS,
nullptr);
461 OS <<
"'" << getToken() <<
"'";
481 MII, STI, getContext(), MCB, &
Check,
true);
500bool HexagonAsmParser::matchBundleOptions() {
506 char const *MemNoShuffMsg =
507 "invalid instruction packet: mem_noshuf specifier not "
508 "supported with this architecture";
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().hasFeature(Hexagon::FeatureMemNoShuf))
522 return getParser().Error(IDLoc, MemNoShuffMsg);
523 }
else if (
Option.compare_insensitive(
"mem_no_order") == 0) {
526 return getParser().Error(IDLoc,
llvm::Twine(
"'") + Option +
527 "' is not a valid bundle option");
535void HexagonAsmParser::canonicalizeImmediates(
MCInst &MCI) {
540 int64_t
Value(
I.getImm());
544 if (
I.isExpr() && cast<HexagonMCExpr>(
I.getExpr())->signMismatch() &&
546 Warning(MCI.getLoc(),
"Signed/Unsigned mismatch");
552bool HexagonAsmParser::matchOneInstruction(
MCInst &MCI,
SMLoc IDLoc,
555 bool MatchingInlineAsm) {
558 MatchInstructionImpl(InstOperands, MCI,
ErrorInfo, MatchingInlineAsm);
559 if (result == Match_Success) {
561 canonicalizeImmediates(MCI);
562 result = processInstruction(MCI, InstOperands, IDLoc);
580 case Match_MissingFeature:
581 return Error(IDLoc,
"invalid instruction");
582 case Match_MnemonicFail:
583 return Error(IDLoc,
"unrecognized instruction");
584 case Match_InvalidOperand:
586 case Match_InvalidTiedOperand:
587 SMLoc ErrorLoc = IDLoc;
590 return Error(IDLoc,
"too few operands for instruction");
592 ErrorLoc = (
static_cast<HexagonOperand *
>(InstOperands[
ErrorInfo].get()))
594 if (ErrorLoc ==
SMLoc())
597 return Error(ErrorLoc,
"invalid operand for instruction");
602void HexagonAsmParser::eatToEndOfPacket() {
611bool HexagonAsmParser::MatchAndEmitInstruction(
SMLoc IDLoc,
unsigned &Opcode,
615 bool MatchingInlineAsm) {
620 HexagonOperand &FirstOperand =
static_cast<HexagonOperand &
>(*
Operands[0]);
621 if (FirstOperand.isToken() && FirstOperand.getToken() ==
"{") {
622 assert(
Operands.size() == 1 &&
"Brackets should be by themselves");
624 getParser().Error(IDLoc,
"Already in a packet");
631 if (FirstOperand.isToken() && FirstOperand.getToken() ==
"}") {
632 assert(
Operands.size() == 1 &&
"Brackets should be by themselves");
634 getParser().Error(IDLoc,
"Not in a packet");
638 if (matchBundleOptions())
640 return finishBundle(IDLoc, Out);
642 MCInst *SubInst = getParser().getContext().createMCInst();
644 MatchingInlineAsm)) {
650 getParser().getContext(), MII, MCB, *SubInst);
653 return finishBundle(IDLoc, Out);
658bool HexagonAsmParser::ParseDirective(
AsmToken DirectiveID) {
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());
671bool HexagonAsmParser::ParseDirectiveSubsection(
SMLoc L) {
672 const MCExpr *Subsection =
nullptr;
676 "Invalid subsection directive");
677 getParser().parseExpression(Subsection);
679 if (!Subsection->evaluateAsAbsolute(Res))
680 return Error(L,
"Cannot evaluate subsection number");
683 return TokError(
"unexpected token in directive");
689 if ((Res < 0) && (Res > -8193))
693 getStreamer().subSection(Subsection);
698bool HexagonAsmParser::ParseDirectiveFalign(
unsigned Size,
SMLoc L) {
700 int64_t MaxBytesToFill = 15;
708 if (!getParser().parseExpression(
Value)) {
710 auto *MCE = cast<MCConstantExpr>(
Value);
711 uint64_t IntValue = MCE->getValue();
713 return Error(ExprLoc,
"literal value out of range (256) for falign");
714 MaxBytesToFill = IntValue;
717 return Error(ExprLoc,
"not a valid expression for falign directive");
721 getTargetStreamer().emitFAlign(16, MaxBytesToFill);
733bool HexagonAsmParser::ParseDirectiveComm(
bool IsLocal,
SMLoc Loc) {
736 if (getStreamer().hasRawTextSupport())
740 if (getParser().parseIdentifier(
Name))
741 return TokError(
"expected identifier in directive");
746 return TokError(
"unexpected token in directive");
750 SMLoc SizeLoc = getLexer().getLoc();
751 if (getParser().parseAbsoluteExpression(
Size))
755 SMLoc ByteAlignmentLoc;
758 ByteAlignmentLoc = getLexer().getLoc();
759 if (getParser().parseAbsoluteExpression(ByteAlignment))
762 return Error(ByteAlignmentLoc,
"alignment must be a power of 2");
765 int64_t AccessAlignment = 0;
769 SMLoc AccessAlignmentLoc;
771 AccessAlignmentLoc = getLexer().getLoc();
772 if (getParser().parseAbsoluteExpression(AccessAlignment))
776 return Error(AccessAlignmentLoc,
"access alignment must be a power of 2");
780 return TokError(
"unexpected token in '.comm' or '.lcomm' directive");
787 return Error(SizeLoc,
"invalid '.comm' or '.lcomm' directive size, can't "
788 "be less than zero");
793 if (ByteAlignment < 0)
794 return Error(ByteAlignmentLoc,
"invalid '.comm' or '.lcomm' directive "
795 "alignment, can't be less than zero");
797 if (!
Sym->isUndefined())
798 return Error(Loc,
"invalid symbol redefinition");
814bool HexagonAsmParser::RegisterMatchesArch(
unsigned MatchNum)
const {
815 if (HexagonMCRegisterClasses[Hexagon::V62RegsRegClassID].
contains(MatchNum))
816 if (!getSTI().hasFeature(Hexagon::ArchV62))
828#define GET_MATCHER_IMPLEMENTATION
829#define GET_REGISTER_MATCHER
830#include "HexagonGenAsmMatcher.inc"
839 return static_cast<HexagonOperand &
>(Operand).getToken().equals_insensitive(
852 AsmToken const &Token = getParser().getTok();
857 std::pair<StringRef, StringRef> HeadTail =
String.split(
'.');
858 if (!HeadTail.first.empty())
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));
865 }
while (!
String.empty());
885 Warning(Begin,
"Missing parenthesis around predicate register");
886 static char const *LParen =
"(";
887 static char const *RParen =
")";
889 HexagonOperand::CreateToken(getContext(), LParen, Begin));
891 HexagonOperand::CreateReg(getContext(),
Register, Begin,
End));
893 if (MaybeDotNew.
is(AsmToken::TokenKind::Identifier) &&
897 HexagonOperand::CreateToken(getContext(), RParen, Begin));
903 Warning(Begin,
"Missing parenthesis around predicate register");
904 static char const *LParen =
"(";
905 static char const *RParen =
")";
907 getContext(), LParen, Begin));
909 HexagonOperand::CreateReg(getContext(),
Register, Begin,
End));
911 if (MaybeDotNew.
is(AsmToken::TokenKind::Identifier) &&
915 HexagonOperand::CreateToken(getContext(), RParen, Begin));
921 HexagonOperand::CreateReg(getContext(),
Register, Begin,
End));
927bool HexagonAsmParser::isLabel(
AsmToken &Token) {
932 if (Token.
is(AsmToken::TokenKind::LCurly) ||
933 Token.
is(AsmToken::TokenKind::RCurly))
939 if (!Token.
is(AsmToken::TokenKind::Identifier))
941 if (!matchRegister(
String.lower()))
946 std::string Collapsed = std::string(Raw);
949 std::pair<StringRef, StringRef> DotSplit = Whole.
split(
'.');
950 if (!matchRegister(DotSplit.first.lower()))
955bool HexagonAsmParser::handleNoncontigiousRegister(
bool Contigious,
958 Error(Loc,
"Register name is not contigious");
962 Warning(Loc,
"Register name is not contigious");
966bool HexagonAsmParser::parseRegister(
MCRegister &RegNo,
SMLoc &StartLoc,
975 StartLoc = getLexer().getLoc();
979 bool NeededWorkaround =
false;
988 Lookahead.
back().getString().data() +
989 Lookahead.
back().getString().size();
995 Again = (Contigious &&
Type) || (Workaround &&
Type);
996 NeededWorkaround = NeededWorkaround || (Again && !(Contigious &&
Type));
998 std::string Collapsed = std::string(RawString);
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()) {
1007 if (handleNoncontigiousRegister(!NeededWorkaround, StartLoc))
1012 size_t First = RawString.find(
'.');
1013 StringRef DotString (RawString.data() + First, RawString.size() - First);
1016 if (handleNoncontigiousRegister(!NeededWorkaround, StartLoc))
1021 std::pair<StringRef, StringRef> ColonSplit =
StringRef(FullString).
split(
':');
1022 unsigned ColonReg = matchRegister(ColonSplit.first.lower());
1023 if (ColonReg != Hexagon::NoRegister && RegisterMatchesArch(DotReg)) {
1029 if (handleNoncontigiousRegister(!NeededWorkaround, StartLoc))
1033 while (!Lookahead.
empty()) {
1053bool HexagonAsmParser::parseExpression(
MCExpr const *&Expr) {
1057 static char const *
Comma =
",";
1061 switch (Tokens.
back().getKind()) {
1062 case AsmToken::TokenKind::Hash:
1063 if (Tokens.
size() > 1)
1064 if ((Tokens.
end() - 2)->getKind() == AsmToken::TokenKind::Plus) {
1066 AsmToken(AsmToken::TokenKind::Comma, Comma));
1070 case AsmToken::TokenKind::RCurly:
1071 case AsmToken::TokenKind::EndOfStatement:
1072 case AsmToken::TokenKind::Eof:
1079 while (!Tokens.
empty()) {
1084 return getParser().parseExpression(Expr, Loc);
1088 if (implicitExpressionLocation(
Operands)) {
1091 MCExpr const *Expr =
nullptr;
1092 bool Error = parseExpression(Expr);
1096 HexagonOperand::CreateImm(getContext(), Expr, Loc, Loc));
1117 Operands.push_back(HexagonOperand::CreateToken(
1124 Operands.push_back(HexagonOperand::CreateToken(
1140 Operands.push_back(HexagonOperand::CreateToken(
1142 Operands.push_back(HexagonOperand::CreateToken(
1148 bool MustNotExtend =
false;
1149 bool ImplicitExpression = implicitExpressionLocation(
Operands);
1151 if (!ImplicitExpression)
1152 Operands.push_back(HexagonOperand::CreateToken(
1155 bool MustExtend =
false;
1156 bool HiOnly =
false;
1157 bool LoOnly =
false;
1161 }
else if (ImplicitExpression)
1162 MustNotExtend =
true;
1166 if (
String.lower() ==
"hi") {
1168 }
else if (
String.lower() ==
"lo") {
1171 if (HiOnly || LoOnly) {
1181 MCExpr const *Expr =
nullptr;
1182 if (parseExpression(Expr))
1187 if (Expr->evaluateAsAbsolute(
Value)) {
1191 if (HiOnly || LoOnly)
1197 if (!
Value.isAbsolute()) {
1198 switch (
Value.getAccessVariant()) {
1199 case MCSymbolRefExpr::VariantKind::VK_TPREL:
1200 case MCSymbolRefExpr::VariantKind::VK_DTPREL:
1202 MustNotExtend = !MustExtend;
1213 std::unique_ptr<HexagonOperand> Operand =
1214 HexagonOperand::CreateImm(getContext(), Expr, ExprLoc, ExprLoc);
1215 Operands.push_back(std::move(Operand));
1221 if (parseExpressionOrOperand(
Operands))
1229 getLexer().UnLex(
ID);
1248 HexagonOperand *
Op =
static_cast<HexagonOperand *
>(&AsmOp);
1253 return Op->isImm() &&
Op->Imm.Val->evaluateAsAbsolute(
Value) &&
Value == 0
1255 : Match_InvalidOperand;
1259 return Op->isImm() &&
Op->Imm.Val->evaluateAsAbsolute(
Value) &&
Value == 1
1261 : Match_InvalidOperand;
1264 if (
Op->Kind == HexagonOperand::Token && Kind != InvalidMatchClass) {
1266 if (matchTokenString(myStringRef.
lower()) == (MatchClassKind)Kind)
1267 return Match_Success;
1268 if (matchTokenString(myStringRef.
upper()) == (MatchClassKind)Kind)
1269 return Match_Success;
1276 return Match_InvalidOperand;
1280bool HexagonAsmParser::OutOfRange(
SMLoc IDLoc,
long long Val,
long long Max) {
1283 ES <<
"value " << Val <<
"(" <<
format_hex(Val, 0) <<
") out of range: ";
1287 ES <<
Max <<
"-" << (-
Max - 1);
1291int HexagonAsmParser::processInstruction(
MCInst &Inst,
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);
1304 return std::make_pair(matchRegister(R1), matchRegister(
R2));
1306 auto GetScalarRegs = [RI, GetRegPair](
unsigned RegPair) {
1308 const RegPairVals RegPair_ = std::make_pair(
Lower + 1,
Lower);
1310 return GetRegPair(RegPair_);
1312 auto GetVecRegs = [GetRegPair](
unsigned VecRegPair) {
1313 const RegPairVals RegPair =
1316 return GetRegPair(RegPair);
1319 bool is32bit =
false;
1325 "Found pseudo instruction with no expansion");
1331 case Hexagon::J2_trap1:
1332 if (!getSTI().hasFeature(Hexagon::ArchV65)) {
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;
1342 case Hexagon::A2_iconst: {
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: {
1367 return Match_InvalidOperand;
1371 case Hexagon::C2_cmpgei: {
1381 case Hexagon::C2_cmpgeui: {
1407 case Hexagon::A2_tfrp: {
1409 const std::pair<unsigned, unsigned> RegPair = GetScalarRegs(MO.
getReg());
1410 MO.
setReg(RegPair.first);
1416 case Hexagon::A2_tfrpt:
1417 case Hexagon::A2_tfrpf: {
1419 const std::pair<unsigned, unsigned> RegPair = GetScalarRegs(MO.
getReg());
1420 MO.
setReg(RegPair.first);
1423 ? Hexagon::C2_ccombinewt
1424 : Hexagon::C2_ccombinewf);
1427 case Hexagon::A2_tfrptnew:
1428 case Hexagon::A2_tfrpfnew: {
1430 const std::pair<unsigned, unsigned> RegPair = GetScalarRegs(MO.
getReg());
1431 MO.
setReg(RegPair.first);
1434 ? Hexagon::C2_ccombinewnewt
1435 : Hexagon::C2_ccombinewnewf);
1440 case Hexagon::V6_vassignp: {
1442 const std::pair<unsigned, unsigned> RegPair = GetVecRegs(MO.
getReg());
1443 MO.
setReg(RegPair.first);
1450 case Hexagon::CONST32:
1454 case Hexagon::CONST64:
1464 std::string myCharStr;
1474 std::string myImmStr = utohexstr(
static_cast<uint32_t>(
Value));
1475 myCharStr =
StringRef(
".gnu.linkonce.l4.CONST_00000000")
1480 std::string myImmStr = utohexstr(
Value);
1481 myCharStr =
StringRef(
".gnu.linkonce.l8.CONST_0000000000000000")
1489 }
else if (MO_1.
isExpr()) {
1491 myCharStr =
".lita";
1498 unsigned byteSize = is32bit ? 4 : 8;
1499 getStreamer().emitCodeAlignment(
Align(byteSize), &getSTI(), byteSize);
1507 Sym = getContext().getOrCreateSymbol(
StringRef(myCharStr.c_str() + 16));
1508 if (
Sym->isUndefined()) {
1509 getStreamer().emitLabel(
Sym);
1511 getStreamer().emitIntValue(
Value, byteSize);
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();
1520 StringStart =
Operands[4]->getStartLoc().getPointer();
1521 StringEnd =
Operands[5]->getStartLoc().getPointer();
1524 unsigned size = StringEnd - StringStart;
1525 std::string DotConst =
".CONST_";
1526 Sym = getContext().getOrCreateSymbol(DotConst +
1529 if (
Sym->isUndefined()) {
1531 getStreamer().emitLabel(
Sym);
1533 getStreamer().emitValue(MO_1.
getExpr(), 4);
1543 TmpInst.
setOpcode(Hexagon::L2_loadrigp);
1545 TmpInst.
setOpcode(Hexagon::L2_loadrdgp);
1556 case Hexagon::A2_tfrpi: {
1568 case Hexagon::TFRI64_V4: {
1575 OutOfRange(IDLoc, s8, -128);
1593 case Hexagon::TFRI64_V2_ext: {
1600 if (s8 < -128 || s8 > 127)
1601 OutOfRange(IDLoc, s8, -128);
1608 case Hexagon::A4_combineii: {
1614 if (s8 < -128 || s8 > 127)
1615 OutOfRange(IDLoc, s8, -128);
1622 case Hexagon::S2_tableidxb_goodsyntax:
1626 case Hexagon::S2_tableidxh_goodsyntax: {
1636 TmpInst.
setOpcode(Hexagon::S2_tableidxh);
1646 case Hexagon::S2_tableidxw_goodsyntax: {
1656 TmpInst.
setOpcode(Hexagon::S2_tableidxw);
1666 case Hexagon::S2_tableidxd_goodsyntax: {
1676 TmpInst.
setOpcode(Hexagon::S2_tableidxd);
1686 case Hexagon::M2_mpyui:
1689 case Hexagon::M2_mpysmi: {
1698 return Match_InvalidOperand;
1701 return Match_InvalidOperand;
1702 if (Value < 0 && Value > -256) {
1715 case Hexagon::S2_asr_i_r_rnd_goodsyntax: {
1721 return Match_InvalidOperand;
1733 TmpInst.
setOpcode(Hexagon::S2_asr_i_r_rnd);
1744 case Hexagon::S2_asr_i_p_rnd_goodsyntax: {
1751 return Match_InvalidOperand;
1755 std::string R1 = r + utostr(RegPairNum + 1);
1757 Rss.
setReg(matchRegister(Reg1));
1759 std::string
R2 = r + utostr(RegPairNum);
1761 TmpInst.
setOpcode(Hexagon::A2_combinew);
1771 Inst.
setOpcode(Hexagon::S2_asr_i_p_rnd);
1776 case Hexagon::A4_boundscheck: {
1780 Inst.
setOpcode(Hexagon::A4_boundscheck_hi);
1781 std::string
Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
1783 Rs.
setReg(matchRegister(RegPair));
1785 Inst.
setOpcode(Hexagon::A4_boundscheck_lo);
1786 std::string
Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
1788 Rs.
setReg(matchRegister(RegPair));
1793 case Hexagon::A2_addsp: {
1798 std::string
Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
1800 Rs.
setReg(matchRegister(RegPair));
1803 std::string
Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
1805 Rs.
setReg(matchRegister(RegPair));
1810 case Hexagon::M2_vrcmpys_s1: {
1814 Inst.
setOpcode(Hexagon::M2_vrcmpys_s1_h);
1815 std::string
Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
1817 Rt.
setReg(matchRegister(RegPair));
1819 Inst.
setOpcode(Hexagon::M2_vrcmpys_s1_l);
1820 std::string
Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
1822 Rt.
setReg(matchRegister(RegPair));
1827 case Hexagon::M2_vrcmpys_acc_s1: {
1834 TmpInst.
setOpcode(Hexagon::M2_vrcmpys_acc_s1_h);
1835 std::string
Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
1837 Rt.
setReg(matchRegister(RegPair));
1839 TmpInst.
setOpcode(Hexagon::M2_vrcmpys_acc_s1_l);
1840 std::string
Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
1842 Rt.
setReg(matchRegister(RegPair));
1853 case Hexagon::M2_vrcmpys_s1rp: {
1857 Inst.
setOpcode(Hexagon::M2_vrcmpys_s1rp_h);
1858 std::string
Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
1860 Rt.
setReg(matchRegister(RegPair));
1862 Inst.
setOpcode(Hexagon::M2_vrcmpys_s1rp_l);
1863 std::string
Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
1865 Rt.
setReg(matchRegister(RegPair));
1870 case Hexagon::S5_asrhub_rnd_sat_goodsyntax: {
1875 return Match_InvalidOperand;
1883 Inst.
setOpcode(Hexagon::S5_asrhub_rnd_sat);
1888 case Hexagon::S5_vasrhrnd_goodsyntax: {
1895 return Match_InvalidOperand;
1899 std::string R1 = r + utostr(RegPairNum + 1);
1901 Rss.
setReg(matchRegister(Reg1));
1903 std::string
R2 = r + utostr(RegPairNum);
1905 TmpInst.
setOpcode(Hexagon::A2_combinew);
1920 case Hexagon::A2_not: {
1932 case Hexagon::PS_loadrubabs:
1936 case Hexagon::PS_loadrbabs:
1940 case Hexagon::PS_loadruhabs:
1944 case Hexagon::PS_loadrhabs:
1948 case Hexagon::PS_loadriabs:
1952 case Hexagon::PS_loadrdabs:
1956 case Hexagon::PS_storerbabs:
1960 case Hexagon::PS_storerhabs:
1964 case Hexagon::PS_storerfabs:
1968 case Hexagon::PS_storeriabs:
1972 case Hexagon::PS_storerdabs:
1976 case Hexagon::PS_storerbnewabs:
1978 Inst.
setOpcode(Hexagon::S2_storerbnewgp);
1980 case Hexagon::PS_storerhnewabs:
1982 Inst.
setOpcode(Hexagon::S2_storerhnewgp);
1984 case Hexagon::PS_storerinewabs:
1986 Inst.
setOpcode(Hexagon::S2_storerinewgp);
1988 case Hexagon::A2_zxtb: {
1996 return Match_Success;
static unsigned MatchRegisterName(StringRef Name)
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
#define LLVM_EXTERNAL_VISIBILITY
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(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))
mir Rename Register Operands
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isImm(const MachineOperand &MO, MachineRegisterInfo *MRI)
This file defines the SmallVector class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Target independent representation for an assembler token.
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
bool is(TokenKind K) const
TokenKind getKind() const
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
Base class for user error types.
Lightweight error class with error context and mandatory checking.
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
static HexagonMCExpr * create(MCExpr const *Expr, MCContext &Ctx)
Generic assembler lexer interface, for use by target specific assembly lexers.
void UnLex(AsmToken const &Token)
const AsmToken peekTok(bool ShouldSkipSpace=true)
Look ahead at the next token to be lexed.
SMLoc getLoc() const
Get the current source location.
const AsmToken & getTok() const
Get the current (last) lexed token.
const AsmToken & Lex()
Consume the next token from the input stream and return it.
bool is(AsmToken::TokenKind K) const
Check if the current token has kind K.
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
MCAsmParser & getParser()
Generic assembler parser interface, for use by target specific assembly parsers.
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.
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)
static const MCBinaryExpr * createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
Base class for the full range of assembler expressions which are needed for parsing.
bool evaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout, const SectionAddrMap &Addrs) const
Try to evaluate the expression to an absolute value.
@ Unary
Unary expressions.
@ SymbolRef
References to labels and assigned expressions.
@ Binary
Binary expressions.
bool evaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const
Try to evaluate the expression to a relocatable value, i.e.
Instances of this class represent a single low-level machine instruction.
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.
unsigned getOpcode() const
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
const MCOperand & getOperand(unsigned i) const
Interface to description of machine instruction set.
MCAssembler & getAssembler()
Instances of this class represent operands of the MCInst class.
static MCOperand createReg(unsigned Reg)
static MCOperand createExpr(const MCExpr *Val)
void setReg(unsigned Reg)
Set the register number.
void setExpr(const MCExpr *Val)
static MCOperand createImm(int64_t Val)
unsigned getReg() const
Returns the register number.
const MCExpr * getExpr() const
static MCOperand createInst(const MCInst *Val)
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.
This represents a section on linux, lots of unix variants and some bare metal systems.
Streaming machine code generation interface.
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.
bool popSection()
Restore the current and previous section from the section stack.
MCTargetStreamer * getTargetStreamer()
void pushSection()
Save the current and previous section on the section stack.
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)
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
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.
MCStreamer & getStreamer()
This represents an "assembler immediate".
Wrapper class representing virtual and physical registers.
Instances of this class encapsulate one diagnostic report, allowing printing to a raw_ostream as a ca...
void print(const char *ProgName, raw_ostream &S, bool ShowColors=true, bool ShowKindLabel=true) const
Represents a location in source code.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
std::string str() const
str - Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
std::string upper() const
Convert the given ASCII string to uppercase.
constexpr size_t size() const
size - Get the string size.
std::string lower() const
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void setOuterLoop(MCInst &MCI)
bool isOuterLoop(MCInst const &MCI)
size_t bundleSize(MCInst const &MCI)
void setS27_2_reloc(MCExpr const &Expr, bool Val=true)
void setInnerLoop(MCInst &MCI)
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)
bool isPseudo(uint64_t TSFlags)
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
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.
bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
static bool isMem(const MachineInstr &MI, unsigned Op)
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Target & getTheHexagonTarget()
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)
format_hex - Output N as a fixed width hexadecimal.
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.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
@ MCSA_Global
.type _foo, @gnu_unique_object
auto mask(ShuffFunc S, unsigned Length, OptArgs... args) -> MaskT
This struct is a compact representation of a valid (non-zero power of two) alignment.
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...