@@ -132,6 +132,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
132
132
OperandMatchResultTy tryParsePSBHint (OperandVector &Operands);
133
133
OperandMatchResultTy tryParseAdrpLabel (OperandVector &Operands);
134
134
OperandMatchResultTy tryParseAdrLabel (OperandVector &Operands);
135
+ template <bool AddFPZeroAsLiteral>
135
136
OperandMatchResultTy tryParseFPImm (OperandVector &Operands);
136
137
OperandMatchResultTy tryParseImmWithOptionalShift (OperandVector &Operands);
137
138
OperandMatchResultTy tryParseGPR64sp0Operand (OperandVector &Operands);
@@ -273,7 +274,8 @@ class AArch64Operand : public MCParsedAsmOperand {
273
274
};
274
275
275
276
struct FPImmOp {
276
- unsigned Val; // Encoded 8-bit representation.
277
+ uint64_t Val; // APFloat value bitcasted to uint64_t.
278
+ bool IsExact; // describes whether parsed value was exact.
277
279
};
278
280
279
281
struct BarrierOp {
@@ -419,9 +421,14 @@ class AArch64Operand : public MCParsedAsmOperand {
419
421
return CondCode.Code ;
420
422
}
421
423
422
- unsigned getFPImm () const {
423
- assert (Kind == k_FPImm && " Invalid access!" );
424
- return FPImm.Val ;
424
+ APFloat getFPImm () const {
425
+ assert (Kind == k_FPImm && " Invalid access!" );
426
+ return APFloat (APFloat::IEEEdouble (), APInt (64 , FPImm.Val , true ));
427
+ }
428
+
429
+ bool getFPImmIsExact () const {
430
+ assert (Kind == k_FPImm && " Invalid access!" );
431
+ return FPImm.IsExact ;
425
432
}
426
433
427
434
unsigned getBarrier () const {
@@ -872,7 +879,11 @@ class AArch64Operand : public MCParsedAsmOperand {
872
879
return AArch64_AM::isMOVNMovAlias (Value, Shift, RegWidth);
873
880
}
874
881
875
- bool isFPImm () const { return Kind == k_FPImm; }
882
+ bool isFPImm () const {
883
+ return Kind == k_FPImm &&
884
+ AArch64_AM::getFP64Imm (getFPImm ().bitcastToAPInt ()) != -1 ;
885
+ }
886
+
876
887
bool isBarrier () const { return Kind == k_Barrier; }
877
888
bool isSysReg () const { return Kind == k_SysReg; }
878
889
@@ -1080,6 +1091,39 @@ class AArch64Operand : public MCParsedAsmOperand {
1080
1091
ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1081
1092
ST == AArch64_AM::MSL);
1082
1093
}
1094
+
1095
+ template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm () const {
1096
+ if (Kind != k_FPImm)
1097
+ return DiagnosticPredicateTy::NoMatch;
1098
+
1099
+ if (getFPImmIsExact ()) {
1100
+ // Lookup the immediate from table of supported immediates.
1101
+ auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum (ImmEnum);
1102
+ assert (Desc && " Unknown enum value" );
1103
+
1104
+ // Calculate its FP value.
1105
+ APFloat RealVal (APFloat::IEEEdouble ());
1106
+ if (RealVal.convertFromString (Desc->Repr , APFloat::rmTowardZero) !=
1107
+ APFloat::opOK)
1108
+ llvm_unreachable (" FP immediate is not exact" );
1109
+
1110
+ if (getFPImm ().bitwiseIsEqual (RealVal))
1111
+ return DiagnosticPredicateTy::Match;
1112
+ }
1113
+
1114
+ return DiagnosticPredicateTy::NearMatch;
1115
+ }
1116
+
1117
+ template <unsigned ImmA, unsigned ImmB>
1118
+ DiagnosticPredicate isExactFPImm () const {
1119
+ DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
1120
+ if ((Res = isExactFPImm<ImmA>()))
1121
+ return DiagnosticPredicateTy::Match;
1122
+ if ((Res = isExactFPImm<ImmB>()))
1123
+ return DiagnosticPredicateTy::Match;
1124
+ return Res;
1125
+ }
1126
+
1083
1127
bool isExtend () const {
1084
1128
if (!isShiftExtend ())
1085
1129
return false ;
@@ -1342,6 +1386,13 @@ class AArch64Operand : public MCParsedAsmOperand {
1342
1386
Inst.addOperand (MCOperand::createImm (getVectorIndex ()));
1343
1387
}
1344
1388
1389
+ template <unsigned ImmIs0, unsigned ImmIs1>
1390
+ void addExactFPImmOperands (MCInst &Inst, unsigned N) const {
1391
+ assert (N == 1 && " Invalid number of operands!" );
1392
+ assert (bool (isExactFPImm<ImmIs0, ImmIs1>()) && " Invalid operand" );
1393
+ Inst.addOperand (MCOperand::createImm (bool (isExactFPImm<ImmIs1>())));
1394
+ }
1395
+
1345
1396
void addImmOperands (MCInst &Inst, unsigned N) const {
1346
1397
assert (N == 1 && " Invalid number of operands!" );
1347
1398
// If this is a pageoff symrefexpr with an addend, adjust the addend
@@ -1481,7 +1532,8 @@ class AArch64Operand : public MCParsedAsmOperand {
1481
1532
1482
1533
void addFPImmOperands (MCInst &Inst, unsigned N) const {
1483
1534
assert (N == 1 && " Invalid number of operands!" );
1484
- Inst.addOperand (MCOperand::createImm (getFPImm ()));
1535
+ Inst.addOperand (MCOperand::createImm (
1536
+ AArch64_AM::getFP64Imm (getFPImm ().bitcastToAPInt ())));
1485
1537
}
1486
1538
1487
1539
void addBarrierOperands (MCInst &Inst, unsigned N) const {
@@ -1700,10 +1752,11 @@ class AArch64Operand : public MCParsedAsmOperand {
1700
1752
return Op;
1701
1753
}
1702
1754
1703
- static std::unique_ptr<AArch64Operand> CreateFPImm ( unsigned Val, SMLoc S,
1704
- MCContext &Ctx) {
1755
+ static std::unique_ptr<AArch64Operand>
1756
+ CreateFPImm (APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
1705
1757
auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
1706
- Op->FPImm .Val = Val;
1758
+ Op->FPImm .Val = Val.bitcastToAPInt ().getSExtValue ();
1759
+ Op->FPImm .IsExact = IsExact;
1707
1760
Op->StartLoc = S;
1708
1761
Op->EndLoc = S;
1709
1762
return Op;
@@ -1791,8 +1844,10 @@ class AArch64Operand : public MCParsedAsmOperand {
1791
1844
void AArch64Operand::print (raw_ostream &OS) const {
1792
1845
switch (Kind) {
1793
1846
case k_FPImm:
1794
- OS << " <fpimm " << getFPImm () << " ("
1795
- << AArch64_AM::getFPImmFloat (getFPImm ()) << " ) >" ;
1847
+ OS << " <fpimm " << getFPImm ().bitcastToAPInt ().getZExtValue ();
1848
+ if (!getFPImmIsExact ())
1849
+ OS << " (inexact)" ;
1850
+ OS << " >" ;
1796
1851
break ;
1797
1852
case k_Barrier: {
1798
1853
StringRef Name = getBarrierName ();
@@ -2285,6 +2340,7 @@ AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2285
2340
}
2286
2341
2287
2342
// / tryParseFPImm - A floating point immediate expression operand.
2343
+ template <bool AddFPZeroAsLiteral>
2288
2344
OperandMatchResultTy
2289
2345
AArch64AsmParser::tryParseFPImm (OperandVector &Operands) {
2290
2346
MCAsmParser &Parser = getParser ();
@@ -2296,45 +2352,44 @@ AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
2296
2352
bool isNegative = parseOptionalToken (AsmToken::Minus);
2297
2353
2298
2354
const AsmToken &Tok = Parser.getTok ();
2299
- if (Tok.is (AsmToken::Real) || Tok.is (AsmToken::Integer)) {
2300
- int64_t Val;
2301
- if (Tok.is (AsmToken::Integer) && Tok.getString ().startswith (" 0x" )) {
2302
- Val = Tok.getIntVal ();
2303
- if (Val > 255 || isNegative) {
2304
- TokError (" encoded floating point value out of range" );
2305
- return MatchOperand_ParseFail;
2306
- }
2307
- } else {
2308
- APFloat RealVal (APFloat::IEEEdouble (), Tok.getString ());
2309
- if (isNegative)
2310
- RealVal.changeSign ();
2355
+ if (!Tok.is (AsmToken::Real) && !Tok.is (AsmToken::Integer)) {
2356
+ if (!Hash)
2357
+ return MatchOperand_NoMatch;
2358
+ TokError (" invalid floating point immediate" );
2359
+ return MatchOperand_ParseFail;
2360
+ }
2311
2361
2312
- uint64_t IntVal = RealVal.bitcastToAPInt ().getZExtValue ();
2313
- Val = AArch64_AM::getFP64Imm (APInt (64 , IntVal));
2314
-
2315
- // Check for out of range values. As an exception we let Zero through,
2316
- // but as tokens instead of an FPImm so that it can be matched by the
2317
- // appropriate alias if one exists.
2318
- if (RealVal.isPosZero ()) {
2319
- Parser.Lex (); // Eat the token.
2320
- Operands.push_back (AArch64Operand::CreateToken (" #0" , false , S, getContext ()));
2321
- Operands.push_back (AArch64Operand::CreateToken (" .0" , false , S, getContext ()));
2322
- return MatchOperand_Success;
2323
- } else if (Val == -1 ) {
2324
- TokError (" expected compatible register or floating-point constant" );
2325
- return MatchOperand_ParseFail;
2326
- }
2362
+ // Parse hexadecimal representation.
2363
+ if (Tok.is (AsmToken::Integer) && Tok.getString ().startswith (" 0x" )) {
2364
+ if (Tok.getIntVal () > 255 || isNegative) {
2365
+ TokError (" encoded floating point value out of range" );
2366
+ return MatchOperand_ParseFail;
2327
2367
}
2328
- Parser.Lex (); // Eat the token.
2329
- Operands.push_back (AArch64Operand::CreateFPImm (Val, S, getContext ()));
2330
- return MatchOperand_Success;
2368
+
2369
+ APFloat F ((double )AArch64_AM::getFPImmFloat (Tok.getIntVal ()));
2370
+ Operands.push_back (
2371
+ AArch64Operand::CreateFPImm (F, true , S, getContext ()));
2372
+ } else {
2373
+ // Parse FP representation.
2374
+ APFloat RealVal (APFloat::IEEEdouble ());
2375
+ auto Status =
2376
+ RealVal.convertFromString (Tok.getString (), APFloat::rmTowardZero);
2377
+ if (isNegative)
2378
+ RealVal.changeSign ();
2379
+
2380
+ if (AddFPZeroAsLiteral && RealVal.isPosZero ()) {
2381
+ Operands.push_back (
2382
+ AArch64Operand::CreateToken (" #0" , false , S, getContext ()));
2383
+ Operands.push_back (
2384
+ AArch64Operand::CreateToken (" .0" , false , S, getContext ()));
2385
+ } else
2386
+ Operands.push_back (AArch64Operand::CreateFPImm (
2387
+ RealVal, Status == APFloat::opOK, S, getContext ()));
2331
2388
}
2332
2389
2333
- if (!Hash)
2334
- return MatchOperand_NoMatch;
2390
+ Parser.Lex (); // Eat the token.
2335
2391
2336
- TokError (" invalid floating point immediate" );
2337
- return MatchOperand_ParseFail;
2392
+ return MatchOperand_Success;
2338
2393
}
2339
2394
2340
2395
// / tryParseImmWithOptionalShift - Parse immediate operand, optionally with
0 commit comments