@@ -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 ;
@@ -1002,6 +1021,11 @@ class AArch64Operand : public MCParsedAsmOperand {
10021021 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains (Reg.RegNum );
10031022 }
10041023
1024+ bool isGPR64as32 () const {
1025+ return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1026+ AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains (Reg.RegNum );
1027+ }
1028+
10051029 bool isWSeqPair () const {
10061030 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
10071031 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains (
@@ -1318,6 +1342,18 @@ class AArch64Operand : public MCParsedAsmOperand {
13181342 Inst.addOperand (MCOperand::createReg (Reg));
13191343 }
13201344
1345+ void addGPR64as32Operands (MCInst &Inst, unsigned N) const {
1346+ assert (N == 1 && " Invalid number of operands!" );
1347+ assert (
1348+ AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains (getReg ()));
1349+
1350+ const MCRegisterInfo *RI = Ctx.getRegisterInfo ();
1351+ uint32_t Reg = RI->getRegClass (AArch64::GPR64RegClassID).getRegister (
1352+ RI->getEncodingValue (getReg ()));
1353+
1354+ Inst.addOperand (MCOperand::createReg (Reg));
1355+ }
1356+
13211357 template <int Width>
13221358 void addFPRasZPRRegOperands (MCInst &Inst, unsigned N) const {
13231359 unsigned Base;
@@ -1668,13 +1704,15 @@ class AArch64Operand : public MCParsedAsmOperand {
16681704
16691705 static std::unique_ptr<AArch64Operand>
16701706 CreateReg (unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
1707+ RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
16711708 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
16721709 unsigned ShiftAmount = 0 ,
16731710 unsigned HasExplicitAmount = false ) {
16741711 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
16751712 Op->Reg .RegNum = RegNum;
16761713 Op->Reg .Kind = Kind;
16771714 Op->Reg .ElementWidth = 0 ;
1715+ Op->Reg .EqualityTy = EqTy;
16781716 Op->Reg .ShiftExtend .Type = ExtTy;
16791717 Op->Reg .ShiftExtend .Amount = ShiftAmount;
16801718 Op->Reg .ShiftExtend .HasExplicitAmount = HasExplicitAmount;
@@ -1692,7 +1730,7 @@ class AArch64Operand : public MCParsedAsmOperand {
16921730 assert ((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
16931731 Kind == RegKind::SVEPredicateVector) &&
16941732 " Invalid vector kind" );
1695- auto Op = CreateReg (RegNum, Kind, S, E, Ctx, ExtTy, ShiftAmount,
1733+ auto Op = CreateReg (RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
16961734 HasExplicitAmount);
16971735 Op->Reg .ElementWidth = ElementWidth;
16981736 return Op;
@@ -3164,7 +3202,7 @@ AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
31643202 return MatchOperand_Success;
31653203}
31663204
3167- template <bool ParseShiftExtend>
3205+ template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy >
31683206OperandMatchResultTy
31693207AArch64AsmParser::tryParseGPROperand (OperandVector &Operands) {
31703208 SMLoc StartLoc = getLoc ();
@@ -3177,7 +3215,7 @@ AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
31773215 // No shift/extend is the default.
31783216 if (!ParseShiftExtend || getParser ().getTok ().isNot (AsmToken::Comma)) {
31793217 Operands.push_back (AArch64Operand::CreateReg (
3180- RegNum, RegKind::Scalar, StartLoc, getLoc (), getContext ()));
3218+ RegNum, RegKind::Scalar, StartLoc, getLoc (), getContext (), EqTy ));
31813219 return MatchOperand_Success;
31823220 }
31833221
@@ -3191,10 +3229,10 @@ AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
31913229 return Res;
31923230
31933231 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 ()));
3232+ Operands.push_back (AArch64Operand::CreateReg (
3233+ RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc (), getContext (), EqTy ,
3234+ Ext->getShiftExtendType (), Ext->getShiftExtendAmount (),
3235+ Ext->hasShiftExtendAmount ()));
31983236
31993237 return MatchOperand_Success;
32003238}
@@ -3412,6 +3450,30 @@ bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
34123450 }
34133451}
34143452
3453+ bool AArch64AsmParser::regsEqual (const MCParsedAsmOperand &Op1,
3454+ const MCParsedAsmOperand &Op2) const {
3455+ auto &AOp1 = static_cast <const AArch64Operand&>(Op1);
3456+ auto &AOp2 = static_cast <const AArch64Operand&>(Op2);
3457+ if (AOp1.getRegEqualityTy () == RegConstraintEqualityTy::EqualsReg &&
3458+ AOp2.getRegEqualityTy () == RegConstraintEqualityTy::EqualsReg)
3459+ return MCTargetAsmParser::regsEqual (Op1, Op2);
3460+
3461+ assert (AOp1.isScalarReg () && AOp2.isScalarReg () &&
3462+ " Testing equality of non-scalar registers not supported" );
3463+
3464+ // Check if a registers match their sub/super register classes.
3465+ if (AOp1.getRegEqualityTy () == EqualsSuperReg)
3466+ return getXRegFromWReg (Op1.getReg ()) == Op2.getReg ();
3467+ if (AOp1.getRegEqualityTy () == EqualsSubReg)
3468+ return getWRegFromXReg (Op1.getReg ()) == Op2.getReg ();
3469+ if (AOp2.getRegEqualityTy () == EqualsSuperReg)
3470+ return getXRegFromWReg (Op2.getReg ()) == Op1.getReg ();
3471+ if (AOp2.getRegEqualityTy () == EqualsSubReg)
3472+ return getWRegFromXReg (Op2.getReg ()) == Op1.getReg ();
3473+
3474+ return false ;
3475+ }
3476+
34153477// / ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
34163478// / operands.
34173479bool AArch64AsmParser::ParseInstruction (ParseInstructionInfo &Info,
@@ -3765,10 +3827,22 @@ static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
37653827 unsigned VariantID = 0 );
37663828
37673829bool AArch64AsmParser::showMatchError (SMLoc Loc, unsigned ErrCode,
3830+ uint64_t ErrorInfo,
37683831 OperandVector &Operands) {
37693832 switch (ErrCode) {
3770- case Match_InvalidTiedOperand:
3771- return Error (Loc, " operand must match destination register" );
3833+ case Match_InvalidTiedOperand: {
3834+ RegConstraintEqualityTy EqTy =
3835+ static_cast <const AArch64Operand &>(*Operands[ErrorInfo])
3836+ .getRegEqualityTy ();
3837+ switch (EqTy) {
3838+ case RegConstraintEqualityTy::EqualsSubReg:
3839+ return Error (Loc, " operand must be 64-bit form of destination register" );
3840+ case RegConstraintEqualityTy::EqualsSuperReg:
3841+ return Error (Loc, " operand must be 32-bit form of destination register" );
3842+ case RegConstraintEqualityTy::EqualsReg:
3843+ return Error (Loc, " operand must match destination register" );
3844+ }
3845+ }
37723846 case Match_MissingFeature:
37733847 return Error (Loc,
37743848 " instruction requires a CPU feature not currently enabled" );
@@ -4389,7 +4463,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
43894463 return Error (IDLoc, Msg);
43904464 }
43914465 case Match_MnemonicFail:
4392- return showMatchError (IDLoc, MatchResult, Operands);
4466+ return showMatchError (IDLoc, MatchResult, ErrorInfo, Operands);
43934467 case Match_InvalidOperand: {
43944468 SMLoc ErrorLoc = IDLoc;
43954469
@@ -4408,7 +4482,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
44084482 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix ())
44094483 MatchResult = Match_InvalidSuffix;
44104484
4411- return showMatchError (ErrorLoc, MatchResult, Operands);
4485+ return showMatchError (ErrorLoc, MatchResult, ErrorInfo, Operands);
44124486 }
44134487 case Match_InvalidTiedOperand:
44144488 case Match_InvalidMemoryIndexed1:
@@ -4546,7 +4620,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
45464620 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc ();
45474621 if (ErrorLoc == SMLoc ())
45484622 ErrorLoc = IDLoc;
4549- return showMatchError (ErrorLoc, MatchResult, Operands);
4623+ return showMatchError (ErrorLoc, MatchResult, ErrorInfo, Operands);
45504624 }
45514625 }
45524626
0 commit comments