@@ -66,6 +66,12 @@ enum class RegKind {
66
66
SVEPredicateVector
67
67
};
68
68
69
+ enum RegConstraintEqualityTy {
70
+ EqualsReg,
71
+ EqualsSuperReg,
72
+ EqualsSubReg
73
+ };
74
+
69
75
class AArch64AsmParser : public MCTargetAsmParser {
70
76
private:
71
77
StringRef Mnemonic; // /< Instruction mnemonic.
@@ -92,7 +98,8 @@ class AArch64AsmParser : public MCTargetAsmParser {
92
98
bool parseOperand (OperandVector &Operands, bool isCondCode,
93
99
bool invertCondCode);
94
100
95
- bool showMatchError (SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
101
+ bool showMatchError (SMLoc Loc, unsigned ErrCode, uint64_t ErrorInfo,
102
+ OperandVector &Operands);
96
103
97
104
bool parseDirectiveArch (SMLoc L);
98
105
bool parseDirectiveCPU (SMLoc L);
@@ -139,7 +146,8 @@ class AArch64AsmParser : public MCTargetAsmParser {
139
146
bool tryParseNeonVectorRegister (OperandVector &Operands);
140
147
OperandMatchResultTy tryParseVectorIndex (OperandVector &Operands);
141
148
OperandMatchResultTy tryParseGPRSeqPair (OperandVector &Operands);
142
- template <bool ParseShiftExtend>
149
+ template <bool ParseShiftExtend,
150
+ RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg>
143
151
OperandMatchResultTy tryParseGPROperand (OperandVector &Operands);
144
152
template <bool ParseShiftExtend, bool ParseSuffix>
145
153
OperandMatchResultTy tryParseSVEDataVector (OperandVector &Operands);
@@ -177,6 +185,8 @@ class AArch64AsmParser : public MCTargetAsmParser {
177
185
setAvailableFeatures (ComputeAvailableFeatures (getSTI ().getFeatureBits ()));
178
186
}
179
187
188
+ bool regsEqual (const MCParsedAsmOperand &Op1,
189
+ const MCParsedAsmOperand &Op2) const override ;
180
190
bool ParseInstruction (ParseInstructionInfo &Info, StringRef Name,
181
191
SMLoc NameLoc, OperandVector &Operands) override ;
182
192
bool ParseRegister (unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override ;
@@ -231,6 +241,10 @@ class AArch64Operand : public MCParsedAsmOperand {
231
241
RegKind Kind;
232
242
int ElementWidth;
233
243
244
+ // The register may be allowed as a different register class,
245
+ // e.g. for GPR64as32 or GPR32as64.
246
+ RegConstraintEqualityTy EqualityTy;
247
+
234
248
// In some cases the shift/extend needs to be explicitly parsed together
235
249
// with the register, rather than as a separate operand. This is needed
236
250
// for addressing modes where the instruction as a whole dictates the
@@ -446,6 +460,11 @@ class AArch64Operand : public MCParsedAsmOperand {
446
460
return Reg.RegNum ;
447
461
}
448
462
463
+ RegConstraintEqualityTy getRegEqualityTy () const {
464
+ assert (Kind == k_Register && " Invalid access!" );
465
+ return Reg.EqualityTy ;
466
+ }
467
+
449
468
unsigned getVectorListStart () const {
450
469
assert (Kind == k_VectorList && " Invalid access!" );
451
470
return VectorList.RegNum ;
@@ -1002,6 +1021,11 @@ class AArch64Operand : public MCParsedAsmOperand {
1002
1021
AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains (Reg.RegNum );
1003
1022
}
1004
1023
1024
+ bool isGPR64as32 () const {
1025
+ return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1026
+ AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains (Reg.RegNum );
1027
+ }
1028
+
1005
1029
bool isWSeqPair () const {
1006
1030
return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1007
1031
AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains (
@@ -1318,6 +1342,18 @@ class AArch64Operand : public MCParsedAsmOperand {
1318
1342
Inst.addOperand (MCOperand::createReg (Reg));
1319
1343
}
1320
1344
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
+
1321
1357
template <int Width>
1322
1358
void addFPRasZPRRegOperands (MCInst &Inst, unsigned N) const {
1323
1359
unsigned Base;
@@ -1668,13 +1704,15 @@ class AArch64Operand : public MCParsedAsmOperand {
1668
1704
1669
1705
static std::unique_ptr<AArch64Operand>
1670
1706
CreateReg (unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
1707
+ RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
1671
1708
AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1672
1709
unsigned ShiftAmount = 0 ,
1673
1710
unsigned HasExplicitAmount = false ) {
1674
1711
auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1675
1712
Op->Reg .RegNum = RegNum;
1676
1713
Op->Reg .Kind = Kind;
1677
1714
Op->Reg .ElementWidth = 0 ;
1715
+ Op->Reg .EqualityTy = EqTy;
1678
1716
Op->Reg .ShiftExtend .Type = ExtTy;
1679
1717
Op->Reg .ShiftExtend .Amount = ShiftAmount;
1680
1718
Op->Reg .ShiftExtend .HasExplicitAmount = HasExplicitAmount;
@@ -1692,7 +1730,7 @@ class AArch64Operand : public MCParsedAsmOperand {
1692
1730
assert ((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1693
1731
Kind == RegKind::SVEPredicateVector) &&
1694
1732
" 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,
1696
1734
HasExplicitAmount);
1697
1735
Op->Reg .ElementWidth = ElementWidth;
1698
1736
return Op;
@@ -3164,7 +3202,7 @@ AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
3164
3202
return MatchOperand_Success;
3165
3203
}
3166
3204
3167
- template <bool ParseShiftExtend>
3205
+ template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy >
3168
3206
OperandMatchResultTy
3169
3207
AArch64AsmParser::tryParseGPROperand (OperandVector &Operands) {
3170
3208
SMLoc StartLoc = getLoc ();
@@ -3177,7 +3215,7 @@ AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3177
3215
// No shift/extend is the default.
3178
3216
if (!ParseShiftExtend || getParser ().getTok ().isNot (AsmToken::Comma)) {
3179
3217
Operands.push_back (AArch64Operand::CreateReg (
3180
- RegNum, RegKind::Scalar, StartLoc, getLoc (), getContext ()));
3218
+ RegNum, RegKind::Scalar, StartLoc, getLoc (), getContext (), EqTy ));
3181
3219
return MatchOperand_Success;
3182
3220
}
3183
3221
@@ -3191,10 +3229,10 @@ AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3191
3229
return Res;
3192
3230
3193
3231
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 ()));
3198
3236
3199
3237
return MatchOperand_Success;
3200
3238
}
@@ -3412,6 +3450,30 @@ bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3412
3450
}
3413
3451
}
3414
3452
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
+
3415
3477
// / ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3416
3478
// / operands.
3417
3479
bool AArch64AsmParser::ParseInstruction (ParseInstructionInfo &Info,
@@ -3765,10 +3827,22 @@ static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3765
3827
unsigned VariantID = 0 );
3766
3828
3767
3829
bool AArch64AsmParser::showMatchError (SMLoc Loc, unsigned ErrCode,
3830
+ uint64_t ErrorInfo,
3768
3831
OperandVector &Operands) {
3769
3832
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
+ }
3772
3846
case Match_MissingFeature:
3773
3847
return Error (Loc,
3774
3848
" instruction requires a CPU feature not currently enabled" );
@@ -4389,7 +4463,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4389
4463
return Error (IDLoc, Msg);
4390
4464
}
4391
4465
case Match_MnemonicFail:
4392
- return showMatchError (IDLoc, MatchResult, Operands);
4466
+ return showMatchError (IDLoc, MatchResult, ErrorInfo, Operands);
4393
4467
case Match_InvalidOperand: {
4394
4468
SMLoc ErrorLoc = IDLoc;
4395
4469
@@ -4408,7 +4482,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4408
4482
((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix ())
4409
4483
MatchResult = Match_InvalidSuffix;
4410
4484
4411
- return showMatchError (ErrorLoc, MatchResult, Operands);
4485
+ return showMatchError (ErrorLoc, MatchResult, ErrorInfo, Operands);
4412
4486
}
4413
4487
case Match_InvalidTiedOperand:
4414
4488
case Match_InvalidMemoryIndexed1:
@@ -4546,7 +4620,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4546
4620
SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc ();
4547
4621
if (ErrorLoc == SMLoc ())
4548
4622
ErrorLoc = IDLoc;
4549
- return showMatchError (ErrorLoc, MatchResult, Operands);
4623
+ return showMatchError (ErrorLoc, MatchResult, ErrorInfo, Operands);
4550
4624
}
4551
4625
}
4552
4626
0 commit comments