@@ -66,6 +66,12 @@ enum class RegKind {
6666 SVEPredicateVector
6767};
6868
69+ enum RegConstraintEqualityTy {
70+ EqualsReg,
71+ EqualsSuperReg,
72+ EqualsSubReg
73+ };
74+
6975class AArch64AsmParser : public MCTargetAsmParser {
7076private:
7177 StringRef Mnemonic; // /< Instruction mnemonic.
@@ -92,7 +98,8 @@ class AArch64AsmParser : public MCTargetAsmParser {
9298 bool parseOperand (OperandVector &Operands, bool isCondCode,
9399 bool invertCondCode);
94100
95- bool showMatchError (SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
101+ bool showMatchError (SMLoc Loc, unsigned ErrCode, uint64_t ErrorInfo,
102+ OperandVector &Operands);
96103
97104 bool parseDirectiveArch (SMLoc L);
98105 bool parseDirectiveCPU (SMLoc L);
@@ -139,7 +146,8 @@ class AArch64AsmParser : public MCTargetAsmParser {
139146 bool tryParseNeonVectorRegister (OperandVector &Operands);
140147 OperandMatchResultTy tryParseVectorIndex (OperandVector &Operands);
141148 OperandMatchResultTy tryParseGPRSeqPair (OperandVector &Operands);
142- template <bool ParseShiftExtend>
149+ template <bool ParseShiftExtend,
150+ RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg>
143151 OperandMatchResultTy tryParseGPROperand (OperandVector &Operands);
144152 template <bool ParseShiftExtend, bool ParseSuffix>
145153 OperandMatchResultTy tryParseSVEDataVector (OperandVector &Operands);
@@ -177,6 +185,8 @@ class AArch64AsmParser : public MCTargetAsmParser {
177185 setAvailableFeatures (ComputeAvailableFeatures (getSTI ().getFeatureBits ()));
178186 }
179187
188+ bool regsEqual (const MCParsedAsmOperand &Op1,
189+ const MCParsedAsmOperand &Op2) const override ;
180190 bool ParseInstruction (ParseInstructionInfo &Info, StringRef Name,
181191 SMLoc NameLoc, OperandVector &Operands) override ;
182192 bool ParseRegister (unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override ;
@@ -231,6 +241,10 @@ class AArch64Operand : public MCParsedAsmOperand {
231241 RegKind Kind;
232242 int ElementWidth;
233243
244+ // The register may be allowed as a different register class,
245+ // e.g. for GPR64as32 or GPR32as64.
246+ RegConstraintEqualityTy EqualityTy;
247+
234248 // In some cases the shift/extend needs to be explicitly parsed together
235249 // with the register, rather than as a separate operand. This is needed
236250 // for addressing modes where the instruction as a whole dictates the
@@ -446,6 +460,11 @@ class AArch64Operand : public MCParsedAsmOperand {
446460 return Reg.RegNum ;
447461 }
448462
463+ RegConstraintEqualityTy getRegEqualityTy () const {
464+ assert (Kind == k_Register && " Invalid access!" );
465+ return Reg.EqualityTy ;
466+ }
467+
449468 unsigned getVectorListStart () const {
450469 assert (Kind == k_VectorList && " Invalid access!" );
451470 return VectorList.RegNum ;
@@ -554,14 +573,16 @@ class AArch64Operand : public MCParsedAsmOperand {
554573 return DiagnosticPredicateTy::NearMatch;
555574 }
556575
557- bool isSVEPattern () const {
576+ DiagnosticPredicate isSVEPattern () const {
558577 if (!isImm ())
559- return false ;
578+ return DiagnosticPredicateTy::NoMatch ;
560579 auto *MCE = dyn_cast<MCConstantExpr>(getImm ());
561580 if (!MCE)
562- return false ;
581+ return DiagnosticPredicateTy::NoMatch ;
563582 int64_t Val = MCE->getValue ();
564- return Val >= 0 && Val < 32 ;
583+ if (Val >= 0 && Val < 32 )
584+ return DiagnosticPredicateTy::Match;
585+ return DiagnosticPredicateTy::NearMatch;
565586 }
566587
567588 bool isSymbolicUImm12Offset (const MCExpr *Expr, unsigned Scale) const {
@@ -1002,6 +1023,11 @@ class AArch64Operand : public MCParsedAsmOperand {
10021023 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains (Reg.RegNum );
10031024 }
10041025
1026+ bool isGPR64as32 () const {
1027+ return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1028+ AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains (Reg.RegNum );
1029+ }
1030+
10051031 bool isWSeqPair () const {
10061032 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
10071033 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains (
@@ -1318,6 +1344,18 @@ class AArch64Operand : public MCParsedAsmOperand {
13181344 Inst.addOperand (MCOperand::createReg (Reg));
13191345 }
13201346
1347+ void addGPR64as32Operands (MCInst &Inst, unsigned N) const {
1348+ assert (N == 1 && " Invalid number of operands!" );
1349+ assert (
1350+ AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains (getReg ()));
1351+
1352+ const MCRegisterInfo *RI = Ctx.getRegisterInfo ();
1353+ uint32_t Reg = RI->getRegClass (AArch64::GPR64RegClassID).getRegister (
1354+ RI->getEncodingValue (getReg ()));
1355+
1356+ Inst.addOperand (MCOperand::createReg (Reg));
1357+ }
1358+
13211359 template <int Width>
13221360 void addFPRasZPRRegOperands (MCInst &Inst, unsigned N) const {
13231361 unsigned Base;
@@ -1668,13 +1706,15 @@ class AArch64Operand : public MCParsedAsmOperand {
16681706
16691707 static std::unique_ptr<AArch64Operand>
16701708 CreateReg (unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
1709+ RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
16711710 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
16721711 unsigned ShiftAmount = 0 ,
16731712 unsigned HasExplicitAmount = false ) {
16741713 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
16751714 Op->Reg .RegNum = RegNum;
16761715 Op->Reg .Kind = Kind;
16771716 Op->Reg .ElementWidth = 0 ;
1717+ Op->Reg .EqualityTy = EqTy;
16781718 Op->Reg .ShiftExtend .Type = ExtTy;
16791719 Op->Reg .ShiftExtend .Amount = ShiftAmount;
16801720 Op->Reg .ShiftExtend .HasExplicitAmount = HasExplicitAmount;
@@ -1692,7 +1732,7 @@ class AArch64Operand : public MCParsedAsmOperand {
16921732 assert ((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
16931733 Kind == RegKind::SVEPredicateVector) &&
16941734 " Invalid vector kind" );
1695- auto Op = CreateReg (RegNum, Kind, S, E, Ctx, ExtTy, ShiftAmount,
1735+ auto Op = CreateReg (RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
16961736 HasExplicitAmount);
16971737 Op->Reg .ElementWidth = ElementWidth;
16981738 return Op;
@@ -3164,7 +3204,7 @@ AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
31643204 return MatchOperand_Success;
31653205}
31663206
3167- template <bool ParseShiftExtend>
3207+ template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy >
31683208OperandMatchResultTy
31693209AArch64AsmParser::tryParseGPROperand (OperandVector &Operands) {
31703210 SMLoc StartLoc = getLoc ();
@@ -3177,7 +3217,7 @@ AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
31773217 // No shift/extend is the default.
31783218 if (!ParseShiftExtend || getParser ().getTok ().isNot (AsmToken::Comma)) {
31793219 Operands.push_back (AArch64Operand::CreateReg (
3180- RegNum, RegKind::Scalar, StartLoc, getLoc (), getContext ()));
3220+ RegNum, RegKind::Scalar, StartLoc, getLoc (), getContext (), EqTy ));
31813221 return MatchOperand_Success;
31823222 }
31833223
@@ -3191,10 +3231,10 @@ AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
31913231 return Res;
31923232
31933233 auto Ext = static_cast <AArch64Operand*>(ExtOpnd.back ().get ());
3194- Operands.push_back (AArch64Operand::CreateReg (RegNum, RegKind::Scalar,
3195- StartLoc, Ext->getEndLoc (), getContext (),
3196- Ext->getShiftExtendType (), Ext->getShiftExtendAmount (),
3197- Ext->hasShiftExtendAmount ()));
3234+ Operands.push_back (AArch64Operand::CreateReg (
3235+ RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc (), getContext (), EqTy ,
3236+ Ext->getShiftExtendType (), Ext->getShiftExtendAmount (),
3237+ Ext->hasShiftExtendAmount ()));
31983238
31993239 return MatchOperand_Success;
32003240}
@@ -3412,6 +3452,30 @@ bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
34123452 }
34133453}
34143454
3455+ bool AArch64AsmParser::regsEqual (const MCParsedAsmOperand &Op1,
3456+ const MCParsedAsmOperand &Op2) const {
3457+ auto &AOp1 = static_cast <const AArch64Operand&>(Op1);
3458+ auto &AOp2 = static_cast <const AArch64Operand&>(Op2);
3459+ if (AOp1.getRegEqualityTy () == RegConstraintEqualityTy::EqualsReg &&
3460+ AOp2.getRegEqualityTy () == RegConstraintEqualityTy::EqualsReg)
3461+ return MCTargetAsmParser::regsEqual (Op1, Op2);
3462+
3463+ assert (AOp1.isScalarReg () && AOp2.isScalarReg () &&
3464+ " Testing equality of non-scalar registers not supported" );
3465+
3466+ // Check if a registers match their sub/super register classes.
3467+ if (AOp1.getRegEqualityTy () == EqualsSuperReg)
3468+ return getXRegFromWReg (Op1.getReg ()) == Op2.getReg ();
3469+ if (AOp1.getRegEqualityTy () == EqualsSubReg)
3470+ return getWRegFromXReg (Op1.getReg ()) == Op2.getReg ();
3471+ if (AOp2.getRegEqualityTy () == EqualsSuperReg)
3472+ return getXRegFromWReg (Op2.getReg ()) == Op1.getReg ();
3473+ if (AOp2.getRegEqualityTy () == EqualsSubReg)
3474+ return getWRegFromXReg (Op2.getReg ()) == Op1.getReg ();
3475+
3476+ return false ;
3477+ }
3478+
34153479// / ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
34163480// / operands.
34173481bool AArch64AsmParser::ParseInstruction (ParseInstructionInfo &Info,
@@ -3765,10 +3829,22 @@ static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
37653829 unsigned VariantID = 0 );
37663830
37673831bool AArch64AsmParser::showMatchError (SMLoc Loc, unsigned ErrCode,
3832+ uint64_t ErrorInfo,
37683833 OperandVector &Operands) {
37693834 switch (ErrCode) {
3770- case Match_InvalidTiedOperand:
3771- return Error (Loc, " operand must match destination register" );
3835+ case Match_InvalidTiedOperand: {
3836+ RegConstraintEqualityTy EqTy =
3837+ static_cast <const AArch64Operand &>(*Operands[ErrorInfo])
3838+ .getRegEqualityTy ();
3839+ switch (EqTy) {
3840+ case RegConstraintEqualityTy::EqualsSubReg:
3841+ return Error (Loc, " operand must be 64-bit form of destination register" );
3842+ case RegConstraintEqualityTy::EqualsSuperReg:
3843+ return Error (Loc, " operand must be 32-bit form of destination register" );
3844+ case RegConstraintEqualityTy::EqualsReg:
3845+ return Error (Loc, " operand must match destination register" );
3846+ }
3847+ }
37723848 case Match_MissingFeature:
37733849 return Error (Loc,
37743850 " instruction requires a CPU feature not currently enabled" );
@@ -4389,7 +4465,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
43894465 return Error (IDLoc, Msg);
43904466 }
43914467 case Match_MnemonicFail:
4392- return showMatchError (IDLoc, MatchResult, Operands);
4468+ return showMatchError (IDLoc, MatchResult, ErrorInfo, Operands);
43934469 case Match_InvalidOperand: {
43944470 SMLoc ErrorLoc = IDLoc;
43954471
@@ -4408,7 +4484,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
44084484 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix ())
44094485 MatchResult = Match_InvalidSuffix;
44104486
4411- return showMatchError (ErrorLoc, MatchResult, Operands);
4487+ return showMatchError (ErrorLoc, MatchResult, ErrorInfo, Operands);
44124488 }
44134489 case Match_InvalidTiedOperand:
44144490 case Match_InvalidMemoryIndexed1:
@@ -4546,7 +4622,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
45464622 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc ();
45474623 if (ErrorLoc == SMLoc ())
45484624 ErrorLoc = IDLoc;
4549- return showMatchError (ErrorLoc, MatchResult, Operands);
4625+ return showMatchError (ErrorLoc, MatchResult, ErrorInfo, Operands);
45504626 }
45514627 }
45524628
0 commit comments