@@ -6384,10 +6384,6 @@ static bool checkIntelFPGARegisterAttrCompatibility(Sema &S, Decl *D,
6384
6384
if (!MA->isImplicit () &&
6385
6385
checkAttrMutualExclusion<IntelFPGAMemoryAttr>(S, D, Attr))
6386
6386
InCompat = true ;
6387
- if (auto *NBA = D->getAttr <IntelFPGANumBanksAttr>())
6388
- if (!NBA->isImplicit () &&
6389
- checkAttrMutualExclusion<IntelFPGANumBanksAttr>(S, D, Attr))
6390
- InCompat = true ;
6391
6387
6392
6388
return InCompat;
6393
6389
}
@@ -6404,21 +6400,178 @@ static void handleIntelFPGARegisterAttr(Sema &S, Decl *D, const ParsedAttr &A) {
6404
6400
handleSimpleAttribute<IntelFPGARegisterAttr>(S, D, A);
6405
6401
}
6406
6402
6407
- // / Handle the [[intelfpga ::bankwidth]] and [[intelfpga ::numbanks]] attributes.
6403
+ // / Handle the [[intel ::bankwidth]] and [[intel ::numbanks]] attributes.
6408
6404
// / These require a single constant power of two greater than zero.
6409
6405
// / These are incompatible with the register attribute.
6410
6406
// / The numbanks and bank_bits attributes are related. If bank_bits exists
6411
6407
// / when handling numbanks they are checked for consistency.
6412
- template <typename AttrType>
6413
- static void handleOneConstantPowerTwoValueAttr (Sema &S, Decl *D,
6414
- const ParsedAttr &A) {
6415
- checkForDuplicateAttribute<AttrType>(S, D, A);
6416
- if (checkAttrMutualExclusion<IntelFPGARegisterAttr>(S, D, A))
6417
- return ;
6418
6408
6409
+ void Sema::AddIntelFPGABankWidthAttr (Decl *D, const AttributeCommonInfo &CI,
6410
+ Expr *E) {
6411
+ if (!E->isValueDependent ()) {
6412
+ // Validate that we have an integer constant expression and then store the
6413
+ // converted constant expression into the semantic attribute so that we
6414
+ // don't have to evaluate it again later.
6415
+ llvm::APSInt ArgVal;
6416
+ ExprResult Res = VerifyIntegerConstantExpression (E, &ArgVal);
6417
+ if (Res.isInvalid ())
6418
+ return ;
6419
+ E = Res.get ();
6420
+
6421
+ // This attribute requires a strictly positive value.
6422
+ if (ArgVal <= 0 ) {
6423
+ Diag (E->getExprLoc (), diag::err_attribute_requires_positive_integer)
6424
+ << CI << /* positive*/ 0 ;
6425
+ return ;
6426
+ }
6427
+
6428
+ // This attribute requires a single constant power of two greater than zero.
6429
+ if (!ArgVal.isPowerOf2 ()) {
6430
+ Diag (E->getExprLoc (), diag::err_attribute_argument_not_power_of_two)
6431
+ << CI;
6432
+ return ;
6433
+ }
6434
+
6435
+ // Check to see if there's a duplicate attribute with different values
6436
+ // already applied to the declaration.
6437
+ if (const auto *DeclAttr = D->getAttr <IntelFPGABankWidthAttr>()) {
6438
+ // If the other attribute argument is instantiation dependent, we won't
6439
+ // have converted it to a constant expression yet and thus we test
6440
+ // whether this is a null pointer.
6441
+ if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue ())) {
6442
+ if (ArgVal != DeclExpr->getResultAsAPSInt ()) {
6443
+ Diag (CI.getLoc (), diag::warn_duplicate_attribute) << CI;
6444
+ Diag (DeclAttr->getLoc (), diag::note_previous_attribute);
6445
+ }
6446
+ // Drop the duplicate attribute.
6447
+ return ;
6448
+ }
6449
+ }
6450
+ }
6451
+
6452
+ // If the declaration does not have an [[intel::fpga_memory]]
6453
+ // attribute, this creates one as an implicit attribute.
6454
+ if (!D->hasAttr <IntelFPGAMemoryAttr>())
6455
+ D->addAttr (IntelFPGAMemoryAttr::CreateImplicit (
6456
+ Context, IntelFPGAMemoryAttr::Default));
6457
+
6458
+ D->addAttr (::new (Context) IntelFPGABankWidthAttr (Context, CI, E));
6459
+ }
6460
+
6461
+ IntelFPGABankWidthAttr *
6462
+ Sema::MergeIntelFPGABankWidthAttr (Decl *D, const IntelFPGABankWidthAttr &A) {
6463
+ // Check to see if there's a duplicate attribute with different values
6464
+ // already applied to the declaration.
6465
+ if (const auto *DeclAttr = D->getAttr <IntelFPGABankWidthAttr>()) {
6466
+ const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue ());
6467
+ const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue ());
6468
+ if (DeclExpr && MergeExpr &&
6469
+ DeclExpr->getResultAsAPSInt () != MergeExpr->getResultAsAPSInt ()) {
6470
+ Diag (DeclAttr->getLoc (), diag::warn_duplicate_attribute) << &A;
6471
+ Diag (A.getLoc (), diag::note_previous_attribute);
6472
+ return nullptr ;
6473
+ }
6474
+ }
6475
+
6476
+ return ::new (Context) IntelFPGABankWidthAttr (Context, A, A.getValue ());
6477
+ }
6478
+
6479
+ static void handleIntelFPGABankWidthAttr (Sema &S, Decl *D,
6480
+ const ParsedAttr &A) {
6481
+ S.CheckDeprecatedSYCLAttributeSpelling (A);
6482
+
6483
+ S.AddIntelFPGABankWidthAttr (D, A, A.getArgAsExpr (0 ));
6484
+ }
6485
+
6486
+ void Sema::AddIntelFPGANumBanksAttr (Decl *D, const AttributeCommonInfo &CI,
6487
+ Expr *E) {
6488
+ if (!E->isValueDependent ()) {
6489
+ // Validate that we have an integer constant expression and then store the
6490
+ // converted constant expression into the semantic attribute so that we
6491
+ // don't have to evaluate it again later.
6492
+ llvm::APSInt ArgVal;
6493
+ ExprResult Res = VerifyIntegerConstantExpression (E, &ArgVal);
6494
+ if (Res.isInvalid ())
6495
+ return ;
6496
+ E = Res.get ();
6497
+
6498
+ // This attribute requires a strictly positive value.
6499
+ if (ArgVal <= 0 ) {
6500
+ Diag (E->getExprLoc (), diag::err_attribute_requires_positive_integer)
6501
+ << CI << /* positive*/ 0 ;
6502
+ return ;
6503
+ }
6504
+
6505
+ // This attribute requires a single constant power of two greater than zero.
6506
+ if (!ArgVal.isPowerOf2 ()) {
6507
+ Diag (E->getExprLoc (), diag::err_attribute_argument_not_power_of_two)
6508
+ << CI;
6509
+ return ;
6510
+ }
6511
+
6512
+ // Check or add the related BankBits attribute.
6513
+ if (auto *BBA = D->getAttr <IntelFPGABankBitsAttr>()) {
6514
+ unsigned NumBankBits = BBA->args_size ();
6515
+ if (NumBankBits != ArgVal.ceilLogBase2 ()) {
6516
+ Diag (E->getExprLoc (), diag::err_bankbits_numbanks_conflicting) << CI;
6517
+ return ;
6518
+ }
6519
+ }
6520
+
6521
+ // Check to see if there's a duplicate attribute with different values
6522
+ // already applied to the declaration.
6523
+ if (const auto *DeclAttr = D->getAttr <IntelFPGANumBanksAttr>()) {
6524
+ // If the other attribute argument is instantiation dependent, we won't
6525
+ // have converted it to a constant expression yet and thus we test
6526
+ // whether this is a null pointer.
6527
+ if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue ())) {
6528
+ if (ArgVal != DeclExpr->getResultAsAPSInt ()) {
6529
+ Diag (CI.getLoc (), diag::warn_duplicate_attribute) << CI;
6530
+ Diag (DeclAttr->getLoc (), diag::note_previous_attribute);
6531
+ }
6532
+ // Drop the duplicate attribute.
6533
+ return ;
6534
+ }
6535
+ }
6536
+ }
6537
+
6538
+ // If the declaration does not have an [[intel::fpga_memory]]
6539
+ // attribute, this creates one as an implicit attribute.
6540
+ if (!D->hasAttr <IntelFPGAMemoryAttr>())
6541
+ D->addAttr (IntelFPGAMemoryAttr::CreateImplicit (
6542
+ Context, IntelFPGAMemoryAttr::Default));
6543
+
6544
+ // We are adding a user NumBanks attribute, drop any implicit default.
6545
+ if (auto *NBA = D->getAttr <IntelFPGANumBanksAttr>()) {
6546
+ if (NBA->isImplicit ())
6547
+ D->dropAttr <IntelFPGANumBanksAttr>();
6548
+ }
6549
+
6550
+ D->addAttr (::new (Context) IntelFPGANumBanksAttr (Context, CI, E));
6551
+ }
6552
+
6553
+ IntelFPGANumBanksAttr *
6554
+ Sema::MergeIntelFPGANumBanksAttr (Decl *D, const IntelFPGANumBanksAttr &A) {
6555
+ // Check to see if there's a duplicate attribute with different values
6556
+ // already applied to the declaration.
6557
+ if (const auto *DeclAttr = D->getAttr <IntelFPGANumBanksAttr>()) {
6558
+ const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue ());
6559
+ const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue ());
6560
+ if (DeclExpr && MergeExpr &&
6561
+ DeclExpr->getResultAsAPSInt () != MergeExpr->getResultAsAPSInt ()) {
6562
+ Diag (DeclAttr->getLoc (), diag::warn_duplicate_attribute) << &A;
6563
+ Diag (A.getLoc (), diag::note_previous_attribute);
6564
+ return nullptr ;
6565
+ }
6566
+ }
6567
+
6568
+ return ::new (Context) IntelFPGANumBanksAttr (Context, A, A.getValue ());
6569
+ }
6570
+
6571
+ static void handleIntelFPGANumBanksAttr (Sema &S, Decl *D, const ParsedAttr &A) {
6419
6572
S.CheckDeprecatedSYCLAttributeSpelling (A);
6420
6573
6421
- S.AddOneConstantPowerTwoValueAttr <AttrType> (D, A, A.getArgAsExpr (0 ));
6574
+ S.AddIntelFPGANumBanksAttr (D, A, A.getArgAsExpr (0 ));
6422
6575
}
6423
6576
6424
6577
static void handleIntelFPGASimpleDualPortAttr (Sema &S, Decl *D,
@@ -10119,10 +10272,10 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
10119
10272
handleIntelFPGARegisterAttr (S, D, AL);
10120
10273
break ;
10121
10274
case ParsedAttr::AT_IntelFPGABankWidth:
10122
- handleOneConstantPowerTwoValueAttr<IntelFPGABankWidthAttr> (S, D, AL);
10275
+ handleIntelFPGABankWidthAttr (S, D, AL);
10123
10276
break ;
10124
10277
case ParsedAttr::AT_IntelFPGANumBanks:
10125
- handleOneConstantPowerTwoValueAttr<IntelFPGANumBanksAttr> (S, D, AL);
10278
+ handleIntelFPGANumBanksAttr (S, D, AL);
10126
10279
break ;
10127
10280
case ParsedAttr::AT_IntelFPGAPrivateCopies:
10128
10281
handleIntelFPGAPrivateCopiesAttr (S, D, AL);
0 commit comments