clang  20.0.0git
SemaSYCLDeclAttr.cpp
Go to the documentation of this file.
1 //===- SemaSYCLDeclAttr.cpp - Semantic Analysis for SYCL attributes -------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 // This implements Semantic Analysis for SYCL attributes.
9 //===----------------------------------------------------------------------===//
10 
12 #include "clang/Basic/TargetInfo.h"
13 #include "clang/Sema/Attr.h"
15 #include "clang/Sema/ParsedAttr.h"
16 #include "clang/Sema/Sema.h"
17 #include "clang/Sema/SemaSYCL.h"
18 
19 using namespace clang;
20 
22  // The 'sycl_kernel' attribute applies only to function templates.
23  const auto *FD = cast<FunctionDecl>(D);
24  const FunctionTemplateDecl *FT = FD->getDescribedFunctionTemplate();
25  assert(FT && "Function template is expected");
26 
27  // Function template must have at least two template parameters so it
28  // can be used in OpenCL kernel generation.
30  if (TL->size() < 2) {
31  Diag(FT->getLocation(), diag::warn_sycl_kernel_num_of_template_params);
32  return;
33  }
34 
35  // The first two template parameters must be typenames.
36  for (unsigned I = 0; I < 2 && I < TL->size(); ++I) {
37  const NamedDecl *TParam = TL->getParam(I);
38  if (isa<NonTypeTemplateParmDecl>(TParam)) {
39  Diag(FT->getLocation(),
40  diag::warn_sycl_kernel_invalid_template_param_type);
41  return;
42  }
43  }
44 
45  // Function must have at least one parameter.
47  Diag(FT->getLocation(), diag::warn_sycl_kernel_num_of_function_params);
48  return;
49  }
50 
51  // Function must return void.
53  if (!RetTy->isVoidType()) {
54  Diag(FT->getLocation(), diag::warn_sycl_kernel_return_type);
55  return;
56  }
57 
58  handleSimpleAttribute<SYCLKernelAttr>(*this, D, AL);
59 }
60 
61 // Returns a DupArgResult value; Same means the args have the same value,
62 // Different means the args do not have the same value, and Unknown means that
63 // the args cannot (yet) be compared.
64 enum class DupArgResult { Unknown, Same, Different };
65 static DupArgResult areArgValuesIdentical(const Expr *LHS, const Expr *RHS) {
66  // If both operands are nullptr they are unspecified and are considered the
67  // same.
68  if (!LHS && !RHS)
69  return DupArgResult::Same;
70 
71  // Otherwise, if either operand is nullptr they are considered different.
72  if (!LHS || !RHS)
74 
75  // Otherwise, if either operand is still value dependent, we can't test
76  // anything.
77  const auto *LHSCE = dyn_cast<ConstantExpr>(LHS);
78  const auto *RHSCE = dyn_cast<ConstantExpr>(RHS);
79  if (!LHSCE || !RHSCE)
80  return DupArgResult::Unknown;
81 
82  // Otherwise, test that the values.
83  return LHSCE->getResultAsAPSInt() == RHSCE->getResultAsAPSInt()
86 }
87 
88 // Returns true if any of the specified dimensions (X,Y,Z) differ between the
89 // arguments.
90 bool SemaSYCL::anyWorkGroupSizesDiffer(const Expr *LHSXDim, const Expr *LHSYDim,
91  const Expr *LHSZDim, const Expr *RHSXDim,
92  const Expr *RHSYDim,
93  const Expr *RHSZDim) {
94  DupArgResult Results[] = {areArgValuesIdentical(LHSXDim, RHSXDim),
95  areArgValuesIdentical(LHSYDim, RHSYDim),
96  areArgValuesIdentical(LHSZDim, RHSZDim)};
97  return llvm::is_contained(Results, DupArgResult::Different);
98 }
99 
100 // Returns true if all of the specified dimensions (X,Y,Z) are the same between
101 // the arguments.
102 bool SemaSYCL::allWorkGroupSizesSame(const Expr *LHSXDim, const Expr *LHSYDim,
103  const Expr *LHSZDim, const Expr *RHSXDim,
104  const Expr *RHSYDim, const Expr *RHSZDim) {
105  DupArgResult Results[] = {areArgValuesIdentical(LHSXDim, RHSXDim),
106  areArgValuesIdentical(LHSYDim, RHSYDim),
107  areArgValuesIdentical(LHSZDim, RHSZDim)};
108  return llvm::all_of(Results,
109  [](DupArgResult V) { return V == DupArgResult::Same; });
110 }
111 
112 // Helper to get CudaArch.
114  if (!TI.getTriple().isNVPTX())
115  llvm_unreachable("getOffloadArch is only valid for NVPTX triple");
116  auto &TO = TI.getTargetOpts();
117  return StringToOffloadArch(TO.CPU);
118 }
119 
120 bool SemaSYCL::hasDependentExpr(Expr **Exprs, const size_t ExprsSize) {
121  return std::any_of(Exprs, Exprs + ExprsSize, [](const Expr *E) {
122  return E->isValueDependent() || E->isTypeDependent();
123  });
124 }
125 
127  StringRef NewName) {
128  // Additionally, diagnose the old [[intel::ii]] spelling.
129  if (A.getKind() == ParsedAttr::AT_SYCLIntelInitiationInterval &&
130  A.getAttrName()->isStr("ii")) {
131  diagnoseDeprecatedAttribute(A, "intel", "initiation_interval");
132  return;
133  }
134 
135  // Diagnose SYCL 2020 spellings in later SYCL modes.
136  if (getLangOpts().getSYCLVersion() >= LangOptions::SYCL_2020) {
137  // All attributes in the cl vendor namespace are deprecated in favor of a
138  // name in the sycl namespace as of SYCL 2020.
139  if (A.hasScope() && A.getScopeName()->isStr("cl")) {
140  diagnoseDeprecatedAttribute(A, "sycl", NewName);
141  return;
142  }
143 
144  // All GNU-style spellings are deprecated in favor of a C++-style spelling.
145  if (A.getSyntax() == ParsedAttr::AS_GNU) {
146  // Note: we cannot suggest an automatic fix-it because GNU-style
147  // spellings can appear in locations that are not valid for a C++-style
148  // spelling, and the attribute could be part of an attribute list within
149  // a single __attribute__ specifier. Just tell the user it's deprecated
150  // manually.
151  //
152  // This currently assumes that the GNU-style spelling is the same as the
153  // SYCL 2020 spelling (sans the vendor namespace).
154  Diag(A.getLoc(), diag::warn_attribute_spelling_deprecated)
155  << "'" + A.getNormalizedFullName() + "'";
156  Diag(A.getLoc(), diag::note_spelling_suggestion)
157  << "'[[sycl::" + A.getNormalizedFullName() + "]]'";
158  return;
159  }
160  }
161 }
162 
164  StringRef NewScope,
165  StringRef NewName) {
166  assert((!NewName.empty() || !NewScope.empty()) &&
167  "Deprecated attribute with no new scope or name?");
168  Diag(A.getLoc(), diag::warn_attribute_spelling_deprecated)
169  << "'" + A.getNormalizedFullName() + "'";
170 
171  FixItHint Fix;
172  std::string NewFullName;
173  if (NewScope.empty() && !NewName.empty()) {
174  // Only have a new name.
175  Fix = FixItHint::CreateReplacement(A.getLoc(), NewName);
176  NewFullName =
177  ((A.hasScope() ? A.getScopeName()->getName() : StringRef("")) +
178  "::" + NewName)
179  .str();
180  } else if (NewName.empty() && !NewScope.empty()) {
181  // Only have a new scope.
182  Fix = FixItHint::CreateReplacement(A.getScopeLoc(), NewScope);
183  NewFullName = (NewScope + "::" + A.getAttrName()->getName()).str();
184  } else {
185  // Have both a new name and a new scope.
186  NewFullName = (NewScope + "::" + NewName).str();
187  Fix = FixItHint::CreateReplacement(A.getRange(), NewFullName);
188  }
189 
190  Diag(A.getLoc(), diag::note_spelling_suggestion)
191  << "'" + NewFullName + "'" << Fix;
192 }
193 
194 // Checks if FPGA memory attributes apply on valid variables.
195 // Returns true if an error occured.
197  // Check for SYCL device compilation context.
198  if (!getLangOpts().SYCLIsDevice) {
199  return false;
200  }
201 
202  const auto *VD = dyn_cast<VarDecl>(D);
203  if (!VD)
204  return false;
205 
206  // Exclude implicit parameters and non-type template parameters.
207  if (VD->getKind() == Decl::ImplicitParam ||
208  VD->getKind() == Decl::NonTypeTemplateParm)
209  return false;
210 
211  // Check for non-static data member.
212  if (isa<FieldDecl>(D))
213  return false;
214 
215  // Check for SYCL device global attribute decoration.
216  if (isTypeDecoratedWithDeclAttribute<SYCLDeviceGlobalAttr>(VD->getType()))
217  return false;
218 
219  // Check for constant variables and variables in the OpenCL constant
220  // address space.
221  if (VD->getType().isConstQualified() ||
222  VD->getType().getAddressSpace() == LangAS::opencl_constant)
223  return false;
224 
225  // Check for static storage class or local storage.
226  if (VD->getStorageClass() == SC_Static || VD->hasLocalStorage())
227  return false;
228 
229  return true;
230 }
231 
232 // Handles reqd_work_group_size.
233 // If the 'reqd_work_group_size' attribute is specified on a declaration along
234 // with 'num_simd_work_items' attribute, the required work group size specified
235 // by 'num_simd_work_items' attribute must evenly divide the index that
236 // increments fastest in the 'reqd_work_group_size' attribute.
237 //
238 // The arguments to reqd_work_group_size are ordered based on which index
239 // increments the fastest. In OpenCL, the first argument is the index that
240 // increments the fastest, and in SYCL, the last argument is the index that
241 // increments the fastest.
242 //
243 // __attribute__((reqd_work_group_size)) follows the OpenCL rules in OpenCL
244 // mode. All spellings of reqd_work_group_size attribute (regardless of
245 // syntax used) follow the SYCL rules when in SYCL mode.
246 bool SemaSYCL::checkWorkGroupSize(const Expr *NSWIValue, const Expr *RWGSXDim,
247  const Expr *RWGSYDim, const Expr *RWGSZDim) {
248  // If any of the operand is still value dependent, we can't test anything.
249  const auto *NSWIValueExpr = dyn_cast<ConstantExpr>(NSWIValue);
250  const auto *RWGSXDimExpr = dyn_cast<ConstantExpr>(RWGSXDim);
251 
252  if (!NSWIValueExpr || !RWGSXDimExpr)
253  return false;
254 
255  // Y and Z may be optional so we allow them to be null and consider them
256  // dependent if the original epxression was not null while the result of the
257  // cast is.
258  const auto *RWGSYDimExpr = dyn_cast_or_null<ConstantExpr>(RWGSYDim);
259  const auto *RWGSZDimExpr = dyn_cast_or_null<ConstantExpr>(RWGSZDim);
260 
261  if ((!RWGSYDimExpr && RWGSYDim) || (!RWGSZDimExpr && RWGSZDim))
262  return false;
263 
264  // Otherwise, check which argument increments the fastest.
265  const ConstantExpr *LastRWGSDimExpr =
266  RWGSZDim ? RWGSZDimExpr : (RWGSYDim ? RWGSYDimExpr : RWGSXDimExpr);
267  unsigned WorkGroupSize = LastRWGSDimExpr->getResultAsAPSInt().getZExtValue();
268 
269  // Check if the required work group size specified by 'num_simd_work_items'
270  // attribute evenly divides the index that increments fastest in the
271  // 'reqd_work_group_size' attribute.
272  return WorkGroupSize % NSWIValueExpr->getResultAsAPSInt().getZExtValue() != 0;
273 }
274 
275 // Checks correctness of mutual usage of different work_group_size attributes:
276 // reqd_work_group_size and max_work_group_size.
277 //
278 // If the 'reqd_work_group_size' attribute is specified on a declaration along
279 // with 'max_work_group_size' attribute, check to see if values of
280 // 'reqd_work_group_size' attribute arguments are equal to or less than values
281 // of 'max_work_group_size' attribute arguments.
282 //
283 // The arguments to reqd_work_group_size are ordered based on which index
284 // increments the fastest. In OpenCL, the first argument is the index that
285 // increments the fastest, and in SYCL, the last argument is the index that
286 // increments the fastest.
287 //
288 // __attribute__((reqd_work_group_size)) follows the OpenCL rules in OpenCL
289 // mode. All spellings of reqd_work_group_size attribute (regardless of
290 // syntax used) follow the SYCL rules when in SYCL mode.
292  const Expr *RWGSXDim, const Expr *RWGSYDim, const Expr *RWGSZDim,
293  const Expr *MWGSXDim, const Expr *MWGSYDim, const Expr *MWGSZDim) {
294  // If any of the operand is still value dependent, we can't test anything.
295  const auto *RWGSXDimExpr = dyn_cast<ConstantExpr>(RWGSXDim);
296  const auto *MWGSXDimExpr = dyn_cast<ConstantExpr>(MWGSXDim);
297  const auto *MWGSYDimExpr = dyn_cast<ConstantExpr>(MWGSYDim);
298  const auto *MWGSZDimExpr = dyn_cast<ConstantExpr>(MWGSZDim);
299 
300  if (!RWGSXDimExpr || !MWGSXDimExpr || !MWGSYDimExpr || !MWGSZDimExpr)
301  return false;
302 
303  // Y and Z may be optional so we allow them to be null and consider them
304  // dependent if the original epxression was not null while the result of the
305  // cast is.
306  const auto *RWGSYDimExpr = dyn_cast_or_null<ConstantExpr>(RWGSYDim);
307  const auto *RWGSZDimExpr = dyn_cast_or_null<ConstantExpr>(RWGSZDim);
308 
309  if ((!RWGSYDimExpr && RWGSYDim) || (!RWGSZDimExpr && RWGSZDim))
310  return false;
311 
312  // SYCL reorders arguments based on the dimensionality.
313  // If we only have the X-dimension, there is no change to the expressions,
314  // otherwise the last specified dimension acts as the first dimension in the
315  // work-group size.
316  const ConstantExpr *FirstRWGDimExpr = RWGSXDimExpr;
317  const ConstantExpr *SecondRWGDimExpr = RWGSYDimExpr;
318  const ConstantExpr *ThirdRWGDimExpr = RWGSZDimExpr;
319  if (getLangOpts().SYCLIsDevice && RWGSYDim)
320  std::swap(FirstRWGDimExpr, RWGSZDim ? ThirdRWGDimExpr : SecondRWGDimExpr);
321 
322  // Check if values of 'reqd_work_group_size' attribute arguments are greater
323  // than values of 'max_work_group_size' attribute arguments.
324  bool CheckFirstArgument =
325  FirstRWGDimExpr->getResultAsAPSInt().getZExtValue() >
326  MWGSZDimExpr->getResultAsAPSInt().getZExtValue();
327 
328  bool CheckSecondArgument =
329  SecondRWGDimExpr && SecondRWGDimExpr->getResultAsAPSInt().getZExtValue() >
330  MWGSYDimExpr->getResultAsAPSInt().getZExtValue();
331 
332  bool CheckThirdArgument =
333  ThirdRWGDimExpr && ThirdRWGDimExpr->getResultAsAPSInt().getZExtValue() >
334  MWGSXDimExpr->getResultAsAPSInt().getZExtValue();
335 
336  return CheckFirstArgument || CheckSecondArgument || CheckThirdArgument;
337 }
338 
339 // Checks correctness of mutual usage of different work_group_size attributes:
340 // reqd_work_group_size, max_work_group_size, and max_global_work_dim.
341 //
342 // If [[intel::max_work_group_size(X, Y, Z)]] or
343 // [[sycl::reqd_work_group_size(X, Y, Z)]] or
344 // [[cl::reqd_work_group_size(X, Y, Z)]]
345 // or __attribute__((reqd_work_group_size)) attribute is specified on a
346 // declaration along with [[intel::max_global_work_dim()]] attribute, check to
347 // see if all arguments of 'max_work_group_size' or different spellings of
348 // 'reqd_work_group_size' attribute hold value 1 in case the argument of
349 // [[intel::max_global_work_dim()]] attribute value equals to 0.
350 bool SemaSYCL::areInvalidWorkGroupSizeAttrs(const Expr *MGValue,
351  const Expr *XDim, const Expr *YDim,
352  const Expr *ZDim) {
353  // If any of the operand is still value dependent, we can't test anything.
354  const auto *MGValueExpr = dyn_cast<ConstantExpr>(MGValue);
355  const auto *XDimExpr = dyn_cast<ConstantExpr>(XDim);
356 
357  if (!MGValueExpr || !XDimExpr)
358  return false;
359 
360  // Y and Z may be optional so we allow them to be null and consider them
361  // dependent if the original epxression was not null while the result of the
362  // cast is.
363  const auto *YDimExpr = dyn_cast_or_null<ConstantExpr>(YDim);
364  const auto *ZDimExpr = dyn_cast_or_null<ConstantExpr>(ZDim);
365 
366  if ((!YDimExpr && YDim) || (!ZDimExpr && ZDim))
367  return false;
368 
369  // Otherwise, check if the attribute values are equal to one.
370  // Y and Z dimensions are optional and are considered trivially 1 if
371  // unspecified.
372  return (MGValueExpr->getResultAsAPSInt() == 0 &&
373  (XDimExpr->getResultAsAPSInt() != 1 ||
374  (YDimExpr && YDimExpr->getResultAsAPSInt() != 1) ||
375  (ZDimExpr && ZDimExpr->getResultAsAPSInt() != 1)));
376 }
377 
379  const AttributeCommonInfo &CI,
380  Expr *E) {
381  if (!E->isValueDependent()) {
382  // Validate that we have an integer constant expression and then store the
383  // converted constant expression into the semantic attribute so that we
384  // don't have to evaluate it again later.
385  llvm::APSInt ArgVal;
387  if (Res.isInvalid())
388  return;
389  E = Res.get();
390 
391  // This attribute accepts values 0 and 1 only.
392  if (ArgVal < 0 || ArgVal > 1) {
393  Diag(E->getBeginLoc(), diag::err_attribute_argument_is_not_valid) << CI;
394  return;
395  }
396 
397  // Check attribute applies to field, constant variables, local variables,
398  // static variables, agent memory arguments, non-static data members,
399  // and device_global variables for the device compilation.
401  Diag(CI.getLoc(), diag::err_fpga_attribute_incorrect_variable)
402  << CI << /*agent memory arguments*/ 1;
403  return;
404  }
405 
406  // Check to see if there's a duplicate attribute with different values
407  // already applied to the declaration.
408  if (const auto *DeclAttr = D->getAttr<SYCLIntelForcePow2DepthAttr>()) {
409  // If the other attribute argument is instantiation dependent, we won't
410  // have converted it to a constant expression yet and thus we test
411  // whether this is a null pointer.
412  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
413  if (ArgVal != DeclExpr->getResultAsAPSInt()) {
414  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
415  Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
416  }
417  // If there is no mismatch, drop any duplicate attributes.
418  return;
419  }
420  }
421  }
422 
423  // If the declaration does not have an [[intel::fpga_memory]]
424  // attribute, this creates one as an implicit attribute.
425  ASTContext &Context = getASTContext();
426  if (!D->hasAttr<SYCLIntelMemoryAttr>())
427  D->addAttr(SYCLIntelMemoryAttr::CreateImplicit(
428  Context, SYCLIntelMemoryAttr::Default));
429 
430  D->addAttr(::new (Context) SYCLIntelForcePow2DepthAttr(Context, CI, E));
431 }
432 
433 /// Handle the [[intel::bankwidth]] and [[intel::numbanks]] attributes.
434 /// These require a single constant power of two greater than zero.
435 /// These are incompatible with the register attribute.
436 /// The numbanks and bank_bits attributes are related. If bank_bits exists
437 /// when handling numbanks they are checked for consistency.
439  Expr *E) {
440  if (!E->isValueDependent()) {
441  // Validate that we have an integer constant expression and then store the
442  // converted constant expression into the semantic attribute so that we
443  // don't have to evaluate it again later.
444  llvm::APSInt ArgVal;
446  if (Res.isInvalid())
447  return;
448  E = Res.get();
449 
450  // This attribute requires a strictly positive value.
451  if (ArgVal <= 0) {
452  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
453  << CI << /*positive*/ 0;
454  return;
455  }
456 
457  // This attribute requires a single constant power of two greater than zero.
458  if (!ArgVal.isPowerOf2()) {
459  Diag(E->getExprLoc(), diag::err_attribute_argument_not_power_of_two)
460  << CI;
461  return;
462  }
463 
464  // Check attribute applies to field, constant variables, local variables,
465  // static variables, agent memory arguments, non-static data members,
466  // and device_global variables for the device compilation.
468  Diag(CI.getLoc(), diag::err_fpga_attribute_incorrect_variable)
469  << CI << /*agent memory arguments*/ 1;
470  return;
471  }
472 
473  // Check to see if there's a duplicate attribute with different values
474  // already applied to the declaration.
475  if (const auto *DeclAttr = D->getAttr<SYCLIntelBankWidthAttr>()) {
476  // If the other attribute argument is instantiation dependent, we won't
477  // have converted it to a constant expression yet and thus we test
478  // whether this is a null pointer.
479  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
480  if (ArgVal != DeclExpr->getResultAsAPSInt()) {
481  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
482  Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
483  }
484  // Drop the duplicate attribute.
485  return;
486  }
487  }
488  }
489 
490  // If the declaration does not have an [[intel::fpga_memory]]
491  // attribute, this creates one as an implicit attribute.
492  ASTContext &Context = getASTContext();
493  if (!D->hasAttr<SYCLIntelMemoryAttr>())
494  D->addAttr(SYCLIntelMemoryAttr::CreateImplicit(
495  Context, SYCLIntelMemoryAttr::Default));
496 
497  D->addAttr(::new (Context) SYCLIntelBankWidthAttr(Context, CI, E));
498 }
499 
501  Expr *E) {
502  if (!E->isValueDependent()) {
503  // Validate that we have an integer constant expression and then store the
504  // converted constant expression into the semantic attribute so that we
505  // don't have to evaluate it again later.
506  llvm::APSInt ArgVal;
508  if (Res.isInvalid())
509  return;
510  E = Res.get();
511 
512  // This attribute requires a strictly positive value.
513  if (ArgVal <= 0) {
514  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
515  << CI << /*positive*/ 0;
516  return;
517  }
518 
519  // This attribute requires a single constant power of two greater than zero.
520  if (!ArgVal.isPowerOf2()) {
521  Diag(E->getExprLoc(), diag::err_attribute_argument_not_power_of_two)
522  << CI;
523  return;
524  }
525 
526  // Check or add the related BankBits attribute.
527  if (auto *BBA = D->getAttr<SYCLIntelBankBitsAttr>()) {
528  unsigned NumBankBits = BBA->args_size();
529  if (NumBankBits != ArgVal.ceilLogBase2()) {
530  Diag(E->getExprLoc(), diag::err_bankbits_numbanks_conflicting) << CI;
531  return;
532  }
533  }
534 
535  // Check attribute applies to constant variables, local variables,
536  // static variables, agent memory arguments, non-static data members,
537  // and device_global variables for the device compilation.
539  Diag(CI.getLoc(), diag::err_fpga_attribute_incorrect_variable)
540  << CI << /*agent memory arguments*/ 1;
541  return;
542  }
543 
544  // Check to see if there's a duplicate attribute with different values
545  // already applied to the declaration.
546  if (const auto *DeclAttr = D->getAttr<SYCLIntelNumBanksAttr>()) {
547  // If the other attribute argument is instantiation dependent, we won't
548  // have converted it to a constant expression yet and thus we test
549  // whether this is a null pointer.
550  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
551  if (ArgVal != DeclExpr->getResultAsAPSInt()) {
552  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
553  Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
554  }
555  // Drop the duplicate attribute.
556  return;
557  }
558  }
559  }
560 
561  // If the declaration does not have an [[intel::fpga_memory]]
562  // attribute, this creates one as an implicit attribute.
563  ASTContext &Context = getASTContext();
564  if (!D->hasAttr<SYCLIntelMemoryAttr>())
565  D->addAttr(SYCLIntelMemoryAttr::CreateImplicit(
566  Context, SYCLIntelMemoryAttr::Default));
567 
568  // We are adding a user NumBanks attribute, drop any implicit default.
569  if (auto *NBA = D->getAttr<SYCLIntelNumBanksAttr>()) {
570  if (NBA->isImplicit())
571  D->dropAttr<SYCLIntelNumBanksAttr>();
572  }
573 
574  D->addAttr(::new (Context) SYCLIntelNumBanksAttr(Context, CI, E));
575 }
576 
578  Expr **Exprs, unsigned Size) {
579  ASTContext &Context = getASTContext();
580  SYCLIntelBankBitsAttr TmpAttr(Context, CI, Exprs, Size);
583  bool ListIsValueDep = false;
584  for (auto *E : TmpAttr.args()) {
585  llvm::APSInt Value(32, /*IsUnsigned=*/false);
586  Expr::EvalResult Result;
587  ListIsValueDep = ListIsValueDep || E->isValueDependent();
588  if (!E->isValueDependent()) {
590  if (ICE.isInvalid())
591  return;
592  if (!Value.isNonNegative()) {
593  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
594  << CI << /*non-negative*/ 1;
595  return;
596  }
597  E = ICE.get();
598  }
599  Args.push_back(E);
600  Values.push_back(Value.getExtValue());
601  }
602 
603  // Check that the list is consecutive.
604  if (!ListIsValueDep && Values.size() > 1) {
605  bool ListIsAscending = Values[0] < Values[1];
606  for (int I = 0, E = Values.size() - 1; I < E; ++I) {
607  if (Values[I + 1] != Values[I] + (ListIsAscending ? 1 : -1)) {
608  Diag(CI.getLoc(), diag::err_bankbits_non_consecutive) << &TmpAttr;
609  return;
610  }
611  }
612  }
613 
614  // Check or add the related numbanks attribute.
615  if (auto *NBA = D->getAttr<SYCLIntelNumBanksAttr>()) {
616  Expr *E = NBA->getValue();
617  if (!E->isValueDependent()) {
618  Expr::EvalResult Result;
619  E->EvaluateAsInt(Result, Context);
620  llvm::APSInt Value = Result.Val.getInt();
621  if (Args.size() != Value.ceilLogBase2()) {
622  Diag(TmpAttr.getLoc(), diag::err_bankbits_numbanks_conflicting);
623  return;
624  }
625  }
626  } else {
627  llvm::APInt Num(32, (unsigned)(1 << Args.size()));
628  Expr *NBE =
629  IntegerLiteral::Create(Context, Num, Context.IntTy, SourceLocation());
630  D->addAttr(SYCLIntelNumBanksAttr::CreateImplicit(Context, NBE));
631  }
632 
633  // Check attribute applies to field, constant variables, local variables,
634  // static variables, agent memory arguments, non-static data members,
635  // and device_global variables for the device compilation.
637  Diag(CI.getLoc(), diag::err_fpga_attribute_incorrect_variable)
638  << CI << /*agent memory arguments*/ 1;
639  return;
640  }
641 
642  if (!D->hasAttr<SYCLIntelMemoryAttr>())
643  D->addAttr(SYCLIntelMemoryAttr::CreateImplicit(
644  Context, SYCLIntelMemoryAttr::Default));
645 
646  D->addAttr(::new (Context)
647  SYCLIntelBankBitsAttr(Context, CI, Args.data(), Args.size()));
648 }
649 
650 bool isDeviceAspectType(const QualType Ty) {
651  const EnumType *ET = Ty->getAs<EnumType>();
652  if (!ET)
653  return false;
654 
655  if (const auto *Attr = ET->getDecl()->getAttr<SYCLTypeAttr>())
656  return Attr->getType() == SYCLTypeAttr::aspect;
657 
658  return false;
659 }
660 
662  Expr **Exprs, unsigned Size) {
663  ASTContext &Context = getASTContext();
664  SYCLDeviceHasAttr TmpAttr(Context, CI, Exprs, Size);
665  SmallVector<Expr *, 5> Aspects;
666  for (auto *E : TmpAttr.aspects())
667  if (!isa<PackExpansionExpr>(E) && !isDeviceAspectType(E->getType()))
668  Diag(E->getExprLoc(), diag::err_sycl_invalid_aspect_argument) << CI;
669 
670  if (const auto *ExistingAttr = D->getAttr<SYCLDeviceHasAttr>()) {
671  Diag(CI.getLoc(), diag::warn_duplicate_attribute_exact) << CI;
672  Diag(ExistingAttr->getLoc(), diag::note_previous_attribute);
673  return;
674  }
675 
676  D->addAttr(::new (Context) SYCLDeviceHasAttr(Context, CI, Exprs, Size));
677 }
678 
680  Expr **Exprs, unsigned Size) {
681  ASTContext &Context = getASTContext();
682  SYCLUsesAspectsAttr TmpAttr(Context, CI, Exprs, Size);
683  SmallVector<Expr *, 5> Aspects;
684  for (auto *E : TmpAttr.aspects())
685  if (!isDeviceAspectType(E->getType()))
686  Diag(E->getExprLoc(), diag::err_sycl_invalid_aspect_argument) << CI;
687 
688  if (const auto *ExistingAttr = D->getAttr<SYCLUsesAspectsAttr>()) {
689  Diag(CI.getLoc(), diag::warn_duplicate_attribute_exact) << CI;
690  Diag(ExistingAttr->getLoc(), diag::note_previous_attribute);
691  return;
692  }
693 
694  D->addAttr(::new (Context) SYCLUsesAspectsAttr(Context, CI, Exprs, Size));
695 }
696 
698  Expr *E) {
699  VarDecl *VD = cast<VarDecl>(D);
700  QualType Ty = VD->getType();
701  // TODO: Applicable only on pipe storages. Currently they are defined
702  // as structures inside of SYCL headers. Add a check for pipe_storage_t
703  // when it is ready.
704  if (!Ty->isStructureType()) {
705  Diag(CI.getLoc(), diag::err_attribute_wrong_decl_type_str)
706  << CI << CI.isRegularKeywordAttribute()
707  << "SYCL pipe storage declaration";
708  return;
709  }
710 
711  if (!E->isValueDependent()) {
712  // Validate that we have an integer constant expression and then store the
713  // converted constant expression into the semantic attribute so that we
714  // don't have to evaluate it again later.
715  llvm::APSInt ArgVal;
717  if (Res.isInvalid())
718  return;
719  E = Res.get();
720 
721  // This attribute requires a non-negative value.
722  if (ArgVal < 0) {
723  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
724  << CI << /*non-negative*/ 1;
725  return;
726  }
727 
728  // Check to see if there's a duplicate attribute with different values
729  // already applied to the declaration.
730  if (const auto *DeclAttr = D->getAttr<SYCLIntelPipeIOAttr>()) {
731  // If the other attribute argument is instantiation dependent, we won't
732  // have converted it to a constant expression yet and thus we test
733  // whether this is a null pointer.
734  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getID())) {
735  if (ArgVal != DeclExpr->getResultAsAPSInt()) {
736  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
737  Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
738  }
739  // Drop the duplicate attribute.
740  return;
741  }
742  }
743  }
744 
745  ASTContext &Context = getASTContext();
746  D->addAttr(::new (Context) SYCLIntelPipeIOAttr(Context, CI, E));
747 }
748 
749 // Handles [[intel::loop_fuse]] and [[intel::loop_fuse_independent]].
751  Expr *E) {
752  if (!E->isValueDependent()) {
753  // Validate that we have an integer constant expression and then store the
754  // converted constant expression into the semantic attribute so that we
755  // don't have to evaluate it again later.
756  llvm::APSInt ArgVal;
758  if (Res.isInvalid())
759  return;
760  E = Res.get();
761 
762  // This attribute requires a non-negative value.
763  if (ArgVal < 0) {
764  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
765  << CI << /*non-negative*/ 1;
766  return;
767  }
768  // Check to see if there's a duplicate attribute with different values
769  // already applied to the declaration.
770  if (const auto *DeclAttr = D->getAttr<SYCLIntelLoopFuseAttr>()) {
771  // [[intel::loop_fuse]] and [[intel::loop_fuse_independent]] are
772  // incompatible.
773  // FIXME: If additional spellings are provided for this attribute,
774  // this code will do the wrong thing.
775  if (DeclAttr->getAttributeSpellingListIndex() !=
777  Diag(CI.getLoc(), diag::err_attributes_are_not_compatible)
778  << CI << DeclAttr << CI.isRegularKeywordAttribute();
779  Diag(DeclAttr->getLocation(), diag::note_conflicting_attribute);
780  return;
781  }
782  // If the other attribute argument is instantiation dependent, we won't
783  // have converted it to a constant expression yet and thus we test
784  // whether this is a null pointer.
785  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
786  if (ArgVal != DeclExpr->getResultAsAPSInt()) {
787  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
788  Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
789  }
790  // Drop the duplicate attribute.
791  return;
792  }
793  }
794  }
795 
796  ASTContext &Context = getASTContext();
797  D->addAttr(::new (Context) SYCLIntelLoopFuseAttr(Context, CI, E));
798 }
799 
801  const AttributeCommonInfo &CI,
802  Expr *E) {
803  ASTContext &Context = getASTContext();
804  if (!E->isValueDependent()) {
805  // Validate that we have an integer constant expression and then store the
806  // converted constant expression into the semantic attribute so that we
807  // don't have to evaluate it again later.
808  llvm::APSInt ArgVal;
810  if (Res.isInvalid())
811  return;
812  E = Res.get();
813 
814  // This attribute requires a strictly positive value.
815  if (ArgVal <= 0) {
816  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
817  << CI << /*positive*/ 0;
818  return;
819  }
820  auto &TI = Context.getTargetInfo();
821  if (TI.getTriple().isNVPTX() && ArgVal != 32)
822  Diag(E->getExprLoc(), diag::warn_reqd_sub_group_attribute_n)
823  << ArgVal.getSExtValue() << TI.getTriple().getArchName() << 32;
824  if (TI.getTriple().isAMDGPU()) {
825  const auto HasWaveFrontSize64 =
826  TI.getTargetOpts().FeatureMap["wavefrontsize64"];
827  const auto HasWaveFrontSize32 =
828  TI.getTargetOpts().FeatureMap["wavefrontsize32"];
829 
830  // CDNA supports only 64 wave front size, for those GPUs allow subgroup
831  // size of 64. Some GPUs support both 32 and 64, for those (and the rest)
832  // only allow 32. Warn on incompatible sizes.
833  const auto SupportedWaveFrontSize =
834  HasWaveFrontSize64 && !HasWaveFrontSize32 ? 64 : 32;
835  if (ArgVal != SupportedWaveFrontSize)
836  Diag(E->getExprLoc(), diag::warn_reqd_sub_group_attribute_n)
837  << ArgVal.getSExtValue() << TI.getTriple().getArchName()
838  << SupportedWaveFrontSize;
839  }
840 
841  // Check to see if there's a duplicate attribute with different values
842  // already applied to the declaration.
843  if (const auto *DeclAttr = D->getAttr<IntelReqdSubGroupSizeAttr>()) {
844  // If the other attribute argument is instantiation dependent, we won't
845  // have converted it to a constant expression yet and thus we test
846  // whether this is a null pointer.
847  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
848  if (ArgVal != DeclExpr->getResultAsAPSInt()) {
849  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
850  Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
851  }
852  // Drop the duplicate attribute.
853  return;
854  }
855  }
856  }
857 
858  D->addAttr(::new (Context) IntelReqdSubGroupSizeAttr(Context, CI, E));
859 }
860 
862  const AttributeCommonInfo &CI,
863  Expr *E) {
864  if (!E->isValueDependent()) {
865  // Validate that we have an integer constant expression and then store the
866  // converted constant expression into the semantic attribute so that we
867  // don't have to evaluate it again later.
868  llvm::APSInt ArgVal;
870  if (Res.isInvalid())
871  return;
872  E = Res.get();
873 
874  // This attribute requires a strictly positive value.
875  if (ArgVal <= 0) {
876  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
877  << CI << /*positive*/ 0;
878  return;
879  }
880 
881  // Check to see if there's a duplicate attribute with different values
882  // already applied to the declaration.
883  if (const auto *DeclAttr = D->getAttr<SYCLIntelNumSimdWorkItemsAttr>()) {
884  // If the other attribute argument is instantiation dependent, we won't
885  // have converted it to a constant expression yet and thus we test
886  // whether this is a null pointer.
887  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
888  if (ArgVal != DeclExpr->getResultAsAPSInt()) {
889  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
890  Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
891  }
892  // Drop the duplicate attribute.
893  return;
894  }
895  }
896 
897  // If the 'reqd_work_group_size' attribute is specified on a declaration
898  // along with 'num_simd_work_items' attribute, the required work group size
899  // specified by 'num_simd_work_items' attribute must evenly divide the index
900  // that increments fastest in the 'reqd_work_group_size' attribute.
901  if (const auto *DeclAttr = D->getAttr<SYCLReqdWorkGroupSizeAttr>()) {
902  if (checkWorkGroupSize(E, DeclAttr->getXDim(), DeclAttr->getYDim(),
903  DeclAttr->getZDim())) {
904  Diag(CI.getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size)
905  << CI << DeclAttr;
906  Diag(DeclAttr->getLoc(), diag::note_conflicting_attribute);
907  return;
908  }
909  }
910  }
911 
912  ASTContext &Context = getASTContext();
913  D->addAttr(::new (Context) SYCLIntelNumSimdWorkItemsAttr(Context, CI, E));
914 }
915 
916 // Handle scheduler_target_fmax_mhz
918  Decl *D, const AttributeCommonInfo &CI, Expr *E) {
919  if (!E->isValueDependent()) {
920  // Validate that we have an integer constant expression and then store the
921  // converted constant expression into the semantic attribute so that we
922  // don't have to evaluate it again later.
923  llvm::APSInt ArgVal;
925  if (Res.isInvalid())
926  return;
927  E = Res.get();
928 
929  // This attribute requires a non-negative value.
930  if (ArgVal < 0) {
931  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
932  << CI << /*non-negative*/ 1;
933  return;
934  }
935  // Check to see if there's a duplicate attribute with different values
936  // already applied to the declaration.
937  if (const auto *DeclAttr =
938  D->getAttr<SYCLIntelSchedulerTargetFmaxMhzAttr>()) {
939  // If the other attribute argument is instantiation dependent, we won't
940  // have converted it to a constant expression yet and thus we test
941  // whether this is a null pointer.
942  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
943  if (ArgVal != DeclExpr->getResultAsAPSInt()) {
944  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
945  Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
946  }
947  // Drop the duplicate attribute.
948  return;
949  }
950  }
951  }
952 
953  ASTContext &Context = getASTContext();
954  D->addAttr(::new (Context)
955  SYCLIntelSchedulerTargetFmaxMhzAttr(Context, CI, E));
956 }
957 
959  const AttributeCommonInfo &CI,
960  Expr *E) {
961  if (!E->isValueDependent()) {
962  // Validate that we have an integer constant expression and then store the
963  // converted constant expression into the semantic attribute so that we
964  // don't have to evaluate it again later.
965  llvm::APSInt ArgVal;
967  if (Res.isInvalid())
968  return;
969  E = Res.get();
970 
971  // Check to see if there's a duplicate attribute with different values
972  // already applied to the declaration.
973  if (const auto *DeclAttr = D->getAttr<SYCLIntelNoGlobalWorkOffsetAttr>()) {
974  // If the other attribute argument is instantiation dependent, we won't
975  // have converted it to a constant expression yet and thus we test
976  // whether this is a null pointer.
977  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
978  if (ArgVal != DeclExpr->getResultAsAPSInt()) {
979  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
980  Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
981  }
982  // Drop the duplicate attribute.
983  return;
984  }
985  }
986  }
987 
988  ASTContext &Context = getASTContext();
989  D->addAttr(::new (Context) SYCLIntelNoGlobalWorkOffsetAttr(Context, CI, E));
990 }
991 
993  const AttributeCommonInfo &CI,
994  Expr *E) {
995  if (!E->isValueDependent()) {
996  // Validate that we have an integer constant expression and then store the
997  // converted constant expression into the semantic attribute so that we
998  // don't have to evaluate it again later.
999  llvm::APSInt ArgVal;
1001  if (Res.isInvalid())
1002  return;
1003  E = Res.get();
1004 
1005  // This attribute must be in the range [0, 3].
1006  if (ArgVal < 0 || ArgVal > 3) {
1007  Diag(E->getBeginLoc(), diag::err_attribute_argument_out_of_range)
1008  << CI << 0 << 3 << E->getSourceRange();
1009  return;
1010  }
1011 
1012  // Check to see if there's a duplicate attribute with different values
1013  // already applied to the declaration.
1014  if (const auto *DeclAttr = D->getAttr<SYCLIntelMaxGlobalWorkDimAttr>()) {
1015  // If the other attribute argument is instantiation dependent, we won't
1016  // have converted it to a constant expression yet and thus we test
1017  // whether this is a null pointer.
1018  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
1019  if (ArgVal != DeclExpr->getResultAsAPSInt()) {
1020  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
1021  Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
1022  }
1023  // Drop the duplicate attribute.
1024  return;
1025  }
1026  }
1027 
1028  // If the declaration has a SYCLIntelMaxWorkGroupSizeAttr or
1029  // SYCLReqdWorkGroupSizeAttr, check to see if the attribute holds values
1030  // equal to (1, 1, 1) in case the value of SYCLIntelMaxGlobalWorkDimAttr
1031  // equals to 0.
1032  if (ArgVal == 0) {
1033  if (checkWorkGroupSizeAttrExpr<SYCLIntelMaxWorkGroupSizeAttr>(D, CI) ||
1034  checkWorkGroupSizeAttrExpr<SYCLReqdWorkGroupSizeAttr>(D, CI))
1035  return;
1036  }
1037  }
1038 
1039  ASTContext &Context = getASTContext();
1040  D->addAttr(::new (Context) SYCLIntelMaxGlobalWorkDimAttr(Context, CI, E));
1041 }
1042 
1043 // Check that the value is a non-negative integer constant that can fit in
1044 // 32-bits. Issue correct error message and return false on failure.
1045 bool static check32BitInt(const Expr *E, SemaSYCL &S, llvm::APSInt &I,
1046  const AttributeCommonInfo &CI) {
1047  if (!I.isIntN(32)) {
1048  S.Diag(E->getExprLoc(), diag::err_ice_too_large)
1049  << llvm::toString(I, 10, false) << 32 << /* Unsigned */ 1;
1050  return false;
1051  }
1052 
1053  if (I.isSigned() && I.isNegative()) {
1054  S.Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
1055  << CI << /* Non-negative */ 1;
1056  return false;
1057  }
1058 
1059  return true;
1060 }
1061 
1063  Decl *D, const AttributeCommonInfo &CI, Expr *E) {
1064  ASTContext &Context = getASTContext();
1065  if (getLangOpts().SYCLIsDevice) {
1066  if (!Context.getTargetInfo().getTriple().isNVPTX()) {
1067  Diag(E->getBeginLoc(), diag::warn_launch_bounds_is_cuda_specific)
1068  << CI << E->getSourceRange();
1069  return;
1070  }
1071 
1072  if (!D->hasAttr<SYCLIntelMaxWorkGroupSizeAttr>()) {
1073  Diag(CI.getLoc(), diag::warn_launch_bounds_missing_attr) << CI << 0;
1074  return;
1075  }
1076  }
1077  if (!E->isValueDependent()) {
1078  // Validate that we have an integer constant expression and then store the
1079  // converted constant expression into the semantic attribute so that we
1080  // don't have to evaluate it again later.
1081  llvm::APSInt ArgVal;
1083  if (Res.isInvalid())
1084  return;
1085  if (!check32BitInt(E, *this, ArgVal, CI))
1086  return;
1087  E = Res.get();
1088 
1089  // Check to see if there's a duplicate attribute with different values
1090  // already applied to the declaration.
1091  if (const auto *DeclAttr =
1092  D->getAttr<SYCLIntelMinWorkGroupsPerComputeUnitAttr>()) {
1093  // If the other attribute argument is instantiation dependent, we won't
1094  // have converted it to a constant expression yet and thus we test
1095  // whether this is a null pointer.
1096  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
1097  if (ArgVal != DeclExpr->getResultAsAPSInt()) {
1098  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
1099  Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
1100  }
1101  // Drop the duplicate attribute.
1102  return;
1103  }
1104  }
1105  }
1106 
1107  D->addAttr(::new (Context)
1108  SYCLIntelMinWorkGroupsPerComputeUnitAttr(Context, CI, E));
1109 }
1110 
1112  Decl *D, const AttributeCommonInfo &CI, Expr *E) {
1113  ASTContext &Context = getASTContext();
1114  auto &TI = Context.getTargetInfo();
1115  if (Context.getLangOpts().SYCLIsDevice) {
1116  if (!TI.getTriple().isNVPTX()) {
1117  Diag(E->getBeginLoc(), diag::warn_launch_bounds_is_cuda_specific)
1118  << CI << E->getSourceRange();
1119  return;
1120  }
1121 
1122  // Feature '.maxclusterrank' requires .target sm_90 or higher.
1123  auto SM = getOffloadArch(TI);
1125  Diag(E->getBeginLoc(), diag::warn_cuda_maxclusterrank_sm_90)
1126  << OffloadArchToString(SM) << CI << E->getSourceRange();
1127  return;
1128  }
1129 
1130  if (!D->hasAttr<SYCLIntelMaxWorkGroupSizeAttr>() ||
1131  !D->hasAttr<SYCLIntelMinWorkGroupsPerComputeUnitAttr>()) {
1132  Diag(CI.getLoc(), diag::warn_launch_bounds_missing_attr) << CI << 1;
1133  return;
1134  }
1135  }
1136  if (!E->isValueDependent()) {
1137  // Validate that we have an integer constant expression and then store the
1138  // converted constant expression into the semantic attribute so that we
1139  // don't have to evaluate it again later.
1140  llvm::APSInt ArgVal;
1142  if (Res.isInvalid())
1143  return;
1144  if (!check32BitInt(E, *this, ArgVal, CI))
1145  return;
1146  E = Res.get();
1147 
1148  // Check to see if there's a duplicate attribute with different values
1149  // already applied to the declaration.
1150  if (const auto *DeclAttr =
1151  D->getAttr<SYCLIntelMaxWorkGroupsPerMultiprocessorAttr>()) {
1152  // If the other attribute argument is instantiation dependent, we won't
1153  // have converted it to a constant expression yet and thus we test
1154  // whether this is a null pointer.
1155  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
1156  if (ArgVal != DeclExpr->getResultAsAPSInt()) {
1157  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
1158  Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
1159  }
1160  // Drop the duplicate attribute.
1161  return;
1162  }
1163  }
1164  }
1165 
1166  D->addAttr(::new (Context)
1167  SYCLIntelMaxWorkGroupsPerMultiprocessorAttr(Context, CI, E));
1168 }
1169 
1171  const AttributeCommonInfo &CI,
1172  Expr *E) {
1173  if (!E->isValueDependent()) {
1174  llvm::APSInt ArgVal;
1176  if (Res.isInvalid())
1177  return;
1178  E = Res.get();
1179 
1180  // This attribute requires a non-negative value.
1181  if (ArgVal < 0) {
1182  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
1183  << CI << /*non-negative*/ 1;
1184  return;
1185  }
1186 
1187  // Check to see if there's a duplicate attribute with different values
1188  // already applied to the declaration.
1189  if (const auto *DeclAttr = D->getAttr<SYCLIntelMaxConcurrencyAttr>()) {
1190  // If the other attribute argument is instantiation dependent, we won't
1191  // have converted it to a constant expression yet and thus we test
1192  // whether this is a null pointer.
1193  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getNExpr())) {
1194  if (ArgVal != DeclExpr->getResultAsAPSInt()) {
1195  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
1196  Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
1197  }
1198  // Drop the duplicate attribute.
1199  return;
1200  }
1201  }
1202  }
1203 
1204  ASTContext &Context = getASTContext();
1205  D->addAttr(::new (Context) SYCLIntelMaxConcurrencyAttr(Context, CI, E));
1206 }
1207 
1209  const AttributeCommonInfo &CI,
1210  Expr *E) {
1211  ASTContext &Context = getASTContext();
1212  if (!E->isValueDependent()) {
1213  // Validate that we have an integer constant expression and then store the
1214  // converted constant expression into the semantic attribute so that we
1215  // don't have to evaluate it again later.
1216  llvm::APSInt ArgVal;
1218  if (Res.isInvalid())
1219  return;
1220  E = Res.get();
1221  // This attribute requires a non-negative value.
1222  if (ArgVal < 0) {
1223  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
1224  << CI << /*non-negative*/ 1;
1225  return;
1226  }
1227 
1228  // Check attribute applies to field as well as const variables, non-static
1229  // local variables, non-static data members, and device_global variables.
1230  // for the device compilation.
1231  if (const auto *VD = dyn_cast<VarDecl>(D)) {
1232  if (Context.getLangOpts().SYCLIsDevice &&
1233  (!(isa<FieldDecl>(D) ||
1234  (VD->getKind() != Decl::ImplicitParam &&
1235  VD->getKind() != Decl::NonTypeTemplateParm &&
1236  VD->getKind() != Decl::ParmVar &&
1237  (VD->hasLocalStorage() ||
1238  isTypeDecoratedWithDeclAttribute<SYCLDeviceGlobalAttr>(
1239  VD->getType())))))) {
1240  Diag(CI.getLoc(), diag::err_fpga_attribute_invalid_decl) << CI;
1241  return;
1242  }
1243  }
1244 
1245  // Check to see if there's a duplicate attribute with different values
1246  // already applied to the declaration.
1247  if (const auto *DeclAttr = D->getAttr<SYCLIntelPrivateCopiesAttr>()) {
1248  // If the other attribute argument is instantiation dependent, we won't
1249  // have converted it to a constant expression yet and thus we test
1250  // whether this is a null pointer.
1251  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
1252  if (ArgVal != DeclExpr->getResultAsAPSInt()) {
1253  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
1254  Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
1255  }
1256  // Drop the duplicate attribute.
1257  return;
1258  }
1259  }
1260  }
1261 
1262  // If the declaration does not have [[intel::fpga_memory]]
1263  // attribute, this creates default implicit memory.
1264  if (!D->hasAttr<SYCLIntelMemoryAttr>())
1265  D->addAttr(SYCLIntelMemoryAttr::CreateImplicit(
1266  Context, SYCLIntelMemoryAttr::Default));
1267 
1268  D->addAttr(::new (Context) SYCLIntelPrivateCopiesAttr(Context, CI, E));
1269 }
1270 
1272  const AttributeCommonInfo &CI,
1273  Expr *E) {
1274  if (!E->isValueDependent()) {
1275  // Validate that we have an integer constant expression and then store the
1276  // converted constant expression into the semantic attribute so that we
1277  // don't have to evaluate it again later.
1278  llvm::APSInt ArgVal;
1280  if (Res.isInvalid())
1281  return;
1282  E = Res.get();
1283  // This attribute requires a strictly positive value.
1284  if (ArgVal <= 0) {
1285  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
1286  << CI << /*positive*/ 0;
1287  return;
1288  }
1289 
1290  // Check attribute applies to field, constant variables, local variables,
1291  // static variables, agent memory arguments, non-static data members,
1292  // and device_global variables for the device compilation.
1294  Diag(CI.getLoc(), diag::err_fpga_attribute_incorrect_variable)
1295  << CI << /*agent memory arguments*/ 1;
1296  return;
1297  }
1298 
1299  // Check to see if there's a duplicate attribute with different values
1300  // already applied to the declaration.
1301  if (const auto *DeclAttr = D->getAttr<SYCLIntelMaxReplicatesAttr>()) {
1302  // If the other attribute argument is instantiation dependent, we won't
1303  // have converted it to a constant expression yet and thus we test
1304  // whether this is a null pointer.
1305  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
1306  if (ArgVal != DeclExpr->getResultAsAPSInt()) {
1307  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
1308  Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
1309  }
1310  // Drop the duplicate attribute.
1311  return;
1312  }
1313  }
1314  }
1315 
1316  // If the declaration does not have an [[intel::fpga_memory]]
1317  // attribute, this creates one as an implicit attribute.
1318  ASTContext &Context = getASTContext();
1319  if (!D->hasAttr<SYCLIntelMemoryAttr>())
1320  D->addAttr(SYCLIntelMemoryAttr::CreateImplicit(
1321  Context, SYCLIntelMemoryAttr::Default));
1322 
1323  D->addAttr(::new (Context) SYCLIntelMaxReplicatesAttr(Context, CI, E));
1324 }
1325 
1326 // Handles initiation_interval attribute.
1328  const AttributeCommonInfo &CI,
1329  Expr *E) {
1330  if (!E->isValueDependent()) {
1331  // Validate that we have an integer constant expression and then store the
1332  // converted constant expression into the semantic attribute so that we
1333  // don't have to evaluate it again later.
1334  llvm::APSInt ArgVal;
1336  if (Res.isInvalid())
1337  return;
1338  E = Res.get();
1339  // This attribute requires a strictly positive value.
1340  if (ArgVal <= 0) {
1341  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
1342  << CI << /*positive*/ 0;
1343  return;
1344  }
1345  // Check to see if there's a duplicate attribute with different values
1346  // already applied to the declaration.
1347  if (const auto *DeclAttr = D->getAttr<SYCLIntelInitiationIntervalAttr>()) {
1348  // If the other attribute argument is instantiation dependent, we won't
1349  // have converted it to a constant expression yet and thus we test
1350  // whether this is a null pointer.
1351  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getNExpr())) {
1352  if (ArgVal != DeclExpr->getResultAsAPSInt()) {
1353  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
1354  Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
1355  }
1356  // Drop the duplicate attribute.
1357  return;
1358  }
1359  }
1360  }
1361 
1362  ASTContext &Context = getASTContext();
1363  D->addAttr(::new (Context) SYCLIntelInitiationIntervalAttr(Context, CI, E));
1364 }
1365 
1367  const AttributeCommonInfo &CI,
1368  Expr *E) {
1369  if (!E->isValueDependent()) {
1370  // Validate that we have an integer constant expression and then store the
1371  // converted constant expression into the semantic attribute so that we
1372  // don't have to evaluate it again later.
1373  llvm::APSInt ArgVal;
1375  if (Res.isInvalid())
1376  return;
1377  E = Res.get();
1378 
1379  if (ArgVal != 8 && ArgVal != 16 && ArgVal != 32) {
1380  Diag(E->getExprLoc(), diag::err_sycl_esimd_vectorize_unsupported_value)
1381  << CI;
1382  return;
1383  }
1384 
1385  // Check to see if there's a duplicate attribute with different values
1386  // already applied to the declaration.
1387  if (const auto *DeclAttr = D->getAttr<SYCLIntelESimdVectorizeAttr>()) {
1388  // If the other attribute argument is instantiation dependent, we won't
1389  // have converted it to a constant expression yet and thus we test
1390  // whether this is a null pointer.
1391  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
1392  if (ArgVal != DeclExpr->getResultAsAPSInt()) {
1393  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
1394  Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
1395  }
1396  // Drop the duplicate attribute.
1397  return;
1398  }
1399  }
1400  }
1401 
1402  ASTContext &Context = getASTContext();
1403  D->addAttr(::new (Context) SYCLIntelESimdVectorizeAttr(Context, CI, E));
1404 }
1405 
1406 // Checks if an expression is a valid filter list for an add_ir_attributes_*
1407 // attribute. Returns true if an error occured.
1408 static bool checkAddIRAttributesFilterListExpr(Expr *FilterListArg, SemaSYCL &S,
1409  const AttributeCommonInfo &CI) {
1410  const auto *FilterListE = cast<InitListExpr>(FilterListArg);
1411  for (const Expr *FilterElemE : FilterListE->inits())
1412  if (!isa<StringLiteral>(FilterElemE))
1413  return S.Diag(FilterElemE->getBeginLoc(),
1414  diag::err_sycl_add_ir_attribute_invalid_filter)
1415  << CI;
1416  return false;
1417 }
1418 
1419 // Returns true if a type is either an array of char or a pointer to char.
1420 static bool isAddIRAttributesValidStringType(QualType T) {
1421  if (!T->isArrayType() && !T->isPointerType())
1422  return false;
1423  QualType ElemT = T->isArrayType()
1424  ? cast<ArrayType>(T.getTypePtr())->getElementType()
1425  : T->getPointeeType();
1426  return ElemT.isConstQualified() && ElemT->isCharType();
1427 }
1428 
1429 // Checks if an expression is a valid attribute value for an add_ir_attributes_*
1430 // attribute. Returns true if an error occured.
1431 static bool checkAddIRAttributesValueExpr(Expr *ValArg, SemaSYCL &S,
1432  const AttributeCommonInfo &CI) {
1433  QualType ValType = ValArg->getType();
1434  if (isAddIRAttributesValidStringType(ValType) || ValType->isNullPtrType() ||
1435  ValType->isIntegralOrEnumerationType() || ValType->isFloatingType())
1436  return false;
1437 
1438  return S.Diag(ValArg->getBeginLoc(),
1439  diag::err_sycl_add_ir_attribute_invalid_value)
1440  << CI;
1441 }
1442 
1443 // Checks if an expression is a valid attribute name for an add_ir_attributes_*
1444 // attribute. Returns true if an error occured.
1445 static bool checkAddIRAttributesNameExpr(Expr *NameArg, SemaSYCL &S,
1446  const AttributeCommonInfo &CI) {
1447  // Only strings and const char * are valid name arguments.
1448  if (isAddIRAttributesValidStringType(NameArg->getType()))
1449  return false;
1450 
1451  return S.Diag(NameArg->getBeginLoc(),
1452  diag::err_sycl_add_ir_attribute_invalid_name)
1453  << CI;
1454 }
1455 
1456 // Checks and evaluates arguments of an add_ir_attributes_* attribute. Returns
1457 // true if an error occured.
1458 static bool evaluateAddIRAttributesArgs(Expr **Args, size_t ArgsSize,
1459  SemaSYCL &S,
1460  const AttributeCommonInfo &CI) {
1461  ASTContext &Context = S.getASTContext();
1462 
1463  // Check filter list if it is the first argument.
1464  bool HasFilter = ArgsSize && isa<InitListExpr>(Args[0]);
1465  if (HasFilter && checkAddIRAttributesFilterListExpr(Args[0], S, CI))
1466  return true;
1467 
1469  bool HasDependentArg = false;
1470  for (unsigned I = HasFilter; I < ArgsSize; I++) {
1471  Expr *&E = Args[I];
1472 
1473  if (isa<InitListExpr>(E))
1474  return S.Diag(E->getBeginLoc(),
1475  diag::err_sycl_add_ir_attr_filter_list_invalid_arg)
1476  << CI;
1477 
1478  if (E->isValueDependent() || E->isTypeDependent()) {
1479  HasDependentArg = true;
1480  continue;
1481  }
1482 
1483  Expr::EvalResult Eval;
1484  Eval.Diag = &Notes;
1485  if (!E->EvaluateAsConstantExpr(Eval, Context) || !Notes.empty()) {
1486  S.Diag(E->getBeginLoc(), diag::err_attribute_argument_n_type)
1487  << CI << (I + 1) << AANT_ArgumentConstantExpr;
1488  for (auto &Note : Notes)
1489  S.Diag(Note.first, Note.second);
1490  return true;
1491  }
1492  assert(Eval.Val.hasValue());
1493  E = ConstantExpr::Create(Context, E, Eval.Val);
1494  }
1495 
1496  // If there are no dependent expressions, check for expected number of args.
1497  if (!HasDependentArg && ArgsSize && (ArgsSize - HasFilter) & 1)
1498  return S.Diag(CI.getLoc(), diag::err_sycl_add_ir_attribute_must_have_pairs)
1499  << CI;
1500 
1501  // If there are no dependent expressions, check argument types.
1502  // First half of the arguments are names, the second half are values.
1503  unsigned MidArg = (ArgsSize - HasFilter) / 2 + HasFilter;
1504  if (!HasDependentArg) {
1505  for (unsigned I = HasFilter; I < ArgsSize; ++I) {
1506  if ((I < MidArg && checkAddIRAttributesNameExpr(Args[I], S, CI)) ||
1507  (I >= MidArg && checkAddIRAttributesValueExpr(Args[I], S, CI)))
1508  return true;
1509  }
1510  }
1511  return false;
1512 }
1513 
1515  Decl *D, const AttributeCommonInfo &CI, MutableArrayRef<Expr *> Args) {
1516  if (const auto *FuncD = dyn_cast<FunctionDecl>(D)) {
1517  if (FuncD->isDefaulted()) {
1518  Diag(CI.getLoc(), diag::err_disallow_attribute_on_func) << CI << 0;
1519  return;
1520  }
1521  if (FuncD->isDeleted()) {
1522  Diag(CI.getLoc(), diag::err_disallow_attribute_on_func) << CI << 1;
1523  return;
1524  }
1525  }
1526 
1527  ASTContext &Context = getASTContext();
1528  auto *Attr = SYCLAddIRAttributesFunctionAttr::Create(Context, Args.data(),
1529  Args.size(), CI);
1530  if (evaluateAddIRAttributesArgs(Attr->args_begin(), Attr->args_size(), *this,
1531  CI))
1532  return;
1533  D->addAttr(Attr);
1534 
1535  // There are compile-time SYCL properties which we would like to turn into
1536  // attributes to enable compiler diagnostics.
1537  // At the moment the only such property is related to virtual functions and
1538  // it is turned into sycl_device attribute. This is a tiny optimization to
1539  // avoid deep dive into the attribute if we already know that a declaration
1540  // is a device declaration. It may have to be removed later if/when we add
1541  // handling of more compile-time properties here.
1542  if (D->hasAttr<SYCLDeviceAttr>())
1543  return;
1544 
1545  // SYCL Headers use template magic to pass key=value pairs to the attribute
1546  // and we should make sure that all template instantiations are done before
1547  // accessing attribute arguments.
1548  if (hasDependentExpr(Attr->args_begin(), Attr->args_size()))
1549  return;
1550 
1552  Attr->getFilteredAttributeNameValuePairs(Context);
1553 
1554  for (const auto &[Key, Value] : Pairs) {
1555  if (Key == "indirectly-callable") {
1556  D->addAttr(SYCLDeviceAttr::CreateImplicit(Context));
1557  break;
1558  }
1559  }
1560 }
1561 
1563  Decl *D, const AttributeCommonInfo &CI, MutableArrayRef<Expr *> Args) {
1564  ASTContext &Context = getASTContext();
1565  auto *Attr = SYCLAddIRAttributesKernelParameterAttr::Create(
1566  Context, Args.data(), Args.size(), CI);
1567  if (evaluateAddIRAttributesArgs(Attr->args_begin(), Attr->args_size(), *this,
1568  CI))
1569  return;
1570  D->addAttr(Attr);
1571 }
1572 
1574  Decl *D, const AttributeCommonInfo &CI, MutableArrayRef<Expr *> Args) {
1575  ASTContext &Context = getASTContext();
1576  auto *Attr = SYCLAddIRAttributesGlobalVariableAttr::Create(
1577  Context, Args.data(), Args.size(), CI);
1578  if (evaluateAddIRAttributesArgs(Attr->args_begin(), Attr->args_size(), *this,
1579  CI))
1580  return;
1581  D->addAttr(Attr);
1582 }
1583 
1585  const AttributeCommonInfo &CI,
1586  MutableArrayRef<Expr *> Args) {
1587  ASTContext &Context = getASTContext();
1588  auto *Attr = SYCLAddIRAnnotationsMemberAttr::Create(Context, Args.data(),
1589  Args.size(), CI);
1590  if (evaluateAddIRAttributesArgs(Attr->args_begin(), Attr->args_size(), *this,
1591  CI))
1592  return;
1593  D->addAttr(Attr);
1594 }
1595 
1597  const AttributeCommonInfo &CI,
1598  Expr *XDim, Expr *YDim,
1599  Expr *ZDim) {
1600  // Returns nullptr if diagnosing, otherwise returns the original expression
1601  // or the original expression converted to a constant expression.
1602  auto CheckAndConvertArg = [&](Expr *E) -> std::optional<Expr *> {
1603  // We can only check if the expression is not value dependent.
1604  if (E && !E->isValueDependent()) {
1605  llvm::APSInt ArgVal;
1607  if (Res.isInvalid())
1608  return std::nullopt;
1609  E = Res.get();
1610 
1611  // This attribute requires a strictly positive value.
1612  if (ArgVal <= 0) {
1613  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
1614  << CI << /*positive*/ 0;
1615  return std::nullopt;
1616  }
1617  }
1618 
1619  return E;
1620  };
1621 
1622  // Check all three argument values, and if any are bad, bail out. This will
1623  // convert the given expressions into constant expressions when possible.
1624  std::optional<Expr *> XDimConvert = CheckAndConvertArg(XDim);
1625  std::optional<Expr *> YDimConvert = CheckAndConvertArg(YDim);
1626  std::optional<Expr *> ZDimConvert = CheckAndConvertArg(ZDim);
1627  if (!XDimConvert || !YDimConvert || !ZDimConvert)
1628  return;
1629  XDim = XDimConvert.value();
1630  YDim = YDimConvert.value();
1631  ZDim = ZDimConvert.value();
1632 
1633  // If the attribute was already applied with different arguments, then
1634  // diagnose the second attribute as a duplicate and don't add it.
1635  if (const auto *Existing = D->getAttr<SYCLWorkGroupSizeHintAttr>()) {
1636  // If any of the results are known to be different, we can diagnose at this
1637  // point and drop the attribute.
1638  if (anyWorkGroupSizesDiffer(XDim, YDim, ZDim, Existing->getXDim(),
1639  Existing->getYDim(), Existing->getZDim())) {
1640  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
1641  Diag(Existing->getLoc(), diag::note_previous_attribute);
1642  return;
1643  }
1644  // If all of the results are known to be the same, we can silently drop the
1645  // attribute. Otherwise, we have to add the attribute and resolve its
1646  // differences later.
1647  if (allWorkGroupSizesSame(XDim, YDim, ZDim, Existing->getXDim(),
1648  Existing->getYDim(), Existing->getZDim()))
1649  return;
1650  }
1651 
1652  ASTContext &Context = getASTContext();
1653  D->addAttr(::new (Context)
1654  SYCLWorkGroupSizeHintAttr(Context, CI, XDim, YDim, ZDim));
1655 }
1656 
1658  const AttributeCommonInfo &CI,
1659  Expr *XDim, Expr *YDim,
1660  Expr *ZDim) {
1661  // Returns nullptr if diagnosing, otherwise returns the original expression
1662  // or the original expression converted to a constant expression.
1663  auto CheckAndConvertArg = [&](Expr *E) -> Expr * {
1664  // Check if the expression is not value dependent.
1665  if (!E->isValueDependent()) {
1666  llvm::APSInt ArgVal;
1668  if (Res.isInvalid())
1669  return nullptr;
1670  E = Res.get();
1671 
1672  // This attribute requires a strictly positive value.
1673  if (ArgVal <= 0) {
1674  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
1675  << CI << /*positive*/ 0;
1676  return nullptr;
1677  }
1678  }
1679  return E;
1680  };
1681 
1682  // Check all three argument values, and if any are bad, bail out. This will
1683  // convert the given expressions into constant expressions when possible.
1684  XDim = CheckAndConvertArg(XDim);
1685  YDim = CheckAndConvertArg(YDim);
1686  ZDim = CheckAndConvertArg(ZDim);
1687  if (!XDim || !YDim || !ZDim)
1688  return;
1689 
1690  // If the 'max_work_group_size' attribute is specified on a declaration along
1691  // with 'reqd_work_group_size' attribute, check to see if values of
1692  // 'reqd_work_group_size' attribute arguments are equal to or less than values
1693  // of 'max_work_group_size' attribute arguments.
1694  //
1695  // We emit diagnostic if values of 'reqd_work_group_size' attribute arguments
1696  // are greater than values of 'max_work_group_size' attribute arguments.
1697  if (const auto *DeclAttr = D->getAttr<SYCLReqdWorkGroupSizeAttr>()) {
1698  if (checkMaxAllowedWorkGroupSize(DeclAttr->getXDim(), DeclAttr->getYDim(),
1699  DeclAttr->getZDim(), XDim, YDim, ZDim)) {
1700  Diag(CI.getLoc(), diag::err_conflicting_sycl_function_attributes)
1701  << CI << DeclAttr;
1702  Diag(DeclAttr->getLoc(), diag::note_conflicting_attribute);
1703  return;
1704  }
1705  }
1706 
1707  // If the declaration has a SYCLIntelMaxWorkGroupSizeAttr, check to see if
1708  // the attribute holds values equal to (1, 1, 1) in case the value of
1709  // SYCLIntelMaxGlobalWorkDimAttr equals to 0.
1710  if (const auto *DeclAttr = D->getAttr<SYCLIntelMaxGlobalWorkDimAttr>()) {
1711  if (areInvalidWorkGroupSizeAttrs(DeclAttr->getValue(), XDim, YDim, ZDim)) {
1712  Diag(CI.getLoc(), diag::err_sycl_x_y_z_arguments_must_be_one)
1713  << CI << DeclAttr;
1714  return;
1715  }
1716  }
1717 
1718  // If the attribute was already applied with different arguments, then
1719  // diagnose the second attribute as a duplicate and don't add it.
1720  if (const auto *Existing = D->getAttr<SYCLIntelMaxWorkGroupSizeAttr>()) {
1721  // If any of the results are known to be different, we can diagnose at this
1722  // point and drop the attribute.
1723  if (anyWorkGroupSizesDiffer(XDim, YDim, ZDim, Existing->getXDim(),
1724  Existing->getYDim(), Existing->getZDim())) {
1725  Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
1726  Diag(Existing->getLoc(), diag::note_previous_attribute);
1727  return;
1728  }
1729  // If all of the results are known to be the same, we can silently drop the
1730  // attribute. Otherwise, we have to add the attribute and resolve its
1731  // differences later.
1732  if (allWorkGroupSizesSame(XDim, YDim, ZDim, Existing->getXDim(),
1733  Existing->getYDim(), Existing->getZDim()))
1734  return;
1735  }
1736 
1737  ASTContext &Context = getASTContext();
1738  D->addAttr(::new (Context)
1739  SYCLIntelMaxWorkGroupSizeAttr(Context, CI, XDim, YDim, ZDim));
1740 }
1741 
1743  const AttributeCommonInfo &CI,
1744  Expr *XDim, Expr *YDim,
1745  Expr *ZDim) {
1746  // Returns nullptr if diagnosing, otherwise returns the original expression
1747  // or the original expression converted to a constant expression.
1748  auto CheckAndConvertArg = [&](Expr *E) -> std::optional<Expr *> {
1749  // Check if the expression is not value dependent.
1750  if (E && !E->isValueDependent()) {
1751  llvm::APSInt ArgVal;
1753  if (Res.isInvalid())
1754  return std::nullopt;
1755  E = Res.get();
1756 
1757  // This attribute requires a strictly positive value.
1758  if (ArgVal <= 0) {
1759  Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
1760  << CI << /*positive*/ 0;
1761  return std::nullopt;
1762  }
1763  }
1764  return E;
1765  };
1766 
1767  // Check all three argument values, and if any are bad, bail out. This will
1768  // convert the given expressions into constant expressions when possible.
1769  std::optional<Expr *> XDimConvert = CheckAndConvertArg(XDim);
1770  std::optional<Expr *> YDimConvert = CheckAndConvertArg(YDim);
1771  std::optional<Expr *> ZDimConvert = CheckAndConvertArg(ZDim);
1772  if (!XDimConvert || !YDimConvert || !ZDimConvert)
1773  return;
1774  XDim = XDimConvert.value();
1775  YDim = YDimConvert.value();
1776  ZDim = ZDimConvert.value();
1777 
1778  // If the declaration has a ReqdWorkGroupSizeAttr, check to see if
1779  // the attribute holds values equal to (1, 1, 1) in case the value of
1780  // SYCLIntelMaxGlobalWorkDimAttr equals to 0.
1781  if (const auto *DeclAttr = D->getAttr<SYCLIntelMaxGlobalWorkDimAttr>()) {
1782  if (areInvalidWorkGroupSizeAttrs(DeclAttr->getValue(), XDim, YDim, ZDim)) {
1783  Diag(CI.getLoc(), diag::err_sycl_x_y_z_arguments_must_be_one)
1784  << CI << DeclAttr;
1785  }
1786  }
1787 
1788  // If the 'max_work_group_size' attribute is specified on a declaration along
1789  // with 'reqd_work_group_size' attribute, check to see if values of
1790  // 'reqd_work_group_size' attribute arguments are equal to or less than values
1791  // of 'max_work_group_size' attribute arguments.
1792  //
1793  // We emit diagnostic if values of 'reqd_work_group_size' attribute arguments
1794  // are greater than values of 'max_work_group_size' attribute arguments.
1795  if (const auto *DeclAttr = D->getAttr<SYCLIntelMaxWorkGroupSizeAttr>()) {
1796  if (checkMaxAllowedWorkGroupSize(XDim, YDim, ZDim, DeclAttr->getXDim(),
1797  DeclAttr->getYDim(),
1798  DeclAttr->getZDim())) {
1799  Diag(CI.getLoc(), diag::err_conflicting_sycl_function_attributes)
1800  << CI << DeclAttr;
1801  Diag(DeclAttr->getLoc(), diag::note_conflicting_attribute);
1802  return;
1803  }
1804  }
1805 
1806  // If the 'reqd_work_group_size' attribute is specified on a declaration
1807  // along with 'num_simd_work_items' attribute, the required work group size
1808  // specified by 'num_simd_work_items' attribute must evenly divide the index
1809  // that increments fastest in the 'reqd_work_group_size' attribute.
1810  if (const auto *DeclAttr = D->getAttr<SYCLIntelNumSimdWorkItemsAttr>()) {
1811  if (checkWorkGroupSize(DeclAttr->getValue(), XDim, YDim, ZDim)) {
1812  Diag(DeclAttr->getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size)
1813  << DeclAttr << CI;
1814  Diag(CI.getLoc(), diag::note_conflicting_attribute);
1815  return;
1816  }
1817  }
1818 
1819  // If the attribute was already applied with different arguments, then
1820  // diagnose the second attribute as a duplicate and don't add it.
1821  if (const auto *Existing = D->getAttr<SYCLReqdWorkGroupSizeAttr>()) {
1822  // If any of the results are known to be different, we can diagnose at this
1823  // point and drop the attribute.
1824  if (anyWorkGroupSizesDiffer(XDim, YDim, ZDim, Existing->getXDim(),
1825  Existing->getYDim(), Existing->getZDim())) {
1826  Diag(CI.getLoc(), diag::err_duplicate_attribute) << CI;
1827  Diag(Existing->getLoc(), diag::note_previous_attribute);
1828  return;
1829  }
1830 
1831  // If all of the results are known to be the same, we can silently drop the
1832  // attribute. Otherwise, we have to add the attribute and resolve its
1833  // differences later.
1834  if (allWorkGroupSizesSame(XDim, YDim, ZDim, Existing->getXDim(),
1835  Existing->getYDim(), Existing->getZDim()))
1836  return;
1837  }
1838 
1839  ASTContext &Context = getASTContext();
1840  D->addAttr(::new (Context)
1841  SYCLReqdWorkGroupSizeAttr(Context, CI, XDim, YDim, ZDim));
1842 }
1843 
1844 // Handles SYCL work_group_size_hint.
1847 
1848  // __attribute__((work_group_size_hint) requires exactly three arguments.
1849  if (AL.getSyntax() == ParsedAttr::AS_GNU || !AL.hasScope() ||
1850  (AL.hasScope() && !AL.getScopeName()->isStr("sycl"))) {
1851  if (!AL.checkExactlyNumArgs(SemaRef, 3))
1852  return;
1853  } else if (!AL.checkAtLeastNumArgs(SemaRef, 1) ||
1854  !AL.checkAtMostNumArgs(SemaRef, 3))
1855  return;
1856 
1857  size_t NumArgs = AL.getNumArgs();
1858  Expr *XDimExpr = NumArgs > 0 ? AL.getArgAsExpr(0) : nullptr;
1859  Expr *YDimExpr = NumArgs > 1 ? AL.getArgAsExpr(1) : nullptr;
1860  Expr *ZDimExpr = NumArgs > 2 ? AL.getArgAsExpr(2) : nullptr;
1861  addSYCLWorkGroupSizeHintAttr(D, AL, XDimExpr, YDimExpr, ZDimExpr);
1862 }
1863 
1864 SYCLWorkGroupSizeHintAttr *
1866  const SYCLWorkGroupSizeHintAttr &A) {
1867  // Check to see if there's a duplicate attribute already applied.
1868  if (const auto *DeclAttr = D->getAttr<SYCLWorkGroupSizeHintAttr>()) {
1869  // If any of the results are known to be different, we can diagnose at this
1870  // point and drop the attribute.
1871  if (anyWorkGroupSizesDiffer(DeclAttr->getXDim(), DeclAttr->getYDim(),
1872  DeclAttr->getZDim(), A.getXDim(), A.getYDim(),
1873  A.getZDim())) {
1874  Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
1875  Diag(A.getLoc(), diag::note_previous_attribute);
1876  return nullptr;
1877  }
1878  // If all of the results are known to be the same, we can silently drop the
1879  // attribute. Otherwise, we have to add the attribute and resolve its
1880  // differences later.
1881  if (allWorkGroupSizesSame(DeclAttr->getXDim(), DeclAttr->getYDim(),
1882  DeclAttr->getZDim(), A.getXDim(), A.getYDim(),
1883  A.getZDim()))
1884  return nullptr;
1885  }
1886  ASTContext &Context = getASTContext();
1887  return ::new (Context) SYCLWorkGroupSizeHintAttr(Context, A, A.getXDim(),
1888  A.getYDim(), A.getZDim());
1889 }
1890 
1891 SYCLIntelMaxWorkGroupSizeAttr *SemaSYCL::mergeSYCLIntelMaxWorkGroupSizeAttr(
1892  Decl *D, const SYCLIntelMaxWorkGroupSizeAttr &A) {
1893  // Check to see if there's a duplicate attribute already applied.
1894  if (const auto *DeclAttr = D->getAttr<SYCLIntelMaxWorkGroupSizeAttr>()) {
1895  // If any of the results are known to be different, we can diagnose at this
1896  // point and drop the attribute.
1897  if (anyWorkGroupSizesDiffer(DeclAttr->getXDim(), DeclAttr->getYDim(),
1898  DeclAttr->getZDim(), A.getXDim(), A.getYDim(),
1899  A.getZDim())) {
1900  Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
1901  Diag(A.getLoc(), diag::note_previous_attribute);
1902  return nullptr;
1903  }
1904  // If all of the results are known to be the same, we can silently drop the
1905  // attribute. Otherwise, we have to add the attribute and resolve its
1906  // differences later.
1907  if (allWorkGroupSizesSame(DeclAttr->getXDim(), DeclAttr->getYDim(),
1908  DeclAttr->getZDim(), A.getXDim(), A.getYDim(),
1909  A.getZDim()))
1910  return nullptr;
1911  }
1912 
1913  // If the 'max_work_group_size' attribute is specified on a declaration along
1914  // with 'reqd_work_group_size' attribute, check to see if values of
1915  // 'reqd_work_group_size' attribute arguments are equal to or less than values
1916  // of 'max_work_group_size' attribute arguments.
1917  //
1918  // We emit diagnostic if values of 'reqd_work_group_size' attribute arguments
1919  // are greater than values of 'max_work_group_size' attribute arguments.
1920  if (const auto *DeclAttr = D->getAttr<SYCLReqdWorkGroupSizeAttr>()) {
1921  if (checkMaxAllowedWorkGroupSize(DeclAttr->getXDim(), DeclAttr->getYDim(),
1922  DeclAttr->getZDim(), A.getXDim(),
1923  A.getYDim(), A.getZDim())) {
1924  Diag(DeclAttr->getLoc(), diag::err_conflicting_sycl_function_attributes)
1925  << DeclAttr << &A;
1926  Diag(A.getLoc(), diag::note_conflicting_attribute);
1927  return nullptr;
1928  }
1929  }
1930 
1931  // If the declaration has a SYCLIntelMaxWorkGroupSizeAttr, check to see if
1932  // the attribute holds values equal to (1, 1, 1) in case the value of
1933  // SYCLIntelMaxGlobalWorkDimAttr equals to 0.
1934  if (const auto *DeclAttr = D->getAttr<SYCLIntelMaxGlobalWorkDimAttr>()) {
1935  if (areInvalidWorkGroupSizeAttrs(DeclAttr->getValue(), A.getXDim(),
1936  A.getYDim(), A.getZDim())) {
1937  Diag(A.getLoc(), diag::err_sycl_x_y_z_arguments_must_be_one)
1938  << &A << DeclAttr;
1939  return nullptr;
1940  }
1941  }
1942 
1943  ASTContext &Context = getASTContext();
1944  return ::new (Context) SYCLIntelMaxWorkGroupSizeAttr(
1945  Context, A, A.getXDim(), A.getYDim(), A.getZDim());
1946 }
1947 
1950 
1951  // __attribute__((reqd_work_group_size)) and [[cl::reqd_work_group_size]]
1952  // all require exactly three arguments.
1953  if ((AL.getKind() == ParsedAttr::AT_ReqdWorkGroupSize &&
1955  SYCLReqdWorkGroupSizeAttr::CXX11_cl_reqd_work_group_size) ||
1956  AL.getSyntax() == ParsedAttr::AS_GNU) {
1957  if (!AL.checkExactlyNumArgs(SemaRef, 3))
1958  return;
1959  } else if (!AL.checkAtLeastNumArgs(SemaRef, 1) ||
1960  !AL.checkAtMostNumArgs(SemaRef, 3))
1961  return;
1962 
1963  size_t NumArgs = AL.getNumArgs();
1964  Expr *XDimExpr = NumArgs > 0 ? AL.getArgAsExpr(0) : nullptr;
1965  Expr *YDimExpr = NumArgs > 1 ? AL.getArgAsExpr(1) : nullptr;
1966  Expr *ZDimExpr = NumArgs > 2 ? AL.getArgAsExpr(2) : nullptr;
1967  addSYCLReqdWorkGroupSizeAttr(D, AL, XDimExpr, YDimExpr, ZDimExpr);
1968 }
1969 
1970 SYCLReqdWorkGroupSizeAttr *
1972  const SYCLReqdWorkGroupSizeAttr &A) {
1973  // If the declaration has a SYCLReqdWorkGroupSizeAttr, check to see if the
1974  // attribute holds values equal to (1, 1, 1) in case the value of
1975  // SYCLIntelMaxGlobalWorkDimAttr equals to 0.
1976  if (const auto *DeclAttr = D->getAttr<SYCLIntelMaxGlobalWorkDimAttr>()) {
1977  if (areInvalidWorkGroupSizeAttrs(DeclAttr->getValue(), A.getXDim(),
1978  A.getYDim(), A.getZDim())) {
1979  Diag(A.getLoc(), diag::err_sycl_x_y_z_arguments_must_be_one)
1980  << &A << DeclAttr;
1981  return nullptr;
1982  }
1983  }
1984 
1985  // If the 'max_work_group_size' attribute is specified on a declaration along
1986  // with 'reqd_work_group_size' attribute, check to see if values of
1987  // 'reqd_work_group_size' attribute arguments are equal or less than values
1988  // of 'max_work_group_size' attribute arguments.
1989  //
1990  // We emit diagnostic if values of 'reqd_work_group_size' attribute arguments
1991  // are greater than values of 'max_work_group_size' attribute arguments.
1992  if (const auto *DeclAttr = D->getAttr<SYCLIntelMaxWorkGroupSizeAttr>()) {
1993  if (checkMaxAllowedWorkGroupSize(A.getXDim(), A.getYDim(), A.getZDim(),
1994  DeclAttr->getXDim(), DeclAttr->getYDim(),
1995  DeclAttr->getZDim())) {
1996  Diag(DeclAttr->getLoc(), diag::err_conflicting_sycl_function_attributes)
1997  << DeclAttr << &A;
1998  Diag(A.getLoc(), diag::note_conflicting_attribute);
1999  return nullptr;
2000  }
2001  }
2002 
2003  // If the 'reqd_work_group_size' attribute is specified on a declaration
2004  // along with 'num_simd_work_items' attribute, the required work group size
2005  // specified by 'num_simd_work_items' attribute must evenly divide the index
2006  // that increments fastest in the 'reqd_work_group_size' attribute.
2007  if (const auto *DeclAttr = D->getAttr<SYCLIntelNumSimdWorkItemsAttr>()) {
2008  if (checkWorkGroupSize(DeclAttr->getValue(), A.getXDim(), A.getYDim(),
2009  A.getZDim())) {
2010  Diag(DeclAttr->getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size)
2011  << DeclAttr << &A;
2012  Diag(A.getLoc(), diag::note_conflicting_attribute);
2013  return nullptr;
2014  }
2015  }
2016 
2017  // Check to see if there's a duplicate attribute already applied.
2018  if (const auto *DeclAttr = D->getAttr<SYCLReqdWorkGroupSizeAttr>()) {
2019  // If any of the results are known to be different, we can diagnose at this
2020  // point and drop the attribute.
2021  if (anyWorkGroupSizesDiffer(DeclAttr->getXDim(), DeclAttr->getYDim(),
2022  DeclAttr->getZDim(), A.getXDim(), A.getYDim(),
2023  A.getZDim())) {
2024  Diag(DeclAttr->getLoc(), diag::err_duplicate_attribute) << &A;
2025  Diag(A.getLoc(), diag::note_previous_attribute);
2026  return nullptr;
2027  }
2028 
2029  // If all of the results are known to be the same, we can silently drop the
2030  // attribute. Otherwise, we have to add the attribute and resolve its
2031  // differences later.
2032  if (allWorkGroupSizesSame(DeclAttr->getXDim(), DeclAttr->getYDim(),
2033  DeclAttr->getZDim(), A.getXDim(), A.getYDim(),
2034  A.getZDim()))
2035  return nullptr;
2036  }
2037 
2038  ASTContext &Context = getASTContext();
2039  return ::new (Context) SYCLReqdWorkGroupSizeAttr(Context, A, A.getXDim(),
2040  A.getYDim(), A.getZDim());
2041 }
2042 
2043 IntelReqdSubGroupSizeAttr *
2045  const IntelReqdSubGroupSizeAttr &A) {
2046  // Check to see if there's a duplicate attribute with different values
2047  // already applied to the declaration.
2048  if (const auto *DeclAttr = D->getAttr<IntelReqdSubGroupSizeAttr>()) {
2049  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
2050  if (const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue())) {
2051  if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
2052  Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
2053  Diag(A.getLoc(), diag::note_previous_attribute);
2054  return nullptr;
2055  }
2056  // Do not add a duplicate attribute.
2057  return nullptr;
2058  }
2059  }
2060  }
2061  ASTContext &Context = getASTContext();
2062  return ::new (Context) IntelReqdSubGroupSizeAttr(Context, A, A.getValue());
2063 }
2064 
2067 
2068  Expr *E = AL.getArgAsExpr(0);
2070 }
2071 
2072 IntelNamedSubGroupSizeAttr *
2074  const IntelNamedSubGroupSizeAttr &A) {
2075  // Check to see if there's a duplicate attribute with different values
2076  // already applied to the declaration.
2077  if (const auto *DeclAttr = D->getAttr<IntelNamedSubGroupSizeAttr>()) {
2078  if (DeclAttr->getType() != A.getType()) {
2079  Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
2080  Diag(A.getLoc(), diag::note_previous_attribute);
2081  }
2082  return nullptr;
2083  }
2084 
2085  ASTContext &Context = getASTContext();
2086  return IntelNamedSubGroupSizeAttr::Create(Context, A.getType(), A);
2087 }
2088 
2090  StringRef SizeStr;
2092  if (AL.isArgIdent(0)) {
2093  IdentifierLoc *IL = AL.getArgAsIdent(0);
2094  SizeStr = IL->Ident->getName();
2095  Loc = IL->Loc;
2096  } else if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, SizeStr, &Loc)) {
2097  return;
2098  }
2099 
2100  IntelNamedSubGroupSizeAttr::SubGroupSizeType SizeType;
2101  if (!IntelNamedSubGroupSizeAttr::ConvertStrToSubGroupSizeType(SizeStr,
2102  SizeType)) {
2103  Diag(Loc, diag::warn_attribute_type_not_supported) << AL << SizeStr;
2104  return;
2105  }
2106  D->addAttr(IntelNamedSubGroupSizeAttr::Create(getASTContext(), SizeType, AL));
2107 }
2108 
2109 SYCLIntelNumSimdWorkItemsAttr *SemaSYCL::mergeSYCLIntelNumSimdWorkItemsAttr(
2110  Decl *D, const SYCLIntelNumSimdWorkItemsAttr &A) {
2111  // Check to see if there's a duplicate attribute with different values
2112  // already applied to the declaration.
2113  if (const auto *DeclAttr = D->getAttr<SYCLIntelNumSimdWorkItemsAttr>()) {
2114  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
2115  if (const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue())) {
2116  if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
2117  Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
2118  Diag(A.getLoc(), diag::note_previous_attribute);
2119  }
2120  // Do not add a duplicate attribute.
2121  return nullptr;
2122  }
2123  }
2124  }
2125 
2126  // If the 'reqd_work_group_size' attribute is specified on a declaration
2127  // along with 'num_simd_work_items' attribute, the required work group size
2128  // specified by 'num_simd_work_items' attribute must evenly divide the index
2129  // that increments fastest in the 'reqd_work_group_size' attribute.
2130  if (const auto *DeclAttr = D->getAttr<SYCLReqdWorkGroupSizeAttr>()) {
2131  if (checkWorkGroupSize(A.getValue(), DeclAttr->getXDim(),
2132  DeclAttr->getYDim(), DeclAttr->getZDim())) {
2133  Diag(A.getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size)
2134  << &A << DeclAttr;
2135  Diag(DeclAttr->getLoc(), diag::note_conflicting_attribute);
2136  return nullptr;
2137  }
2138  }
2139 
2140  ASTContext &Context = getASTContext();
2141  return ::new (Context)
2142  SYCLIntelNumSimdWorkItemsAttr(Context, A, A.getValue());
2143 }
2144 
2146  const ParsedAttr &A) {
2148 
2150 }
2151 
2152 SYCLIntelInitiationIntervalAttr *SemaSYCL::mergeSYCLIntelInitiationIntervalAttr(
2153  Decl *D, const SYCLIntelInitiationIntervalAttr &A) {
2154  // Check to see if there's a duplicate attribute with different values
2155  // already applied to the declaration.
2156  if (const auto *DeclAttr = D->getAttr<SYCLIntelInitiationIntervalAttr>()) {
2157  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getNExpr())) {
2158  if (const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getNExpr())) {
2159  if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
2160  Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
2161  Diag(A.getLoc(), diag::note_previous_attribute);
2162  }
2163  // Do not add a duplicate attribute.
2164  return nullptr;
2165  }
2166  }
2167  }
2168 
2169  ASTContext &Context = getASTContext();
2170  return ::new (Context)
2171  SYCLIntelInitiationIntervalAttr(Context, A, A.getNExpr());
2172 }
2173 
2175  const ParsedAttr &AL) {
2176  Expr *E = AL.getArgAsExpr(0);
2178 }
2179 
2180 SYCLIntelSchedulerTargetFmaxMhzAttr *
2182  Decl *D, const SYCLIntelSchedulerTargetFmaxMhzAttr &A) {
2183  // Check to see if there's a duplicate attribute with different values
2184  // already applied to the declaration.
2185  if (const auto *DeclAttr =
2186  D->getAttr<SYCLIntelSchedulerTargetFmaxMhzAttr>()) {
2187  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
2188  if (const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue())) {
2189  if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
2190  Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
2191  Diag(A.getLoc(), diag::note_previous_attribute);
2192  return nullptr;
2193  }
2194  // Do not add a duplicate attribute.
2195  return nullptr;
2196  }
2197  }
2198  }
2199  ASTContext &Context = getASTContext();
2200  return ::new (Context)
2201  SYCLIntelSchedulerTargetFmaxMhzAttr(Context, A, A.getValue());
2202 }
2203 
2205  const ParsedAttr &AL) {
2206  Expr *E = AL.getArgAsExpr(0);
2208 }
2209 
2210 SYCLIntelMaxGlobalWorkDimAttr *SemaSYCL::mergeSYCLIntelMaxGlobalWorkDimAttr(
2211  Decl *D, const SYCLIntelMaxGlobalWorkDimAttr &A) {
2212  // Check to see if there's a duplicate attribute with different values
2213  // already applied to the declaration.
2214  if (const auto *DeclAttr = D->getAttr<SYCLIntelMaxGlobalWorkDimAttr>()) {
2215  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
2216  if (const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue())) {
2217  if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
2218  Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
2219  Diag(A.getLoc(), diag::note_previous_attribute);
2220  }
2221  // Do not add a duplicate attribute.
2222  return nullptr;
2223  }
2224  }
2225  }
2226 
2227  // If the declaration has a SYCLIntelMaxWorkGroupSizeAttr or
2228  // SYCLReqdWorkGroupSizeAttr, check to see if the attribute holds values equal
2229  // to (1, 1, 1) in case the value of SYCLIntelMaxGlobalWorkDimAttr equals to
2230  // 0.
2231  const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue());
2232  if (MergeExpr && MergeExpr->getResultAsAPSInt() == 0) {
2233  if (checkWorkGroupSizeAttrExpr<SYCLIntelMaxWorkGroupSizeAttr>(D, A) ||
2234  checkWorkGroupSizeAttrExpr<SYCLReqdWorkGroupSizeAttr>(D, A))
2235  return nullptr;
2236  }
2237 
2238  ASTContext &Context = getASTContext();
2239  return ::new (Context)
2240  SYCLIntelMaxGlobalWorkDimAttr(Context, A, A.getValue());
2241 }
2242 
2243 SYCLIntelMinWorkGroupsPerComputeUnitAttr *
2245  Decl *D, const SYCLIntelMinWorkGroupsPerComputeUnitAttr &A) {
2246  // Check to see if there's a duplicate attribute with different values
2247  // already applied to the declaration.
2248  if (const auto *DeclAttr =
2249  D->getAttr<SYCLIntelMinWorkGroupsPerComputeUnitAttr>()) {
2250  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
2251  if (const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue())) {
2252  if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
2253  Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
2254  Diag(A.getLoc(), diag::note_previous_attribute);
2255  }
2256  // Do not add a duplicate attribute.
2257  return nullptr;
2258  }
2259  }
2260  }
2261 
2262  ASTContext &Context = getASTContext();
2263  return ::new (Context)
2264  SYCLIntelMinWorkGroupsPerComputeUnitAttr(Context, A, A.getValue());
2265 }
2266 
2267 SYCLIntelMaxWorkGroupsPerMultiprocessorAttr *
2269  Decl *D, const SYCLIntelMaxWorkGroupsPerMultiprocessorAttr &A) {
2270  // Check to see if there's a duplicate attribute with different values
2271  // already applied to the declaration.
2272  if (const auto *DeclAttr =
2273  D->getAttr<SYCLIntelMaxWorkGroupsPerMultiprocessorAttr>()) {
2274  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
2275  if (const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue())) {
2276  if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
2277  Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
2278  Diag(A.getLoc(), diag::note_previous_attribute);
2279  }
2280  // Do not add a duplicate attribute.
2281  return nullptr;
2282  }
2283  }
2284  }
2285 
2286  ASTContext &Context = getASTContext();
2287  return ::new (Context)
2288  SYCLIntelMaxWorkGroupsPerMultiprocessorAttr(Context, A, A.getValue());
2289 }
2290 
2292  // If no attribute argument is specified, set to default value '1'.
2293  ASTContext &Context = getASTContext();
2294  Expr *E = A.isArgExpr(0) ? A.getArgAsExpr(0)
2295  : IntegerLiteral::Create(Context, llvm::APInt(32, 1),
2296  Context.IntTy, A.getLoc());
2297 
2299 }
2300 
2301 SYCLIntelLoopFuseAttr *
2302 SemaSYCL::mergeSYCLIntelLoopFuseAttr(Decl *D, const SYCLIntelLoopFuseAttr &A) {
2303  // Check to see if there's a duplicate attribute with different values
2304  // already applied to the declaration.
2305  if (const auto *DeclAttr = D->getAttr<SYCLIntelLoopFuseAttr>()) {
2306  // [[intel::loop_fuse]] and [[intel::loop_fuse_independent]] are
2307  // incompatible.
2308  // FIXME: If additional spellings are provided for this attribute,
2309  // this code will do the wrong thing.
2310  if (DeclAttr->getAttributeSpellingListIndex() !=
2311  A.getAttributeSpellingListIndex()) {
2312  Diag(A.getLoc(), diag::err_attributes_are_not_compatible)
2313  << &A << DeclAttr << A.isRegularKeywordAttribute();
2314  Diag(DeclAttr->getLoc(), diag::note_conflicting_attribute);
2315  return nullptr;
2316  }
2317  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
2318  if (const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue())) {
2319  if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
2320  Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
2321  Diag(A.getLoc(), diag::note_previous_attribute);
2322  }
2323  // Do not add a duplicate attribute.
2324  return nullptr;
2325  }
2326  }
2327  }
2328 
2329  ASTContext &Context = getASTContext();
2330  return ::new (Context) SYCLIntelLoopFuseAttr(Context, A, A.getValue());
2331 }
2332 
2335 
2336  Expr *E = A.getArgAsExpr(0);
2338 }
2339 
2340 SYCLIntelESimdVectorizeAttr *SemaSYCL::mergeSYCLIntelESimdVectorizeAttr(
2341  Decl *D, const SYCLIntelESimdVectorizeAttr &A) {
2342  // Check to see if there's a duplicate attribute with different values
2343  // already applied to the declaration.
2344  if (const auto *DeclAttr = D->getAttr<SYCLIntelESimdVectorizeAttr>()) {
2345  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
2346  if (const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue())) {
2347  if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
2348  Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
2349  Diag(A.getLoc(), diag::note_previous_attribute);
2350  }
2351  // Do not add a duplicate attribute.
2352  return nullptr;
2353  }
2354  }
2355  }
2356  ASTContext &Context = getASTContext();
2357  return ::new (Context) SYCLIntelESimdVectorizeAttr(Context, A, A.getValue());
2358 }
2359 
2361  const ParsedAttr &A) {
2362  // If no attribute argument is specified, set to default value '1'.
2363  ASTContext &Context = getASTContext();
2364  Expr *E = A.isArgExpr(0) ? A.getArgAsExpr(0)
2365  : IntegerLiteral::Create(Context, llvm::APInt(32, 1),
2366  Context.IntTy, A.getLoc());
2367 
2369 }
2370 
2371 SYCLIntelNoGlobalWorkOffsetAttr *SemaSYCL::mergeSYCLIntelNoGlobalWorkOffsetAttr(
2372  Decl *D, const SYCLIntelNoGlobalWorkOffsetAttr &A) {
2373  // Check to see if there's a duplicate attribute with different values
2374  // already applied to the declaration.
2375  if (const auto *DeclAttr = D->getAttr<SYCLIntelNoGlobalWorkOffsetAttr>()) {
2376  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
2377  if (const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue())) {
2378  if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
2379  Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
2380  Diag(A.getLoc(), diag::note_previous_attribute);
2381  }
2382  // Do not add a duplicate attribute.
2383  return nullptr;
2384  }
2385  }
2386  }
2387  ASTContext &Context = getASTContext();
2388  return ::new (Context)
2389  SYCLIntelNoGlobalWorkOffsetAttr(Context, A, A.getValue());
2390 }
2391 
2394 }
2395 
2396 SYCLIntelBankWidthAttr *
2398  const SYCLIntelBankWidthAttr &A) {
2399  // Check to see if there's a duplicate attribute with different values
2400  // already applied to the declaration.
2401  if (const auto *DeclAttr = D->getAttr<SYCLIntelBankWidthAttr>()) {
2402  const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue());
2403  const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue());
2404  if (DeclExpr && MergeExpr &&
2405  DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
2406  Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
2407  Diag(A.getLoc(), diag::note_previous_attribute);
2408  return nullptr;
2409  }
2410  }
2411 
2412  ASTContext &Context = getASTContext();
2413  return ::new (Context) SYCLIntelBankWidthAttr(Context, A, A.getValue());
2414 }
2415 
2418 }
2419 
2420 SYCLIntelNumBanksAttr *
2421 SemaSYCL::mergeSYCLIntelNumBanksAttr(Decl *D, const SYCLIntelNumBanksAttr &A) {
2422  // Check to see if there's a duplicate attribute with different values
2423  // already applied to the declaration.
2424  if (const auto *DeclAttr = D->getAttr<SYCLIntelNumBanksAttr>()) {
2425  const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue());
2426  const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue());
2427  if (DeclExpr && MergeExpr &&
2428  DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
2429  Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
2430  Diag(A.getLoc(), diag::note_previous_attribute);
2431  return nullptr;
2432  }
2433  }
2434 
2435  ASTContext &Context = getASTContext();
2436  return ::new (Context) SYCLIntelNumBanksAttr(Context, A, A.getValue());
2437 }
2438 
2441 }
2442 
2443 SYCLIntelMaxReplicatesAttr *
2445  const SYCLIntelMaxReplicatesAttr &A) {
2446  // Check to see if there's a duplicate attribute with different values
2447  // already applied to the declaration.
2448  if (const auto *DeclAttr = D->getAttr<SYCLIntelMaxReplicatesAttr>()) {
2449  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
2450  if (const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue())) {
2451  if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
2452  Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
2453  Diag(A.getLoc(), diag::note_previous_attribute);
2454  }
2455  // Do not add a duplicate attribute.
2456  return nullptr;
2457  }
2458  }
2459  }
2460 
2461  ASTContext &Context = getASTContext();
2462  return ::new (Context) SYCLIntelMaxReplicatesAttr(Context, A, A.getValue());
2463 }
2464 
2467 }
2468 
2469 SYCLIntelForcePow2DepthAttr *SemaSYCL::mergeSYCLIntelForcePow2DepthAttr(
2470  Decl *D, const SYCLIntelForcePow2DepthAttr &A) {
2471  // Check to see if there's a duplicate attribute with different values
2472  // already applied to the declaration.
2473  if (const auto *DeclAttr = D->getAttr<SYCLIntelForcePow2DepthAttr>()) {
2474  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
2475  if (const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue())) {
2476  if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
2477  Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
2478  Diag(A.getLoc(), diag::note_previous_attribute);
2479  }
2480  // If there is no mismatch, drop any duplicate attributes.
2481  return nullptr;
2482  }
2483  }
2484  }
2485 
2486  ASTContext &Context = getASTContext();
2487  return ::new (Context) SYCLIntelForcePow2DepthAttr(Context, A, A.getValue());
2488 }
2489 
2491  Expr *E = A.getArgAsExpr(0);
2492  addSYCLIntelPipeIOAttr(D, A, E);
2493 }
2494 
2495 SYCLIntelPipeIOAttr *
2496 SemaSYCL::mergeSYCLIntelPipeIOAttr(Decl *D, const SYCLIntelPipeIOAttr &A) {
2497  // Check to see if there's a duplicate attribute with different values
2498  // already applied to the declaration.
2499  if (const auto *DeclAttr = D->getAttr<SYCLIntelPipeIOAttr>()) {
2500  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getID())) {
2501  if (const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getID())) {
2502  if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
2503  Diag(DeclAttr->getLoc(), diag::err_disallowed_duplicate_attribute)
2504  << &A;
2505  Diag(A.getLoc(), diag::note_conflicting_attribute);
2506  }
2507  // Do not add a duplicate attribute.
2508  return nullptr;
2509  }
2510  }
2511  }
2512 
2513  ASTContext &Context = getASTContext();
2514  return ::new (Context) SYCLIntelPipeIOAttr(Context, A, A.getID());
2515 }
2516 
2518  Expr *E = A.getArgAsExpr(0);
2520 }
2521 
2522 SYCLIntelMaxConcurrencyAttr *SemaSYCL::mergeSYCLIntelMaxConcurrencyAttr(
2523  Decl *D, const SYCLIntelMaxConcurrencyAttr &A) {
2524  // Check to see if there's a duplicate attribute with different values
2525  // already applied to the declaration.
2526  if (const auto *DeclAttr = D->getAttr<SYCLIntelMaxConcurrencyAttr>()) {
2527  if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getNExpr())) {
2528  if (const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getNExpr())) {
2529  if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
2530  Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
2531  Diag(A.getLoc(), diag::note_previous_attribute);
2532  }
2533  // Do not add a duplicate attribute.
2534  return nullptr;
2535  }
2536  }
2537  }
2538 
2539  ASTContext &Context = getASTContext();
2540  return ::new (Context) SYCLIntelMaxConcurrencyAttr(Context, A, A.getNExpr());
2541 }
2542 
2544  const ParsedAttr &A) {
2546  Args.reserve(A.getNumArgs() - 1);
2547  for (unsigned I = 0; I < A.getNumArgs(); I++) {
2548  assert(A.isArgExpr(I));
2549  Args.push_back(A.getArgAsExpr(I));
2550  }
2551 
2553 }
2554 
2555 static bool hasSameSYCLAddIRAttributes(
2556  const SmallVector<std::pair<std::string, std::string>, 4> &LAttrs,
2557  const SmallVector<std::pair<std::string, std::string>, 4> &RAttrs) {
2558  std::set<std::pair<std::string, std::string>> LNameValSet{LAttrs.begin(),
2559  LAttrs.end()};
2560  std::set<std::pair<std::string, std::string>> RNameValSet{RAttrs.begin(),
2561  RAttrs.end()};
2562  return LNameValSet == RNameValSet;
2563 }
2564 
2565 template <typename AddIRAttrT>
2566 static bool checkSYCLAddIRAttributesMergeability(const AddIRAttrT &NewAttr,
2567  const AddIRAttrT &ExistingAttr,
2568  SemaSYCL &S) {
2569  ASTContext &Context = S.getASTContext();
2570  // If there are no dependent argument expressions and the filters or the
2571  // attributes are different, then fail due to differing duplicates.
2572  if (!S.hasDependentExpr(NewAttr.args_begin(), NewAttr.args_size()) &&
2573  !S.hasDependentExpr(ExistingAttr.args_begin(),
2574  ExistingAttr.args_size()) &&
2575  (NewAttr.getAttributeFilter() != ExistingAttr.getAttributeFilter() ||
2576  !hasSameSYCLAddIRAttributes(
2577  NewAttr.getAttributeNameValuePairs(Context),
2578  ExistingAttr.getAttributeNameValuePairs(Context)))) {
2579  S.Diag(ExistingAttr.getLoc(), diag::err_duplicate_attribute) << &NewAttr;
2580  S.Diag(NewAttr.getLoc(), diag::note_conflicting_attribute);
2581  return true;
2582  }
2583  return false;
2584 }
2585 
2586 SYCLAddIRAttributesFunctionAttr *SemaSYCL::mergeSYCLAddIRAttributesFunctionAttr(
2587  Decl *D, const SYCLAddIRAttributesFunctionAttr &A) {
2588  if (const auto *ExistingAttr =
2589  D->getAttr<SYCLAddIRAttributesFunctionAttr>()) {
2590  checkSYCLAddIRAttributesMergeability(A, *ExistingAttr, *this);
2591  return nullptr;
2592  }
2593  ASTContext &Context = getASTContext();
2594  return A.clone(Context);
2595 }
2596 
2598  Decl *D, const ParsedAttr &A) {
2600  Args.reserve(A.getNumArgs() - 1);
2601  for (unsigned I = 0; I < A.getNumArgs(); I++) {
2602  assert(A.getArgAsExpr(I));
2603  Args.push_back(A.getArgAsExpr(I));
2604  }
2605 
2607 }
2608 
2609 SYCLAddIRAttributesKernelParameterAttr *
2611  Decl *D, const SYCLAddIRAttributesKernelParameterAttr &A) {
2612  if (const auto *ExistingAttr =
2613  D->getAttr<SYCLAddIRAttributesKernelParameterAttr>()) {
2614  checkSYCLAddIRAttributesMergeability(A, *ExistingAttr, *this);
2615  return nullptr;
2616  }
2617  ASTContext &Context = getASTContext();
2618  return A.clone(Context);
2619 }
2620 
2622  Decl *D, const ParsedAttr &A) {
2624  Args.reserve(A.getNumArgs() - 1);
2625  for (unsigned I = 0; I < A.getNumArgs(); I++) {
2626  assert(A.getArgAsExpr(I));
2627  Args.push_back(A.getArgAsExpr(I));
2628  }
2629 
2631 }
2632 
2633 SYCLAddIRAttributesGlobalVariableAttr *
2635  Decl *D, const SYCLAddIRAttributesGlobalVariableAttr &A) {
2636  if (const auto *ExistingAttr =
2637  D->getAttr<SYCLAddIRAttributesGlobalVariableAttr>()) {
2638  checkSYCLAddIRAttributesMergeability(A, *ExistingAttr, *this);
2639  return nullptr;
2640  }
2641  ASTContext &Context = getASTContext();
2642  return A.clone(Context);
2643 }
2644 
2646  const ParsedAttr &A) {
2648  Args.reserve(A.getNumArgs());
2649  for (unsigned I = 0; I < A.getNumArgs(); I++) {
2650  assert(A.getArgAsExpr(I));
2651  Args.push_back(A.getArgAsExpr(I));
2652  }
2653 
2655 }
2656 
2657 SYCLAddIRAnnotationsMemberAttr *SemaSYCL::mergeSYCLAddIRAnnotationsMemberAttr(
2658  Decl *D, const SYCLAddIRAnnotationsMemberAttr &A) {
2659  if (const auto *ExistingAttr = D->getAttr<SYCLAddIRAnnotationsMemberAttr>()) {
2660  checkSYCLAddIRAttributesMergeability(A, *ExistingAttr, *this);
2661  return nullptr;
2662  }
2663  ASTContext &Context = getASTContext();
2664  return A.clone(Context);
2665 }
2666 
2668  // Ignore the attribute if compiling for the host side because aspects may not
2669  // be marked properly for such compilation
2670  if (!getLangOpts().SYCLIsDevice)
2671  return;
2672 
2674  for (unsigned I = 0; I < A.getNumArgs(); ++I)
2675  Args.push_back(A.getArgAsExpr(I));
2676 
2677  addSYCLDeviceHasAttr(D, A, Args.data(), Args.size());
2678 }
2679 
2680 SYCLDeviceHasAttr *
2681 SemaSYCL::mergeSYCLDeviceHasAttr(Decl *D, const SYCLDeviceHasAttr &A) {
2682  if (const auto *ExistingAttr = D->getAttr<SYCLDeviceHasAttr>()) {
2683  Diag(ExistingAttr->getLoc(), diag::warn_duplicate_attribute_exact) << &A;
2684  Diag(A.getLoc(), diag::note_previous_attribute);
2685  return nullptr;
2686  }
2687 
2689  for (auto *E : A.aspects())
2690  Args.push_back(E);
2691  ASTContext &Context = getASTContext();
2692  return ::new (Context)
2693  SYCLDeviceHasAttr(Context, A, Args.data(), Args.size());
2694 }
2695 
2697  // Ignore the attribute if compiling for the host because aspects may not be
2698  // marked properly for such compilation
2699  if (!getLangOpts().SYCLIsDevice)
2700  return;
2701 
2703  for (unsigned I = 0; I < A.getNumArgs(); ++I)
2704  Args.push_back(A.getArgAsExpr(I));
2705 
2706  addSYCLUsesAspectsAttr(D, A, Args.data(), Args.size());
2707 }
2708 
2709 SYCLUsesAspectsAttr *
2710 SemaSYCL::mergeSYCLUsesAspectsAttr(Decl *D, const SYCLUsesAspectsAttr &A) {
2711  if (const auto *ExistingAttr = D->getAttr<SYCLUsesAspectsAttr>()) {
2712  Diag(ExistingAttr->getLoc(), diag::warn_duplicate_attribute_exact) << &A;
2713  Diag(A.getLoc(), diag::note_previous_attribute);
2714  return nullptr;
2715  }
2716 
2718  for (auto *E : A.aspects())
2719  Args.push_back(E);
2720  ASTContext &Context = getASTContext();
2721  return ::new (Context)
2722  SYCLUsesAspectsAttr(Context, A, Args.data(), Args.size());
2723 }
2724 
2725 void SemaSYCL::handleSYCLTypeAttr(Decl *D, const ParsedAttr &AL) {
2726  if (!AL.isArgIdent(0)) {
2727  Diag(AL.getLoc(), diag::err_attribute_argument_type)
2728  << AL << AANT_ArgumentIdentifier;
2729  return;
2730  }
2731 
2732  IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
2733  SYCLTypeAttr::SYCLType Type;
2734 
2735  if (!SYCLTypeAttr::ConvertStrToSYCLType(II->getName(), Type)) {
2736  Diag(AL.getLoc(), diag::err_attribute_argument_not_supported) << AL << II;
2737  return;
2738  }
2739 
2740  if (SYCLTypeAttr *NewAttr = mergeSYCLTypeAttr(D, AL, Type))
2741  D->addAttr(NewAttr);
2742 }
2743 
2744 SYCLTypeAttr *SemaSYCL::mergeSYCLTypeAttr(Decl *D,
2745  const AttributeCommonInfo &CI,
2746  SYCLTypeAttr::SYCLType TypeName) {
2747  if (const auto *ExistingAttr = D->getAttr<SYCLTypeAttr>()) {
2748  if (ExistingAttr->getType() != TypeName) {
2749  Diag(ExistingAttr->getLoc(), diag::err_duplicate_attribute)
2750  << ExistingAttr;
2751  Diag(CI.getLoc(), diag::note_previous_attribute);
2752  }
2753  // Do not add duplicate attribute
2754  return nullptr;
2755  }
2756  ASTContext &Context = getASTContext();
2757  return ::new (Context) SYCLTypeAttr(Context, CI, TypeName);
2758 }
2759 
2760 /// Handle the [[intel::doublepump]] attribute.
2762  // 'doublepump' Attribute does not take any argument. Give a warning for
2763  // duplicate attributes but not if it's one we've implicitly added and drop
2764  // any duplicates.
2765  if (const auto *ExistingAttr = D->getAttr<SYCLIntelDoublePumpAttr>()) {
2766  if (ExistingAttr && !ExistingAttr->isImplicit()) {
2767  Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact) << &AL;
2768  Diag(ExistingAttr->getLoc(), diag::note_previous_attribute);
2769  return;
2770  }
2771  }
2772 
2773  // Check attribute applies to field, constant variables, local variables,
2774  // static variables, non-static data members, and device_global variables
2775  // for the device compilation.
2776  if ((D->getKind() == Decl::ParmVar) || checkValidFPGAMemoryAttributesVar(D)) {
2777  Diag(AL.getLoc(), diag::err_fpga_attribute_incorrect_variable)
2778  << AL << /*agent memory arguments*/ 0;
2779  return;
2780  }
2781 
2782  ASTContext &Context = getASTContext();
2783  // If the declaration does not have an [[intel::fpga_memory]]
2784  // attribute, this creates one as an implicit attribute.
2785  if (!D->hasAttr<SYCLIntelMemoryAttr>())
2786  D->addAttr(SYCLIntelMemoryAttr::CreateImplicit(
2787  Context, SYCLIntelMemoryAttr::Default));
2788 
2789  D->addAttr(::new (Context) SYCLIntelDoublePumpAttr(Context, AL));
2790 }
2791 
2792 /// Handle the [[intel::singlepump]] attribute.
2794  // 'singlepump' Attribute does not take any argument. Give a warning for
2795  // duplicate attributes but not if it's one we've implicitly added and drop
2796  // any duplicates.
2797  if (const auto *ExistingAttr = D->getAttr<SYCLIntelSinglePumpAttr>()) {
2798  if (ExistingAttr && !ExistingAttr->isImplicit()) {
2799  Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact) << &AL;
2800  Diag(ExistingAttr->getLoc(), diag::note_previous_attribute);
2801  return;
2802  }
2803  }
2804 
2805  // Check attribute applies to field, constant variables, local variables,
2806  // static variables, non-static data members, and device_global variables
2807  // for the device compilation.
2808  if (D->getKind() == Decl::ParmVar || checkValidFPGAMemoryAttributesVar(D)) {
2809  Diag(AL.getLoc(), diag::err_fpga_attribute_incorrect_variable)
2810  << AL << /*agent memory arguments*/ 0;
2811  return;
2812  }
2813 
2814  // If the declaration does not have an [[intel::fpga_memory]]
2815  // attribute, this creates one as an implicit attribute.
2816  ASTContext &Context = getASTContext();
2817  if (!D->hasAttr<SYCLIntelMemoryAttr>())
2818  D->addAttr(SYCLIntelMemoryAttr::CreateImplicit(
2819  Context, SYCLIntelMemoryAttr::Default));
2820 
2821  D->addAttr(::new (Context) SYCLIntelSinglePumpAttr(Context, AL));
2822 }
2823 
2824 /// Handle the [[intel::fpga_memory]] attribute.
2825 /// This is incompatible with the [[intel::fpga_register]] attribute.
2827  SYCLIntelMemoryAttr::MemoryKind Kind;
2828  if (AL.getNumArgs() == 0)
2829  Kind = SYCLIntelMemoryAttr::Default;
2830  else {
2831  StringRef Str;
2832  if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str))
2833  return;
2834  if (Str.empty() ||
2835  !SYCLIntelMemoryAttr::ConvertStrToMemoryKind(Str, Kind)) {
2836  SmallString<256> ValidStrings;
2837  SYCLIntelMemoryAttr::generateValidStrings(ValidStrings);
2838  Diag(AL.getLoc(), diag::err_intel_fpga_memory_arg_invalid)
2839  << AL << ValidStrings;
2840  return;
2841  }
2842  }
2843 
2844  if (auto *MA = D->getAttr<SYCLIntelMemoryAttr>()) {
2845  // Check to see if there's a duplicate memory attribute with different
2846  // values already applied to the declaration.
2847  if (!MA->isImplicit()) {
2848  if (MA->getKind() != Kind) {
2849  Diag(AL.getLoc(), diag::warn_duplicate_attribute) << &AL;
2850  Diag(MA->getLocation(), diag::note_previous_attribute);
2851  }
2852  // Drop the duplicate attribute.
2853  return;
2854  }
2855  // We are adding a user memory attribute, drop any implicit default.
2856  D->dropAttr<SYCLIntelMemoryAttr>();
2857  }
2858 
2859  // Check attribute applies to field, constant variables, local variables,
2860  // static variables, agent memory arguments, non-static data members,
2861  // and device_global variables for the device compilation.
2863  Diag(AL.getLoc(), diag::err_fpga_attribute_incorrect_variable)
2864  << AL << /*agent memory arguments*/ 1;
2865  return;
2866  }
2867 
2868  ASTContext &Context = getASTContext();
2869  D->addAttr(::new (Context) SYCLIntelMemoryAttr(Context, AL, Kind));
2870 }
2871 
2872 /// Handle the [[intel::fpga_register]] attribute.
2873 /// This is incompatible with most of the other memory attributes.
2875  // 'fpga_register' Attribute does not take any argument. Give a warning for
2876  // duplicate attributes but not if it's one we've implicitly added and drop
2877  // any duplicates.
2878  if (const auto *ExistingAttr = D->getAttr<SYCLIntelRegisterAttr>()) {
2879  if (ExistingAttr && !ExistingAttr->isImplicit()) {
2880  Diag(A.getLoc(), diag::warn_duplicate_attribute_exact) << &A;
2881  Diag(ExistingAttr->getLoc(), diag::note_previous_attribute);
2882  return;
2883  }
2884  }
2885 
2886  // Check attribute applies to field, constant variables, local variables,
2887  // static variables, non-static data members, and device_global variables
2888  // for the device compilation.
2889  if (D->getKind() == Decl::ParmVar || checkValidFPGAMemoryAttributesVar(D)) {
2890  Diag(A.getLoc(), diag::err_fpga_attribute_incorrect_variable)
2891  << A << /*agent memory arguments*/ 0;
2892  return;
2893  }
2894 
2895  ASTContext &Context = getASTContext();
2896  D->addAttr(::new (Context) SYCLIntelRegisterAttr(Context, A));
2897 }
2898 
2900  // 'simple_dual_port' Attribute does not take any argument. Give a warning for
2901  // duplicate attributes but not if it's one we've implicitly added and drop
2902  // any duplicates.
2903  if (const auto *ExistingAttr = D->getAttr<SYCLIntelSimpleDualPortAttr>()) {
2904  if (ExistingAttr && !ExistingAttr->isImplicit()) {
2905  Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact) << &AL;
2906  Diag(ExistingAttr->getLoc(), diag::note_previous_attribute);
2907  return;
2908  }
2909  }
2910 
2911  // Check attribute applies to field, constant variables, local variables,
2912  // static variables, agent memory arguments, non-static data members,
2913  // and device_global variables for the device compilation.
2915  Diag(AL.getLoc(), diag::err_fpga_attribute_incorrect_variable)
2916  << AL << /*agent memory arguments*/ 1;
2917  return;
2918  }
2919 
2920  ASTContext &Context = getASTContext();
2921  if (!D->hasAttr<SYCLIntelMemoryAttr>())
2922  D->addAttr(SYCLIntelMemoryAttr::CreateImplicit(
2923  Context, SYCLIntelMemoryAttr::Default));
2924 
2925  D->addAttr(::new (Context) SYCLIntelSimpleDualPortAttr(Context, AL));
2926 }
2927 
2928 /// Handle the merge attribute.
2929 /// This requires two string arguments. The first argument is a name, the
2930 /// second is a direction. The direction must be "depth" or "width".
2931 /// This is incompatible with the register attribute.
2933  SmallVector<StringRef, 2> Results;
2934  for (int I = 0; I < 2; I++) {
2935  StringRef Str;
2936  if (!SemaRef.checkStringLiteralArgumentAttr(AL, I, Str))
2937  return;
2938 
2939  if (I == 1 && Str != "depth" && Str != "width") {
2940  Diag(AL.getLoc(), diag::err_intel_fpga_merge_dir_invalid) << AL;
2941  return;
2942  }
2943  Results.push_back(Str);
2944  }
2945 
2946  // Warn about duplicate attributes if they have different arguments, no
2947  // diagnostic is emitted if the arguments match, and drop any duplicate
2948  // attributes.
2949  if (const auto *Existing = D->getAttr<SYCLIntelMergeAttr>()) {
2950  if (Existing && !(Existing->getName() == Results[0] &&
2951  Existing->getDirection() == Results[1])) {
2952  Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
2953  Diag(Existing->getLoc(), diag::note_previous_attribute);
2954  }
2955  // If there is no mismatch, drop any duplicate attributes.
2956  return;
2957  }
2958 
2959  // Check attribute applies to field, constant variables, local variables,
2960  // static variables, non-static data members, and device_global variables
2961  // for the device compilation.
2962  if (D->getKind() == Decl::ParmVar || checkValidFPGAMemoryAttributesVar(D)) {
2963  Diag(AL.getLoc(), diag::err_fpga_attribute_incorrect_variable)
2964  << AL << /*agent memory arguments*/ 0;
2965  return;
2966  }
2967 
2968  ASTContext &Context = getASTContext();
2969  if (!D->hasAttr<SYCLIntelMemoryAttr>())
2970  D->addAttr(SYCLIntelMemoryAttr::CreateImplicit(
2971  Context, SYCLIntelMemoryAttr::Default));
2972 
2973  D->addAttr(::new (Context)
2974  SYCLIntelMergeAttr(Context, AL, Results[0], Results[1]));
2975 }
2976 
2977 /// Give a warning for duplicate attributes, return true if duplicate.
2978 template <typename AttrType>
2979 static bool checkForDuplicateAttribute(SemaSYCL &S, Decl *D,
2980  const ParsedAttr &Attr) {
2981  // Give a warning for duplicates but not if it's one we've implicitly added.
2982  auto *A = D->getAttr<AttrType>();
2983  if (A && !A->isImplicit()) {
2984  S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute_exact) << A;
2985  return true;
2986  }
2987  return false;
2988 }
2989 
2990 /// Handle the bank_bits attribute.
2991 /// This attribute accepts a list of values greater than zero.
2992 /// This is incompatible with the register attribute.
2993 /// The numbanks and bank_bits attributes are related. If numbanks exists
2994 /// when handling bank_bits they are checked for consistency. If numbanks
2995 /// hasn't been added yet an implicit one is added with the correct value.
2996 /// If the user later adds a numbanks attribute the implicit one is removed.
2997 /// The values must be consecutive values (i.e. 3,4,5 or 2,1).
2999  checkForDuplicateAttribute<SYCLIntelBankBitsAttr>(*this, D, A);
3000 
3001  if (!A.checkAtLeastNumArgs(SemaRef, 1))
3002  return;
3003 
3005  for (unsigned I = 0; I < A.getNumArgs(); ++I) {
3006  Args.push_back(A.getArgAsExpr(I));
3007  }
3008 
3009  addSYCLIntelBankBitsAttr(D, A, Args.data(), Args.size());
3010 }
3011 
3014 }
3015 
3017  const ParsedAttr &A) {
3018  Expr *E = A.getArgAsExpr(0);
3020 }
3021 
3022 // Handles use_stall_enable_clusters
3024  const ParsedAttr &A) {
3025  ASTContext &Context = getASTContext();
3026  D->addAttr(::new (Context) SYCLIntelUseStallEnableClustersAttr(Context, A));
3027 }
3028 
3029 // Handles max_work_group_size attribute.
3032  AL.getArgAsExpr(1), AL.getArgAsExpr(2));
3033 }
3034 
3035 // Handles min_work_groups_per_cu attribute.
3037  Decl *D, const ParsedAttr &AL) {
3039 }
3040 
3041 // Handles max_work_groups_per_mp attribute.
3043  Decl *D, const ParsedAttr &AL) {
3045 }
3046 
3047 void SemaSYCL::handleSYCLDeviceAttr(Decl *D, const ParsedAttr &AL) {
3048  auto *ND = cast<NamedDecl>(D);
3049  if (!ND->isExternallyVisible()) {
3050  Diag(AL.getLoc(), diag::err_sycl_attribute_internal_decl)
3051  << AL << !isa<FunctionDecl>(ND);
3052  return;
3053  }
3054 
3055  if (auto *VD = dyn_cast<VarDecl>(D)) {
3056  QualType VarType = VD->getType();
3057  // Diagnose only for non-dependent types since dependent type don't have
3058  // attributes applied on them ATM.
3059  if (!VarType->isDependentType() &&
3060  !isTypeDecoratedWithDeclAttribute<SYCLDeviceGlobalAttr>(
3061  VD->getType())) {
3062  Diag(AL.getLoc(), diag::err_sycl_attribute_not_device_global) << AL;
3063  return;
3064  }
3065  }
3066 
3067  handleSimpleAttribute<SYCLDeviceAttr>(*this, D, AL);
3068 }
3069 
3071  const ParsedAttr &AL) {
3072  auto *FD = cast<FunctionDecl>(D);
3073  if (!FD->isExternallyVisible()) {
3074  Diag(AL.getLoc(), diag::err_sycl_attribute_internal_decl)
3075  << AL << /*function*/ 0;
3076  return;
3077  }
3078 
3079  ASTContext &Context = getASTContext();
3080  D->addAttr(SYCLDeviceAttr::CreateImplicit(Context));
3081  handleSimpleAttribute<SYCLDeviceIndirectlyCallableAttr>(*this, D, AL);
3082 }
3083 
3085  ASTContext &Context = getASTContext();
3086  if (!Context.getSourceManager().isInSystemHeader(D->getLocation())) {
3087  Diag(AL.getLoc(), diag::err_attribute_only_system_header) << AL;
3088  return;
3089  }
3090 
3091  handleSimpleAttribute<SYCLGlobalVarAttr>(*this, D, AL);
3092 }
3093 
3095  if (!AL.checkExactlyNumArgs(SemaRef, 1))
3096  return;
3097  uint32_t RegNo = 0;
3098  const Expr *E = AL.getArgAsExpr(0);
3099  if (!SemaRef.checkUInt32Argument(AL, E, RegNo, 0, /*StrictlyUnsigned=*/true))
3100  return;
3101  ASTContext &Context = getASTContext();
3102  D->addAttr(::new (Context) SYCLRegisterNumAttr(Context, AL, RegNo));
3103 }
3104 
3106  const auto *AddIRFuncAttr = D->getAttr<SYCLAddIRAttributesFunctionAttr>();
3107 
3108  // If there is no such attribute there is nothing to check. If there are
3109  // dependent arguments we cannot know the actual number of arguments so we
3110  // defer the check.
3111  if (!AddIRFuncAttr ||
3112  hasDependentExpr(AddIRFuncAttr->args_begin(), AddIRFuncAttr->args_size()))
3113  return;
3114 
3115  // If there are no name-value pairs in the attribute it will not have an
3116  // effect and we can skip the check. The filter is ignored.
3117  size_t NumArgsWithoutFilter =
3118  AddIRFuncAttr->args_size() - (AddIRFuncAttr->hasFilterList() ? 1 : 0);
3119  if (NumArgsWithoutFilter == 0)
3120  return;
3121 
3122  // "sycl-single-task" is present on all single_task invocations, implicitly
3123  // added by the SYCL headers. It can only conflict with max_global_work_dim,
3124  // but the value will be the same so there is no need for a warning.
3125  ASTContext &Context = getASTContext();
3126  if (NumArgsWithoutFilter == 2) {
3127  auto NameValuePairs = AddIRFuncAttr->getAttributeNameValuePairs(Context);
3128  if (NameValuePairs.size() > 0 &&
3129  NameValuePairs[0].first == "sycl-single-task")
3130  return;
3131  }
3132 
3133  // If there are potentially conflicting attributes, we issue a warning.
3134  for (const auto *Attr : std::vector<AttributeCommonInfo *>{
3135  D->getAttr<SYCLReqdWorkGroupSizeAttr>(),
3136  D->getAttr<IntelReqdSubGroupSizeAttr>(),
3137  D->getAttr<SYCLWorkGroupSizeHintAttr>(),
3138  D->getAttr<SYCLDeviceHasAttr>()})
3139  if (Attr)
3140  Diag(Attr->getLoc(), diag::warn_sycl_old_and_new_kernel_attributes)
3141  << Attr;
3142 }
#define V(N, I)
Definition: ASTContext.h:3346
#define SM(sm)
Definition: Cuda.cpp:83
const Decl * D
enum clang::sema::@1659::IndirectLocalPathEntry::EntryKind Kind
Expr * E
llvm::APSInt APSInt
Definition: Compiler.cpp:22
SourceLocation Loc
Definition: SemaObjC.cpp:759
DupArgResult
static DupArgResult areArgValuesIdentical(const Expr *LHS, const Expr *RHS)
This file declares semantic analysis for SYCL constructs.
Defines the SourceManager interface.
bool hasValue() const
Definition: APValue.h:399
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:187
SourceManager & getSourceManager()
Definition: ASTContext.h:721
const LangOptions & getLangOpts() const
Definition: ASTContext.h:797
CanQualType IntTy
Definition: ASTContext.h:1128
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:779
PtrTy get() const
Definition: Ownership.h:170
bool isInvalid() const
Definition: Ownership.h:166
Attr - This represents one attribute.
Definition: Attr.h:46
SourceLocation getScopeLoc() const
std::string getNormalizedFullName() const
Gets the normalized full name, which consists of both scope and name and with surrounding underscores...
Definition: Attributes.cpp:155
unsigned getAttributeSpellingListIndex() const
const IdentifierInfo * getAttrName() const
SourceLocation getLoc() const
const IdentifierInfo * getScopeName() const
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
Definition: Expr.h:1077
llvm::APSInt getResultAsAPSInt() const
Definition: Expr.cpp:401
static ConstantExpr * Create(const ASTContext &Context, Expr *E, const APValue &Result)
Definition: Expr.cpp:350
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
void addAttr(Attr *A)
Definition: DeclBase.cpp:1013
SourceLocation getLocation() const
Definition: DeclBase.h:446
void dropAttr()
Definition: DeclBase.h:563
bool hasAttr() const
Definition: DeclBase.h:584
Kind getKind() const
Definition: DeclBase.h:449
T * getAttr() const
Definition: DeclBase.h:580
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
Definition: Type.h:6001
EnumDecl * getDecl() const
Definition: Type.h:6008
This represents one expression.
Definition: Expr.h:110
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition: Expr.h:175
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition: Expr.h:192
bool EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx, ConstantExprKind Kind=ConstantExprKind::Normal) const
Evaluate an expression that is required to be a constant expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:277
QualType getType() const
Definition: Expr.h:142
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
Definition: Diagnostic.h:72
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
Definition: Diagnostic.h:135
Declaration of a template function.
Definition: DeclTemplate.h:957
One of these records is kept for each identifier that is lexed.
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
StringRef getName() const
Return the actual identifier string.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Definition: Expr.cpp:1032
This represents a decl that may have a name.
Definition: Decl.h:249
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:129
IdentifierLoc * getArgAsIdent(unsigned Arg) const
Definition: ParsedAttr.h:406
bool checkExactlyNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has exactly as many args as Num.
Definition: ParsedAttr.cpp:302
Expr * getArgAsExpr(unsigned Arg) const
Definition: ParsedAttr.h:398
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
Definition: ParsedAttr.h:386
bool isArgIdent(unsigned Arg) const
Definition: ParsedAttr.h:402
bool checkAtLeastNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has at least as many args as Num.
Definition: ParsedAttr.cpp:307
AttributeCommonInfo::Kind getKind() const
Definition: ParsedAttr.h:632
bool isArgExpr(unsigned Arg) const
Definition: ParsedAttr.h:394
bool checkAtMostNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has at most as many args as Num.
Definition: ParsedAttr.cpp:312
A (possibly-)qualified type.
Definition: Type.h:941
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition: Type.h:7833
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:64
ASTContext & getASTContext() const
Definition: SemaBase.cpp:9
Sema & SemaRef
Definition: SemaBase.h:40
const LangOptions & getLangOpts() const
Definition: SemaBase.cpp:11
void handleSYCLAddIRAttributesFunctionAttr(Decl *D, const ParsedAttr &AL)
void handleSYCLIntelSinglePumpAttr(Decl *D, const ParsedAttr &AL)
SYCLIntelNumSimdWorkItemsAttr * mergeSYCLIntelNumSimdWorkItemsAttr(Decl *D, const SYCLIntelNumSimdWorkItemsAttr &A)
void addSYCLDeviceHasAttr(Decl *D, const AttributeCommonInfo &CI, Expr **Exprs, unsigned Size)
SYCLDeviceHasAttr * mergeSYCLDeviceHasAttr(Decl *D, const SYCLDeviceHasAttr &A)
SYCLReqdWorkGroupSizeAttr * mergeSYCLReqdWorkGroupSizeAttr(Decl *D, const SYCLReqdWorkGroupSizeAttr &A)
void handleIntelNamedSubGroupSizeAttr(Decl *D, const ParsedAttr &AL)
SYCLAddIRAnnotationsMemberAttr * mergeSYCLAddIRAnnotationsMemberAttr(Decl *D, const SYCLAddIRAnnotationsMemberAttr &A)
SYCLTypeAttr * mergeSYCLTypeAttr(Decl *D, const AttributeCommonInfo &CI, SYCLTypeAttr::SYCLType TypeName)
void handleSYCLIntelMergeAttr(Decl *D, const ParsedAttr &AL)
bool areInvalidWorkGroupSizeAttrs(const Expr *MGValue, const Expr *XDim, const Expr *YDim, const Expr *ZDim)
SYCLIntelMaxWorkGroupSizeAttr * mergeSYCLIntelMaxWorkGroupSizeAttr(Decl *D, const SYCLIntelMaxWorkGroupSizeAttr &A)
SYCLAddIRAttributesGlobalVariableAttr * mergeSYCLAddIRAttributesGlobalVariableAttr(Decl *D, const SYCLAddIRAttributesGlobalVariableAttr &A)
void handleSYCLIntelMaxWorkGroupSize(Decl *D, const ParsedAttr &AL)
IntelReqdSubGroupSizeAttr * mergeIntelReqdSubGroupSizeAttr(Decl *D, const IntelReqdSubGroupSizeAttr &A)
void handleSYCLAddIRAttributesGlobalVariableAttr(Decl *D, const ParsedAttr &AL)
void addSYCLIntelPipeIOAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E)
void handleSYCLIntelLoopFuseAttr(Decl *D, const ParsedAttr &AL)
SYCLIntelNoGlobalWorkOffsetAttr * mergeSYCLIntelNoGlobalWorkOffsetAttr(Decl *D, const SYCLIntelNoGlobalWorkOffsetAttr &A)
IntelNamedSubGroupSizeAttr * mergeIntelNamedSubGroupSizeAttr(Decl *D, const IntelNamedSubGroupSizeAttr &A)
void handleSYCLRegisterNumAttr(Decl *D, const ParsedAttr &AL)
static OffloadArch getOffloadArch(const TargetInfo &TI)
void checkSYCLAddIRAttributesFunctionAttrConflicts(Decl *D)
void handleSYCLIntelNoGlobalWorkOffsetAttr(Decl *D, const ParsedAttr &AL)
void handleSYCLAddIRAttributesKernelParameterAttr(Decl *D, const ParsedAttr &AL)
void addSYCLAddIRAnnotationsMemberAttr(Decl *D, const AttributeCommonInfo &CI, MutableArrayRef< Expr * > Args)
void addSYCLAddIRAttributesFunctionAttr(Decl *D, const AttributeCommonInfo &CI, MutableArrayRef< Expr * > Args)
void handleSYCLAddIRAnnotationsMemberAttr(Decl *D, const ParsedAttr &AL)
void addSYCLIntelMaxReplicatesAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E)
void addSYCLIntelMaxConcurrencyAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E)
void addSYCLIntelLoopFuseAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E)
bool checkWorkGroupSize(const Expr *NSWIValue, const Expr *RWGSXDim, const Expr *RWGSYDim, const Expr *RWGSZDim)
void handleSYCLIntelPipeIOAttr(Decl *D, const ParsedAttr &AL)
void handleSYCLGlobalVarAttr(Decl *D, const ParsedAttr &AL)
bool checkMaxAllowedWorkGroupSize(const Expr *RWGSXDim, const Expr *RWGSYDim, const Expr *RWGSZDim, const Expr *MWGSXDim, const Expr *MWGSYDim, const Expr *MWGSZDim)
void handleSYCLDeviceIndirectlyCallableAttr(Decl *D, const ParsedAttr &AL)
void handleSYCLTypeAttr(Decl *D, const ParsedAttr &AL)
void handleSYCLIntelBankBitsAttr(Decl *D, const ParsedAttr &AL)
void handleSYCLIntelMaxGlobalWorkDimAttr(Decl *D, const ParsedAttr &AL)
void handleSYCLIntelUseStallEnableClustersAttr(Decl *D, const ParsedAttr &AL)
void handleSYCLIntelPrivateCopiesAttr(Decl *D, const ParsedAttr &AL)
void checkDeprecatedSYCLAttributeSpelling(const ParsedAttr &A, StringRef NewName="")
Diagnoses an attribute in the 'intelfpga' namespace and suggests using the attribute in the 'intel' n...
SYCLAddIRAttributesKernelParameterAttr * mergeSYCLAddIRAttributesKernelParameterAttr(Decl *D, const SYCLAddIRAttributesKernelParameterAttr &A)
void addSYCLAddIRAttributesKernelParameterAttr(Decl *D, const AttributeCommonInfo &CI, MutableArrayRef< Expr * > Args)
void addSYCLIntelInitiationIntervalAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E)
void addSYCLIntelMaxWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI, Expr *XDim, Expr *YDim, Expr *ZDim)
void addSYCLIntelSchedulerTargetFmaxMhzAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E)
SYCLIntelESimdVectorizeAttr * mergeSYCLIntelESimdVectorizeAttr(Decl *D, const SYCLIntelESimdVectorizeAttr &A)
void addSYCLIntelNoGlobalWorkOffsetAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E)
SYCLAddIRAttributesFunctionAttr * mergeSYCLAddIRAttributesFunctionAttr(Decl *D, const SYCLAddIRAttributesFunctionAttr &A)
void handleSYCLIntelMaxReplicatesAttr(Decl *D, const ParsedAttr &AL)
SYCLIntelMaxConcurrencyAttr * mergeSYCLIntelMaxConcurrencyAttr(Decl *D, const SYCLIntelMaxConcurrencyAttr &A)
bool anyWorkGroupSizesDiffer(const Expr *LHSXDim, const Expr *LHSYDim, const Expr *LHSZDim, const Expr *RHSXDim, const Expr *RHSYDim, const Expr *RHSZDim)
void handleSYCLIntelMemoryAttr(Decl *D, const ParsedAttr &AL)
void addSYCLIntelNumSimdWorkItemsAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E)
void handleSYCLUsesAspectsAttr(Decl *D, const ParsedAttr &AL)
void addSYCLAddIRAttributesGlobalVariableAttr(Decl *D, const AttributeCommonInfo &CI, MutableArrayRef< Expr * > Args)
void addSYCLIntelMaxGlobalWorkDimAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E)
void handleSYCLIntelForcePow2DepthAttr(Decl *D, const ParsedAttr &AL)
void addIntelReqdSubGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E)
SYCLWorkGroupSizeHintAttr * mergeSYCLWorkGroupSizeHintAttr(Decl *D, const SYCLWorkGroupSizeHintAttr &A)
void addSYCLWorkGroupSizeHintAttr(Decl *D, const AttributeCommonInfo &CI, Expr *XDim, Expr *YDim, Expr *ZDim)
SYCLIntelPipeIOAttr * mergeSYCLIntelPipeIOAttr(Decl *D, const SYCLIntelPipeIOAttr &A)
SYCLIntelSchedulerTargetFmaxMhzAttr * mergeSYCLIntelSchedulerTargetFmaxMhzAttr(Decl *D, const SYCLIntelSchedulerTargetFmaxMhzAttr &A)
static bool hasDependentExpr(Expr **Exprs, const size_t ExprsSize)
SYCLIntelForcePow2DepthAttr * mergeSYCLIntelForcePow2DepthAttr(Decl *D, const SYCLIntelForcePow2DepthAttr &A)
SYCLUsesAspectsAttr * mergeSYCLUsesAspectsAttr(Decl *D, const SYCLUsesAspectsAttr &A)
SYCLIntelMaxGlobalWorkDimAttr * mergeSYCLIntelMaxGlobalWorkDimAttr(Decl *D, const SYCLIntelMaxGlobalWorkDimAttr &A)
void addSYCLIntelESimdVectorizeAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E)
void handleSYCLDeviceAttr(Decl *D, const ParsedAttr &AL)
void handleSYCLIntelInitiationIntervalAttr(Decl *D, const ParsedAttr &AL)
void handleSYCLIntelMaxWorkGroupsPerMultiprocessor(Decl *D, const ParsedAttr &AL)
SYCLIntelMaxReplicatesAttr * mergeSYCLIntelMaxReplicatesAttr(Decl *D, const SYCLIntelMaxReplicatesAttr &A)
void handleKernelAttr(Decl *D, const ParsedAttr &AL)
SYCLIntelMaxWorkGroupsPerMultiprocessorAttr * mergeSYCLIntelMaxWorkGroupsPerMultiprocessorAttr(Decl *D, const SYCLIntelMaxWorkGroupsPerMultiprocessorAttr &A)
void handleSYCLIntelNumSimdWorkItemsAttr(Decl *D, const ParsedAttr &AL)
void addSYCLIntelPrivateCopiesAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E)
void addSYCLUsesAspectsAttr(Decl *D, const AttributeCommonInfo &CI, Expr **Exprs, unsigned Size)
void handleIntelSimpleDualPortAttr(Decl *D, const ParsedAttr &AL)
void diagnoseDeprecatedAttribute(const ParsedAttr &A, StringRef NewScope, StringRef NewName)
Emit a diagnostic about the given attribute having a deprecated name, and also emit a fixit hint to g...
void addSYCLIntelBankWidthAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E)
void handleSYCLWorkGroupSizeHintAttr(Decl *D, const ParsedAttr &AL)
void handleSYCLIntelNumBanksAttr(Decl *D, const ParsedAttr &AL)
void addSYCLIntelForcePow2DepthAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E)
void handleIntelReqdSubGroupSizeAttr(Decl *D, const ParsedAttr &AL)
bool checkValidFPGAMemoryAttributesVar(Decl *D)
void handleSYCLReqdWorkGroupSizeAttr(Decl *D, const ParsedAttr &AL)
void handleSYCLIntelRegisterAttr(Decl *D, const ParsedAttr &AL)
void handleSYCLIntelBankWidthAttr(Decl *D, const ParsedAttr &AL)
void handleSYCLIntelMaxConcurrencyAttr(Decl *D, const ParsedAttr &AL)
SYCLIntelNumBanksAttr * mergeSYCLIntelNumBanksAttr(Decl *D, const SYCLIntelNumBanksAttr &A)
void handleSYCLIntelSchedulerTargetFmaxMhzAttr(Decl *D, const ParsedAttr &AL)
void handleSYCLIntelDoublePumpAttr(Decl *D, const ParsedAttr &AL)
void addSYCLReqdWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI, Expr *XDim, Expr *YDim, Expr *ZDim)
void handleSYCLIntelMinWorkGroupsPerComputeUnit(Decl *D, const ParsedAttr &AL)
bool allWorkGroupSizesSame(const Expr *LHSXDim, const Expr *LHSYDim, const Expr *LHSZDim, const Expr *RHSXDim, const Expr *RHSYDim, const Expr *RHSZDim)
SYCLIntelBankWidthAttr * mergeSYCLIntelBankWidthAttr(Decl *D, const SYCLIntelBankWidthAttr &A)
SYCLIntelLoopFuseAttr * mergeSYCLIntelLoopFuseAttr(Decl *D, const SYCLIntelLoopFuseAttr &A)
void addSYCLIntelNumBanksAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E)
SYCLIntelInitiationIntervalAttr * mergeSYCLIntelInitiationIntervalAttr(Decl *D, const SYCLIntelInitiationIntervalAttr &A)
SYCLIntelMinWorkGroupsPerComputeUnitAttr * mergeSYCLIntelMinWorkGroupsPerComputeUnitAttr(Decl *D, const SYCLIntelMinWorkGroupsPerComputeUnitAttr &A)
void handleSYCLIntelESimdVectorizeAttr(Decl *D, const ParsedAttr &AL)
void handleSYCLDeviceHasAttr(Decl *D, const ParsedAttr &AL)
void addSYCLIntelMinWorkGroupsPerComputeUnitAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E)
void addSYCLIntelMaxWorkGroupsPerMultiprocessorAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E)
void addSYCLIntelBankBitsAttr(Decl *D, const AttributeCommonInfo &CI, Expr **Exprs, unsigned Size)
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=NoFold)
VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...
Definition: SemaExpr.cpp:17006
bool checkUInt32Argument(const AttrInfo &AI, const Expr *Expr, uint32_t &Val, unsigned Idx=UINT_MAX, bool StrictlyUnsigned=false)
If Expr is a valid integer constant, get the value of the integer expression and return success or fa...
Definition: Sema.h:4450
ASTContext & getASTContext() const
Definition: Sema.h:560
bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, const Expr *E, StringRef &Str, SourceLocation *ArgLocation=nullptr)
Check if the argument E is a ASCII string literal.
Encodes a location in the source.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:326
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:338
Exposes information about the current target.
Definition: TargetInfo.h:218
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1256
TargetOptions & getTargetOpts() const
Retrieve the target options.
Definition: TargetInfo.h:312
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Definition: DeclTemplate.h:413
Stores a list of template parameters for a TemplateDecl and its derived classes.
Definition: DeclTemplate.h:73
NamedDecl * getParam(unsigned Idx)
Definition: DeclTemplate.h:144
The base class of the type hierarchy.
Definition: Type.h:1829
bool isStructureType() const
Definition: Type.cpp:629
bool isVoidType() const
Definition: Type.h:8347
bool isArrayType() const
Definition: Type.h:8085
bool isCharType() const
Definition: Type.cpp:2089
bool isPointerType() const
Definition: Type.h:8013
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:705
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:8462
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2701
bool isFloatingType() const
Definition: Type.cpp:2249
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8568
bool isNullPtrType() const
Definition: Type.h:8380
QualType getType() const
Definition: Decl.h:679
Represents a variable declaration or definition.
Definition: Decl.h:880
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition: Decl.h:1133
Defines the clang::TargetInfo interface.
llvm::APInt APInt
Definition: Integral.h:29
std::string toString(const til::SExpr *E)
The JSON file list parser is used to communicate input to InstallAPI.
QualType getFunctionOrMethodResultType(const Decl *D)
Definition: Attr.h:98
OffloadArch
Definition: Cuda.h:55
@ SC_Static
Definition: Specifiers.h:252
@ AANT_ArgumentConstantExpr
Definition: ParsedAttr.h:1089
@ AANT_ArgumentIdentifier
Definition: ParsedAttr.h:1088
OffloadArch StringToOffloadArch(llvm::StringRef S)
Definition: Cuda.cpp:175
const char * OffloadArchToString(OffloadArch A)
Definition: Cuda.cpp:157
const FunctionProtoType * T
unsigned getFunctionOrMethodNumParams(const Decl *D)
getFunctionOrMethodNumParams - Return number of function or method parameters.
Definition: Attr.h:64
unsigned int uint32_t
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:642
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:644
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Definition: Expr.h:630
Wraps an identifier and optional source location for the identifier.
Definition: ParsedAttr.h:103
SourceLocation Loc
Definition: ParsedAttr.h:104
IdentifierInfo * Ident
Definition: ParsedAttr.h:105