clang  19.0.0git
SemaSYCL.cpp
Go to the documentation of this file.
1 //===- SemaSYCL.cpp - Semantic Analysis for SYCL constructs ---------------===//
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 constructs.
9 //===----------------------------------------------------------------------===//
10 
11 #include "clang/Sema/SemaSYCL.h"
12 #include "TreeTransform.h"
13 #include "clang/AST/AST.h"
14 #include "clang/AST/Mangle.h"
16 #include "clang/AST/RecordLayout.h"
19 #include "clang/AST/TypeVisitor.h"
21 #include "clang/Basic/Attributes.h"
22 #include "clang/Basic/Builtins.h"
23 #include "clang/Basic/Diagnostic.h"
24 #include "clang/Basic/TargetInfo.h"
25 #include "clang/Basic/Version.h"
27 #include "clang/Sema/Sema.h"
28 #include "llvm/ADT/APSInt.h"
29 #include "llvm/ADT/SmallPtrSet.h"
30 #include "llvm/ADT/SmallVector.h"
31 #include "llvm/ADT/StringExtras.h"
32 #include "llvm/Support/FileSystem.h"
33 #include "llvm/Support/Path.h"
34 #include "llvm/Support/raw_ostream.h"
35 
36 #include <array>
37 #include <functional>
38 #include <initializer_list>
39 
40 using namespace clang;
41 using namespace std::placeholders;
42 
44 
45 enum target {
46  global_buffer = 2014,
53 };
54 
55 using ParamDesc = std::tuple<QualType, IdentifierInfo *, TypeSourceInfo *>;
56 
62 };
63 
64 static constexpr llvm::StringLiteral InitMethodName = "__init";
65 static constexpr llvm::StringLiteral InitESIMDMethodName = "__init_esimd";
66 static constexpr llvm::StringLiteral InitSpecConstantsBuffer =
67  "__init_specialization_constants_buffer";
68 static constexpr llvm::StringLiteral FinalizeMethodName = "__finalize";
69 static constexpr llvm::StringLiteral LibstdcxxFailedAssertion =
70  "__failed_assertion";
71 constexpr unsigned MaxKernelArgsSize = 2048;
72 
73 bool SemaSYCL::isSyclType(QualType Ty, SYCLTypeAttr::SYCLType TypeName) {
74  const auto *RD = Ty->getAsCXXRecordDecl();
75  if (!RD)
76  return false;
77 
78  if (const auto *Attr = RD->getAttr<SYCLTypeAttr>())
79  return Attr->getType() == TypeName;
80 
81  if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
83  CTSD->getSpecializedTemplate()->getTemplatedDecl())
84  if (const auto *Attr = TemplateDecl->getAttr<SYCLTypeAttr>())
85  return Attr->getType() == TypeName;
86 
87  return false;
88 }
89 
90 static bool isSyclAccessorType(QualType Ty) {
91  return SemaSYCL::isSyclType(Ty, SYCLTypeAttr::accessor) ||
92  SemaSYCL::isSyclType(Ty, SYCLTypeAttr::local_accessor);
93 }
94 
95 // FIXME: Accessor property lists should be modified to use compile-time
96 // properties. Once implemented, this function (and possibly all/most code
97 // in SemaSYCL.cpp handling no_alias and buffer_location property) can be
98 // removed.
100  SYCLTypeAttr::SYCLType TypeName) {
101  if (const auto *RD = Ty->getAsCXXRecordDecl())
102  if (const auto *Parent = dyn_cast<CXXRecordDecl>(RD->getParent()))
103  if (const auto *Attr = Parent->getAttr<SYCLTypeAttr>())
104  return Attr->getType() == TypeName;
105 
106  return false;
107 }
108 
109 static bool isSyclSpecialType(QualType Ty, SemaSYCL &S) {
110  return S.isTypeDecoratedWithDeclAttribute<SYCLSpecialClassAttr>(Ty);
111 }
112 
114  TypeSourceInfo *TInfo = nullptr;
115  QualType QT = Sema::GetTypeFromParser(PT, &TInfo);
116  assert(TInfo && "couldn't get type info from a type from the parser?");
118 
119  return BuildSYCLBuiltinNumFieldsExpr(TypeLoc, QT);
120 }
121 
123  QualType SourceTy) {
124  if (!SourceTy->isDependentType()) {
125  if (SemaRef.RequireCompleteType(
126  Loc, SourceTy, diag::err_sycl_type_trait_requires_complete_type,
127  /*__builtin_num_fields*/ 0))
128  return ExprError();
129 
130  if (!SourceTy->isRecordType()) {
131  Diag(Loc, diag::err_sycl_type_trait_requires_record_type)
132  << /*__builtin_num_fields*/ 0;
133  return ExprError();
134  }
135  }
136  return new (getASTContext())
137  SYCLBuiltinNumFieldsExpr(Loc, SourceTy, getASTContext().getSizeType());
138 }
139 
141  TypeSourceInfo *TInfo = nullptr;
142  QualType QT = Sema::GetTypeFromParser(PT, &TInfo);
143  assert(TInfo && "couldn't get type info from a type from the parser?");
145 
146  return BuildSYCLBuiltinFieldTypeExpr(TypeLoc, QT, Idx);
147 }
148 
150  QualType SourceTy,
151  Expr *Idx) {
152  // If the expression appears in an evaluated context, we want to give an
153  // error so that users don't attempt to use the value of this expression.
154  if (!SemaRef.isUnevaluatedContext()) {
155  Diag(Loc, diag::err_sycl_builtin_type_trait_evaluated)
156  << /*__builtin_field_type*/ 0;
157  return ExprError();
158  }
159 
160  // We may not be able to calculate the field type (the source type may be a
161  // dependent type), so use the source type as a basic fallback. This will
162  // ensure that the AST node will have a dependent type that gets resolved
163  // later to the real type.
164  QualType FieldTy = SourceTy;
165  ExprValueKind ValueKind = VK_PRValue;
166  if (!SourceTy->isDependentType()) {
167  if (SemaRef.RequireCompleteType(
168  Loc, SourceTy, diag::err_sycl_type_trait_requires_complete_type,
169  /*__builtin_field_type*/ 1))
170  return ExprError();
171 
172  if (!SourceTy->isRecordType()) {
173  Diag(Loc, diag::err_sycl_type_trait_requires_record_type)
174  << /*__builtin_field_type*/ 1;
175  return ExprError();
176  }
177 
178  if (!Idx->isValueDependent()) {
179  std::optional<llvm::APSInt> IdxVal =
180  Idx->getIntegerConstantExpr(getASTContext());
181  if (IdxVal) {
182  RecordDecl *RD = SourceTy->getAsRecordDecl();
183  assert(RD && "Record type but no record decl?");
184  int64_t Index = IdxVal->getExtValue();
185 
186  if (Index < 0) {
187  Diag(Idx->getExprLoc(),
188  diag::err_sycl_type_trait_requires_nonnegative_index)
189  << /*fields*/ 0;
190  return ExprError();
191  }
192 
193  // Ensure that the index is within range.
194  int64_t NumFields = std::distance(RD->field_begin(), RD->field_end());
195  if (Index >= NumFields) {
196  Diag(Idx->getExprLoc(),
197  diag::err_sycl_builtin_type_trait_index_out_of_range)
198  << toString(*IdxVal, 10) << SourceTy << /*fields*/ 0;
199  return ExprError();
200  }
201  const FieldDecl *FD = *std::next(RD->field_begin(), Index);
202  FieldTy = FD->getType();
203 
204  // If the field type was a reference type, adjust it now.
205  if (FieldTy->isLValueReferenceType()) {
206  ValueKind = VK_LValue;
207  FieldTy = FieldTy.getNonReferenceType();
208  } else if (FieldTy->isRValueReferenceType()) {
209  ValueKind = VK_XValue;
210  FieldTy = FieldTy.getNonReferenceType();
211  }
212  }
213  }
214  }
215  return new (getASTContext())
216  SYCLBuiltinFieldTypeExpr(Loc, SourceTy, Idx, FieldTy, ValueKind);
217 }
218 
220  TypeSourceInfo *TInfo = nullptr;
221  QualType QT = Sema::GetTypeFromParser(PT, &TInfo);
222  assert(TInfo && "couldn't get type info from a type from the parser?");
224 
225  return BuildSYCLBuiltinNumBasesExpr(TypeLoc, QT);
226 }
227 
229  QualType SourceTy) {
230  if (!SourceTy->isDependentType()) {
231  if (SemaRef.RequireCompleteType(
232  Loc, SourceTy, diag::err_sycl_type_trait_requires_complete_type,
233  /*__builtin_num_bases*/ 2))
234  return ExprError();
235 
236  if (!SourceTy->isRecordType()) {
237  Diag(Loc, diag::err_sycl_type_trait_requires_record_type)
238  << /*__builtin_num_bases*/ 2;
239  return ExprError();
240  }
241  }
242  return new (getASTContext())
243  SYCLBuiltinNumBasesExpr(Loc, SourceTy, getASTContext().getSizeType());
244 }
245 
247  TypeSourceInfo *TInfo = nullptr;
248  QualType QT = SemaRef.GetTypeFromParser(PT, &TInfo);
249  assert(TInfo && "couldn't get type info from a type from the parser?");
251 
252  return BuildSYCLBuiltinBaseTypeExpr(TypeLoc, QT, Idx);
253 }
254 
256  QualType SourceTy,
257  Expr *Idx) {
258  // If the expression appears in an evaluated context, we want to give an
259  // error so that users don't attempt to use the value of this expression.
260  if (!SemaRef.isUnevaluatedContext()) {
261  Diag(Loc, diag::err_sycl_builtin_type_trait_evaluated)
262  << /*__builtin_base_type*/ 1;
263  return ExprError();
264  }
265 
266  // We may not be able to calculate the base type (the source type may be a
267  // dependent type), so use the source type as a basic fallback. This will
268  // ensure that the AST node will have a dependent type that gets resolved
269  // later to the real type.
270  QualType BaseTy = SourceTy;
271  if (!SourceTy->isDependentType()) {
272  if (SemaRef.RequireCompleteType(
273  Loc, SourceTy, diag::err_sycl_type_trait_requires_complete_type,
274  /*__builtin_base_type*/ 3))
275  return ExprError();
276 
277  if (!SourceTy->isRecordType()) {
278  Diag(Loc, diag::err_sycl_type_trait_requires_record_type)
279  << /*__builtin_base_type*/ 3;
280  return ExprError();
281  }
282 
283  if (!Idx->isValueDependent()) {
284  std::optional<llvm::APSInt> IdxVal =
285  Idx->getIntegerConstantExpr(getASTContext());
286  if (IdxVal) {
287  CXXRecordDecl *RD = SourceTy->getAsCXXRecordDecl();
288  assert(RD && "Record type but no record decl?");
289  int64_t Index = IdxVal->getExtValue();
290 
291  if (Index < 0) {
292  Diag(Idx->getExprLoc(),
293  diag::err_sycl_type_trait_requires_nonnegative_index)
294  << /*bases*/ 1;
295  return ExprError();
296  }
297 
298  // Ensure that the index is within range.
299  if (Index >= RD->getNumBases()) {
300  Diag(Idx->getExprLoc(),
301  diag::err_sycl_builtin_type_trait_index_out_of_range)
302  << toString(*IdxVal, 10) << SourceTy << /*bases*/ 1;
303  return ExprError();
304  }
305 
306  const CXXBaseSpecifier &Spec = *std::next(RD->bases_begin(), Index);
307  BaseTy = Spec.getType();
308  }
309  }
310  }
311  return new (getASTContext())
312  SYCLBuiltinBaseTypeExpr(Loc, SourceTy, Idx, BaseTy);
313 }
314 
315 // This information is from Section 4.13 of the SYCL spec
316 // https://www.khronos.org/registry/SYCL/specs/sycl-1.2.1.pdf
317 // This function returns false if the math lib function
318 // corresponding to the input builtin is not supported
319 // for SYCL
320 static bool IsSyclMathFunc(unsigned BuiltinID) {
321  switch (BuiltinID) {
322  case Builtin::BIlround:
323  case Builtin::BI__builtin_lround:
324  case Builtin::BIceill:
325  case Builtin::BI__builtin_ceill:
326  case Builtin::BIcopysignl:
327  case Builtin::BI__builtin_copysignl:
328  case Builtin::BIcosl:
329  case Builtin::BI__builtin_cosl:
330  case Builtin::BIexpl:
331  case Builtin::BI__builtin_expl:
332  case Builtin::BIexp2l:
333  case Builtin::BI__builtin_exp2l:
334  case Builtin::BIfabsl:
335  case Builtin::BI__builtin_fabsl:
336  case Builtin::BIfloorl:
337  case Builtin::BI__builtin_floorl:
338  case Builtin::BIfmal:
339  case Builtin::BI__builtin_fmal:
340  case Builtin::BIfmaxl:
341  case Builtin::BI__builtin_fmaxl:
342  case Builtin::BIfminl:
343  case Builtin::BI__builtin_fminl:
344  case Builtin::BIfmodl:
345  case Builtin::BI__builtin_fmodl:
346  case Builtin::BIlogl:
347  case Builtin::BI__builtin_logl:
348  case Builtin::BIlog10l:
349  case Builtin::BI__builtin_log10l:
350  case Builtin::BIlog2l:
351  case Builtin::BI__builtin_log2l:
352  case Builtin::BIpowl:
353  case Builtin::BI__builtin_powl:
354  case Builtin::BIrintl:
355  case Builtin::BI__builtin_rintl:
356  case Builtin::BIroundl:
357  case Builtin::BI__builtin_roundl:
358  case Builtin::BIsinl:
359  case Builtin::BI__builtin_sinl:
360  case Builtin::BIsqrtl:
361  case Builtin::BI__builtin_sqrtl:
362  case Builtin::BItruncl:
363  case Builtin::BI__builtin_truncl:
364  case Builtin::BIlroundl:
365  case Builtin::BI__builtin_lroundl:
366  case Builtin::BIlroundf:
367  case Builtin::BI__builtin_lroundf:
368  return false;
369  default:
370  break;
371  }
372  return true;
373 }
374 
376  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
377  const IdentifierInfo *II = FD->getIdentifier();
378 
379  // Allow __builtin_assume_aligned and __builtin_printf to be called from
380  // within device code.
381  if (FD->getBuiltinID() &&
382  (FD->getBuiltinID() == Builtin::BI__builtin_assume_aligned ||
383  FD->getBuiltinID() == Builtin::BI__builtin_printf))
384  return true;
385 
386  const DeclContext *DC = FD->getDeclContext();
387  if (II && II->isStr("__spirv_ocl_printf") &&
388  !FD->isDefined() &&
389  FD->getLanguageLinkage() == CXXLanguageLinkage &&
391  return true;
392  }
393  return false;
394 }
395 
397  : SemaBase(S), SyclIntHeader(nullptr), SyclIntFooter(nullptr) {}
398 
399 static bool isZeroSizedArray(SemaSYCL &S, QualType Ty) {
400  if (const auto *CAT = S.getASTContext().getAsConstantArrayType(Ty))
401  return CAT->isZeroSize();
402  return false;
403 }
404 
407  SourceRange UsedAtLoc = SourceRange()) {
408  // Not all variable types are supported inside SYCL kernels,
409  // for example the quad type __float128 will cause errors in the
410  // SPIR-V translation phase.
411  // Here we check any potentially unsupported declaration and issue
412  // a deferred diagnostic, which will be emitted iff the declaration
413  // is discovered to reside in kernel code.
414  // The optional UsedAtLoc param is used when the SYCL usage is at a
415  // different location than the variable declaration and we need to
416  // inform the user of both, e.g. struct member usage vs declaration.
417 
418  bool Emitting = false;
419 
420  //--- check types ---
421 
422  // zero length arrays
423  if (isZeroSizedArray(S, Ty)) {
424  S.DiagIfDeviceCode(Loc.getBegin(), diag::err_typecheck_zero_array_size)
425  << 1;
426  Emitting = true;
427  }
428 
429  // variable length arrays
430  if (Ty->isVariableArrayType()) {
431  S.DiagIfDeviceCode(Loc.getBegin(), diag::err_vla_unsupported) << 0;
432  Emitting = true;
433  }
434 
435  // Sub-reference array or pointer, then proceed with that type.
436  while (Ty->isAnyPointerType() || Ty->isArrayType())
437  Ty = QualType{Ty->getPointeeOrArrayElementType(), 0};
438 
439  // __int128, __int128_t, __uint128_t, long double, __float128
440  if (Ty->isSpecificBuiltinType(BuiltinType::Int128) ||
441  Ty->isSpecificBuiltinType(BuiltinType::UInt128) ||
442  Ty->isSpecificBuiltinType(BuiltinType::LongDouble) ||
443  Ty->isSpecificBuiltinType(BuiltinType::BFloat16) ||
444  (Ty->isSpecificBuiltinType(BuiltinType::Float128) &&
446  S.DiagIfDeviceCode(Loc.getBegin(), diag::err_type_unsupported)
448  Emitting = true;
449  }
450 
451  if (Emitting && UsedAtLoc.isValid())
452  S.DiagIfDeviceCode(UsedAtLoc.getBegin(), diag::note_used_here);
453 
454  //--- now recurse ---
455  // Pointers complicate recursion. Add this type to Visited.
456  // If already there, bail out.
457  if (!Visited.insert(Ty).second)
458  return;
459 
460  if (const auto *ATy = dyn_cast<AttributedType>(Ty))
461  return checkSYCLType(S, ATy->getModifiedType(), Loc, Visited);
462 
463  if (const auto *RD = Ty->getAsRecordDecl()) {
464  for (const auto &Field : RD->fields())
465  checkSYCLType(S, Field->getType(), Field->getSourceRange(), Visited, Loc);
466  } else if (const auto *FPTy = dyn_cast<FunctionProtoType>(Ty)) {
467  for (const auto &ParamTy : FPTy->param_types())
468  checkSYCLType(S, ParamTy, Loc, Visited);
469  checkSYCLType(S, FPTy->getReturnType(), Loc, Visited);
470  }
471 }
472 
474  assert(getLangOpts().SYCLIsDevice &&
475  "Should only be called during SYCL compilation");
476  QualType Ty = Var->getType();
477  SourceRange Loc = Var->getLocation();
479 
480  checkSYCLType(*this, Ty, Loc, Visited);
481 }
482 
483 // Tests whether given function is a lambda function or '()' operator used as
484 // SYCL kernel body function (e.g. in parallel_for).
485 // NOTE: This is incomplete implemenation. See TODO in the FE TODO list for the
486 // ESIMD extension.
488  return FD->getOverloadedOperator() == OO_Call;
489 }
490 
491 static bool isSYCLUndefinedAllowed(const FunctionDecl *Callee,
492  const SourceManager &SrcMgr) {
493  if (!Callee)
494  return false;
495 
496  // The check below requires declaration name, make sure we have it.
497  if (!Callee->getIdentifier())
498  return false;
499 
500  // libstdc++-11 introduced an undefined function "void __failed_assertion()"
501  // which may lead to SemaSYCL check failure. However, this undefined function
502  // is used to trigger some compilation error when the check fails at compile
503  // time and will be ignored when the check succeeds. We allow calls to this
504  // function to support some important std functions in SYCL device.
505  return (Callee->getName() == LibstdcxxFailedAssertion) &&
506  Callee->getNumParams() == 0 && Callee->getReturnType()->isVoidType() &&
507  SrcMgr.isInSystemHeader(Callee->getLocation());
508 }
509 
510 // Helper function to report conflicting function attributes.
511 // F - the function, A1 - function attribute, A2 - the attribute it conflicts
512 // with.
513 static void reportConflictingAttrs(SemaSYCL &S, FunctionDecl *F, const Attr *A1,
514  const Attr *A2) {
515  S.Diag(F->getLocation(), diag::err_conflicting_sycl_kernel_attributes);
516  S.Diag(A1->getLocation(), diag::note_conflicting_attribute);
517  S.Diag(A2->getLocation(), diag::note_conflicting_attribute);
518  F->setInvalidDecl();
519 }
520 
521 /// Returns the signed constant integer value represented by given expression
522 static int64_t getIntExprValue(const Expr *E, ASTContext &Ctx) {
523  return E->getIntegerConstantExpr(Ctx)->getSExtValue();
524 }
525 
526 // Collect function attributes related to SYCL.
529  bool DirectlyCalled) {
530  if (!FD->hasAttrs())
531  return;
532 
533  // In SYCL 1.2.1 mode, the attributes are propagated from the function they
534  // are applied to onto the kernel which calls the function.
535  // In SYCL 2020 mode, the attributes are not propagated to the kernel.
536  if (DirectlyCalled || S.getASTContext().getLangOpts().getSYCLVersion() <
538  llvm::copy_if(FD->getAttrs(), std::back_inserter(Attrs), [](Attr *A) {
539  // FIXME: Make this list self-adapt as new SYCL attributes are added.
540  return isa<IntelReqdSubGroupSizeAttr, IntelNamedSubGroupSizeAttr,
541  SYCLReqdWorkGroupSizeAttr, SYCLWorkGroupSizeHintAttr,
542  SYCLIntelKernelArgsRestrictAttr, SYCLIntelNumSimdWorkItemsAttr,
543  SYCLIntelSchedulerTargetFmaxMhzAttr,
544  SYCLIntelMaxWorkGroupSizeAttr, SYCLIntelMaxGlobalWorkDimAttr,
545  SYCLIntelMinWorkGroupsPerComputeUnitAttr,
546  SYCLIntelMaxWorkGroupsPerMultiprocessorAttr,
547  SYCLIntelNoGlobalWorkOffsetAttr, SYCLSimdAttr>(A);
548  });
549  }
550 
551  // Attributes that should not be propagated from device functions to a kernel.
552  if (DirectlyCalled) {
553  llvm::copy_if(FD->getAttrs(), std::back_inserter(Attrs), [](Attr *A) {
554  return isa<SYCLIntelLoopFuseAttr, SYCLIntelMaxConcurrencyAttr,
555  SYCLIntelDisableLoopPipeliningAttr,
556  SYCLIntelInitiationIntervalAttr,
557  SYCLIntelUseStallEnableClustersAttr, SYCLDeviceHasAttr,
558  SYCLAddIRAttributesFunctionAttr>(A);
559  });
560  }
561 }
562 
563 class DiagDeviceFunction : public RecursiveASTVisitor<DiagDeviceFunction> {
564  SemaSYCL &SemaSYCLRef;
565  const llvm::SmallPtrSetImpl<const FunctionDecl *> &RecursiveFuncs;
566 
567 public:
569  SemaSYCL &S,
570  const llvm::SmallPtrSetImpl<const FunctionDecl *> &RecursiveFuncs)
571  : RecursiveASTVisitor(), SemaSYCLRef(S), RecursiveFuncs(RecursiveFuncs) {}
572 
573  void CheckBody(Stmt *ToBeDiagnosed) { TraverseStmt(ToBeDiagnosed); }
574 
576  if (FunctionDecl *Callee = e->getDirectCallee()) {
577  Callee = Callee->getCanonicalDecl();
578  assert(Callee && "Device function canonical decl must be available");
579 
580  // Remember that all SYCL kernel functions have deferred
581  // instantiation as template functions. It means that
582  // all functions used by kernel have already been parsed and have
583  // definitions.
584  if (RecursiveFuncs.count(Callee)) {
585  SemaSYCLRef.Diag(e->getExprLoc(), diag::err_sycl_restrict)
587  SemaSYCLRef.Diag(Callee->getSourceRange().getBegin(),
588  diag::note_sycl_recursive_function_declared_here)
590  }
591 
592  if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Callee))
593  if (Method->isVirtual() &&
594  !SemaSYCLRef.getLangOpts().SYCLAllowVirtualFunctions)
595  SemaSYCLRef.Diag(e->getExprLoc(), diag::err_sycl_restrict)
597 
598  if (auto const *FD = dyn_cast<FunctionDecl>(Callee)) {
599  // FIXME: We need check all target specified attributes for error if
600  // that function with attribute can not be called from sycl kernel. The
601  // info is in ParsedAttr. We don't have to map from Attr to ParsedAttr
602  // currently. Erich is currently working on that in LLVM, once that is
603  // committed we need to change this".
604  if (FD->hasAttr<DLLImportAttr>()) {
605  SemaSYCLRef.Diag(e->getExprLoc(), diag::err_sycl_restrict)
607  SemaSYCLRef.Diag(FD->getLocation(), diag::note_callee_decl) << FD;
608  }
609  }
610  // Specifically check if the math library function corresponding to this
611  // builtin is supported for SYCL
612  unsigned BuiltinID = Callee->getBuiltinID();
613  if (BuiltinID && !IsSyclMathFunc(BuiltinID)) {
614  StringRef Name =
615  SemaSYCLRef.getASTContext().BuiltinInfo.getName(BuiltinID);
616  SemaSYCLRef.Diag(e->getExprLoc(), diag::err_builtin_target_unsupported)
617  << Name << "SYCL device";
618  }
619  } else if (!SemaSYCLRef.getLangOpts().SYCLAllowFuncPtr &&
620  !e->isTypeDependent() &&
621  !isa<CXXPseudoDestructorExpr>(e->getCallee())) {
622  bool MaybeConstantExpr = false;
623  Expr *NonDirectCallee = e->getCallee();
624  if (!NonDirectCallee->isValueDependent())
625  MaybeConstantExpr =
626  NonDirectCallee->isCXX11ConstantExpr(SemaSYCLRef.getASTContext());
627  if (!MaybeConstantExpr)
628  SemaSYCLRef.Diag(e->getExprLoc(), diag::err_sycl_restrict)
630  }
631  return true;
632  }
633 
635  SemaSYCLRef.Diag(E->getExprLoc(), diag::err_sycl_restrict)
637  return true;
638  }
639 
641  SemaSYCLRef.Diag(E->getExprLoc(), diag::err_sycl_restrict)
643  return true;
644  }
645 
646  // Skip checking rules on variables initialized during constant evaluation.
648  if (VD->isConstexpr())
649  return true;
650  return RecursiveASTVisitor::TraverseVarDecl(VD);
651  }
652 
653  // Skip checking rules on template arguments, since these are constant
654  // expressions.
656  return true;
657  }
658 
659  // Skip checking the static assert, both components are required to be
660  // constant expressions.
661  bool TraverseStaticAssertDecl(StaticAssertDecl *D) { return true; }
662 
663  // Make sure we skip the condition of the case, since that is a constant
664  // expression.
666  return TraverseStmt(S->getSubStmt());
667  }
668 
669  // Skip checking the size expr, since a constant array type loc's size expr is
670  // a constant expression.
672  return true;
673  }
674 
676  if (std::optional<Stmt *> ActiveStmt =
677  S->getNondiscardedCase(SemaSYCLRef.getASTContext())) {
678  if (*ActiveStmt)
679  return TraverseStmt(*ActiveStmt);
680  return true;
681  }
682  return RecursiveASTVisitor::TraverseIfStmt(S);
683  }
684 };
685 
686 // This type manages the list of device functions and recursive functions, as
687 // well as an entry point for attribute collection, for the translation unit
688 // during MarkDevices. On construction, this type makes sure that all of the
689 // root-device functions, (that is, those marked with SYCL_EXTERNAL) are
690 // collected. On destruction, it manages and runs the diagnostics required.
691 // When processing individual kernel/external functions, the
692 // SingleDeviceFunctionTracker type updates this type.
695  CallGraph CG;
696  SemaSYCL &SemaSYCLRef;
697  // The list of functions used on the device, kept so we can diagnose on them
698  // later.
701 
702  void CollectSyclExternalFuncs() {
704  if (auto *FD = dyn_cast<FunctionDecl>(Record.Callee->getDecl()))
705  if (FD->hasBody() && FD->hasAttr<SYCLDeviceAttr>())
706  SemaSYCLRef.addSyclDeviceDecl(FD);
707  }
708 
709  CallGraphNode *getNodeForKernel(FunctionDecl *Kernel) {
710  assert(CG.getNode(Kernel) && "No call graph entry for a kernel?");
711  return CG.getNode(Kernel);
712  }
713 
714  void AddSingleFunction(
715  const llvm::SmallPtrSetImpl<FunctionDecl *> &DevFuncs,
716  const llvm::SmallPtrSetImpl<const FunctionDecl *> &Recursive) {
717  DeviceFunctions.insert(DevFuncs.begin(), DevFuncs.end());
718  RecursiveFunctions.insert(Recursive.begin(), Recursive.end());
719  }
720 
721 public:
722  DeviceFunctionTracker(SemaSYCL &S) : SemaSYCLRef(S) {
725  CollectSyclExternalFuncs();
726  }
727 
729  DiagDeviceFunction Diagnoser{SemaSYCLRef, RecursiveFunctions};
730  for (const FunctionDecl *FD : DeviceFunctions)
731  if (const FunctionDecl *Def = FD->getDefinition())
732  Diagnoser.CheckBody(Def->getBody());
733  }
734 };
735 
736 /// This function checks whether given DeclContext contains a topmost
737 /// namespace with name "sycl".
738 static bool isDeclaredInSYCLNamespace(const Decl *D) {
740  const auto *ND = dyn_cast<NamespaceDecl>(DC);
741  // If this is not a namespace, then we are done.
742  if (!ND)
743  return false;
744 
745  // While it is a namespace, find its parent scope.
746  while (const DeclContext *Parent = ND->getParent()) {
747  if (!isa<NamespaceDecl>(Parent))
748  break;
749  ND = cast<NamespaceDecl>(Parent);
750  }
751 
752  return ND && ND->getName() == "sycl";
753 }
754 
755 // This type does the heavy lifting for the management of device functions,
756 // recursive function detection, and attribute collection for a single
757 // kernel/external function. It walks the callgraph to find all functions that
758 // are called, marks the recursive-functions, and figures out the list of
759 // attributes that apply to this kernel.
760 //
761 // Upon destruction, this type updates the DeviceFunctionTracker.
764  FunctionDecl *SYCLKernel = nullptr;
765  FunctionDecl *KernelBody = nullptr;
768  llvm::SmallVector<Attr *> CollectedAttributes;
769 
770  FunctionDecl *GetFDFromNode(CallGraphNode *Node) {
771  FunctionDecl *FD = Node->getDecl()->getAsFunction();
772  if (!FD)
773  return nullptr;
774 
775  return FD->getMostRecentDecl();
776  }
777 
778  void VisitCallNode(CallGraphNode *Node, FunctionDecl *CurrentDecl,
780  // If this isn't a function, I don't think there is anything we can do here.
781  if (!CurrentDecl)
782  return;
783 
784  // Determine if this is a recursive function. If so, we're done.
785  if (llvm::is_contained(CallStack, CurrentDecl)) {
786  RecursiveFunctions.insert(CurrentDecl->getCanonicalDecl());
787  return;
788  }
789 
790  // If this is a routine that is not defined and it does not have either
791  // a SYCLKernel or SYCLDevice attribute on it, add it to the set of
792  // routines potentially reachable on device. This is to diagnose such
793  // cases later in finalizeSYCLDelayedAnalysis().
794  if (!CurrentDecl->isDefined() && !CurrentDecl->hasAttr<SYCLKernelAttr>() &&
795  !CurrentDecl->hasAttr<SYCLDeviceAttr>())
796  Parent.SemaSYCLRef.addFDToReachableFromSyclDevice(CurrentDecl,
797  CallStack.back());
798 
799  // If this is a parallel_for_work_item that is declared in the
800  // sycl namespace, mark it with the WorkItem scope attribute.
801  // Note: Here, we assume that this is called from within a
802  // parallel_for_work_group; it is undefined to call it otherwise.
803  // We deliberately do not diagnose a violation.
804  if (CurrentDecl->getIdentifier() &&
805  CurrentDecl->getIdentifier()->getName() == "parallel_for_work_item" &&
806  isDeclaredInSYCLNamespace(CurrentDecl) &&
807  !CurrentDecl->hasAttr<SYCLScopeAttr>()) {
808  CurrentDecl->addAttr(SYCLScopeAttr::CreateImplicit(
809  Parent.SemaSYCLRef.getASTContext(), SYCLScopeAttr::Level::WorkItem));
810  }
811 
812  // We previously thought we could skip this function if we'd seen it before,
813  // but if we haven't seen it before in this call graph, we can end up
814  // missing a recursive call. SO, we have to revisit call-graphs we've
815  // already seen, just in case it ALSO has recursion. For example:
816  // void recurse1();
817  // void recurse2() { recurse1(); }
818  // void recurse1() { recurse2(); }
819  // void CallerInKernel() { recurse1(); recurse2(); }
820  // When checking 'recurse1', we'd have ended up 'visiting' recurse2 without
821  // realizing it was recursive, since we never went into the
822  // child-of-its-child, since THAT was recursive and exited early out of
823  // necessity.
824  // Then when we go to visit the kernel's call to recurse2, we would
825  // immediately escape not noticing it was recursive. SO, we have to do a
826  // little extra work in this case, and make sure we visit the entire call
827  // graph.
828  DeviceFunctions.insert(CurrentDecl);
829 
830  // Collect attributes for functions that aren't the root kernel.
831  if (!CallStack.empty()) {
832  bool DirectlyCalled = CallStack.size() == 1;
833  collectSYCLAttributes(Parent.SemaSYCLRef, CurrentDecl,
834  CollectedAttributes, DirectlyCalled);
835  }
836 
837  // Calculate the kernel body. Note the 'isSYCLKernelBodyFunction' only
838  // tests that it is operator(), so hopefully this doesn't get us too many
839  // false-positives.
840  if (isSYCLKernelBodyFunction(CurrentDecl)) {
841  // This is a direct callee of the kernel.
842  if (CallStack.size() == 1 &&
843  CallStack.back()->hasAttr<SYCLKernelAttr>()) {
844  assert(!KernelBody && "inconsistent call graph - only one kernel body "
845  "function can be called");
846  KernelBody = CurrentDecl;
847  } else if (CallStack.size() == 2 && KernelBody == CallStack.back()) {
848  // To implement rounding-up of a parallel-for range the
849  // SYCL header implementation modifies the kernel call like this:
850  // auto Wrapper = [=](TransformedArgType Arg) {
851  // if (Arg[0] >= NumWorkItems[0])
852  // return;
853  // Arg.set_allowed_range(NumWorkItems);
854  // KernelFunc(Arg);
855  // };
856  //
857  // This transformation leads to a condition where a kernel body
858  // function becomes callable from a new kernel body function.
859  // Hence this test.
860  // FIXME: We need to be more selective here, this can be hit by simply
861  // having a kernel lambda with a lambda call inside of it.
862  KernelBody = CurrentDecl;
863  }
864  }
865 
866  // Recurse.
867  CallStack.push_back(CurrentDecl);
869  for (CallGraphNode *CI : Node->callees()) {
870  FunctionDecl *CurFD = GetFDFromNode(CI);
871 
872  // Make sure we only visit each callee 1x from this function to avoid very
873  // time consuming template recursion cases.
874  if (!llvm::is_contained(SeenCallees, CurFD)) {
875  VisitCallNode(CI, CurFD, CallStack);
876  SeenCallees.insert(CurFD);
877  }
878  }
879  CallStack.pop_back();
880  }
881 
882  // Function to walk the call graph and identify the important information.
883  void Init() {
884  CallGraphNode *KernelNode = Parent.getNodeForKernel(SYCLKernel);
886  VisitCallNode(KernelNode, GetFDFromNode(KernelNode), CallStack);
887 
888  // Always inline the KernelBody in the kernel entry point. For ESIMD
889  // inlining is handled later down the pipeline.
890  if (KernelBody &&
891  Parent.SemaSYCLRef.getLangOpts().SYCLForceInlineKernelLambda &&
892  !KernelBody->hasAttr<NoInlineAttr>() &&
893  !KernelBody->hasAttr<AlwaysInlineAttr>() &&
894  !KernelBody->hasAttr<SYCLSimdAttr>()) {
895  KernelBody->addAttr(AlwaysInlineAttr::CreateImplicit(
896  KernelBody->getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
897  }
898  }
899 
900 public:
902  : Parent(P), SYCLKernel(Kernel->getAsFunction()) {
903  Init();
904  }
905 
906  FunctionDecl *GetSYCLKernel() { return SYCLKernel; }
907 
908  FunctionDecl *GetKernelBody() { return KernelBody; }
909 
911  return CollectedAttributes;
912  }
913 
914  llvm::SmallPtrSetImpl<FunctionDecl *> &GetDeviceFunctions() {
915  return DeviceFunctions;
916  }
917 
919  Parent.AddSingleFunction(DeviceFunctions, RecursiveFunctions);
920  }
921 };
922 
923 class KernelBodyTransform : public TreeTransform<KernelBodyTransform> {
924 public:
925  KernelBodyTransform(std::pair<DeclaratorDecl *, DeclaratorDecl *> &MPair,
926  Sema &S)
927  : TreeTransform<KernelBodyTransform>(S), MappingPair(MPair), SemaRef(S) {}
928  bool AlwaysRebuild() { return true; }
929 
931  auto Ref = dyn_cast<DeclaratorDecl>(DRE->getDecl());
932  if (Ref && Ref == MappingPair.first) {
933  auto NewDecl = MappingPair.second;
934  return DeclRefExpr::Create(
935  SemaRef.getASTContext(), DRE->getQualifierLoc(),
936  DRE->getTemplateKeywordLoc(), NewDecl, false, DRE->getNameInfo(),
937  NewDecl->getType(), DRE->getValueKind());
938  }
939  return DRE;
940  }
941 
942 private:
943  std::pair<DeclaratorDecl *, DeclaratorDecl *> MappingPair;
944  Sema &SemaRef;
945 };
946 
947 /// Creates a kernel parameter descriptor
948 /// \param Src field declaration to construct name from
949 /// \param Ty the desired parameter type
950 /// \return the constructed descriptor
951 static ParamDesc makeParamDesc(const FieldDecl *Src, QualType Ty) {
952  ASTContext &Ctx = Src->getASTContext();
953  std::string Name = (Twine("_arg_") + Src->getName()).str();
954  return std::make_tuple(Ty, &Ctx.Idents.get(Name),
955  Ctx.getTrivialTypeSourceInfo(Ty));
956 }
957 static ParamDesc makeParamDesc(const ParmVarDecl *Src, QualType Ty) {
958  ASTContext &Ctx = Src->getASTContext();
959  std::string Name = (Twine("__arg_") + Src->getName()).str();
960  return std::make_tuple(Ty, &Ctx.Idents.get(Name),
961  Ctx.getTrivialTypeSourceInfo(Ty));
962 }
963 
964 static ParamDesc makeParamDesc(ASTContext &Ctx, StringRef Name, QualType Ty) {
965  return std::make_tuple(Ty, &Ctx.Idents.get(Name),
966  Ctx.getTrivialTypeSourceInfo(Ty));
967 }
968 
970  llvm::report_fatal_error("Only scalars and pointers are permitted as "
971  "free function parameters");
972 }
973 
974 class MarkWIScopeFnVisitor : public RecursiveASTVisitor<MarkWIScopeFnVisitor> {
975 public:
976  MarkWIScopeFnVisitor(ASTContext &Ctx) : Ctx(Ctx) {}
977 
979  FunctionDecl *Callee = Call->getDirectCallee();
980  if (!Callee)
981  // not a direct call - continue search
982  return true;
983  QualType Ty = Ctx.getRecordType(Call->getRecordDecl());
984  if (!SemaSYCL::isSyclType(Ty, SYCLTypeAttr::group))
985  // not a member of sycl::group - continue search
986  return true;
987  auto Name = Callee->getName();
988  if (Name != "wait_for" ||
989  Callee->hasAttr<SYCLScopeAttr>())
990  return true;
991  // it is a call to sycl::group::wait_for - mark the callee
992  Callee->addAttr(
993  SYCLScopeAttr::CreateImplicit(Ctx, SYCLScopeAttr::Level::WorkItem));
994  // continue search as there can be other wait_for calls
995  return true;
996  }
997 
998 private:
999  ASTContext &Ctx;
1000 };
1001 
1003  return SemaSYCL::isSyclType(VD->getType(), SYCLTypeAttr::private_memory);
1004 }
1005 
1007  for (Decl *D : F.decls()) {
1008  VarDecl *VD = dyn_cast<VarDecl>(D);
1009 
1010  if (!VD || isa<ParmVarDecl>(VD) ||
1012  continue;
1013  // Local variables of private_memory type in the WG scope still have WI
1014  // scope, all the rest - WG scope. Simple logic
1015  // "if no scope than it is WG scope" won't work, because compiler may add
1016  // locals not declared in user code (lambda object parameter, byval
1017  // arguments) which will result in alloca w/o any attribute, so need WI
1018  // scope too.
1020  ? SYCLScopeAttr::Level::WorkItem
1021  : SYCLScopeAttr::Level::WorkGroup;
1022  VD->addAttr(SYCLScopeAttr::CreateImplicit(F.getASTContext(), L));
1023  }
1024 }
1025 
1026 /// Return method by name
1028  StringRef MethodName) {
1029  CXXMethodDecl *Method;
1030  auto It = std::find_if(CRD->methods().begin(), CRD->methods().end(),
1031  [MethodName](const CXXMethodDecl *Method) {
1032  return Method->getNameAsString() == MethodName;
1033  });
1034  Method = (It != CRD->methods().end()) ? *It : nullptr;
1035  return Method;
1036 }
1037 
1038 static KernelInvocationKind
1040  return llvm::StringSwitch<KernelInvocationKind>(KernelCallerFunc->getName())
1041  .Case("kernel_single_task", InvokeSingleTask)
1042  .Case("kernel_parallel_for", InvokeParallelFor)
1043  .Case("kernel_parallel_for_work_group", InvokeParallelForWorkGroup)
1044  .Default(InvokeUnknown);
1045 }
1046 
1047 // The SYCL kernel's 'object type' used for diagnostics and naming/mangling is
1048 // the first parameter to a function template using the sycl_kernel
1049 // attribute. In SYCL 1.2.1, this was passed by value,
1050 // and in SYCL 2020, it is passed by reference.
1051 static QualType GetSYCLKernelObjectType(const FunctionDecl *KernelCaller) {
1052  assert(KernelCaller->getNumParams() > 0 && "Insufficient kernel parameters");
1053  QualType KernelParamTy = KernelCaller->getParamDecl(0)->getType();
1054 
1055  // SYCL 2020 kernels are passed by reference.
1056  if (KernelParamTy->isReferenceType())
1057  KernelParamTy = KernelParamTy->getPointeeType();
1058 
1059  // SYCL 1.2.1
1060  return KernelParamTy.getUnqualifiedType();
1061 }
1062 
1063 /// \return the target of given SYCL accessor type
1065  const ClassTemplateSpecializationDecl *AccTy) {
1066  if (SemaSYCL::isSyclType(FieldTy, SYCLTypeAttr::local_accessor))
1067  return local;
1068 
1069  return static_cast<target>(
1070  AccTy->getTemplateArgs()[3].getAsIntegral().getExtValue());
1071 }
1072 
1073 // FIXME: Free functions must have void return type, be declared at file scope,
1074 // outside any namespaces, and with the SYCL_DEVICE attribute. If the
1075 // SYCL_DEVICE attribute is not specified this function is not entered since the
1076 // possibility of the function being a free function is ruled out already.
1077 static bool isFreeFunction(SemaSYCL &SemaSYCLRef, const FunctionDecl *FD) {
1078  for (auto *IRAttr : FD->specific_attrs<SYCLAddIRAttributesFunctionAttr>()) {
1080  IRAttr->getAttributeNameValuePairs(SemaSYCLRef.getASTContext());
1081  for (const auto &NameValuePair : NameValuePairs) {
1082  if (NameValuePair.first == "sycl-nd-range-kernel" ||
1083  NameValuePair.first == "sycl-single-task-kernel") {
1084  if (!FD->getReturnType()->isVoidType()) {
1085  llvm::report_fatal_error(
1086  "Only functions at file scope with void return "
1087  "type are permitted as free functions");
1088  return false;
1089  }
1090  return true;
1091  }
1092  }
1093  }
1094  return false;
1095 }
1096 
1097 // Creates a name for the free function kernel function.
1098 // Consider a free function named "MyFunction". The normal device function will
1099 // be given its mangled name, say "_Z10MyFunctionIiEvPT_S0_". The corresponding
1100 // kernel function for this free function will be named
1101 // "_Z24__sycl_kernel_MyFunctionIiEvPT_S0_". This is the mangled name of a
1102 // fictitious function that has the same template and function parameters as the
1103 // original free function but with identifier prefixed with __sycl_kernel_.
1104 // We generate this name by starting with the mangled name of the free function
1105 // and adjusting it textually to simulate the __sycl_kernel_ prefix.
1106 // Because free functions are allowed only at file scope and cannot be within
1107 // namespaces the mangled name has the format _Z<length><identifier>... where
1108 // length is the identifier's length. The text manipulation inserts the prefix
1109 // __sycl_kernel_ and adjusts the length, leaving the rest of the name as-is.
1110 static std::pair<std::string, std::string> constructFreeFunctionKernelName(
1111  SemaSYCL &SemaSYCLRef, const FunctionDecl *FreeFunc, MangleContext &MC) {
1112  SmallString<256> Result;
1113  llvm::raw_svector_ostream Out(Result);
1114  std::string StableName;
1115 
1116  MC.mangleName(FreeFunc, Out);
1117  std::string MangledName(Out.str());
1118  size_t StartNums = MangledName.find_first_of("0123456789");
1119  size_t EndNums = MangledName.find_first_not_of("0123456789", StartNums);
1120  size_t NameLength =
1121  std::stoi(MangledName.substr(StartNums, EndNums - StartNums));
1122  size_t NewNameLength = 14 /*length of __sycl_kernel_*/ + NameLength;
1123  std::string NewName = MangledName.substr(0, StartNums) +
1124  std::to_string(NewNameLength) + "__sycl_kernel_" +
1125  MangledName.substr(EndNums);
1126  StableName = NewName;
1127  return {NewName, StableName};
1128 }
1129 
1130 // The first template argument to the kernel caller function is used to identify
1131 // the kernel itself.
1133  const FunctionDecl *KernelCallerFunc) {
1134  const TemplateArgumentList *TAL =
1135  KernelCallerFunc->getTemplateSpecializationArgs();
1136  assert(TAL && "No template argument info");
1137  return TAL->get(0).getAsType().getCanonicalType();
1138 }
1139 
1140 // Gets a name for the OpenCL kernel function, calculated from the first
1141 // template argument of the kernel caller function.
1142 static std::pair<std::string, std::string>
1143 constructKernelName(SemaSYCL &S, const FunctionDecl *KernelCallerFunc,
1144  MangleContext &MC) {
1145  QualType KernelNameType =
1146  calculateKernelNameType(S.getASTContext(), KernelCallerFunc);
1147 
1148  SmallString<256> Result;
1149  llvm::raw_svector_ostream Out(Result);
1150 
1151  MC.mangleCanonicalTypeName(KernelNameType, Out);
1152  std::string MangledName(Out.str());
1153 
1154  std::string StableName =
1156 
1157  // For NativeCPU the kernel name is set to the stable GNU-mangled name
1158  // because the default mangling may be different, for example on Windows.
1159  // This is needed for compiling kernels for multiple SYCL targets to ensure
1160  // the same kernel name can be used for kernel lookup in different target
1161  // binaries. This assumes that all SYCL targets use the same mangling
1162  // produced for the stable name.
1163  // Todo: Check if this assumption is valid, and if it would be better
1164  // instead to always compile the NativeCPU device code in GNU mode which
1165  // may cause issues when compiling headers with non-standard extensions
1166  // written for compilers with different C++ ABIs (like MS VS).
1167  if (S.getLangOpts().SYCLIsNativeCPU) {
1168  MangledName = StableName;
1169  }
1170 
1171  return {MangledName, StableName};
1172 }
1173 
1174 static bool isDefaultSPIRArch(ASTContext &Context) {
1175  llvm::Triple T = Context.getTargetInfo().getTriple();
1176  if (T.isSPIR() && T.getSubArch() == llvm::Triple::NoSubArch)
1177  return true;
1178  return false;
1179 }
1180 
1182  // Specialization constants in SYCL 2020 are not captured by lambda and
1183  // accessed through new optional lambda argument kernel_handler
1184  auto IsHandlerLambda = [](ParmVarDecl *PVD) {
1185  return SemaSYCL::isSyclType(PVD->getType(), SYCLTypeAttr::kernel_handler);
1186  };
1187 
1188  assert(llvm::count_if(KernelCallerFunc->parameters(), IsHandlerLambda) <= 1 &&
1189  "Multiple kernel_handler parameters");
1190 
1191  auto KHArg = llvm::find_if(KernelCallerFunc->parameters(), IsHandlerLambda);
1192 
1193  return (KHArg != KernelCallerFunc->param_end()) ? *KHArg : nullptr;
1194 }
1195 
1196 static bool isReadOnlyAccessor(const TemplateArgument &AccessModeArg) {
1197  const auto *AccessModeArgEnumType =
1198  AccessModeArg.getIntegralType()->castAs<EnumType>();
1199  const EnumDecl *ED = AccessModeArgEnumType->getDecl();
1200 
1201  auto ReadOnly =
1202  llvm::find_if(ED->enumerators(), [&](const EnumConstantDecl *E) {
1203  return E->getName() == "read";
1204  });
1205 
1206  return ReadOnly != ED->enumerator_end() &&
1207  (*ReadOnly)->getInitVal() == AccessModeArg.getAsIntegral();
1208 }
1209 
1210 // anonymous namespace so these don't get linkage.
1211 namespace {
1212 
1213 template <typename T> struct bind_param { using type = T; };
1214 
1215 template <> struct bind_param<CXXBaseSpecifier &> {
1216  using type = const CXXBaseSpecifier &;
1217 };
1218 
1219 template <> struct bind_param<FieldDecl *&> { using type = FieldDecl *; };
1220 
1221 template <> struct bind_param<FieldDecl *const &> { using type = FieldDecl *; };
1222 
1223 template <typename T> using bind_param_t = typename bind_param<T>::type;
1224 
1225 class KernelObjVisitor {
1226  SemaSYCL &SemaSYCLRef;
1227 
1228  template <typename ParentTy, typename... HandlerTys>
1229  void VisitUnionImpl(const CXXRecordDecl *Owner, ParentTy &Parent,
1230  const CXXRecordDecl *Wrapper, HandlerTys &... Handlers) {
1231  (void)std::initializer_list<int>{
1232  (Handlers.enterUnion(Owner, Parent), 0)...};
1233  VisitRecordHelper(Wrapper, Wrapper->fields(), Handlers...);
1234  (void)std::initializer_list<int>{
1235  (Handlers.leaveUnion(Owner, Parent), 0)...};
1236  }
1237 
1238  // These enable handler execution only when previous Handlers succeed.
1239  template <typename... Tn>
1240  bool handleField(FieldDecl *FD, QualType FDTy, Tn &&... tn) {
1241  bool result = true;
1242  (void)std::initializer_list<int>{(result = result && tn(FD, FDTy), 0)...};
1243  return result;
1244  }
1245  template <typename... Tn>
1246  bool handleField(const CXXBaseSpecifier &BD, QualType BDTy, Tn &&... tn) {
1247  bool result = true;
1248  std::initializer_list<int>{(result = result && tn(BD, BDTy), 0)...};
1249  return result;
1250  }
1251 
1252 // This definition using std::bind is necessary because of a gcc 7.x bug.
1253 #define KF_FOR_EACH(FUNC, Item, Qt) \
1254  handleField( \
1255  Item, Qt, \
1256  std::bind(static_cast<bool (std::decay_t<decltype(Handlers)>::*)( \
1257  bind_param_t<decltype(Item)>, QualType)>( \
1258  &std::decay_t<decltype(Handlers)>::FUNC), \
1259  std::ref(Handlers), _1, _2)...)
1260 
1261  // The following simpler definition works with gcc 8.x and later.
1262  //#define KF_FOR_EACH(FUNC) \
1263 // handleField(Field, FieldTy, ([&](FieldDecl *FD, QualType FDTy) { \
1264 // return Handlers.f(FD, FDTy); \
1265 // })...)
1266 
1267  // This enables handler execution only when previous Handlers succeed.
1268  template <typename... Tn>
1269  bool handleParam(ParmVarDecl *PD, QualType PDTy, Tn &&...tn) {
1270  bool result = true;
1271  (void)std::initializer_list<int>{(result = result && tn(PD, PDTy), 0)...};
1272  return result;
1273  }
1274 
1275  // This definition using std::bind is necessary because of a gcc 7.x bug.
1276 #define KP_FOR_EACH(FUNC, Item, Qt) \
1277  handleParam( \
1278  Item, Qt, \
1279  std::bind(static_cast<bool (std::decay_t<decltype(Handlers)>::*)( \
1280  bind_param_t<decltype(Item)>, QualType)>( \
1281  &std::decay_t<decltype(Handlers)>::FUNC), \
1282  std::ref(Handlers), _1, _2)...)
1283 
1284  // Parent contains the FieldDecl or CXXBaseSpecifier that was used to enter
1285  // the Wrapper structure that we're currently visiting. Owner is the parent
1286  // type (which doesn't exist in cases where it is a FieldDecl in the
1287  // 'root'), and Wrapper is the current struct being unwrapped.
1288  template <typename ParentTy, typename... HandlerTys>
1289  void visitComplexRecord(const CXXRecordDecl *Owner, ParentTy &Parent,
1290  const CXXRecordDecl *Wrapper, QualType RecordTy,
1291  HandlerTys &... Handlers) {
1292  (void)std::initializer_list<int>{
1293  (Handlers.enterStruct(Owner, Parent, RecordTy), 0)...};
1294  VisitRecordHelper(Wrapper, Wrapper->bases(), Handlers...);
1295  VisitRecordHelper(Wrapper, Wrapper->fields(), Handlers...);
1296  (void)std::initializer_list<int>{
1297  (Handlers.leaveStruct(Owner, Parent, RecordTy), 0)...};
1298  }
1299 
1300  template <typename ParentTy, typename... HandlerTys>
1301  void visitSimpleRecord(const CXXRecordDecl *Owner, ParentTy &Parent,
1302  const CXXRecordDecl *Wrapper, QualType RecordTy,
1303  HandlerTys &... Handlers) {
1304  (void)std::initializer_list<int>{
1305  (Handlers.handleNonDecompStruct(Owner, Parent, RecordTy), 0)...};
1306  }
1307 
1308  template <typename ParentTy, typename... HandlerTys>
1309  void visitRecord(const CXXRecordDecl *Owner, ParentTy &Parent,
1310  const CXXRecordDecl *Wrapper, QualType RecordTy,
1311  HandlerTys &... Handlers);
1312 
1313  template <typename ParentTy, typename... HandlerTys>
1314  void VisitUnion(const CXXRecordDecl *Owner, ParentTy &Parent,
1315  const CXXRecordDecl *Wrapper, HandlerTys &... Handlers);
1316 
1317  template <typename... HandlerTys>
1318  void VisitRecordHelper(const CXXRecordDecl *Owner,
1320  HandlerTys &... Handlers) {
1321  for (const auto &Base : Range) {
1322  QualType BaseTy = Base.getType();
1323  // Handle accessor class as base
1324  if (isSyclSpecialType(BaseTy, SemaSYCLRef))
1325  (void)std::initializer_list<int>{
1326  (Handlers.handleSyclSpecialType(Owner, Base, BaseTy), 0)...};
1327  else
1328  // For all other bases, visit the record
1329  visitRecord(Owner, Base, BaseTy->getAsCXXRecordDecl(), BaseTy,
1330  Handlers...);
1331  }
1332  }
1333 
1334  template <typename... HandlerTys>
1335  void VisitRecordHelper(const CXXRecordDecl *Owner,
1337  HandlerTys &... Handlers) {
1338  VisitRecordFields(Owner, Handlers...);
1339  }
1340 
1341  template <typename... HandlerTys>
1342  void visitArrayElementImpl(const CXXRecordDecl *Owner, FieldDecl *ArrayField,
1343  QualType ElementTy, uint64_t Index,
1344  HandlerTys &... Handlers) {
1345  (void)std::initializer_list<int>{
1346  (Handlers.nextElement(ElementTy, Index), 0)...};
1347  visitField(Owner, ArrayField, ElementTy, Handlers...);
1348  }
1349 
1350  template <typename... HandlerTys>
1351  void visitFirstArrayElement(const CXXRecordDecl *Owner, FieldDecl *ArrayField,
1352  QualType ElementTy, HandlerTys &... Handlers) {
1353  visitArrayElementImpl(Owner, ArrayField, ElementTy, 0, Handlers...);
1354  }
1355  template <typename... HandlerTys>
1356  void visitNthArrayElement(const CXXRecordDecl *Owner, FieldDecl *ArrayField,
1357  QualType ElementTy, uint64_t Index,
1358  HandlerTys &... Handlers);
1359 
1360  template <typename... HandlerTys>
1361  void visitSimpleArray(const CXXRecordDecl *Owner, FieldDecl *Field,
1362  QualType ArrayTy, HandlerTys &... Handlers) {
1363  (void)std::initializer_list<int>{
1364  (Handlers.handleSimpleArrayType(Field, ArrayTy), 0)...};
1365  }
1366 
1367  template <typename... HandlerTys>
1368  void visitComplexArray(const CXXRecordDecl *Owner, FieldDecl *Field,
1369  QualType ArrayTy, HandlerTys &... Handlers) {
1370  // Array workflow is:
1371  // handleArrayType
1372  // enterArray
1373  // nextElement
1374  // VisitField (same as before, note that The FieldDecl is the of array
1375  // itself, not the element)
1376  // ... repeat per element, opt-out for duplicates.
1377  // leaveArray
1378 
1379  if (!KF_FOR_EACH(handleArrayType, Field, ArrayTy))
1380  return;
1381 
1382  const ConstantArrayType *CAT =
1383  SemaSYCLRef.getASTContext().getAsConstantArrayType(ArrayTy);
1384  assert(CAT && "Should only be called on constant-size array.");
1385  QualType ET = CAT->getElementType();
1386  uint64_t ElemCount = CAT->getSize().getZExtValue();
1387 
1388  (void)std::initializer_list<int>{
1389  (Handlers.enterArray(Field, ArrayTy, ET), 0)...};
1390 
1391  visitFirstArrayElement(Owner, Field, ET, Handlers...);
1392  for (uint64_t Index = 1; Index < ElemCount; ++Index)
1393  visitNthArrayElement(Owner, Field, ET, Index, Handlers...);
1394 
1395  (void)std::initializer_list<int>{
1396  (Handlers.leaveArray(Field, ArrayTy, ET), 0)...};
1397  }
1398 
1399  template <typename... HandlerTys>
1400  void visitField(const CXXRecordDecl *Owner, FieldDecl *Field,
1401  QualType FieldTy, HandlerTys &... Handlers) {
1402  if (isSyclSpecialType(FieldTy, SemaSYCLRef))
1403  KF_FOR_EACH(handleSyclSpecialType, Field, FieldTy);
1404  else if (FieldTy->isStructureOrClassType()) {
1405  if (KF_FOR_EACH(handleStructType, Field, FieldTy)) {
1406  CXXRecordDecl *RD = FieldTy->getAsCXXRecordDecl();
1407  visitRecord(Owner, Field, RD, FieldTy, Handlers...);
1408  }
1409  } else if (FieldTy->isUnionType()) {
1410  if (KF_FOR_EACH(handleUnionType, Field, FieldTy)) {
1411  CXXRecordDecl *RD = FieldTy->getAsCXXRecordDecl();
1412  VisitUnion(Owner, Field, RD, Handlers...);
1413  }
1414  } else if (FieldTy->isReferenceType())
1415  KF_FOR_EACH(handleReferenceType, Field, FieldTy);
1416  else if (FieldTy->isPointerType())
1417  KF_FOR_EACH(handlePointerType, Field, FieldTy);
1418  else if (FieldTy->isArrayType())
1419  visitArray(Owner, Field, FieldTy, Handlers...);
1420  else if (FieldTy->isScalarType() || FieldTy->isVectorType())
1421  KF_FOR_EACH(handleScalarType, Field, FieldTy);
1422  else
1423  KF_FOR_EACH(handleOtherType, Field, FieldTy);
1424  }
1425 
1426  template <typename... HandlerTys>
1427  void visitParam(ParmVarDecl *Param, QualType ParamTy,
1428  HandlerTys &...Handlers) {
1429  if (isSyclSpecialType(ParamTy, SemaSYCLRef))
1430  KP_FOR_EACH(handleOtherType, Param, ParamTy);
1431  else if (ParamTy->isStructureOrClassType())
1432  KP_FOR_EACH(handleOtherType, Param, ParamTy);
1433  else if (ParamTy->isUnionType())
1434  KP_FOR_EACH(handleOtherType, Param, ParamTy);
1435  else if (ParamTy->isReferenceType())
1436  KP_FOR_EACH(handleOtherType, Param, ParamTy);
1437  else if (ParamTy->isPointerType())
1438  KP_FOR_EACH(handlePointerType, Param, ParamTy);
1439  else if (ParamTy->isArrayType())
1440  KP_FOR_EACH(handleOtherType, Param, ParamTy);
1441  else if (ParamTy->isScalarType())
1442  KP_FOR_EACH(handleScalarType, Param, ParamTy);
1443  else
1444  KP_FOR_EACH(handleOtherType, Param, ParamTy);
1445  }
1446 
1447 public:
1448  KernelObjVisitor(SemaSYCL &S) : SemaSYCLRef(S) {}
1449 
1450  template <typename... HandlerTys>
1451  void VisitRecordBases(const CXXRecordDecl *KernelFunctor,
1452  HandlerTys &... Handlers) {
1453  VisitRecordHelper(KernelFunctor, KernelFunctor->bases(), Handlers...);
1454  }
1455 
1456  // A visitor function that dispatches to functions as defined in
1457  // SyclKernelFieldHandler for the purposes of kernel generation.
1458  template <typename... HandlerTys>
1459  void VisitRecordFields(const CXXRecordDecl *Owner, HandlerTys &... Handlers) {
1460  for (const auto Field : Owner->fields())
1461  visitField(Owner, Field, Field->getType(), Handlers...);
1462  }
1463 
1464  template <typename... HandlerTys>
1465  void visitArray(const CXXRecordDecl *Owner, FieldDecl *Field,
1466  QualType ArrayTy, HandlerTys &...Handlers);
1467 
1468  // A visitor function that dispatches to functions as defined in
1469  // SyclKernelFieldHandler by iterating over a free function parameter list.
1470  template <typename... HandlerTys>
1471  void VisitFunctionParameters(FunctionDecl *FreeFunc,
1472  HandlerTys &...Handlers) {
1473  for (ParmVarDecl *Param : FreeFunc->parameters())
1474  visitParam(Param, Param->getType(), Handlers...);
1475  }
1476 
1477 #undef KF_FOR_EACH
1478 #undef KP_FOR_EACH
1479 };
1480 
1481 // A base type that the SYCL OpenCL Kernel construction task uses to implement
1482 // individual tasks.
1483 class SyclKernelFieldHandlerBase {
1484 public:
1485  static constexpr const bool VisitUnionBody = false;
1486  static constexpr const bool VisitNthArrayElement = true;
1487  // Opt-in based on whether we should visit inside simple containers (structs,
1488  // arrays). All of the 'check' types should likely be true, the int-header,
1489  // and kernel decl creation types should not.
1490  static constexpr const bool VisitInsideSimpleContainers = true;
1491  static constexpr const bool VisitInsideSimpleContainersWithPointer = false;
1492  // Mark these virtual so that we can use override in the implementer classes,
1493  // despite virtual dispatch never being used.
1494 
1495  // SYCL special class can be a base class or a field decl, so both must be
1496  // handled.
1497  virtual bool handleSyclSpecialType(const CXXRecordDecl *,
1498  const CXXBaseSpecifier &, QualType) {
1499  return true;
1500  }
1501  virtual bool handleSyclSpecialType(FieldDecl *, QualType) { return true; }
1502  virtual bool handleSyclSpecialType(ParmVarDecl *, QualType) { return true; }
1503 
1504  virtual bool handleStructType(FieldDecl *, QualType) { return true; }
1505  virtual bool handleStructType(ParmVarDecl *, QualType) { return true; }
1506  virtual bool handleUnionType(FieldDecl *, QualType) { return true; }
1507  virtual bool handleUnionType(ParmVarDecl *, QualType) { return true; }
1508  virtual bool handleReferenceType(FieldDecl *, QualType) { return true; }
1509  virtual bool handleReferenceType(ParmVarDecl *, QualType) { return true; }
1510  virtual bool handlePointerType(FieldDecl *, QualType) { return true; }
1511  virtual bool handlePointerType(ParmVarDecl *, QualType) { return true; }
1512  virtual bool handleArrayType(FieldDecl *, QualType) { return true; }
1513  virtual bool handleArrayType(ParmVarDecl *, QualType) { return true; }
1514  virtual bool handleScalarType(FieldDecl *, QualType) { return true; }
1515  virtual bool handleScalarType(ParmVarDecl *, QualType) { return true; }
1516  // Most handlers shouldn't be handling this, just the field checker.
1517  virtual bool handleOtherType(FieldDecl *, QualType) { return true; }
1518  virtual bool handleOtherType(ParmVarDecl *, QualType) { return true; }
1519 
1520  // Handle a simple struct that doesn't need to be decomposed, only called on
1521  // handlers with VisitInsideSimpleContainers as false. Replaces
1522  // handleStructType, enterStruct, leaveStruct, and visiting of sub-elements.
1523  virtual bool handleNonDecompStruct(const CXXRecordDecl *, FieldDecl *,
1524  QualType) {
1525  return true;
1526  }
1527 
1528  virtual bool handleNonDecompStruct(const CXXRecordDecl *, ParmVarDecl *,
1529  QualType) {
1530  return true;
1531  }
1532 
1533  virtual bool handleNonDecompStruct(const CXXRecordDecl *,
1534  const CXXBaseSpecifier &, QualType) {
1535  return true;
1536  }
1537 
1538  // Instead of handleArrayType, enterArray, leaveArray, and nextElement (plus
1539  // descending down the elements), this function gets called in the event of an
1540  // array containing simple elements (even in the case of an MD array).
1541  virtual bool handleSimpleArrayType(FieldDecl *, QualType) { return true; }
1542 
1543  // The following are only used for keeping track of where we are in the base
1544  // class/field graph. Int Headers use this to calculate offset, most others
1545  // don't have a need for these.
1546 
1547  virtual bool enterStruct(const CXXRecordDecl *, FieldDecl *, QualType) {
1548  return true;
1549  }
1550  virtual bool leaveStruct(const CXXRecordDecl *, FieldDecl *, QualType) {
1551  return true;
1552  }
1553  virtual bool enterStruct(const CXXRecordDecl *, ParmVarDecl *, QualType) {
1554  return true;
1555  }
1556  virtual bool leaveStruct(const CXXRecordDecl *, ParmVarDecl *, QualType) {
1557  return true;
1558  }
1559  virtual bool enterStruct(const CXXRecordDecl *, const CXXBaseSpecifier &,
1560  QualType) {
1561  return true;
1562  }
1563  virtual bool leaveStruct(const CXXRecordDecl *, const CXXBaseSpecifier &,
1564  QualType) {
1565  return true;
1566  }
1567  virtual bool enterUnion(const CXXRecordDecl *, FieldDecl *) { return true; }
1568  virtual bool leaveUnion(const CXXRecordDecl *, FieldDecl *) { return true; }
1569  virtual bool enterUnion(const CXXRecordDecl *, ParmVarDecl *) { return true; }
1570  virtual bool leaveUnion(const CXXRecordDecl *, ParmVarDecl *) { return true; }
1571 
1572  // The following are used for stepping through array elements.
1573  virtual bool enterArray(FieldDecl *, QualType ArrayTy, QualType ElementTy) {
1574  return true;
1575  }
1576  virtual bool leaveArray(FieldDecl *, QualType ArrayTy, QualType ElementTy) {
1577  return true;
1578  }
1579  virtual bool enterArray(ParmVarDecl *, QualType ArrayTy, QualType ElementTy) {
1580  return true;
1581  }
1582  virtual bool leaveArray(ParmVarDecl *, QualType ArrayTy, QualType ElementTy) {
1583  return true;
1584  }
1585 
1586  virtual bool nextElement(QualType, uint64_t) { return true; }
1587 
1588  virtual ~SyclKernelFieldHandlerBase() = default;
1589 };
1590 
1591 // A class to act as the direct base for all the SYCL OpenCL Kernel construction
1592 // tasks that contains a reference to Sema (and potentially any other
1593 // universally required data).
1594 class SyclKernelFieldHandler : public SyclKernelFieldHandlerBase {
1595 protected:
1596  SemaSYCL &SemaSYCLRef;
1597  SyclKernelFieldHandler(SemaSYCL &S) : SemaSYCLRef(S) {}
1598 
1599  // Returns 'true' if the thing we're visiting (Based on the FD/QualType pair)
1600  // is an element of an array. FD will always be the array field. When
1601  // traversing the array field, Ty will be the type of the array field or the
1602  // type of array element (or some decomposed type from array).
1603  bool isArrayElement(const FieldDecl *FD, QualType Ty) const {
1604  return !SemaSYCLRef.getASTContext().hasSameType(FD->getType(), Ty);
1605  }
1606 };
1607 
1608 // A class to represent the 'do nothing' case for filtering purposes.
1609 class SyclEmptyHandler final : public SyclKernelFieldHandlerBase {};
1610 SyclEmptyHandler GlobalEmptyHandler;
1611 
1612 template <bool Keep, typename H> struct HandlerFilter;
1613 template <typename H> struct HandlerFilter<true, H> {
1614  H &Handler;
1615  HandlerFilter(H &Handler) : Handler(Handler) {}
1616 };
1617 template <typename H> struct HandlerFilter<false, H> {
1618  SyclEmptyHandler &Handler = GlobalEmptyHandler;
1619  HandlerFilter(H &Handler) {}
1620 };
1621 
1622 template <bool B, bool... Rest> struct AnyTrue;
1623 
1624 template <bool B> struct AnyTrue<B> { static constexpr bool Value = B; };
1625 
1626 template <bool B, bool... Rest> struct AnyTrue {
1627  static constexpr bool Value = B || AnyTrue<Rest...>::Value;
1628 };
1629 
1630 template <bool B, bool... Rest> struct AllTrue;
1631 
1632 template <bool B> struct AllTrue<B> { static constexpr bool Value = B; };
1633 
1634 template <bool B, bool... Rest> struct AllTrue {
1635  static constexpr bool Value = B && AllTrue<Rest...>::Value;
1636 };
1637 
1638 template <typename ParentTy, typename... Handlers>
1639 void KernelObjVisitor::VisitUnion(const CXXRecordDecl *Owner, ParentTy &Parent,
1640  const CXXRecordDecl *Wrapper,
1641  Handlers &... handlers) {
1642  // Don't continue descending if none of the handlers 'care'. This could be 'if
1643  // constexpr' starting in C++17. Until then, we have to count on the
1644  // optimizer to realize "if (false)" is a dead branch.
1646  VisitUnionImpl(
1647  Owner, Parent, Wrapper,
1648  HandlerFilter<Handlers::VisitUnionBody, Handlers>(handlers).Handler...);
1649 }
1650 
1651 template <typename... Handlers>
1652 void KernelObjVisitor::visitNthArrayElement(const CXXRecordDecl *Owner,
1653  FieldDecl *ArrayField,
1654  QualType ElementTy, uint64_t Index,
1655  Handlers &... handlers) {
1656  // Don't continue descending if none of the handlers 'care'. This could be 'if
1657  // constexpr' starting in C++17. Until then, we have to count on the
1658  // optimizer to realize "if (false)" is a dead branch.
1660  visitArrayElementImpl(
1661  Owner, ArrayField, ElementTy, Index,
1662  HandlerFilter<Handlers::VisitNthArrayElement, Handlers>(handlers)
1663  .Handler...);
1664 }
1665 
1666 template <typename ParentTy, typename... HandlerTys>
1667 void KernelObjVisitor::visitRecord(const CXXRecordDecl *Owner, ParentTy &Parent,
1668  const CXXRecordDecl *Wrapper,
1669  QualType RecordTy,
1670  HandlerTys &... Handlers) {
1671  RecordDecl *RD = RecordTy->getAsRecordDecl();
1672  assert(RD && "should not be null.");
1673  if (RD->hasAttr<SYCLRequiresDecompositionAttr>()) {
1674  // If this container requires decomposition, we have to visit it as
1675  // 'complex', so all handlers are called in this case with the 'complex'
1676  // case.
1677  visitComplexRecord(Owner, Parent, Wrapper, RecordTy, Handlers...);
1678  } else if (AnyTrue<HandlerTys::VisitInsideSimpleContainersWithPointer...>::
1679  Value) {
1680  // We are currently in PointerHandler visitor.
1681  if (RD->hasAttr<SYCLGenerateNewTypeAttr>()) {
1682  // This is a record containing pointers.
1683  visitComplexRecord(Owner, Parent, Wrapper, RecordTy, Handlers...);
1684  } else {
1685  // This is a record without pointers.
1686  visitSimpleRecord(Owner, Parent, Wrapper, RecordTy, Handlers...);
1687  }
1688  } else {
1689  // "Simple" Containers are those that do NOT need to be decomposed,
1690  // "Complex" containers are those that DO. In the case where the container
1691  // does NOT need to be decomposed, we can call VisitSimpleRecord on the
1692  // handlers that have opted-out of VisitInsideSimpleContainers. The 'if'
1693  // makes sure we only do that if at least 1 has opted out.
1695  visitSimpleRecord(
1696  Owner, Parent, Wrapper, RecordTy,
1697  HandlerFilter<!HandlerTys::VisitInsideSimpleContainers, HandlerTys>(
1698  Handlers)
1699  .Handler...);
1700 
1701  // Even though this is a 'simple' container, some handlers (via
1702  // VisitInsideSimpleContainers = true) need to treat it as if it needs
1703  // decomposing, so we call VisitComplexRecord iif at least one has.
1705  visitComplexRecord(
1706  Owner, Parent, Wrapper, RecordTy,
1707  HandlerFilter<HandlerTys::VisitInsideSimpleContainers, HandlerTys>(
1708  Handlers)
1709  .Handler...);
1710  }
1711 }
1712 
1713 template <typename... HandlerTys>
1714 void KernelObjVisitor::visitArray(const CXXRecordDecl *Owner, FieldDecl *Field,
1715  QualType ArrayTy, HandlerTys &... Handlers) {
1716 
1717  if (Field->hasAttr<SYCLRequiresDecompositionAttr>()) {
1718  visitComplexArray(Owner, Field, ArrayTy, Handlers...);
1719  } else if (AnyTrue<HandlerTys::VisitInsideSimpleContainersWithPointer...>::
1720  Value) {
1721  // We are currently in PointerHandler visitor.
1722  if (Field->hasAttr<SYCLGenerateNewTypeAttr>()) {
1723  // This is an array of pointers, or an array of a type containing
1724  // pointers.
1725  visitComplexArray(Owner, Field, ArrayTy, Handlers...);
1726  } else {
1727  // This is an array which does not contain pointers.
1728  visitSimpleArray(Owner, Field, ArrayTy, Handlers...);
1729  }
1730  } else {
1732  visitSimpleArray(
1733  Owner, Field, ArrayTy,
1734  HandlerFilter<!HandlerTys::VisitInsideSimpleContainers, HandlerTys>(
1735  Handlers)
1736  .Handler...);
1737 
1739  visitComplexArray(
1740  Owner, Field, ArrayTy,
1741  HandlerFilter<HandlerTys::VisitInsideSimpleContainers, HandlerTys>(
1742  Handlers)
1743  .Handler...);
1744  }
1745 }
1746 
1747 // A type to check the validity of all of the argument types.
1748 class SyclKernelFieldChecker : public SyclKernelFieldHandler {
1749  bool IsInvalid = false;
1751  // Keeps track of whether we are currently handling fields inside a struct.
1752  // Fields of kernel functor or direct kernel captures will have a depth 0.
1753  int StructFieldDepth = 0;
1754  // Initialize with -1 so that fields of a base class of the kernel functor
1755  // has depth 0. Visitor method enterStruct increments this to 0 when the base
1756  // class is entered.
1757  int StructBaseDepth = -1;
1758 
1759  // Check whether the object should be disallowed from being copied to kernel.
1760  // Return true if not copyable, false if copyable.
1761  bool checkNotCopyableToKernel(const FieldDecl *FD, QualType FieldTy) {
1762  if (FieldTy->isArrayType()) {
1763  if (const auto *CAT =
1764  SemaSYCLRef.getASTContext().getAsConstantArrayType(FieldTy)) {
1765  QualType ET = CAT->getElementType();
1766  return checkNotCopyableToKernel(FD, ET);
1767  }
1768  return Diag.Report(FD->getLocation(),
1769  diag::err_sycl_non_constant_array_type)
1770  << FieldTy;
1771  }
1772 
1773  return false;
1774  }
1775 
1776  bool checkPropertyListType(TemplateArgument PropList, SourceLocation Loc) {
1777  if (PropList.getKind() != TemplateArgument::ArgKind::Type)
1778  return SemaSYCLRef.Diag(
1779  Loc, diag::err_sycl_invalid_accessor_property_template_param);
1780 
1781  QualType PropListTy = PropList.getAsType();
1782  if (!SemaSYCL::isSyclType(PropListTy, SYCLTypeAttr::accessor_property_list))
1783  return SemaSYCLRef.Diag(
1784  Loc, diag::err_sycl_invalid_accessor_property_template_param);
1785 
1786  const auto *AccPropListDecl =
1787  cast<ClassTemplateSpecializationDecl>(PropListTy->getAsRecordDecl());
1788  if (AccPropListDecl->getTemplateArgs().size() != 1)
1789  return SemaSYCLRef.Diag(Loc,
1790  diag::err_sycl_invalid_property_list_param_number)
1791  << "accessor_property_list";
1792 
1793  const auto TemplArg = AccPropListDecl->getTemplateArgs()[0];
1794  if (TemplArg.getKind() != TemplateArgument::ArgKind::Pack)
1795  return SemaSYCLRef.Diag(
1796  Loc,
1797  diag::err_sycl_invalid_accessor_property_list_template_param)
1798  << /*accessor_property_list*/ 0 << /*parameter pack*/ 0;
1799 
1800  for (TemplateArgument::pack_iterator Prop = TemplArg.pack_begin();
1801  Prop != TemplArg.pack_end(); ++Prop) {
1802  if (Prop->getKind() != TemplateArgument::ArgKind::Type)
1803  return SemaSYCLRef.Diag(
1804  Loc,
1805  diag::err_sycl_invalid_accessor_property_list_template_param)
1806  << /*accessor_property_list pack argument*/ 1 << /*type*/ 1;
1807  QualType PropTy = Prop->getAsType();
1808  if (isAccessorPropertyType(PropTy, SYCLTypeAttr::buffer_location) &&
1809  checkBufferLocationType(PropTy, Loc))
1810  return true;
1811  }
1812  return false;
1813  }
1814 
1815  bool checkBufferLocationType(QualType PropTy, SourceLocation Loc) {
1816  const auto *PropDecl =
1817  cast<ClassTemplateSpecializationDecl>(PropTy->getAsRecordDecl());
1818  if (PropDecl->getTemplateArgs().size() != 1)
1819  return SemaSYCLRef.Diag(Loc,
1820  diag::err_sycl_invalid_property_list_param_number)
1821  << "buffer_location";
1822 
1823  const auto BufferLoc = PropDecl->getTemplateArgs()[0];
1824  if (BufferLoc.getKind() != TemplateArgument::ArgKind::Integral)
1825  return SemaSYCLRef.Diag(
1826  Loc,
1827  diag::err_sycl_invalid_accessor_property_list_template_param)
1828  << /*buffer_location*/ 2 << /*non-negative integer*/ 2;
1829 
1830  int LocationID = static_cast<int>(BufferLoc.getAsIntegral().getExtValue());
1831  if (LocationID < 0)
1832  return SemaSYCLRef.Diag(
1833  Loc,
1834  diag::err_sycl_invalid_accessor_property_list_template_param)
1835  << /*buffer_location*/ 2 << /*non-negative integer*/ 2;
1836 
1837  return false;
1838  }
1839 
1840  bool checkSyclSpecialType(QualType Ty, SourceRange Loc) {
1841  assert(isSyclSpecialType(Ty, SemaSYCLRef) &&
1842  "Should only be called on sycl special class types.");
1843 
1844  // Annotated pointers and annotated arguments must be captured
1845  // directly by the SYCL kernel.
1846  if ((SemaSYCL::isSyclType(Ty, SYCLTypeAttr::annotated_ptr) ||
1847  SemaSYCL::isSyclType(Ty, SYCLTypeAttr::annotated_arg)) &&
1848  (StructFieldDepth > 0 || StructBaseDepth > 0))
1849  return SemaSYCLRef.Diag(Loc.getBegin(),
1850  diag::err_bad_kernel_param_data_members)
1851  << Ty << /*Struct*/ 1;
1852 
1853  const RecordDecl *RecD = Ty->getAsRecordDecl();
1854  if (const ClassTemplateSpecializationDecl *CTSD =
1855  dyn_cast<ClassTemplateSpecializationDecl>(RecD)) {
1856  const TemplateArgumentList &TAL = CTSD->getTemplateArgs();
1857  TemplateArgument TA = TAL.get(0);
1858 
1859  // Parameter packs are used by properties so they are always valid.
1860  if (TA.getKind() != TemplateArgument::Pack) {
1862  checkSYCLType(SemaSYCLRef, TA.getAsType(), Loc, Visited);
1863  }
1864 
1865  if (TAL.size() > 5)
1866  return checkPropertyListType(TAL.get(5), Loc.getBegin());
1867  }
1868  return false;
1869  }
1870 
1871 public:
1872  SyclKernelFieldChecker(SemaSYCL &S)
1873  : SyclKernelFieldHandler(S), Diag(S.getASTContext().getDiagnostics()) {}
1874  static constexpr const bool VisitNthArrayElement = false;
1875  bool isValid() { return !IsInvalid; }
1876 
1877  bool handleReferenceType(FieldDecl *FD, QualType FieldTy) final {
1878  Diag.Report(FD->getLocation(), diag::err_bad_kernel_param_type) << FieldTy;
1879  IsInvalid = true;
1880  return isValid();
1881  }
1882 
1883  bool handleReferenceType(ParmVarDecl *PD, QualType ParamTy) final {
1884  Diag.Report(PD->getLocation(), diag::err_bad_kernel_param_type) << ParamTy;
1885  IsInvalid = true;
1886  return isValid();
1887  }
1888 
1889  bool handleStructType(FieldDecl *FD, QualType FieldTy) final {
1890  CXXRecordDecl *RD = FieldTy->getAsCXXRecordDecl();
1891  assert(RD && "Not a RecordDecl inside the handler for struct type");
1892  if (RD->isLambda()) {
1893  for (const LambdaCapture &LC : RD->captures())
1894  if (LC.capturesThis() && LC.isImplicit()) {
1895  SemaSYCLRef.Diag(LC.getLocation(), diag::err_implicit_this_capture);
1896  IsInvalid = true;
1897  }
1898  }
1899  return isValid();
1900  }
1901 
1902  bool handleStructType(ParmVarDecl *PD, QualType ParamTy) final {
1903  Diag.Report(PD->getLocation(), diag::err_bad_kernel_param_type) << ParamTy;
1904  IsInvalid = true;
1905  return isValid();
1906  }
1907 
1908  bool handleSyclSpecialType(const CXXRecordDecl *, const CXXBaseSpecifier &BS,
1909  QualType FieldTy) final {
1910  IsInvalid |= checkSyclSpecialType(FieldTy, BS.getBeginLoc());
1911  return isValid();
1912  }
1913 
1914  bool handleSyclSpecialType(FieldDecl *FD, QualType FieldTy) final {
1915  IsInvalid |= checkSyclSpecialType(FieldTy, FD->getLocation());
1916  return isValid();
1917  }
1918 
1919  bool handleSyclSpecialType(ParmVarDecl *PD, QualType ParamTy) final {
1920  Diag.Report(PD->getLocation(), diag::err_bad_kernel_param_type) << ParamTy;
1921  IsInvalid = true;
1922  return isValid();
1923  }
1924 
1925  bool handleArrayType(FieldDecl *FD, QualType FieldTy) final {
1926  IsInvalid |= checkNotCopyableToKernel(FD, FieldTy);
1927  return isValid();
1928  }
1929 
1930  bool handleArrayType(ParmVarDecl *PD, QualType ParamTy) final {
1931  Diag.Report(PD->getLocation(), diag::err_bad_kernel_param_type) << ParamTy;
1932  IsInvalid = true;
1933  return isValid();
1934  }
1935 
1936  bool handlePointerType(FieldDecl *FD, QualType FieldTy) final {
1937  while (FieldTy->isAnyPointerType()) {
1938  FieldTy = QualType{FieldTy->getPointeeOrArrayElementType(), 0};
1939  if (FieldTy->isVariableArrayType()) {
1940  Diag.Report(FD->getLocation(), diag::err_vla_unsupported) << 0;
1941  IsInvalid = true;
1942  break;
1943  }
1944  }
1945  return isValid();
1946  }
1947 
1948  bool handlePointerType(ParmVarDecl *PD, QualType ParamTy) final {
1949  while (ParamTy->isAnyPointerType()) {
1950  ParamTy = QualType{ParamTy->getPointeeOrArrayElementType(), 0};
1951  if (ParamTy->isVariableArrayType()) {
1952  Diag.Report(PD->getLocation(), diag::err_vla_unsupported) << 0;
1953  IsInvalid = true;
1954  break;
1955  }
1956  }
1957  return isValid();
1958  }
1959 
1960  bool handleOtherType(FieldDecl *FD, QualType FieldTy) final {
1961  Diag.Report(FD->getLocation(), diag::err_bad_kernel_param_type) << FieldTy;
1962  IsInvalid = true;
1963  return isValid();
1964  }
1965 
1966  bool handleOtherType(ParmVarDecl *PD, QualType ParamTy) final {
1967  Diag.Report(PD->getLocation(), diag::err_bad_kernel_param_type) << ParamTy;
1968  IsInvalid = true;
1969  return isValid();
1970  }
1971 
1972  bool enterStruct(const CXXRecordDecl *, FieldDecl *, QualType) final {
1973  ++StructFieldDepth;
1974  return true;
1975  }
1976 
1977  bool leaveStruct(const CXXRecordDecl *, FieldDecl *, QualType) final {
1978  --StructFieldDepth;
1979  return true;
1980  }
1981 
1982  bool enterStruct(const CXXRecordDecl *, ParmVarDecl *, QualType) final {
1983  // TODO
1985  return true;
1986  }
1987 
1988  bool leaveStruct(const CXXRecordDecl *, ParmVarDecl *, QualType) final {
1989  // TODO
1991  return true;
1992  }
1993 
1994  bool enterStruct(const CXXRecordDecl *, const CXXBaseSpecifier &BS,
1995  QualType FieldTy) final {
1996  ++StructBaseDepth;
1997  return true;
1998  }
1999 
2000  bool leaveStruct(const CXXRecordDecl *, const CXXBaseSpecifier &BS,
2001  QualType FieldTy) final {
2002  --StructBaseDepth;
2003  return true;
2004  }
2005 };
2006 
2007 // A type to check the validity of accessing accessor/sampler/stream
2008 // types as kernel parameters inside union.
2009 class SyclKernelUnionChecker : public SyclKernelFieldHandler {
2010  int UnionCount = 0;
2011  bool IsInvalid = false;
2013 
2014 public:
2015  SyclKernelUnionChecker(SemaSYCL &S)
2016  : SyclKernelFieldHandler(S), Diag(S.getASTContext().getDiagnostics()) {}
2017  bool isValid() { return !IsInvalid; }
2018  static constexpr const bool VisitUnionBody = true;
2019  static constexpr const bool VisitNthArrayElement = false;
2020 
2021  bool checkType(SourceLocation Loc, QualType Ty) {
2022  if (UnionCount) {
2023  IsInvalid = true;
2024  Diag.Report(Loc, diag::err_bad_kernel_param_data_members)
2025  << Ty << /*Union*/ 0;
2026  }
2027  return isValid();
2028  }
2029 
2030  bool enterUnion(const CXXRecordDecl *RD, FieldDecl *FD) override {
2031  ++UnionCount;
2032  return true;
2033  }
2034 
2035  bool enterUnion(const CXXRecordDecl *, ParmVarDecl *) override {
2036  // TODO
2038  return true;
2039  }
2040 
2041  bool leaveUnion(const CXXRecordDecl *RD, FieldDecl *FD) override {
2042  --UnionCount;
2043  return true;
2044  }
2045 
2046  bool leaveUnion(const CXXRecordDecl *, ParmVarDecl *) override {
2047  // TODO
2049  return true;
2050  }
2051 
2052  bool handleSyclSpecialType(FieldDecl *FD, QualType FieldTy) final {
2053  return checkType(FD->getLocation(), FieldTy);
2054  }
2055 
2056  bool handleSyclSpecialType(ParmVarDecl *PD, QualType ParamTy) final {
2057  // TODO
2059  return true;
2060  }
2061 
2062  bool handleSyclSpecialType(const CXXRecordDecl *, const CXXBaseSpecifier &BS,
2063  QualType FieldTy) final {
2064  return checkType(BS.getBeginLoc(), FieldTy);
2065  }
2066 };
2067 
2068 // A type to mark whether a collection requires decomposition
2069 // or needs to be transformed to a new type. If a collection
2070 // contains pointers, and is not decomposed, a new type must
2071 // be generated with all pointers in global address space.
2072 class SyclKernelDecompMarker : public SyclKernelFieldHandler {
2073  llvm::SmallVector<bool, 16> CollectionStack;
2074  llvm::SmallVector<bool, 16> PointerStack;
2075 
2076 public:
2077  static constexpr const bool VisitUnionBody = false;
2078  static constexpr const bool VisitNthArrayElement = false;
2079 
2080  SyclKernelDecompMarker(SemaSYCL &S) : SyclKernelFieldHandler(S) {
2081  // In order to prevent checking this over and over, just add a dummy-base
2082  // entry.
2083  CollectionStack.push_back(true);
2084  PointerStack.push_back(true);
2085  }
2086 
2087  bool handleSyclSpecialType(const CXXRecordDecl *, const CXXBaseSpecifier &,
2088  QualType) final {
2089  CollectionStack.back() = true;
2090  return true;
2091  }
2092  bool handleSyclSpecialType(FieldDecl *, QualType) final {
2093  CollectionStack.back() = true;
2094  return true;
2095  }
2096 
2097  bool handleSyclSpecialType(ParmVarDecl *, QualType) final {
2098  // TODO
2100  return true;
2101  }
2102 
2103  bool handlePointerType(FieldDecl *, QualType) final {
2104  PointerStack.back() = true;
2105  return true;
2106  }
2107 
2108  bool handlePointerType(ParmVarDecl *, QualType) final {
2109  // TODO
2111  return true;
2112  }
2113 
2114  bool enterStruct(const CXXRecordDecl *, FieldDecl *, QualType) final {
2115  CollectionStack.push_back(false);
2116  PointerStack.push_back(false);
2117  return true;
2118  }
2119 
2120  bool enterStruct(const CXXRecordDecl *, ParmVarDecl *, QualType) final {
2121  // TODO
2123  return true;
2124  }
2125 
2126  bool leaveStruct(const CXXRecordDecl *, FieldDecl *, QualType Ty) final {
2127  // If a record needs to be decomposed, it is marked with
2128  // SYCLRequiresDecompositionAttr. Else if a record contains
2129  // a pointer, it is marked with SYCLGenerateNewTypeAttr. A record
2130  // will never be marked with both attributes.
2131  CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
2132  assert(RD && "should not be null.");
2133  if (CollectionStack.pop_back_val()) {
2134  if (!RD->hasAttr<SYCLRequiresDecompositionAttr>())
2135  RD->addAttr(SYCLRequiresDecompositionAttr::CreateImplicit(
2136  SemaSYCLRef.getASTContext()));
2137  CollectionStack.back() = true;
2138  PointerStack.pop_back();
2139  } else if (PointerStack.pop_back_val()) {
2140  PointerStack.back() = true;
2141  if (!RD->hasAttr<SYCLGenerateNewTypeAttr>())
2142  RD->addAttr(SYCLGenerateNewTypeAttr::CreateImplicit(
2143  SemaSYCLRef.getASTContext()));
2144  }
2145  return true;
2146  }
2147 
2148  bool leaveStruct(const CXXRecordDecl *RD, ParmVarDecl *PD,
2149  QualType ParamTy) final {
2150  // TODO
2152  return true;
2153  }
2154 
2155  bool enterStruct(const CXXRecordDecl *, const CXXBaseSpecifier &,
2156  QualType) final {
2157  CollectionStack.push_back(false);
2158  PointerStack.push_back(false);
2159  return true;
2160  }
2161 
2162  bool leaveStruct(const CXXRecordDecl *, const CXXBaseSpecifier &,
2163  QualType Ty) final {
2164  // If a record needs to be decomposed, it is marked with
2165  // SYCLRequiresDecompositionAttr. Else if a record contains
2166  // a pointer, it is marked with SYCLGenerateNewTypeAttr. A record
2167  // will never be marked with both attributes.
2168  CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
2169  assert(RD && "should not be null.");
2170  if (CollectionStack.pop_back_val()) {
2171  if (!RD->hasAttr<SYCLRequiresDecompositionAttr>())
2172  RD->addAttr(SYCLRequiresDecompositionAttr::CreateImplicit(
2173  SemaSYCLRef.getASTContext()));
2174  CollectionStack.back() = true;
2175  PointerStack.pop_back();
2176  } else if (PointerStack.pop_back_val()) {
2177  PointerStack.back() = true;
2178  if (!RD->hasAttr<SYCLGenerateNewTypeAttr>())
2179  RD->addAttr(SYCLGenerateNewTypeAttr::CreateImplicit(
2180  SemaSYCLRef.getASTContext()));
2181  }
2182  return true;
2183  }
2184 
2185  bool enterArray(FieldDecl *, QualType ArrayTy, QualType ElementTy) final {
2186  CollectionStack.push_back(false);
2187  PointerStack.push_back(false);
2188  return true;
2189  }
2190 
2191  bool enterArray(ParmVarDecl *, QualType ArrayTy, QualType ElementTy) final {
2192  // TODO
2194  return true;
2195  }
2196 
2197  bool leaveArray(FieldDecl *FD, QualType ArrayTy, QualType ElementTy) final {
2198  // If an array needs to be decomposed, it is marked with
2199  // SYCLRequiresDecompositionAttr. Else if the array is an array of pointers
2200  // or an array of structs containing pointers, it is marked with
2201  // SYCLGenerateNewTypeAttr. An array will never be marked with both
2202  // attributes.
2203  if (CollectionStack.pop_back_val()) {
2204  // Cannot assert, since in MD arrays we'll end up marking them multiple
2205  // times.
2206  if (!FD->hasAttr<SYCLRequiresDecompositionAttr>())
2207  FD->addAttr(SYCLRequiresDecompositionAttr::CreateImplicit(
2208  SemaSYCLRef.getASTContext()));
2209  CollectionStack.back() = true;
2210  PointerStack.pop_back();
2211  } else if (PointerStack.pop_back_val()) {
2212  if (!FD->hasAttr<SYCLGenerateNewTypeAttr>())
2213  FD->addAttr(SYCLGenerateNewTypeAttr::CreateImplicit(
2214  SemaSYCLRef.getASTContext()));
2215  PointerStack.back() = true;
2216  }
2217  return true;
2218  }
2219 
2220  bool leaveArray(ParmVarDecl *PD, QualType ArrayTy, QualType ElementTy) final {
2221  // TODO
2223  return true;
2224  }
2225 };
2226 
2227 static QualType ModifyAddressSpace(SemaSYCL &SemaSYCLRef, QualType Ty) {
2228  // USM allows to use raw pointers instead of buffers/accessors, but these
2229  // pointers point to the specially allocated memory. For pointer fields,
2230  // except for function pointer fields, we add a kernel argument with the
2231  // same type as field but global address space, because OpenCL requires it.
2232  // Function pointers should have program address space. This is set in
2233  // CodeGen.
2234  QualType PointeeTy = Ty->getPointeeType();
2235  Qualifiers Quals = PointeeTy.getQualifiers();
2236  LangAS AS = Quals.getAddressSpace();
2237  // Leave global_device and global_host address spaces as is to help FPGA
2238  // device in memory allocations.
2239  if (!PointeeTy->isFunctionType() && AS != LangAS::sycl_global_device &&
2242  PointeeTy = SemaSYCLRef.getASTContext().getQualifiedType(
2243  PointeeTy.getUnqualifiedType(), Quals);
2244  return SemaSYCLRef.getASTContext().getPointerType(PointeeTy);
2245 }
2246 
2247 // This visitor is used to traverse a non-decomposed record/array to
2248 // generate a new type corresponding to this record/array.
2249 class SyclKernelPointerHandler : public SyclKernelFieldHandler {
2250  llvm::SmallVector<CXXRecordDecl *, 8> ModifiedRecords;
2251  SmallVector<CXXBaseSpecifier *, 8> ModifiedBases;
2252  SmallVector<QualType, 8> ModifiedArrayElementsOrArray;
2253 
2254  IdentifierInfo *getModifiedName(IdentifierInfo *Id) {
2255  std::string Name =
2256  Id ? (Twine("__generated_") + Id->getName()).str() : "__generated_";
2257  return &SemaSYCLRef.getASTContext().Idents.get(Name);
2258  }
2259 
2260  // Create Decl for the new type we are generating.
2261  // The fields (and base classes) of this record will be generated as
2262  // the visitor traverses kernel object record fields.
2263  void createNewType(const CXXRecordDecl *RD) {
2264  auto *ModifiedRD = CXXRecordDecl::Create(
2265  SemaSYCLRef.getASTContext(), RD->getTagKind(),
2266  const_cast<DeclContext *>(RD->getDeclContext()), SourceLocation(),
2267  SourceLocation(), getModifiedName(RD->getIdentifier()));
2268  ModifiedRD->startDefinition();
2269  if (RD->hasAttrs())
2270  ModifiedRD->setAttrs(RD->getAttrs());
2271  ModifiedRecords.push_back(ModifiedRD);
2272  }
2273 
2274  // Create and add FieldDecl for FieldTy to generated record.
2275  void addField(const FieldDecl *FD, QualType FieldTy) {
2276  assert(!ModifiedRecords.empty() &&
2277  "ModifiedRecords should have at least 1 record");
2278  ASTContext &Ctx = SemaSYCLRef.getASTContext();
2279  auto *Field = FieldDecl::Create(
2280  Ctx, ModifiedRecords.back(), SourceLocation(), SourceLocation(),
2281  getModifiedName(FD->getIdentifier()), FieldTy,
2282  Ctx.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), /*BW=*/nullptr,
2283  /*Mutable=*/false, ICIS_NoInit);
2284  Field->setAccess(FD->getAccess());
2285  if (FD->hasAttrs())
2286  Field->setAttrs(FD->getAttrs());
2287  // Add generated field to generated record.
2288  ModifiedRecords.back()->addDecl(Field);
2289  }
2290 
2291  void createBaseSpecifier(const CXXRecordDecl *Parent, const CXXRecordDecl *RD,
2292  const CXXBaseSpecifier &BS) {
2293  TypeSourceInfo *TInfo =
2295  QualType(RD->getTypeForDecl(), 0), SourceLocation());
2296  CXXBaseSpecifier *ModifiedBase = SemaSYCLRef.SemaRef.CheckBaseSpecifier(
2297  const_cast<CXXRecordDecl *>(Parent), SourceRange(), BS.isVirtual(),
2298  BS.getAccessSpecifier(), TInfo, SourceLocation());
2299  ModifiedBases.push_back(ModifiedBase);
2300  }
2301 
2302  CXXRecordDecl *getGeneratedNewRecord(const CXXRecordDecl *OldBaseDecl) {
2303  // At this point we have finished generating fields for the new
2304  // class corresponding to OldBaseDecl. Pop out the generated
2305  // record.
2306  CXXRecordDecl *ModifiedRD = ModifiedRecords.pop_back_val();
2307  ModifiedRD->completeDefinition();
2308  // Check the 'old' class for base classes.
2309  // Set bases classes for newly generated class if it has any.
2310  if (OldBaseDecl->getNumBases() > 0) {
2311  SmallVector<CXXBaseSpecifier *, 8> BasesForGeneratedClass;
2312  for (size_t I = 0; I < OldBaseDecl->getNumBases(); ++I)
2313  BasesForGeneratedClass.insert(BasesForGeneratedClass.begin(),
2314  ModifiedBases.pop_back_val());
2315  ModifiedRD->setBases(BasesForGeneratedClass.data(),
2316  OldBaseDecl->getNumBases());
2317  }
2318  return ModifiedRD;
2319  }
2320 
2321 public:
2322  static constexpr const bool VisitInsideSimpleContainersWithPointer = true;
2323  static constexpr const bool VisitNthArrayElement = false;
2324  SyclKernelPointerHandler(SemaSYCL &S, const CXXRecordDecl *RD)
2325  : SyclKernelFieldHandler(S) {
2326  createNewType(RD);
2327  }
2328 
2329  SyclKernelPointerHandler(SemaSYCL &S) : SyclKernelFieldHandler(S) {}
2330 
2331  bool enterStruct(const CXXRecordDecl *, FieldDecl *, QualType Ty) final {
2332  createNewType(Ty->getAsCXXRecordDecl());
2333  return true;
2334  }
2335 
2336  bool enterStruct(const CXXRecordDecl *, ParmVarDecl *,
2337  QualType ParamTy) final {
2338  // TODO
2340  return true;
2341  }
2342 
2343  bool leaveStruct(const CXXRecordDecl *, FieldDecl *FD, QualType Ty) final {
2344  CXXRecordDecl *ModifiedRD = getGeneratedNewRecord(Ty->getAsCXXRecordDecl());
2345 
2346  // Add this record as a field of it's parent record if it is not an
2347  // array element.
2348  if (!isArrayElement(FD, Ty))
2349  addField(FD, QualType(ModifiedRD->getTypeForDecl(), 0));
2350  else
2351  ModifiedArrayElementsOrArray.push_back(
2352  QualType(ModifiedRD->getTypeForDecl(), 0));
2353 
2354  return true;
2355  }
2356 
2357  bool leaveStruct(const CXXRecordDecl *, ParmVarDecl *PD,
2358  QualType ParamTy) final {
2359  // TODO
2361  return true;
2362  }
2363 
2364  bool enterStruct(const CXXRecordDecl *, const CXXBaseSpecifier &,
2365  QualType Ty) final {
2366  createNewType(Ty->getAsCXXRecordDecl());
2367  return true;
2368  }
2369 
2370  bool leaveStruct(const CXXRecordDecl *Parent, const CXXBaseSpecifier &BS,
2371  QualType Ty) final {
2372  CXXRecordDecl *ModifiedRD = getGeneratedNewRecord(Ty->getAsCXXRecordDecl());
2373 
2374  // Create CXXBaseSpecifier for this generated class.
2375  createBaseSpecifier(Parent, ModifiedRD, BS);
2376  return true;
2377  }
2378 
2379  bool leaveArray(FieldDecl *FD, QualType ArrayTy, QualType ET) final {
2380  QualType ModifiedArrayElement = ModifiedArrayElementsOrArray.pop_back_val();
2381 
2382  const ConstantArrayType *CAT =
2383  SemaSYCLRef.getASTContext().getAsConstantArrayType(ArrayTy);
2384  assert(CAT && "Should only be called on constant-size array.");
2385  QualType ModifiedArray = SemaSYCLRef.getASTContext().getConstantArrayType(
2386  ModifiedArrayElement, CAT->getSize(),
2387  const_cast<Expr *>(CAT->getSizeExpr()), CAT->getSizeModifier(),
2388  CAT->getIndexTypeCVRQualifiers());
2389 
2390  if (ModifiedRecords.empty()) {
2391  // This is a top-level kernel argument.
2392  ModifiedArrayElementsOrArray.push_back(ModifiedArray);
2393  } else if (!isArrayElement(FD, ArrayTy)) {
2394  // Add this array field as a field of it's parent record.
2395  addField(FD, ModifiedArray);
2396  } else {
2397  // Multi-dimensional array element.
2398  ModifiedArrayElementsOrArray.push_back(ModifiedArray);
2399  }
2400 
2401  return true;
2402  }
2403 
2404  bool leaveArray(ParmVarDecl *PD, QualType ArrayTy, QualType ET) final {
2405  // TODO
2407  return true;
2408  }
2409 
2410  bool handlePointerType(FieldDecl *FD, QualType FieldTy) final {
2411  QualType ModifiedPointerType = ModifyAddressSpace(SemaSYCLRef, FieldTy);
2412  if (!isArrayElement(FD, FieldTy))
2413  addField(FD, ModifiedPointerType);
2414  else
2415  ModifiedArrayElementsOrArray.push_back(ModifiedPointerType);
2416  // We do not need to wrap pointers since this is a pointer inside
2417  // non-decomposed struct.
2418  return true;
2419  }
2420 
2421  bool handlePointerType(ParmVarDecl *PD, QualType ParamTy) final {
2422  // TODO
2424  return true;
2425  }
2426 
2427  bool handleScalarType(FieldDecl *FD, QualType FieldTy) final {
2428  addField(FD, FieldTy);
2429  return true;
2430  }
2431 
2432  bool handleScalarType(ParmVarDecl *PD, QualType ParamTy) final {
2433  // TODO
2435  return true;
2436  }
2437 
2438  bool handleUnionType(FieldDecl *FD, QualType FieldTy) final {
2439  return handleScalarType(FD, FieldTy);
2440  }
2441 
2442  bool handleUnionType(ParmVarDecl *PD, QualType ParamTy) final {
2443  // TODO
2445  return true;
2446  }
2447 
2448  bool handleNonDecompStruct(const CXXRecordDecl *, FieldDecl *FD,
2449  QualType Ty) final {
2450  addField(FD, Ty);
2451  return true;
2452  }
2453 
2454  bool handleNonDecompStruct(const CXXRecordDecl *, ParmVarDecl *PD,
2455  QualType ParamTy) final {
2456  // TODO
2458  return true;
2459  }
2460 
2461  bool handleNonDecompStruct(const CXXRecordDecl *Parent,
2462  const CXXBaseSpecifier &BS, QualType Ty) final {
2463  createBaseSpecifier(Parent, Ty->getAsCXXRecordDecl(), BS);
2464  return true;
2465  }
2466 
2467  bool handleSimpleArrayType(FieldDecl *FD, QualType Ty) final {
2468  addField(FD, Ty);
2469  return true;
2470  }
2471 
2472 public:
2473  QualType getNewRecordType() {
2474  CXXRecordDecl *ModifiedRD = ModifiedRecords.pop_back_val();
2475  ModifiedRD->completeDefinition();
2476 
2477  if (!ModifiedBases.empty())
2478  ModifiedRD->setBases(ModifiedBases.data(), ModifiedBases.size());
2479 
2480  return QualType(ModifiedRD->getTypeForDecl(), 0);
2481  }
2482  QualType getNewArrayType() {
2483  return ModifiedArrayElementsOrArray.pop_back_val();
2484  }
2485 };
2486 
2487 // A type to Create and own the FunctionDecl for the kernel.
2488 class SyclKernelDeclCreator : public SyclKernelFieldHandler {
2489  bool IsFreeFunction = false;
2490  FunctionDecl *KernelDecl = nullptr;
2492  Sema::ContextRAII FuncContext;
2493  // Holds the last handled field's first parameter. This doesn't store an
2494  // iterator as push_back invalidates iterators.
2495  size_t LastParamIndex = 0;
2496  // Keeps track of whether we are currently handling fields inside a struct.
2497  int StructDepth = 0;
2498 
2499  void addParam(const FieldDecl *FD, QualType FieldTy) {
2500  ParamDesc newParamDesc = makeParamDesc(FD, FieldTy);
2501  addParam(newParamDesc, FieldTy);
2502  }
2503 
2504  void addParam(const ParmVarDecl *PD, QualType ParamTy) {
2505  ParamDesc newParamDesc = makeParamDesc(PD, ParamTy);
2506  addParam(newParamDesc, ParamTy);
2507  }
2508 
2509  void addParam(const CXXBaseSpecifier &BS, QualType FieldTy) {
2510  // TODO: There is no name for the base available, but duplicate names are
2511  // seemingly already possible, so we'll give them all the same name for now.
2512  // This only happens with the accessor types.
2513  StringRef Name = "_arg__base";
2514  ParamDesc newParamDesc =
2515  makeParamDesc(SemaSYCLRef.getASTContext(), Name, FieldTy);
2516  addParam(newParamDesc, FieldTy);
2517  }
2518  // Add a parameter with specified name and type
2519  void addParam(StringRef Name, QualType ParamTy) {
2520  ParamDesc newParamDesc =
2521  makeParamDesc(SemaSYCLRef.getASTContext(), Name, ParamTy);
2522  addParam(newParamDesc, ParamTy);
2523  }
2524 
2525  void addParam(ParamDesc newParamDesc, QualType FieldTy) {
2526  // Create a new ParmVarDecl based on the new info.
2527  ASTContext &Ctx = SemaSYCLRef.getASTContext();
2528  auto *NewParam = ParmVarDecl::Create(
2529  Ctx, KernelDecl, SourceLocation(), SourceLocation(),
2530  std::get<1>(newParamDesc), std::get<0>(newParamDesc),
2531  std::get<2>(newParamDesc), SC_None, /*DefArg*/ nullptr);
2532  NewParam->setScopeInfo(0, Params.size());
2533  NewParam->setIsUsed();
2534 
2535  LastParamIndex = Params.size();
2536  Params.push_back(NewParam);
2537  }
2538 
2539  // Handle accessor properties. If any properties were found in
2540  // the accessor_property_list - add the appropriate attributes to ParmVarDecl.
2541  void handleAccessorPropertyList(ParmVarDecl *Param,
2542  const CXXRecordDecl *RecordDecl,
2543  SourceLocation Loc) {
2544  const auto *AccTy = cast<ClassTemplateSpecializationDecl>(RecordDecl);
2545  if (AccTy->getTemplateArgs().size() < 6)
2546  return;
2547  const auto PropList = cast<TemplateArgument>(AccTy->getTemplateArgs()[5]);
2548  QualType PropListTy = PropList.getAsType();
2549  const auto *AccPropListDecl =
2550  cast<ClassTemplateSpecializationDecl>(PropListTy->getAsRecordDecl());
2551  const auto TemplArg = AccPropListDecl->getTemplateArgs()[0];
2552  // Move through TemplateArgs list of a property list and search for
2553  // properties. If found - apply the appropriate attribute to ParmVarDecl.
2554  for (TemplateArgument::pack_iterator Prop = TemplArg.pack_begin();
2555  Prop != TemplArg.pack_end(); ++Prop) {
2556  QualType PropTy = Prop->getAsType();
2557  if (isAccessorPropertyType(PropTy, SYCLTypeAttr::no_alias))
2558  handleNoAliasProperty(Param, PropTy, Loc);
2559  if (isAccessorPropertyType(PropTy, SYCLTypeAttr::buffer_location))
2560  handleBufferLocationProperty(Param, PropTy, Loc);
2561  }
2562  }
2563 
2564  void handleNoAliasProperty(ParmVarDecl *Param, QualType PropTy,
2565  SourceLocation Loc) {
2566  ASTContext &Ctx = SemaSYCLRef.getASTContext();
2567  Param->addAttr(RestrictAttr::CreateImplicit(Ctx, Loc));
2568  }
2569 
2570  // Obtain an integer value stored in a template parameter of buffer_location
2571  // property to pass it to buffer_location kernel attribute
2572  void handleBufferLocationProperty(ParmVarDecl *Param, QualType PropTy,
2573  SourceLocation Loc) {
2574  // If we have more than 1 buffer_location properties on a single
2575  // accessor - emit an error
2576  if (Param->hasAttr<SYCLIntelBufferLocationAttr>()) {
2577  SemaSYCLRef.Diag(Loc, diag::err_sycl_compiletime_property_duplication)
2578  << "buffer_location";
2579  return;
2580  }
2581  ASTContext &Ctx = SemaSYCLRef.getASTContext();
2582  const auto *PropDecl =
2583  cast<ClassTemplateSpecializationDecl>(PropTy->getAsRecordDecl());
2584  const auto BufferLoc = PropDecl->getTemplateArgs()[0];
2585  int LocationID = static_cast<int>(BufferLoc.getAsIntegral().getExtValue());
2586  Param->addAttr(
2587  SYCLIntelBufferLocationAttr::CreateImplicit(Ctx, LocationID));
2588  }
2589 
2590  // Additional processing is required for accessor type.
2591  void handleAccessorType(QualType FieldTy, const CXXRecordDecl *RecordDecl,
2592  SourceLocation Loc) {
2593  handleAccessorPropertyList(Params.back(), RecordDecl, Loc);
2594 
2595  // If "accessor" type check if read only
2596  if (SemaSYCL::isSyclType(FieldTy, SYCLTypeAttr::accessor)) {
2597  // Get access mode of accessor.
2598  const auto *AccessorSpecializationDecl =
2599  cast<ClassTemplateSpecializationDecl>(RecordDecl);
2600  const TemplateArgument &AccessModeArg =
2601  AccessorSpecializationDecl->getTemplateArgs().get(2);
2602  if (isReadOnlyAccessor(AccessModeArg))
2603  Params.back()->addAttr(SYCLAccessorReadonlyAttr::CreateImplicit(
2604  SemaSYCLRef.getASTContext()));
2605  }
2606 
2607  // Add implicit attribute to parameter decl when it is a read only
2608  // SYCL accessor.
2609  Params.back()->addAttr(
2610  SYCLAccessorPtrAttr::CreateImplicit(SemaSYCLRef.getASTContext()));
2611  }
2612 
2613  // All special SYCL objects must have __init method. We extract types for
2614  // kernel parameters from __init method parameters. We will use __init method
2615  // and kernel parameters which we build here to initialize special objects in
2616  // the kernel body.
2617  bool handleSpecialType(FieldDecl *FD, QualType FieldTy) {
2618  const auto *RecordDecl = FieldTy->getAsCXXRecordDecl();
2619  assert(RecordDecl && "The type must be a RecordDecl");
2620  llvm::StringLiteral MethodName =
2621  KernelDecl->hasAttr<SYCLSimdAttr>() && isSyclAccessorType(FieldTy)
2623  : InitMethodName;
2624  CXXMethodDecl *InitMethod = getMethodByName(RecordDecl, MethodName);
2625  assert(InitMethod && "The type must have the __init method");
2626 
2627  // Don't do -1 here because we count on this to be the first parameter added
2628  // (if any).
2629  size_t ParamIndex = Params.size();
2630  for (const ParmVarDecl *Param : InitMethod->parameters()) {
2631  QualType ParamTy = Param->getType();
2632  addParam(FD, ParamTy.getCanonicalType());
2633 
2634  // Propagate add_ir_attributes_kernel_parameter attribute.
2635  if (const auto *AddIRAttr =
2636  Param->getAttr<SYCLAddIRAttributesKernelParameterAttr>())
2637  Params.back()->addAttr(AddIRAttr->clone(SemaSYCLRef.getASTContext()));
2638 
2639  // FIXME: This code is temporary, and will be removed once __init_esimd
2640  // is removed and property list refactored.
2641  // The function handleAccessorType includes a call to
2642  // handleAccessorPropertyList. If new classes with property list are
2643  // added, this code needs to be refactored to call
2644  // handleAccessorPropertyList for each class which requires it.
2645  if (ParamTy.getTypePtr()->isPointerType() && isSyclAccessorType(FieldTy))
2646  handleAccessorType(FieldTy, RecordDecl, FD->getBeginLoc());
2647  }
2648  LastParamIndex = ParamIndex;
2649  return true;
2650  }
2651 
2652  static void setKernelImplicitAttrs(ASTContext &Context, FunctionDecl *FD,
2653  bool IsSIMDKernel) {
2654  // Set implicit attributes.
2655  FD->addAttr(OpenCLKernelAttr::CreateImplicit(Context));
2656  FD->addAttr(ArtificialAttr::CreateImplicit(Context));
2657  if (IsSIMDKernel)
2658  FD->addAttr(SYCLSimdAttr::CreateImplicit(Context));
2659  }
2660 
2661  static FunctionDecl *createKernelDecl(ASTContext &Ctx, SourceLocation Loc,
2662  bool IsInline, bool IsSIMDKernel) {
2663  // Create this with no prototype, and we can fix this up after we've seen
2664  // all the params.
2666  QualType FuncType = Ctx.getFunctionType(Ctx.VoidTy, {}, Info);
2667 
2670  FuncType, Ctx.getTrivialTypeSourceInfo(Ctx.VoidTy), SC_None);
2671  FD->setImplicitlyInline(IsInline);
2672  setKernelImplicitAttrs(Ctx, FD, IsSIMDKernel);
2673 
2674  // Add kernel to translation unit to see it in AST-dump.
2675  Ctx.getTranslationUnitDecl()->addDecl(FD);
2676  return FD;
2677  }
2678 
2679  // If the record has been marked with SYCLGenerateNewTypeAttr,
2680  // it implies that it contains a pointer within. This function
2681  // defines a PointerHandler visitor which visits this record
2682  // recursively and modifies the address spaces of any pointer
2683  // found as required, thereby generating a new record with all
2684  // pointers in 'right' address space. PointerHandler.getNewRecordType()
2685  // returns this generated type.
2686  QualType GenerateNewRecordType(const CXXRecordDecl *RD) {
2687  SyclKernelPointerHandler PointerHandler(SemaSYCLRef, RD);
2688  KernelObjVisitor Visitor{SemaSYCLRef};
2689  Visitor.VisitRecordBases(RD, PointerHandler);
2690  Visitor.VisitRecordFields(RD, PointerHandler);
2691  return PointerHandler.getNewRecordType();
2692  }
2693 
2694  // If the array has been marked with SYCLGenerateNewTypeAttr,
2695  // it implies that this is an array of pointers, or an array
2696  // of a type which contains pointers. This function generates
2697  // a new array with all pointers in the required address space.
2698  QualType GenerateNewArrayType(FieldDecl *FD, QualType FieldTy) {
2699  const auto *Owner = dyn_cast<CXXRecordDecl>(FD->getParent());
2700  SyclKernelPointerHandler PointerHandler(SemaSYCLRef);
2701  KernelObjVisitor Visitor{SemaSYCLRef};
2702  Visitor.visitArray(Owner, FD, FieldTy, PointerHandler);
2703  return PointerHandler.getNewArrayType();
2704  }
2705 
2706 public:
2707  static constexpr const bool VisitInsideSimpleContainers = false;
2708  SyclKernelDeclCreator(SemaSYCL &S, SourceLocation Loc, bool IsInline,
2709  bool IsSIMDKernel, bool IsFreeFunction,
2710  FunctionDecl *SYCLKernel)
2711  : SyclKernelFieldHandler(S), IsFreeFunction(IsFreeFunction),
2712  KernelDecl(
2713  createKernelDecl(S.getASTContext(), Loc, IsInline, IsSIMDKernel)),
2714  FuncContext(SemaSYCLRef.SemaRef, KernelDecl) {
2715  S.addSyclOpenCLKernel(SYCLKernel, KernelDecl);
2716  for (const auto *IRAttr :
2717  SYCLKernel->specific_attrs<SYCLAddIRAttributesFunctionAttr>()) {
2718  KernelDecl->addAttr(IRAttr->clone(SemaSYCLRef.getASTContext()));
2719  }
2720  }
2721 
2722  ~SyclKernelDeclCreator() {
2723  ASTContext &Ctx = SemaSYCLRef.getASTContext();
2725 
2726  SmallVector<QualType, 8> ArgTys;
2727  std::transform(std::begin(Params), std::end(Params),
2728  std::back_inserter(ArgTys),
2729  [](const ParmVarDecl *PVD) { return PVD->getType(); });
2730 
2731  QualType FuncType = Ctx.getFunctionType(Ctx.VoidTy, ArgTys, Info);
2732  KernelDecl->setType(FuncType);
2733  KernelDecl->setParams(Params);
2734 
2735  // Make sure that this is marked as a kernel so that the code-gen can make
2736  // decisions based on that. We cannot add this earlier, otherwise the call
2737  // to TransformStmt in replaceWithLocalClone can diagnose something that got
2738  // diagnosed on the actual kernel.
2739  KernelDecl->addAttr(
2740  SYCLKernelAttr::CreateImplicit(SemaSYCLRef.getASTContext()));
2741 
2742  SemaSYCLRef.addSyclDeviceDecl(KernelDecl);
2743  }
2744 
2745  bool enterStruct(const CXXRecordDecl *, FieldDecl *, QualType) final {
2746  ++StructDepth;
2747  return true;
2748  }
2749 
2750  bool enterStruct(const CXXRecordDecl *, ParmVarDecl *, QualType) final {
2751  // TODO
2753  return true;
2754  }
2755 
2756  bool leaveStruct(const CXXRecordDecl *, FieldDecl *, QualType) final {
2757  --StructDepth;
2758  return true;
2759  }
2760 
2761  bool leaveStruct(const CXXRecordDecl *, ParmVarDecl *, QualType) final {
2762  // TODO
2764  return true;
2765  }
2766 
2767  bool enterStruct(const CXXRecordDecl *, const CXXBaseSpecifier &BS,
2768  QualType FieldTy) final {
2769  ++StructDepth;
2770  return true;
2771  }
2772 
2773  bool leaveStruct(const CXXRecordDecl *, const CXXBaseSpecifier &BS,
2774  QualType FieldTy) final {
2775  --StructDepth;
2776  return true;
2777  }
2778 
2779  bool handleSyclSpecialType(const CXXRecordDecl *, const CXXBaseSpecifier &BS,
2780  QualType FieldTy) final {
2781  const auto *RecordDecl = FieldTy->getAsCXXRecordDecl();
2782  assert(RecordDecl && "The type must be a RecordDecl");
2783  llvm::StringLiteral MethodName =
2784  KernelDecl->hasAttr<SYCLSimdAttr>() && isSyclAccessorType(FieldTy)
2786  : InitMethodName;
2787  CXXMethodDecl *InitMethod = getMethodByName(RecordDecl, MethodName);
2788  assert(InitMethod && "The type must have the __init method");
2789 
2790  // Don't do -1 here because we count on this to be the first parameter added
2791  // (if any).
2792  size_t ParamIndex = Params.size();
2793  for (const ParmVarDecl *Param : InitMethod->parameters()) {
2794  QualType ParamTy = Param->getType();
2795  addParam(BS, ParamTy.getCanonicalType());
2796  // FIXME: This code is temporary, and will be removed once __init_esimd
2797  // is removed and property list refactored.
2798  // The function handleAccessorType includes a call to
2799  // handleAccessorPropertyList. If new classes with property list are
2800  // added, this code needs to be refactored to call
2801  // handleAccessorPropertyList for each class which requires it.
2802  if (ParamTy.getTypePtr()->isPointerType() && isSyclAccessorType(FieldTy))
2803  handleAccessorType(FieldTy, RecordDecl, BS.getBeginLoc());
2804  }
2805  LastParamIndex = ParamIndex;
2806  return true;
2807  }
2808 
2809  bool handleSyclSpecialType(FieldDecl *FD, QualType FieldTy) final {
2810  return handleSpecialType(FD, FieldTy);
2811  }
2812 
2813  bool handleSyclSpecialType(ParmVarDecl *, QualType) final {
2814  // TODO
2816  return true;
2817  }
2818 
2819  RecordDecl *wrapField(FieldDecl *Field, QualType FieldTy) {
2820  RecordDecl *WrapperClass =
2821  SemaSYCLRef.getASTContext().buildImplicitRecord("__wrapper_class");
2822  WrapperClass->startDefinition();
2824  SemaSYCLRef.getASTContext(), WrapperClass, SourceLocation(),
2825  SourceLocation(), /*Id=*/nullptr, FieldTy,
2826  SemaSYCLRef.getASTContext().getTrivialTypeSourceInfo(FieldTy,
2827  SourceLocation()),
2828  /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
2829  Field->setAccess(AS_public);
2830  WrapperClass->addDecl(Field);
2831  WrapperClass->completeDefinition();
2832  return WrapperClass;
2833  };
2834 
2835  bool handlePointerType(FieldDecl *FD, QualType FieldTy) final {
2836  QualType ModTy = ModifyAddressSpace(SemaSYCLRef, FieldTy);
2837  // When the kernel is generated, struct type kernel arguments are
2838  // decomposed; i.e. the parameters of the kernel are the fields of the
2839  // struct, and not the struct itself. This causes an error in the backend
2840  // when the struct field is a pointer, since non-USM pointers cannot be
2841  // passed directly. To work around this issue, all pointers inside the
2842  // struct are wrapped in a generated '__wrapper_class'.
2843  if (StructDepth) {
2844  RecordDecl *WrappedPointer = wrapField(FD, ModTy);
2845  ModTy = SemaSYCLRef.getASTContext().getRecordType(WrappedPointer);
2846  }
2847 
2848  addParam(FD, ModTy);
2849  return true;
2850  }
2851 
2852  bool handlePointerType(ParmVarDecl *PD, QualType ParamTy) final {
2853  QualType ModTy = ModifyAddressSpace(SemaSYCLRef, ParamTy);
2854  addParam(PD, ModTy);
2855  return true;
2856  }
2857 
2858  bool handleSimpleArrayType(FieldDecl *FD, QualType FieldTy) final {
2859  QualType ArrayTy = FieldTy;
2860 
2861  // This is an array of pointers or an array of a type with pointer.
2862  if (FD->hasAttr<SYCLGenerateNewTypeAttr>())
2863  ArrayTy = GenerateNewArrayType(FD, FieldTy);
2864 
2865  // Arrays are wrapped in a struct since they cannot be passed directly.
2866  RecordDecl *WrappedArray = wrapField(FD, ArrayTy);
2867  addParam(FD, SemaSYCLRef.getASTContext().getRecordType(WrappedArray));
2868  return true;
2869  }
2870 
2871  bool handleScalarType(FieldDecl *FD, QualType FieldTy) final {
2872  addParam(FD, FieldTy);
2873  return true;
2874  }
2875 
2876  bool handleScalarType(ParmVarDecl *PD, QualType ParamTy) final {
2877  addParam(PD, ParamTy);
2878  return true;
2879  }
2880 
2881  bool handleNonDecompStruct(const CXXRecordDecl *RD, FieldDecl *FD,
2882  QualType Ty) final {
2883  // This is a field which should not be decomposed.
2884  CXXRecordDecl *FieldRecordDecl = Ty->getAsCXXRecordDecl();
2885  assert(FieldRecordDecl && "Type must be a C++ record type");
2886  // Check if we need to generate a new type for this record,
2887  // i.e. this record contains pointers.
2888  if (FieldRecordDecl->hasAttr<SYCLGenerateNewTypeAttr>())
2889  addParam(FD, GenerateNewRecordType(FieldRecordDecl));
2890  else
2891  addParam(FD, Ty);
2892  return true;
2893  }
2894 
2895  bool handleNonDecompStruct(const CXXRecordDecl *RD, ParmVarDecl *PD,
2896  QualType ParamTy) final {
2897  // TODO
2899  return true;
2900  }
2901 
2902  bool handleNonDecompStruct(const CXXRecordDecl *Base,
2903  const CXXBaseSpecifier &BS, QualType Ty) final {
2904  // This is a base class which should not be decomposed.
2905  CXXRecordDecl *BaseRecordDecl = Ty->getAsCXXRecordDecl();
2906  assert(BaseRecordDecl && "Type must be a C++ record type");
2907  // Check if we need to generate a new type for this record,
2908  // i.e. this record contains pointers.
2909  if (BaseRecordDecl->hasAttr<SYCLGenerateNewTypeAttr>())
2910  addParam(BS, GenerateNewRecordType(BaseRecordDecl));
2911  else
2912  addParam(BS, Ty);
2913  return true;
2914  }
2915 
2916  bool handleUnionType(FieldDecl *FD, QualType FieldTy) final {
2917  return handleScalarType(FD, FieldTy);
2918  }
2919 
2920  bool handleUnionType(ParmVarDecl *PD, QualType ParamTy) final {
2921  // TODO
2923  return true;
2924  }
2925 
2926  // Generate kernel argument to initialize specialization constants.
2927  void handleSyclKernelHandlerType() {
2928  ASTContext &Context = SemaSYCLRef.getASTContext();
2929  StringRef Name = "_arg__specialization_constants_buffer";
2930  addParam(Name, Context.getPointerType(Context.getAddrSpaceQualType(
2931  Context.CharTy, LangAS::sycl_global)));
2932  }
2933 
2934  void setBody(CompoundStmt *KB) { KernelDecl->setBody(KB); }
2935 
2936  FunctionDecl *getKernelDecl() { return KernelDecl; }
2937 
2938  llvm::ArrayRef<ParmVarDecl *> getParamVarDeclsForCurrentField() {
2939  return ArrayRef<ParmVarDecl *>(std::begin(Params) + LastParamIndex,
2940  std::end(Params));
2941  }
2942 };
2943 
2944 // This Visitor traverses the AST of the function with
2945 // `sycl_kernel` attribute and returns the version of “operator()()” that is
2946 // called by KernelFunc. There will only be one call to KernelFunc in that
2947 // AST because the DPC++ headers are structured such that the user’s
2948 // kernel function is only called once. This ensures that the correct
2949 // “operator()()” function call is returned, when a named function object used
2950 // to define a kernel has more than one “operator()()” calls defined in it. For
2951 // example, in the code below, 'operator()(sycl::id<1> id)' is returned based on
2952 // the 'parallel_for' invocation which takes a 'sycl::range<1>(16)' argument.
2953 // class MyKernel {
2954 // public:
2955 // void operator()() const {
2956 // // code
2957 // }
2958 //
2959 // [[intel::reqd_sub_group_size(4)]] void operator()(sycl::id<1> id) const
2960 // {
2961 // // code
2962 // }
2963 // };
2964 //
2965 // int main() {
2966 //
2967 // Q.submit([&](sycl::handler& cgh) {
2968 // MyKernel kernelFunctorObject;
2969 // cgh.parallel_for(sycl::range<1>(16), kernelFunctorObject);
2970 // });
2971 // return 0;
2972 // }
2973 
2974 class KernelCallOperatorVisitor
2975  : public RecursiveASTVisitor<KernelCallOperatorVisitor> {
2976 
2977  FunctionDecl *KernelCallerFunc;
2978 
2979 public:
2980  CXXMethodDecl *CallOperator = nullptr;
2981  const CXXRecordDecl *KernelObj;
2982 
2983  KernelCallOperatorVisitor(FunctionDecl *KernelCallerFunc,
2984  const CXXRecordDecl *KernelObj)
2985  : KernelCallerFunc(KernelCallerFunc), KernelObj(KernelObj) {}
2986 
2987  bool VisitCallExpr(CallExpr *CE) {
2988  Decl *CalleeDecl = CE->getCalleeDecl();
2989  if (isa_and_nonnull<CXXMethodDecl>(CalleeDecl)) {
2990  CXXMethodDecl *MD = cast<CXXMethodDecl>(CalleeDecl);
2991  if (MD->getOverloadedOperator() == OO_Call &&
2992  MD->getParent() == KernelObj) {
2993  CallOperator = MD;
2994  }
2995  }
2996  return true;
2997  }
2998 
2999  CXXMethodDecl *getCallOperator() {
3000  if (CallOperator)
3001  return CallOperator;
3002 
3003  TraverseDecl(KernelCallerFunc);
3004  return CallOperator;
3005  }
3006 };
3007 
3008 class ESIMDKernelDiagnostics : public SyclKernelFieldHandler {
3009 
3010  SourceLocation KernelLoc;
3011  bool IsESIMD = false;
3012 
3013  bool handleSpecialType(QualType FieldTy) {
3014  const CXXRecordDecl *RecordDecl = FieldTy->getAsCXXRecordDecl();
3015 
3016  if (IsESIMD && !isSyclAccessorType(FieldTy))
3017  return SemaSYCLRef.Diag(KernelLoc,
3018  diag::err_sycl_esimd_not_supported_for_type)
3019  << RecordDecl;
3020  return true;
3021  }
3022 
3023 public:
3024  ESIMDKernelDiagnostics(SemaSYCL &S, SourceLocation Loc, bool IsESIMD)
3025  : SyclKernelFieldHandler(S), KernelLoc(Loc), IsESIMD(IsESIMD) {}
3026 
3027  bool handleSyclSpecialType(FieldDecl *FD, QualType FieldTy) final {
3028  return handleSpecialType(FieldTy);
3029  }
3030 
3031  bool handleSyclSpecialType(const CXXRecordDecl *, const CXXBaseSpecifier &BS,
3032  QualType FieldTy) final {
3033  return handleSpecialType(FieldTy);
3034  }
3035 
3036  using SyclKernelFieldHandler::handleSyclSpecialType;
3037 };
3038 
3039 class SyclKernelArgsSizeChecker : public SyclKernelFieldHandler {
3040  SourceLocation KernelLoc;
3041  unsigned SizeOfParams = 0;
3042  bool IsESIMD = false;
3043 
3044  void addParam(QualType ArgTy) {
3045  SizeOfParams +=
3046  SemaSYCLRef.getASTContext().getTypeSizeInChars(ArgTy).getQuantity();
3047  }
3048 
3049  bool handleSpecialType(QualType FieldTy) {
3050  const CXXRecordDecl *RecordDecl = FieldTy->getAsCXXRecordDecl();
3051  assert(RecordDecl && "The type must be a RecordDecl");
3052  llvm::StringLiteral MethodName = (IsESIMD && isSyclAccessorType(FieldTy))
3054  : InitMethodName;
3055  CXXMethodDecl *InitMethod = getMethodByName(RecordDecl, MethodName);
3056  assert(InitMethod && "The type must have the __init method");
3057  for (const ParmVarDecl *Param : InitMethod->parameters())
3058  addParam(Param->getType());
3059  return true;
3060  }
3061 
3062 public:
3063  static constexpr const bool VisitInsideSimpleContainers = false;
3064  SyclKernelArgsSizeChecker(SemaSYCL &S, SourceLocation Loc, bool IsESIMD)
3065  : SyclKernelFieldHandler(S), KernelLoc(Loc), IsESIMD(IsESIMD) {}
3066 
3067  ~SyclKernelArgsSizeChecker() {
3068  if (SizeOfParams > MaxKernelArgsSize)
3069  SemaSYCLRef.Diag(KernelLoc, diag::warn_sycl_kernel_too_big_args)
3070  << SizeOfParams << MaxKernelArgsSize;
3071  }
3072 
3073  bool handleSyclSpecialType(FieldDecl *FD, QualType FieldTy) final {
3074  return handleSpecialType(FieldTy);
3075  }
3076 
3077  bool handleSyclSpecialType(ParmVarDecl *PD, QualType ParamTy) final {
3078  // TODO
3080  return true;
3081  }
3082 
3083  bool handleSyclSpecialType(const CXXRecordDecl *, const CXXBaseSpecifier &BS,
3084  QualType FieldTy) final {
3085  return handleSpecialType(FieldTy);
3086  }
3087 
3088  bool handlePointerType(FieldDecl *FD, QualType FieldTy) final {
3089  addParam(FieldTy);
3090  return true;
3091  }
3092 
3093  bool handlePointerType(ParmVarDecl *PD, QualType ParamTy) final {
3094  addParam(ParamTy);
3095  return true;
3096  }
3097 
3098  bool handleScalarType(FieldDecl *FD, QualType FieldTy) final {
3099  addParam(FieldTy);
3100  return true;
3101  }
3102 
3103  bool handleScalarType(ParmVarDecl *PD, QualType ParamTy) final {
3104  addParam(ParamTy);
3105  return true;
3106  }
3107 
3108  bool handleSimpleArrayType(FieldDecl *FD, QualType FieldTy) final {
3109  addParam(FieldTy);
3110  return true;
3111  }
3112 
3113  bool handleNonDecompStruct(const CXXRecordDecl *, FieldDecl *FD,
3114  QualType Ty) final {
3115  addParam(Ty);
3116  return true;
3117  }
3118 
3119  bool handleNonDecompStruct(const CXXRecordDecl *, ParmVarDecl *,
3120  QualType ParamTy) final {
3121  // TODO
3123  return true;
3124  }
3125 
3126  bool handleNonDecompStruct(const CXXRecordDecl *Base,
3127  const CXXBaseSpecifier &BS, QualType Ty) final {
3128  addParam(Ty);
3129  return true;
3130  }
3131 
3132  bool handleUnionType(FieldDecl *FD, QualType FieldTy) final {
3133  return handleScalarType(FD, FieldTy);
3134  }
3135 
3136  bool handleUnionType(ParmVarDecl *PD, QualType ParamTy) final {
3137  // TODO
3139  return true;
3140  }
3141 };
3142 
3143 std::string getKernelArgDesc(StringRef KernelArgDescription) {
3144  if (KernelArgDescription == "")
3145  return "";
3146  return ("Compiler generated argument for " + KernelArgDescription + ",")
3147  .str();
3148 }
3149 
3150 class SyclOptReportCreator : public SyclKernelFieldHandler {
3151  SyclKernelDeclCreator &DC;
3152  SourceLocation KernelInvocationLoc;
3153 
3154  void addParam(const FieldDecl *KernelArg, QualType KernelArgType,
3155  StringRef KernelArgDescription,
3156  bool IsCompilerGeneratedType = false) {
3157  StringRef NameToEmitInDescription = KernelArg->getName();
3158  const RecordDecl *KernelArgParent = KernelArg->getParent();
3159  if (KernelArgParent && KernelArgDescription == "decomposed struct/class")
3160  NameToEmitInDescription = KernelArgParent->getName();
3161 
3162  unsigned KernelArgSize = SemaSYCLRef.getASTContext()
3163  .getTypeSizeInChars(KernelArgType)
3164  .getQuantity();
3165 
3167  DC.getKernelDecl(), NameToEmitInDescription,
3168  IsCompilerGeneratedType ? "Compiler generated"
3169  : KernelArgType.getAsString(),
3170  KernelInvocationLoc, KernelArgSize,
3171  getKernelArgDesc(KernelArgDescription),
3172  (KernelArgDescription == "decomposed struct/class")
3173  ? ("Field:" + KernelArg->getName().str() + ", ")
3174  : "");
3175  }
3176 
3177  void addParam(const FieldDecl *FD, QualType FieldTy) {
3178  std::string KernelArgDescription = "";
3179  const RecordDecl *RD = FD->getParent();
3180  if (RD && RD->hasAttr<SYCLRequiresDecompositionAttr>())
3181  KernelArgDescription = "decomposed struct/class";
3182 
3183  addParam(FD, FieldTy, KernelArgDescription);
3184  }
3185 
3186  // Handles base classes.
3187  void addParam(const CXXBaseSpecifier &, QualType KernelArgType,
3188  StringRef KernelArgDescription,
3189  bool IsCompilerGeneratedType = false) {
3190  unsigned KernelArgSize = SemaSYCLRef.getASTContext()
3191  .getTypeSizeInChars(KernelArgType)
3192  .getQuantity();
3194  DC.getKernelDecl(), KernelArgType.getAsString(),
3195  IsCompilerGeneratedType ? "Compiler generated"
3196  : KernelArgType.getAsString(),
3197  KernelInvocationLoc, KernelArgSize,
3198  getKernelArgDesc(KernelArgDescription), "");
3199  }
3200 
3201  // Handles specialization constants.
3202  void addParam(QualType KernelArgType, std::string KernelArgDescription) {
3203  unsigned KernelArgSize = SemaSYCLRef.getASTContext()
3204  .getTypeSizeInChars(KernelArgType)
3205  .getQuantity();
3207  DC.getKernelDecl(), "", KernelArgType.getAsString(),
3208  KernelInvocationLoc, KernelArgSize,
3209  getKernelArgDesc(KernelArgDescription), "");
3210  }
3211 
3212 public:
3213  static constexpr const bool VisitInsideSimpleContainers = false;
3214  SyclOptReportCreator(SemaSYCL &S, SyclKernelDeclCreator &DC,
3216  : SyclKernelFieldHandler(S), DC(DC), KernelInvocationLoc(Loc) {}
3217 
3218  using SyclKernelFieldHandler::handleSyclSpecialType;
3219  bool handleSyclSpecialType(FieldDecl *FD, QualType FieldTy) final {
3220  for (const auto *Param : DC.getParamVarDeclsForCurrentField())
3221  addParam(FD, Param->getType(), FieldTy.getAsString());
3222  return true;
3223  }
3224 
3225  bool handleSyclSpecialType(const CXXRecordDecl *, const CXXBaseSpecifier &BS,
3226  QualType FieldTy) final {
3227  std::string KernelArgDescription = "base class " + FieldTy.getAsString();
3228  for (const auto *Param : DC.getParamVarDeclsForCurrentField()) {
3229  QualType KernelArgType = Param->getType();
3230  unsigned KernelArgSize = SemaSYCLRef.getASTContext()
3231  .getTypeSizeInChars(KernelArgType)
3232  .getQuantity();
3234  DC.getKernelDecl(), FieldTy.getAsString(),
3235  KernelArgType.getAsString(), KernelInvocationLoc, KernelArgSize,
3236  getKernelArgDesc(KernelArgDescription), "");
3237  }
3238  return true;
3239  }
3240 
3241  using SyclKernelFieldHandler::handlePointerType;
3242  bool handlePointerType(FieldDecl *FD, QualType FieldTy) final {
3243  std::string KernelArgDescription = "";
3244  bool IsCompilerGeneratedType = false;
3245  ParmVarDecl *KernelParameter = DC.getParamVarDeclsForCurrentField()[0];
3246  // Compiler generated openCL kernel argument for current pointer field
3247  // is not a pointer. This means we are processing a nested pointer and
3248  // the openCL kernel argument is of type __wrapper_class.
3249  if (!KernelParameter->getType()->isPointerType()) {
3250  KernelArgDescription = "nested pointer";
3251  IsCompilerGeneratedType = true;
3252  }
3253 
3254  for (const auto *Param : DC.getParamVarDeclsForCurrentField())
3255  addParam(FD, Param->getType(), KernelArgDescription,
3256  IsCompilerGeneratedType);
3257  return true;
3258  }
3259 
3260  using SyclKernelFieldHandler::handleScalarType;
3261  bool handleScalarType(FieldDecl *FD, QualType FieldTy) final {
3262  addParam(FD, FieldTy);
3263  return true;
3264  }
3265 
3266  using SyclKernelFieldHandler::handleSimpleArrayType;
3267  bool handleSimpleArrayType(FieldDecl *FD, QualType FieldTy) final {
3268  // Simple arrays are always wrapped.
3269  for (const auto *Param : DC.getParamVarDeclsForCurrentField())
3270  addParam(FD, Param->getType(), "array", /*IsCompilerGeneratedType*/ true);
3271  return true;
3272  }
3273 
3274  using SyclKernelFieldHandler::handleNonDecompStruct;
3275  bool handleNonDecompStruct(const CXXRecordDecl *, FieldDecl *FD,
3276  QualType Ty) final {
3277  CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
3278  assert(RD && "Type must be a C++ record type");
3279  if (RD->hasAttr<SYCLGenerateNewTypeAttr>())
3280  addParam(FD, Ty, "object with pointer", /*IsCompilerGeneratedType*/ true);
3281  else
3282  addParam(FD, Ty);
3283  return true;
3284  }
3285 
3286  bool handleNonDecompStruct(const CXXRecordDecl *, const CXXBaseSpecifier &BS,
3287  QualType Ty) final {
3288  CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
3289  assert(RD && "Type must be a C++ record type");
3290  if (RD->hasAttr<SYCLGenerateNewTypeAttr>())
3291  addParam(BS, Ty, "base class with pointer",
3292  /*IsCompilerGeneratedType*/ true);
3293  else
3294  addParam(BS, Ty, "base class");
3295  return true;
3296  }
3297 
3298  using SyclKernelFieldHandler::handleUnionType;
3299  bool handleUnionType(FieldDecl *FD, QualType FieldTy) final {
3300  return handleScalarType(FD, FieldTy);
3301  }
3302 
3303  void handleSyclKernelHandlerType() {
3304  addParam(DC.getParamVarDeclsForCurrentField()[0]->getType(),
3305  "SYCL2020 specialization constant");
3306  }
3307 };
3308 
3309 static bool isESIMDKernelType(CXXMethodDecl *CallOperator) {
3310  return (CallOperator != nullptr) && CallOperator->hasAttr<SYCLSimdAttr>();
3311 }
3312 
3313 class SyclKernelBodyCreator : public SyclKernelFieldHandler {
3314  SyclKernelDeclCreator &DeclCreator;
3316  llvm::SmallVector<InitListExpr *, 16> CollectionInitExprs;
3317  llvm::SmallVector<Stmt *, 16> FinalizeStmts;
3318  // This collection contains the information required to add/remove information
3319  // about arrays as we enter them. The InitializedEntity component is
3320  // necessary for initializing child members. uin64_t is the index of the
3321  // current element being worked on, which is updated every time we visit
3322  // nextElement.
3324  VarDecl *KernelObjClone;
3325  InitializedEntity VarEntity;
3326  llvm::SmallVector<Expr *, 16> MemberExprBases;
3327  llvm::SmallVector<Expr *, 16> ArrayParamBases;
3328  FunctionDecl *KernelCallerFunc;
3329  SourceLocation KernelCallerSrcLoc; // KernelCallerFunc source location.
3330  // Contains a count of how many containers we're in. This is used by the
3331  // pointer-struct-wrapping code to ensure that we don't try to wrap
3332  // top-level pointers.
3333  uint64_t StructDepth = 0;
3334  VarDecl *KernelHandlerClone = nullptr;
3335  bool IsESIMD = false;
3336  CXXMethodDecl *CallOperator = nullptr;
3337 
3338  Stmt *replaceWithLocalClone(ParmVarDecl *OriginalParam, VarDecl *LocalClone,
3339  Stmt *FunctionBody) {
3340  // DeclRefExpr with valid source location but with decl which is not marked
3341  // as used is invalid.
3342  LocalClone->setIsUsed();
3343  std::pair<DeclaratorDecl *, DeclaratorDecl *> MappingPair =
3344  std::make_pair(OriginalParam, LocalClone);
3345  KernelBodyTransform KBT(MappingPair, SemaSYCLRef.SemaRef);
3346  return KBT.TransformStmt(FunctionBody).get();
3347  }
3348 
3349  // Using the statements/init expressions that we've created, this generates
3350  // the kernel body compound stmt. CompoundStmt needs to know its number of
3351  // statements in advance to allocate it, so we cannot do this as we go along.
3352  CompoundStmt *createKernelBody() {
3353  // Push the Kernel function scope to ensure the scope isn't empty
3354  SemaSYCLRef.SemaRef.PushFunctionScope();
3355 
3356  // Initialize kernel object local clone
3357  assert(CollectionInitExprs.size() == 1 &&
3358  "Should have been popped down to just the first one");
3359  KernelObjClone->setInit(CollectionInitExprs.back());
3360 
3361  // Replace references to the kernel object in kernel body, to use the
3362  // compiler generated local clone
3363  Stmt *NewBody =
3364  replaceWithLocalClone(KernelCallerFunc->getParamDecl(0), KernelObjClone,
3365  KernelCallerFunc->getBody());
3366 
3367  // If kernel_handler argument is passed by SYCL kernel, replace references
3368  // to this argument in kernel body, to use the compiler generated local
3369  // clone
3370  if (ParmVarDecl *KernelHandlerParam =
3371  getSyclKernelHandlerArg(KernelCallerFunc))
3372  NewBody = replaceWithLocalClone(KernelHandlerParam, KernelHandlerClone,
3373  NewBody);
3374 
3375  // Use transformed body (with clones) as kernel body
3376  BodyStmts.push_back(NewBody);
3377 
3378  BodyStmts.insert(BodyStmts.end(), FinalizeStmts.begin(),
3379  FinalizeStmts.end());
3380 
3381  return CompoundStmt::Create(SemaSYCLRef.getASTContext(), BodyStmts,
3382  FPOptionsOverride(), {}, {});
3383  }
3384 
3385  void annotateHierarchicalParallelismAPICalls() {
3386  // Is this a hierarchical parallelism kernel invocation?
3387  if (getKernelInvocationKind(KernelCallerFunc) != InvokeParallelForWorkGroup)
3388  return;
3389 
3390  // Mark kernel object with work-group scope attribute to avoid work-item
3391  // scope memory allocation.
3392  KernelObjClone->addAttr(SYCLScopeAttr::CreateImplicit(
3393  SemaSYCLRef.getASTContext(), SYCLScopeAttr::Level::WorkGroup));
3394 
3395  assert(CallOperator && "non callable object is passed as kernel obj");
3396  // Mark the function that it "works" in a work group scope:
3397  // NOTE: In case of wait_for the marker call itself is
3398  // marked with work item scope attribute, here the '()' operator of the
3399  // object passed as parameter is marked. This is an optimization -
3400  // there are a lot of locals created at parallel_for_work_group
3401  // scope before calling the lambda - it is more efficient to have
3402  // all of them in the private address space rather then sharing via
3403  // the local AS. See parallel_for_work_group implementation in the
3404  // SYCL headers.
3405  if (!CallOperator->hasAttr<SYCLScopeAttr>()) {
3406  CallOperator->addAttr(SYCLScopeAttr::CreateImplicit(
3407  SemaSYCLRef.getASTContext(), SYCLScopeAttr::Level::WorkGroup));
3408  // Search and mark wait_for calls:
3409  MarkWIScopeFnVisitor MarkWIScope(SemaSYCLRef.getASTContext());
3410  MarkWIScope.TraverseDecl(CallOperator);
3411  // Now mark local variables declared in the PFWG lambda with work group
3412  // scope attribute
3413  addScopeAttrToLocalVars(*CallOperator);
3414  }
3415  }
3416 
3417  // Creates a DeclRefExpr to the ParmVar that represents the current field.
3418  Expr *createParamReferenceExpr() {
3419  ParmVarDecl *KernelParameter =
3420  DeclCreator.getParamVarDeclsForCurrentField()[0];
3421 
3422  QualType ParamType = KernelParameter->getOriginalType();
3423  Expr *DRE = SemaSYCLRef.SemaRef.BuildDeclRefExpr(
3424  KernelParameter, ParamType, VK_LValue, KernelCallerSrcLoc);
3425  return DRE;
3426  }
3427 
3428  // Creates a DeclRefExpr to the ParmVar that represents the current pointer
3429  // field.
3430  Expr *createPointerParamReferenceExpr(QualType PointerTy, bool Wrapped) {
3431  ParmVarDecl *KernelParameter =
3432  DeclCreator.getParamVarDeclsForCurrentField()[0];
3433 
3434  QualType ParamType = KernelParameter->getOriginalType();
3435  Expr *DRE = SemaSYCLRef.SemaRef.BuildDeclRefExpr(
3436  KernelParameter, ParamType, VK_LValue, KernelCallerSrcLoc);
3437 
3438  // Struct Type kernel arguments are decomposed. The pointer fields are
3439  // then wrapped inside a compiler generated struct. Therefore when
3440  // generating the initializers, we have to 'unwrap' the pointer.
3441  if (Wrapped) {
3442  CXXRecordDecl *WrapperStruct = ParamType->getAsCXXRecordDecl();
3443  // Pointer field wrapped inside __wrapper_class
3444  FieldDecl *Pointer = *(WrapperStruct->field_begin());
3445  DRE = buildMemberExpr(DRE, Pointer);
3446  ParamType = Pointer->getType();
3447  }
3448 
3449  DRE = ImplicitCastExpr::Create(SemaSYCLRef.getASTContext(), ParamType,
3450  CK_LValueToRValue, DRE, /*BasePath=*/nullptr,
3452 
3453  if (PointerTy->getPointeeType().getAddressSpace() !=
3454  ParamType->getPointeeType().getAddressSpace())
3455  DRE = ImplicitCastExpr::Create(SemaSYCLRef.getASTContext(), PointerTy,
3456  CK_AddressSpaceConversion, DRE, nullptr,
3458 
3459  return DRE;
3460  }
3461 
3462  Expr *createSimpleArrayParamReferenceExpr(QualType ArrayTy) {
3463  ParmVarDecl *KernelParameter =
3464  DeclCreator.getParamVarDeclsForCurrentField()[0];
3465  QualType ParamType = KernelParameter->getOriginalType();
3466  Expr *DRE = SemaSYCLRef.SemaRef.BuildDeclRefExpr(
3467  KernelParameter, ParamType, VK_LValue, KernelCallerSrcLoc);
3468 
3469  // Unwrap the array.
3470  CXXRecordDecl *WrapperStruct = ParamType->getAsCXXRecordDecl();
3471  FieldDecl *ArrayField = *(WrapperStruct->field_begin());
3472  return buildMemberExpr(DRE, ArrayField);
3473  }
3474 
3475  // Creates an initialized entity for a field/item. In the case where this is a
3476  // field, returns a normal member initializer, if we're in a sub-array of a MD
3477  // array, returns an element initializer.
3478  InitializedEntity getFieldEntity(FieldDecl *FD, QualType Ty) {
3479  if (isArrayElement(FD, Ty))
3481  ArrayInfos.back().second,
3482  ArrayInfos.back().first);
3483  return InitializedEntity::InitializeMember(FD, &VarEntity);
3484  }
3485 
3486  void addFieldInit(FieldDecl *FD, QualType Ty, MultiExprArg ParamRef) {
3487  InitializationKind InitKind =
3488  InitializationKind::CreateCopy(KernelCallerSrcLoc, KernelCallerSrcLoc);
3489  addFieldInit(FD, Ty, ParamRef, InitKind);
3490  }
3491 
3492  void addFieldInit(FieldDecl *FD, QualType Ty, MultiExprArg ParamRef,
3493  InitializationKind InitKind) {
3494  addFieldInit(FD, Ty, ParamRef, InitKind, getFieldEntity(FD, Ty));
3495  }
3496 
3497  void addFieldInit(FieldDecl *FD, QualType Ty, MultiExprArg ParamRef,
3498  InitializationKind InitKind, InitializedEntity Entity) {
3499  InitializationSequence InitSeq(SemaSYCLRef.SemaRef, Entity, InitKind,
3500  ParamRef);
3501  ExprResult Init =
3502  InitSeq.Perform(SemaSYCLRef.SemaRef, Entity, InitKind, ParamRef);
3503 
3504  InitListExpr *ParentILE = CollectionInitExprs.back();
3505  ParentILE->updateInit(SemaSYCLRef.getASTContext(), ParentILE->getNumInits(),
3506  Init.get());
3507  }
3508 
3509  void addBaseInit(const CXXBaseSpecifier &BS, QualType Ty,
3510  InitializationKind InitKind) {
3512  SemaSYCLRef.getASTContext(), &BS, /*IsInheritedVirtualBase*/ false,
3513  &VarEntity);
3514  InitializationSequence InitSeq(SemaSYCLRef.SemaRef, Entity, InitKind,
3515  std::nullopt);
3516  ExprResult Init =
3517  InitSeq.Perform(SemaSYCLRef.SemaRef, Entity, InitKind, std::nullopt);
3518 
3519  InitListExpr *ParentILE = CollectionInitExprs.back();
3520  ParentILE->updateInit(SemaSYCLRef.getASTContext(), ParentILE->getNumInits(),
3521  Init.get());
3522  }
3523 
3524  void addBaseInit(const CXXBaseSpecifier &BS, QualType Ty,
3525  InitializationKind InitKind, MultiExprArg Args) {
3527  SemaSYCLRef.getASTContext(), &BS, /*IsInheritedVirtualBase*/ false,
3528  &VarEntity);
3529  InitializationSequence InitSeq(SemaSYCLRef.SemaRef, Entity, InitKind, Args);
3530  ExprResult Init =
3531  InitSeq.Perform(SemaSYCLRef.SemaRef, Entity, InitKind, Args);
3532 
3533  InitListExpr *ParentILE = CollectionInitExprs.back();
3534  ParentILE->updateInit(SemaSYCLRef.getASTContext(), ParentILE->getNumInits(),
3535  Init.get());
3536  }
3537 
3538  void addSimpleBaseInit(const CXXBaseSpecifier &BS, QualType Ty) {
3539  InitializationKind InitKind =
3540  InitializationKind::CreateCopy(KernelCallerSrcLoc, KernelCallerSrcLoc);
3541 
3543  SemaSYCLRef.getASTContext(), &BS, /*IsInheritedVirtualBase*/ false,
3544  &VarEntity);
3545 
3546  Expr *ParamRef = createParamReferenceExpr();
3547  InitializationSequence InitSeq(SemaSYCLRef.SemaRef, Entity, InitKind,
3548  ParamRef);
3549  ExprResult Init =
3550  InitSeq.Perform(SemaSYCLRef.SemaRef, Entity, InitKind, ParamRef);
3551 
3552  InitListExpr *ParentILE = CollectionInitExprs.back();
3553  ParentILE->updateInit(SemaSYCLRef.getASTContext(), ParentILE->getNumInits(),
3554  Init.get());
3555  }
3556 
3557  // Adds an initializer that handles a simple initialization of a field.
3558  void addSimpleFieldInit(FieldDecl *FD, QualType Ty) {
3559  Expr *ParamRef = createParamReferenceExpr();
3560  addFieldInit(FD, Ty, ParamRef);
3561  }
3562 
3563  Expr *createGetAddressOf(Expr *E) {
3564  return UnaryOperator::Create(
3565  SemaSYCLRef.getASTContext(), E, UO_AddrOf,
3566  SemaSYCLRef.getASTContext().getPointerType(E->getType()), VK_PRValue,
3567  OK_Ordinary, KernelCallerSrcLoc, false,
3568  SemaSYCLRef.SemaRef.CurFPFeatureOverrides());
3569  }
3570 
3571  Expr *createDerefOp(Expr *E) {
3572  return UnaryOperator::Create(SemaSYCLRef.getASTContext(), E, UO_Deref,
3573  E->getType()->getPointeeType(), VK_LValue,
3574  OK_Ordinary, KernelCallerSrcLoc, false,
3575  SemaSYCLRef.SemaRef.CurFPFeatureOverrides());
3576  }
3577 
3578  Expr *createReinterpretCastExpr(Expr *E, QualType To) {
3580  SemaSYCLRef.getASTContext(), To, VK_PRValue, CK_BitCast, E,
3581  /*Path=*/nullptr,
3582  SemaSYCLRef.getASTContext().getTrivialTypeSourceInfo(To),
3584  }
3585 
3586  void handleGeneratedType(FieldDecl *FD, QualType Ty) {
3587  // Equivalent of the following code is generated here:
3588  // void ocl_kernel(__generated_type GT) {
3589  // Kernel KernelObjClone { *(reinterpret_cast<UsersType*>(&GT)) };
3590  // }
3591 
3592  Expr *RCE = createReinterpretCastExpr(
3593  createGetAddressOf(createParamReferenceExpr()),
3594  SemaSYCLRef.getASTContext().getPointerType(Ty));
3595  Expr *Initializer = createDerefOp(RCE);
3596  addFieldInit(FD, Ty, Initializer);
3597  }
3598 
3599  void handleGeneratedType(const CXXRecordDecl *RD, const CXXBaseSpecifier &BS,
3600  QualType Ty) {
3601  // Equivalent of the following code is generated here:
3602  // void ocl_kernel(__generated_type GT) {
3603  // Kernel KernelObjClone { *(reinterpret_cast<UsersType*>(&GT)) };
3604  // }
3605  Expr *RCE = createReinterpretCastExpr(
3606  createGetAddressOf(createParamReferenceExpr()),
3607  SemaSYCLRef.getASTContext().getPointerType(Ty));
3608  Expr *Initializer = createDerefOp(RCE);
3609  InitializationKind InitKind =
3610  InitializationKind::CreateCopy(KernelCallerSrcLoc, KernelCallerSrcLoc);
3611  addBaseInit(BS, Ty, InitKind, Initializer);
3612  }
3613 
3614  MemberExpr *buildMemberExpr(Expr *Base, ValueDecl *Member) {
3615  DeclAccessPair MemberDAP = DeclAccessPair::make(Member, AS_none);
3616  MemberExpr *Result = SemaSYCLRef.SemaRef.BuildMemberExpr(
3617  Base, /*IsArrow */ false, KernelCallerSrcLoc, NestedNameSpecifierLoc(),
3618  KernelCallerSrcLoc, Member, MemberDAP,
3619  /*HadMultipleCandidates*/ false,
3620  DeclarationNameInfo(Member->getDeclName(), KernelCallerSrcLoc),
3621  Member->getType(), VK_LValue, OK_Ordinary);
3622  return Result;
3623  }
3624 
3625  void addFieldMemberExpr(FieldDecl *FD, QualType Ty) {
3626  if (!isArrayElement(FD, Ty))
3627  MemberExprBases.push_back(buildMemberExpr(MemberExprBases.back(), FD));
3628  }
3629 
3630  void removeFieldMemberExpr(const FieldDecl *FD, QualType Ty) {
3631  if (!isArrayElement(FD, Ty))
3632  MemberExprBases.pop_back();
3633  }
3634 
3635  void createSpecialMethodCall(const CXXRecordDecl *RD, StringRef MethodName,
3636  SmallVectorImpl<Stmt *> &AddTo) {
3637  CXXMethodDecl *Method = getMethodByName(RD, MethodName);
3638  if (!Method)
3639  return;
3640 
3641  unsigned NumParams = Method->getNumParams();
3642  llvm::SmallVector<Expr *, 4> ParamDREs(NumParams);
3643  llvm::ArrayRef<ParmVarDecl *> KernelParameters =
3644  DeclCreator.getParamVarDeclsForCurrentField();
3645  for (size_t I = 0; I < NumParams; ++I) {
3646  QualType ParamType = KernelParameters[I]->getOriginalType();
3647  ParamDREs[I] = SemaSYCLRef.SemaRef.BuildDeclRefExpr(
3648  KernelParameters[I], ParamType, VK_LValue, KernelCallerSrcLoc);
3649  }
3650 
3651  MemberExpr *MethodME = buildMemberExpr(MemberExprBases.back(), Method);
3652 
3653  QualType ResultTy = Method->getReturnType();
3655  ResultTy = ResultTy.getNonLValueExprType(SemaSYCLRef.getASTContext());
3656  llvm::SmallVector<Expr *, 4> ParamStmts;
3657  const auto *Proto = cast<FunctionProtoType>(Method->getType());
3658  SemaSYCLRef.SemaRef.GatherArgumentsForCall(KernelCallerSrcLoc, Method,
3659  Proto, 0, ParamDREs, ParamStmts);
3660  // [kernel_obj or wrapper object].accessor.__init(_ValueType*,
3661  // range<int>, range<int>, id<int>)
3662  AddTo.push_back(CXXMemberCallExpr::Create(
3663  SemaSYCLRef.getASTContext(), MethodME, ParamStmts, ResultTy, VK,
3664  KernelCallerSrcLoc, FPOptionsOverride()));
3665  }
3666 
3667  // Creates an empty InitListExpr of the correct number of child-inits
3668  // of this to append into.
3669  void addCollectionInitListExpr(const CXXRecordDecl *RD) {
3670  const ASTRecordLayout &Info =
3671  SemaSYCLRef.getASTContext().getASTRecordLayout(RD);
3672  uint64_t NumInitExprs = Info.getFieldCount() + RD->getNumBases();
3673  addCollectionInitListExpr(QualType(RD->getTypeForDecl(), 0), NumInitExprs);
3674  }
3675 
3676  InitListExpr *createInitListExpr(const CXXRecordDecl *RD) {
3677  const ASTRecordLayout &Info =
3678  SemaSYCLRef.getASTContext().getASTRecordLayout(RD);
3679  uint64_t NumInitExprs = Info.getFieldCount() + RD->getNumBases();
3680  return createInitListExpr(QualType(RD->getTypeForDecl(), 0), NumInitExprs);
3681  }
3682 
3683  InitListExpr *createInitListExpr(QualType InitTy, uint64_t NumChildInits) {
3684  InitListExpr *ILE = new (SemaSYCLRef.getASTContext())
3685  InitListExpr(SemaSYCLRef.getASTContext(), KernelCallerSrcLoc, {},
3686  KernelCallerSrcLoc);
3687  ILE->reserveInits(SemaSYCLRef.getASTContext(), NumChildInits);
3688  ILE->setType(InitTy);
3689 
3690  return ILE;
3691  }
3692 
3693  // Create an empty InitListExpr of the type/size for the rest of the visitor
3694  // to append into.
3695  void addCollectionInitListExpr(QualType InitTy, uint64_t NumChildInits) {
3696 
3697  InitListExpr *ILE = createInitListExpr(InitTy, NumChildInits);
3698  InitListExpr *ParentILE = CollectionInitExprs.back();
3699  ParentILE->updateInit(SemaSYCLRef.getASTContext(), ParentILE->getNumInits(),
3700  ILE);
3701 
3702  CollectionInitExprs.push_back(ILE);
3703  }
3704 
3705  static VarDecl *createKernelObjClone(ASTContext &Ctx, DeclContext *DC,
3706  const CXXRecordDecl *KernelObj) {
3707  TypeSourceInfo *TSInfo =
3708  KernelObj->isLambda() ? KernelObj->getLambdaTypeInfo() : nullptr;
3709  IdentifierInfo *Ident = KernelObj->getIdentifier();
3710  if (!Ident)
3711  Ident = &Ctx.Idents.get("__SYCLKernel");
3712 
3713  VarDecl *VD = VarDecl::Create(
3714  Ctx, DC, KernelObj->getLocation(), KernelObj->getLocation(), Ident,
3715  QualType(KernelObj->getTypeForDecl(), 0), TSInfo, SC_None);
3716  return VD;
3717  }
3718 
3719  const llvm::StringLiteral getInitMethodName() const {
3720  return IsESIMD ? InitESIMDMethodName : InitMethodName;
3721  }
3722 
3723  // Default inits the type, then calls the init-method in the body.
3724  bool handleSpecialType(FieldDecl *FD, QualType Ty) {
3725  addFieldInit(FD, Ty, std::nullopt,
3726  InitializationKind::CreateDefault(KernelCallerSrcLoc));
3727 
3728  addFieldMemberExpr(FD, Ty);
3729 
3730  const auto *RecordDecl = Ty->getAsCXXRecordDecl();
3731  createSpecialMethodCall(RecordDecl, getInitMethodName(), BodyStmts);
3732  CXXMethodDecl *FinalizeMethod =
3734  // A finalize-method is expected for special type such as stream.
3735  if (FinalizeMethod)
3736  createSpecialMethodCall(RecordDecl, FinalizeMethodName, FinalizeStmts);
3737 
3738  removeFieldMemberExpr(FD, Ty);
3739 
3740  return true;
3741  }
3742 
3743  bool handleSpecialType(const CXXBaseSpecifier &BS, QualType Ty) {
3744  const auto *RecordDecl = Ty->getAsCXXRecordDecl();
3745  addBaseInit(BS, Ty, InitializationKind::CreateDefault(KernelCallerSrcLoc));
3746  createSpecialMethodCall(RecordDecl, getInitMethodName(), BodyStmts);
3747  return true;
3748  }
3749 
3750  // Generate __init call for kernel handler argument
3751  void handleSpecialType(QualType KernelHandlerTy) {
3752  DeclRefExpr *KernelHandlerCloneRef = DeclRefExpr::Create(
3753  SemaSYCLRef.getASTContext(), NestedNameSpecifierLoc(),
3754  KernelCallerSrcLoc, KernelHandlerClone, false, DeclarationNameInfo(),
3755  KernelHandlerTy, VK_LValue);
3756  const auto *RecordDecl =
3757  KernelHandlerClone->getType()->getAsCXXRecordDecl();
3758  MemberExprBases.push_back(KernelHandlerCloneRef);
3759  createSpecialMethodCall(RecordDecl, InitSpecConstantsBuffer, BodyStmts);
3760  MemberExprBases.pop_back();
3761  }
3762 
3763  void createKernelHandlerClone(ASTContext &Ctx, DeclContext *DC,
3764  ParmVarDecl *KernelHandlerArg) {
3765  QualType Ty = KernelHandlerArg->getType();
3766  TypeSourceInfo *TSInfo = Ctx.getTrivialTypeSourceInfo(Ty);
3767  KernelHandlerClone =
3768  VarDecl::Create(Ctx, DC, KernelCallerSrcLoc, KernelCallerSrcLoc,
3769  KernelHandlerArg->getIdentifier(), Ty, TSInfo, SC_None);
3770 
3771  // Default initialize clone
3772  InitializedEntity VarEntity =
3773  InitializedEntity::InitializeVariable(KernelHandlerClone);
3774  InitializationKind InitKind =
3775  InitializationKind::CreateDefault(KernelCallerSrcLoc);
3776  InitializationSequence InitSeq(SemaSYCLRef.SemaRef, VarEntity, InitKind,
3777  std::nullopt);
3778  ExprResult Init =
3779  InitSeq.Perform(SemaSYCLRef.SemaRef, VarEntity, InitKind, std::nullopt);
3780  KernelHandlerClone->setInit(
3781  SemaSYCLRef.SemaRef.MaybeCreateExprWithCleanups(Init.get()));
3782  KernelHandlerClone->setInitStyle(VarDecl::CallInit);
3783  }
3784 
3785  Expr *createArraySubscriptExpr(uint64_t Index, Expr *ArrayRef) {
3786  QualType SizeT = SemaSYCLRef.getASTContext().getSizeType();
3787  llvm::APInt IndexVal{
3788  static_cast<unsigned>(SemaSYCLRef.getASTContext().getTypeSize(SizeT)),
3789  Index, SizeT->isSignedIntegerType()};
3790  auto IndexLiteral = IntegerLiteral::Create(
3791  SemaSYCLRef.getASTContext(), IndexVal, SizeT, KernelCallerSrcLoc);
3792  ExprResult IndexExpr = SemaSYCLRef.SemaRef.CreateBuiltinArraySubscriptExpr(
3793  ArrayRef, KernelCallerSrcLoc, IndexLiteral, KernelCallerSrcLoc);
3794  assert(!IndexExpr.isInvalid());
3795  return IndexExpr.get();
3796  }
3797 
3798  void addSimpleArrayInit(FieldDecl *FD, QualType FieldTy) {
3799  Expr *ArrayRef = createSimpleArrayParamReferenceExpr(FieldTy);
3801 
3802  InitializedEntity Entity =
3803  InitializedEntity::InitializeMember(FD, &VarEntity, /*Implicit*/ true);
3804 
3805  addFieldInit(FD, FieldTy, ArrayRef, InitKind, Entity);
3806  }
3807 
3808  void addArrayElementInit(FieldDecl *FD, QualType T) {
3809  Expr *RCE = createReinterpretCastExpr(
3810  createGetAddressOf(ArrayParamBases.pop_back_val()),
3811  SemaSYCLRef.getASTContext().getPointerType(T));
3812  Expr *Initializer = createDerefOp(RCE);
3813  addFieldInit(FD, T, Initializer);
3814  }
3815 
3816  // This function is recursive in order to handle
3817  // multi-dimensional arrays. If the array element is
3818  // an array, it implies that the array is multi-dimensional.
3819  // We continue recursion till we reach a non-array element to
3820  // generate required array subscript expressions.
3821  void createArrayInit(FieldDecl *FD, QualType T) {
3822  const ConstantArrayType *CAT =
3823  SemaSYCLRef.getASTContext().getAsConstantArrayType(T);
3824 
3825  if (!CAT) {
3826  addArrayElementInit(FD, T);
3827  return;
3828  }
3829 
3830  QualType ET = CAT->getElementType();
3831  uint64_t ElemCount = CAT->getSize().getZExtValue();
3832  enterArray(FD, T, ET);
3833 
3834  for (uint64_t Index = 0; Index < ElemCount; ++Index) {
3835  ArrayInfos.back().second = Index;
3837  createArraySubscriptExpr(Index, ArrayParamBases.back());
3838  ArrayParamBases.push_back(ArraySubscriptExpr);
3839  createArrayInit(FD, ET);
3840  }
3841 
3842  leaveArray(FD, T, ET);
3843  }
3844 
3845  // This function is used to create initializers for a top
3846  // level array which contains pointers. The openCl kernel
3847  // parameter for this array will be a wrapper class
3848  // which contains the generated type. This function generates
3849  // code equivalent to:
3850  // void ocl_kernel(__wrapper_class WrappedGT) {
3851  // Kernel KernelObjClone {
3852  // *reinterpret_cast<UserArrayET*>(&WrappedGT.GeneratedArr[0]),
3853  // *reinterpret_cast<UserArrayET*>(&WrappedGT.GeneratedArr[1]),
3854  // *reinterpret_cast<UserArrayET*>(&WrappedGT.GeneratedArr[2])
3855  // };
3856  // }
3857  void handleGeneratedArrayType(FieldDecl *FD, QualType FieldTy) {
3858  ArrayParamBases.push_back(createSimpleArrayParamReferenceExpr(FieldTy));
3859  createArrayInit(FD, FieldTy);
3860  }
3861 
3862 public:
3863  static constexpr const bool VisitInsideSimpleContainers = false;
3864  SyclKernelBodyCreator(SemaSYCL &S, SyclKernelDeclCreator &DC,
3865  const CXXRecordDecl *KernelObj,
3866  FunctionDecl *KernelCallerFunc, bool IsSIMDKernel,
3867  CXXMethodDecl *CallOperator)
3868  : SyclKernelFieldHandler(S), DeclCreator(DC),
3869  KernelObjClone(createKernelObjClone(S.getASTContext(),
3870  DC.getKernelDecl(), KernelObj)),
3871  VarEntity(InitializedEntity::InitializeVariable(KernelObjClone)),
3872  KernelCallerFunc(KernelCallerFunc),
3873  KernelCallerSrcLoc(KernelCallerFunc->getLocation()),
3874  IsESIMD(IsSIMDKernel), CallOperator(CallOperator) {
3875  CollectionInitExprs.push_back(createInitListExpr(KernelObj));
3876  annotateHierarchicalParallelismAPICalls();
3877 
3878  Stmt *DS = new (S.getASTContext()) DeclStmt(
3879  DeclGroupRef(KernelObjClone), KernelCallerSrcLoc, KernelCallerSrcLoc);
3880  BodyStmts.push_back(DS);
3881  DeclRefExpr *KernelObjCloneRef = DeclRefExpr::Create(
3882  S.getASTContext(), NestedNameSpecifierLoc(), KernelCallerSrcLoc,
3883  KernelObjClone, false, DeclarationNameInfo(),
3884  QualType(KernelObj->getTypeForDecl(), 0), VK_LValue);
3885  MemberExprBases.push_back(KernelObjCloneRef);
3886  }
3887 
3888  ~SyclKernelBodyCreator() {
3889  CompoundStmt *KernelBody = createKernelBody();
3890  DeclCreator.setBody(KernelBody);
3891  }
3892 
3893  bool handleSyclSpecialType(FieldDecl *FD, QualType Ty) final {
3894  return handleSpecialType(FD, Ty);
3895  }
3896 
3897  bool handleSyclSpecialType(const CXXRecordDecl *, const CXXBaseSpecifier &BS,
3898  QualType Ty) final {
3899  return handleSpecialType(BS, Ty);
3900  }
3901 
3902  bool handlePointerType(FieldDecl *FD, QualType FieldTy) final {
3903  Expr *PointerRef =
3904  createPointerParamReferenceExpr(FieldTy, StructDepth != 0);
3905  addFieldInit(FD, FieldTy, PointerRef);
3906  return true;
3907  }
3908 
3909  bool handleSimpleArrayType(FieldDecl *FD, QualType FieldTy) final {
3910  if (FD->hasAttr<SYCLGenerateNewTypeAttr>())
3911  handleGeneratedArrayType(FD, FieldTy);
3912  else
3913  addSimpleArrayInit(FD, FieldTy);
3914  return true;
3915  }
3916 
3917  bool handleNonDecompStruct(const CXXRecordDecl *, FieldDecl *FD,
3918  QualType Ty) final {
3919  CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
3920  assert(RD && "Type must be a C++ record type");
3921  if (RD->hasAttr<SYCLGenerateNewTypeAttr>())
3922  handleGeneratedType(FD, Ty);
3923  else
3924  addSimpleFieldInit(FD, Ty);
3925  return true;
3926  }
3927 
3928  bool handleNonDecompStruct(const CXXRecordDecl *RD,
3929  const CXXBaseSpecifier &BS, QualType Ty) final {
3930  CXXRecordDecl *BaseDecl = Ty->getAsCXXRecordDecl();
3931  assert(BaseDecl && "Type must be a C++ record type");
3932  if (BaseDecl->hasAttr<SYCLGenerateNewTypeAttr>())
3933  handleGeneratedType(RD, BS, Ty);
3934  else
3935  addSimpleBaseInit(BS, Ty);
3936  return true;
3937  }
3938 
3939  bool handleScalarType(FieldDecl *FD, QualType FieldTy) final {
3940  addSimpleFieldInit(FD, FieldTy);
3941  return true;
3942  }
3943 
3944  bool handleUnionType(FieldDecl *FD, QualType FieldTy) final {
3945  addSimpleFieldInit(FD, FieldTy);
3946  return true;
3947  }
3948 
3949  // Default inits the type, then calls the init-method in the body
3950  void handleSyclKernelHandlerType(ParmVarDecl *KernelHandlerArg) {
3951 
3952  // Create and default initialize local clone of kernel handler
3953  createKernelHandlerClone(SemaSYCLRef.getASTContext(),
3954  DeclCreator.getKernelDecl(), KernelHandlerArg);
3955 
3956  // Add declaration statement to openCL kernel body
3957  Stmt *DS = new (SemaSYCLRef.getASTContext())
3958  DeclStmt(DeclGroupRef(KernelHandlerClone), KernelCallerSrcLoc,
3959  KernelCallerSrcLoc);
3960  BodyStmts.push_back(DS);
3961 
3962  // Generate
3963  // KernelHandlerClone.__init_specialization_constants_buffer(specialization_constants_buffer)
3964  // call if target does not have native support for specialization constants.
3965  // Here, specialization_constants_buffer is the compiler generated kernel
3966  // argument of type char*.
3967  if (!isDefaultSPIRArch(SemaSYCLRef.getASTContext()))
3968  handleSpecialType(KernelHandlerArg->getType());
3969  }
3970 
3971  bool enterStruct(const CXXRecordDecl *RD, FieldDecl *FD, QualType Ty) final {
3972  ++StructDepth;
3973  addCollectionInitListExpr(Ty->getAsCXXRecordDecl());
3974 
3975  addFieldMemberExpr(FD, Ty);
3976  return true;
3977  }
3978 
3979  bool leaveStruct(const CXXRecordDecl *, FieldDecl *FD, QualType Ty) final {
3980  --StructDepth;
3981  CollectionInitExprs.pop_back();
3982 
3983  removeFieldMemberExpr(FD, Ty);
3984  return true;
3985  }
3986 
3987  bool enterStruct(const CXXRecordDecl *RD, const CXXBaseSpecifier &BS,
3988  QualType) final {
3989  ++StructDepth;
3990 
3991  CXXCastPath BasePath;
3992  QualType DerivedTy(RD->getTypeForDecl(), 0);
3993  QualType BaseTy = BS.getType();
3995  DerivedTy, BaseTy, KernelCallerSrcLoc, SourceRange(), &BasePath,
3996  /*IgnoreBaseAccess*/ true);
3998  SemaSYCLRef.getASTContext(), BaseTy, CK_DerivedToBase,
3999  MemberExprBases.back(),
4000  /* CXXCastPath=*/&BasePath, VK_LValue, FPOptionsOverride());
4001  MemberExprBases.push_back(Cast);
4002  addCollectionInitListExpr(BaseTy->getAsCXXRecordDecl());
4003  return true;
4004  }
4005 
4006  bool leaveStruct(const CXXRecordDecl *RD, const CXXBaseSpecifier &BS,
4007  QualType) final {
4008  --StructDepth;
4009  MemberExprBases.pop_back();
4010  CollectionInitExprs.pop_back();
4011  return true;
4012  }
4013 
4014  bool enterArray(FieldDecl *FD, QualType ArrayType,
4015  QualType ElementType) final {
4016  const ConstantArrayType *CAT =
4018  assert(CAT && "Should only be called on constant-size array.");
4019  uint64_t ArraySize = CAT->getSize().getZExtValue();
4020  addCollectionInitListExpr(ArrayType, ArraySize);
4021  ArrayInfos.emplace_back(getFieldEntity(FD, ArrayType), 0);
4022 
4023  // If this is the top-level array, we need to make a MemberExpr in addition
4024  // to an array subscript.
4025  addFieldMemberExpr(FD, ArrayType);
4026  return true;
4027  }
4028 
4029  bool nextElement(QualType, uint64_t Index) final {
4030  ArrayInfos.back().second = Index;
4031 
4032  // Pop off the last member expr base.
4033  if (Index != 0)
4034  MemberExprBases.pop_back();
4035 
4036  MemberExprBases.push_back(
4037  createArraySubscriptExpr(Index, MemberExprBases.back()));
4038  return true;
4039  }
4040 
4041  bool leaveArray(FieldDecl *FD, QualType ArrayType,
4042  QualType ElementType) final {
4043  CollectionInitExprs.pop_back();
4044  ArrayInfos.pop_back();
4045 
4046  // Remove the IndexExpr.
4047  if (!FD->hasAttr<SYCLGenerateNewTypeAttr>())
4048  MemberExprBases.pop_back();
4049  else
4050  ArrayParamBases.pop_back();
4051 
4052  // Remove the field access expr as well.
4053  removeFieldMemberExpr(FD, ArrayType);
4054  return true;
4055  }
4056  using SyclKernelFieldHandler::enterArray;
4057  using SyclKernelFieldHandler::enterStruct;
4058  using SyclKernelFieldHandler::handleNonDecompStruct;
4059  using SyclKernelFieldHandler::handlePointerType;
4060  using SyclKernelFieldHandler::handleScalarType;
4061  using SyclKernelFieldHandler::handleSyclSpecialType;
4062  using SyclKernelFieldHandler::handleUnionType;
4063  using SyclKernelFieldHandler::leaveArray;
4064  using SyclKernelFieldHandler::leaveStruct;
4065 };
4066 
4067 class FreeFunctionKernelBodyCreator : public SyclKernelFieldHandler {
4068  SyclKernelDeclCreator &DeclCreator;
4070  FunctionDecl *FreeFunc = nullptr;
4071  SourceLocation FreeFunctionSrcLoc; // Free function source location.
4073 
4074  // Creates a DeclRefExpr to the ParmVar that represents the current free
4075  // function parameter.
4076  Expr *createParamReferenceExpr() {
4077  ParmVarDecl *FreeFunctionParameter =
4078  DeclCreator.getParamVarDeclsForCurrentField()[0];
4079 
4080  QualType FreeFunctionParamType = FreeFunctionParameter->getOriginalType();
4081  Expr *DRE = SemaSYCLRef.SemaRef.BuildDeclRefExpr(
4082  FreeFunctionParameter, FreeFunctionParamType, VK_LValue,
4083  FreeFunctionSrcLoc);
4084  DRE = SemaSYCLRef.SemaRef.DefaultLvalueConversion(DRE).get();
4085  return DRE;
4086  }
4087 
4088  // Creates a DeclRefExpr to the ParmVar that represents the current pointer
4089  // parameter.
4090  Expr *createPointerParamReferenceExpr(QualType PointerTy, bool Wrapped) {
4091  ParmVarDecl *FreeFunctionParameter =
4092  DeclCreator.getParamVarDeclsForCurrentField()[0];
4093 
4094  QualType FreeFunctionParamType = FreeFunctionParameter->getOriginalType();
4095  Expr *DRE = SemaSYCLRef.SemaRef.BuildDeclRefExpr(
4096  FreeFunctionParameter, FreeFunctionParamType, VK_LValue,
4097  FreeFunctionSrcLoc);
4098  DRE = SemaSYCLRef.SemaRef.DefaultLvalueConversion(DRE).get();
4099 
4100  if (PointerTy->getPointeeType().getAddressSpace() !=
4101  FreeFunctionParamType->getPointeeType().getAddressSpace())
4102  DRE = ImplicitCastExpr::Create(SemaSYCLRef.getASTContext(), PointerTy,
4103  CK_AddressSpaceConversion, DRE, nullptr,
4105  return DRE;
4106  }
4107 
4108  // For a free function such as:
4109  // void f(int i, int* p, struct Simple S) { ... }
4110  //
4111  // Keep the function as-is for the version callable from device code.
4112  // void f(int i, int *p, struct Simple S) { ... }
4113  //
4114  // For the host-callable kernel function generate this:
4115  // void __sycl_kernel_f(int __arg_i, int* __arg_p, struct Simple __arg_S)
4116  // {
4117  // f(__arg_i, __arg_p, __arg_S);
4118  // }
4119  CompoundStmt *createFreeFunctionKernelBody() {
4120  SemaSYCLRef.SemaRef.PushFunctionScope();
4121  Expr *Fn = SemaSYCLRef.SemaRef.BuildDeclRefExpr(
4122  FreeFunc, FreeFunc->getType(), VK_LValue, FreeFunctionSrcLoc);
4123  ASTContext &Context = SemaSYCLRef.getASTContext();
4124  QualType ResultTy = FreeFunc->getReturnType();
4126  ResultTy = ResultTy.getNonLValueExprType(Context);
4127  Fn = ImplicitCastExpr::Create(Context,
4128  Context.getPointerType(FreeFunc->getType()),
4129  CK_FunctionToPointerDecay, Fn, nullptr,
4131  auto CallExpr = CallExpr::Create(Context, Fn, ArgExprs, ResultTy, VK,
4132  FreeFunctionSrcLoc, FPOptionsOverride());
4133  BodyStmts.push_back(CallExpr);
4134  return CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(), {},
4135  {});
4136  }
4137 
4138 public:
4139  static constexpr const bool VisitInsideSimpleContainers = false;
4140 
4141  FreeFunctionKernelBodyCreator(SemaSYCL &S, SyclKernelDeclCreator &DC,
4142  FunctionDecl *FF)
4143  : SyclKernelFieldHandler(S), DeclCreator(DC), FreeFunc(FF),
4144  FreeFunctionSrcLoc(FF->getLocation()) {}
4145 
4146  ~FreeFunctionKernelBodyCreator() {
4147  CompoundStmt *KernelBody = createFreeFunctionKernelBody();
4148  DeclCreator.setBody(KernelBody);
4149  }
4150 
4151  bool handleSyclSpecialType(FieldDecl *FD, QualType Ty) final {
4152  // TODO
4154  return true;
4155  }
4156 
4157  bool handleSyclSpecialType(ParmVarDecl *, QualType) final {
4158  // TODO
4160  return true;
4161  }
4162 
4163  bool handleSyclSpecialType(const CXXRecordDecl *, const CXXBaseSpecifier &BS,
4164  QualType Ty) final {
4165  // TODO
4167  return true;
4168  }
4169 
4170  bool handlePointerType(FieldDecl *FD, QualType FieldTy) final {
4171  // TODO
4173  return true;
4174  }
4175 
4176  bool handlePointerType(ParmVarDecl *PD, QualType ParamTy) final {
4177  Expr *PointerRef = createPointerParamReferenceExpr(ParamTy, false);
4178  ArgExprs.push_back(PointerRef);
4179  return true;
4180  }
4181 
4182  bool handleSimpleArrayType(FieldDecl *FD, QualType FieldTy) final {
4183  // TODO
4185  return true;
4186  }
4187 
4188  bool handleNonDecompStruct(const CXXRecordDecl *, FieldDecl *FD,
4189  QualType Ty) final {
4190  // TODO
4192  return true;
4193  }
4194 
4195  bool handleNonDecompStruct(const CXXRecordDecl *, ParmVarDecl *,
4196  QualType) final {
4197  // TODO
4199  return true;
4200  }
4201 
4202  bool handleNonDecompStruct(const CXXRecordDecl *RD,
4203  const CXXBaseSpecifier &BS, QualType Ty) final {
4204  // TODO
4206  return true;
4207  }
4208 
4209  bool handleScalarType(FieldDecl *FD, QualType FieldTy) final {
4210  // TODO
4212  return true;
4213  }
4214 
4215  bool handleScalarType(ParmVarDecl *, QualType) final {
4216  Expr *ParamRef = createParamReferenceExpr();
4217  ArgExprs.push_back(ParamRef);
4218  return true;
4219  }
4220 
4221  bool handleUnionType(FieldDecl *FD, QualType FieldTy) final {
4222  // TODO
4224  return true;
4225  }
4226 
4227  bool handleUnionType(ParmVarDecl *, QualType) final {
4228  // TODO
4230  return true;
4231  }
4232 
4233  bool enterStruct(const CXXRecordDecl *RD, FieldDecl *FD, QualType Ty) final {
4234  // TODO
4236  return true;
4237  }
4238 
4239  bool enterStruct(const CXXRecordDecl *, ParmVarDecl *, QualType) final {
4240  // TODO
4242  return true;
4243  }
4244 
4245  bool leaveStruct(const CXXRecordDecl *, FieldDecl *FD, QualType Ty) final {
4246  // TODO
4248  return true;
4249  }
4250 
4251  bool leaveStruct(const CXXRecordDecl *, ParmVarDecl *, QualType) final {
4252  // TODO
4254  return true;
4255  }
4256 
4257  bool enterStruct(const CXXRecordDecl *RD, const CXXBaseSpecifier &BS,
4258  QualType) final {
4259  // TODO
4261  return true;
4262  }
4263 
4264  bool leaveStruct(const CXXRecordDecl *RD, const CXXBaseSpecifier &BS,
4265  QualType) final {
4266  // TODO
4268  return true;
4269  }
4270 
4271  bool enterArray(FieldDecl *FD, QualType ArrayType,
4272  QualType ElementType) final {
4273  // TODO
4275  return true;
4276  }
4277 
4278  bool enterArray(ParmVarDecl *PD, QualType ArrayType,
4279  QualType ElementType) final {
4280  // TODO
4282  return true;
4283  }
4284 
4285  bool leaveArray(FieldDecl *FD, QualType ArrayType,
4286  QualType ElementType) final {
4287  // TODO
4289  return true;
4290  }
4291 
4292  bool leaveArray(ParmVarDecl *PD, QualType ArrayType,
4293  QualType ElementType) final {
4294  // TODO
4296  return true;
4297  }
4298 };
4299 
4300 // Kernels are only the unnamed-lambda feature if the feature is enabled, AND
4301 // the first template argument has been corrected by the library to match the
4302 // functor type.
4303 static bool IsSYCLUnnamedKernel(SemaSYCL &SemaSYCLRef, const FunctionDecl *FD) {
4304  if (!SemaSYCLRef.getLangOpts().SYCLUnnamedLambda)
4305  return false;
4306 
4307  QualType FunctorTy = GetSYCLKernelObjectType(FD);
4308  QualType TmplArgTy = calculateKernelNameType(SemaSYCLRef.getASTContext(), FD);
4309  return SemaSYCLRef.getASTContext().hasSameType(FunctorTy, TmplArgTy);
4310 }
4311 
4312 class SyclKernelIntHeaderCreator : public SyclKernelFieldHandler {
4313  SYCLIntegrationHeader &Header;
4314  int64_t CurOffset = 0;
4315  llvm::SmallVector<size_t, 16> ArrayBaseOffsets;
4316  int StructDepth = 0;
4317 
4318  // A series of functions to calculate the change in offset based on the type.
4319  int64_t offsetOf(const FieldDecl *FD, QualType ArgTy) const {
4320  return isArrayElement(FD, ArgTy)
4321  ? 0
4322  : SemaSYCLRef.getASTContext().getFieldOffset(FD) / 8;
4323  }
4324  // For free functions each parameter is stand-alone, so offsets within a
4325  // lambda/function object are not relevant. Therefore offsetOf will always be
4326  // 0.
4327  int64_t offsetOf(const ParmVarDecl *, QualType) const { return 0; }
4328 
4329  int64_t offsetOf(const CXXRecordDecl *RD, const CXXRecordDecl *Base) const {
4330  const ASTRecordLayout &Layout =
4331  SemaSYCLRef.getASTContext().getASTRecordLayout(RD);
4332  return Layout.getBaseClassOffset(Base).getQuantity();
4333  }
4334 
4335  void addParam(const FieldDecl *FD, QualType ArgTy,
4337  addParam(ArgTy, Kind, offsetOf(FD, ArgTy));
4338  }
4339 
4340  // For free functions we increment the current offset as each parameter is
4341  // added.
4342  void addParam(const ParmVarDecl *PD, QualType ParamTy,
4344  addParam(ParamTy, Kind, offsetOf(PD, ParamTy));
4345  CurOffset +=
4346  SemaSYCLRef.getASTContext().getTypeSizeInChars(ParamTy).getQuantity();
4347  }
4348 
4349  void addParam(QualType ParamTy,
4351  uint64_t OffsetAdj) {
4352  uint64_t Size;
4353  Size =
4354  SemaSYCLRef.getASTContext().getTypeSizeInChars(ParamTy).getQuantity();
4355  Header.addParamDesc(Kind, static_cast<unsigned>(Size),
4356  static_cast<unsigned>(CurOffset + OffsetAdj));
4357  }
4358 
4359 public:
4360  static constexpr const bool VisitInsideSimpleContainers = false;
4361  SyclKernelIntHeaderCreator(bool IsESIMD, SemaSYCL &S,
4363  const CXXRecordDecl *KernelObj, QualType NameType,
4364  FunctionDecl *KernelFunc)
4365  : SyclKernelFieldHandler(S), Header(H) {
4366 
4367  // The header needs to access the kernel object size.
4368  int64_t ObjSize = SemaSYCLRef.getASTContext()
4369  .getTypeSizeInChars(KernelObj->getTypeForDecl())
4370  .getQuantity();
4371  Header.startKernel(KernelFunc, NameType, KernelObj->getLocation(), IsESIMD,
4372  IsSYCLUnnamedKernel(S, KernelFunc), ObjSize);
4373  }
4374 
4375  SyclKernelIntHeaderCreator(SemaSYCL &S, SYCLIntegrationHeader &H,
4376  QualType NameType, FunctionDecl *FreeFunc)
4377  : SyclKernelFieldHandler(S), Header(H) {
4378  Header.startKernel(FreeFunc, NameType, FreeFunc->getLocation(),
4379  false /*IsESIMD*/, true /*IsSYCLUnnamedKernel*/,
4380  0 /*ObjSize*/);
4381  }
4382 
4383  bool handleSyclSpecialType(const CXXRecordDecl *RD,
4384  const CXXBaseSpecifier &BC,
4385  QualType FieldTy) final {
4386  const auto *AccTy =
4387  cast<ClassTemplateSpecializationDecl>(FieldTy->getAsRecordDecl());
4388  assert(AccTy->getTemplateArgs().size() >= 2 &&
4389  "Incorrect template args for Accessor Type");
4390  int Dims = static_cast<int>(
4391  AccTy->getTemplateArgs()[1].getAsIntegral().getExtValue());
4392  int Info = getAccessTarget(FieldTy, AccTy) | (Dims << 11);
4394  CurOffset +
4395  offsetOf(RD, BC.getType()->getAsCXXRecordDecl()));
4396  return true;
4397  }
4398 
4399  bool handleSyclSpecialType(FieldDecl *FD, QualType FieldTy) final {
4400  const auto *ClassTy = FieldTy->getAsCXXRecordDecl();
4401  assert(ClassTy && "Type must be a C++ record type");
4402  if (isSyclAccessorType(FieldTy)) {
4403  const auto *AccTy =
4404  cast<ClassTemplateSpecializationDecl>(FieldTy->getAsRecordDecl());
4405  assert(AccTy->getTemplateArgs().size() >= 2 &&
4406  "Incorrect template args for Accessor Type");
4407  int Dims = static_cast<int>(
4408  AccTy->getTemplateArgs()[1].getAsIntegral().getExtValue());
4409  int Info = getAccessTarget(FieldTy, AccTy) | (Dims << 11);
4410 
4412  CurOffset + offsetOf(FD, FieldTy));
4413  } else if (SemaSYCL::isSyclType(FieldTy, SYCLTypeAttr::stream)) {
4414  addParam(FD, FieldTy, SYCLIntegrationHeader::kind_stream);
4415  } else if (SemaSYCL::isSyclType(FieldTy, SYCLTypeAttr::sampler) ||
4416  SemaSYCL::isSyclType(FieldTy, SYCLTypeAttr::annotated_ptr) ||
4417  SemaSYCL::isSyclType(FieldTy, SYCLTypeAttr::annotated_arg)) {
4418  CXXMethodDecl *InitMethod = getMethodByName(ClassTy, InitMethodName);
4419  assert(InitMethod && "type must have __init method");
4420  const ParmVarDecl *InitArg = InitMethod->getParamDecl(0);
4421  assert(InitArg && "Init method must have arguments");
4422  QualType T = InitArg->getType();
4424  SemaSYCL::isSyclType(FieldTy, SYCLTypeAttr::sampler)
4428  addParam(T, ParamKind, offsetOf(FD, FieldTy));
4429  } else {
4430  llvm_unreachable(
4431  "Unexpected SYCL special class when generating integration header");
4432  }
4433  return true;
4434  }
4435 
4436  bool handleSyclSpecialType(ParmVarDecl *, QualType) final {
4437  // TODO
4439  return true;
4440  }
4441 
4442  bool handlePointerType(FieldDecl *FD, QualType FieldTy) final {
4443  addParam(FD, FieldTy,
4446  return true;
4447  }
4448 
4449  bool handlePointerType(ParmVarDecl *PD, QualType ParamTy) final {
4450  addParam(PD, ParamTy, SYCLIntegrationHeader::kind_pointer);
4451  return true;
4452  }
4453 
4454  bool handleScalarType(FieldDecl *FD, QualType FieldTy) final {
4455  addParam(FD, FieldTy, SYCLIntegrationHeader::kind_std_layout);
4456  return true;
4457  }
4458 
4459  bool handleScalarType(ParmVarDecl *PD, QualType ParamTy) final {
4460  addParam(PD, ParamTy, SYCLIntegrationHeader::kind_std_layout);
4461  return true;
4462  }
4463 
4464  bool handleSimpleArrayType(FieldDecl *FD, QualType FieldTy) final {
4465  // Arrays are always wrapped inside of structs, so just treat it as a simple
4466  // struct.
4467  addParam(FD, FieldTy, SYCLIntegrationHeader::kind_std_layout);
4468  return true;
4469  }
4470 
4471  bool handleNonDecompStruct(const CXXRecordDecl *, FieldDecl *FD,
4472  QualType Ty) final {
4473  addParam(FD, Ty, SYCLIntegrationHeader::kind_std_layout);
4474  return true;
4475  }
4476 
4477  bool handleNonDecompStruct(const CXXRecordDecl *, ParmVarDecl *PD,
4478  QualType ParamTy) final {
4479  // TODO
4481  return true;
4482  }
4483 
4484  bool handleNonDecompStruct(const CXXRecordDecl *Base,
4485  const CXXBaseSpecifier &, QualType Ty) final {
4487  offsetOf(Base, Ty->getAsCXXRecordDecl()));
4488  return true;
4489  }
4490 
4491  bool handleUnionType(FieldDecl *FD, QualType FieldTy) final {
4492  return handleScalarType(FD, FieldTy);
4493  }
4494 
4495  bool handleUnionType(ParmVarDecl *PD, QualType ParamTy) final {
4496  // TODO
4498  return true;
4499  }
4500 
4501  void handleSyclKernelHandlerType(QualType Ty) {
4502  // The compiler generated kernel argument used to initialize SYCL 2020
4503  // specialization constants, `specialization_constants_buffer`, should
4504  // have corresponding entry in integration header.
4505  ASTContext &Context = SemaSYCLRef.getASTContext();
4506  // Offset is zero since kernel_handler argument is not part of
4507  // kernel object (i.e. it is not captured)
4508  addParam(Context.getPointerType(Context.CharTy),
4510  }
4511 
4512  bool enterStruct(const CXXRecordDecl *, FieldDecl *FD, QualType Ty) final {
4513  ++StructDepth;
4514  CurOffset += offsetOf(FD, Ty);
4515  return true;
4516  }
4517 
4518  bool enterStruct(const CXXRecordDecl *, ParmVarDecl *, QualType) final {
4519  // TODO
4521  return true;
4522  }
4523 
4524  bool leaveStruct(const CXXRecordDecl *, FieldDecl *FD, QualType Ty) final {
4525  --StructDepth;
4526  CurOffset -= offsetOf(FD, Ty);
4527  return true;
4528  }
4529 
4530  bool leaveStruct(const CXXRecordDecl *, ParmVarDecl *, QualType) final {
4531  // TODO
4533  return true;
4534  }
4535 
4536  bool enterStruct(const CXXRecordDecl *RD, const CXXBaseSpecifier &BS,
4537  QualType) final {
4538  CurOffset += offsetOf(RD, BS.getType()->getAsCXXRecordDecl());
4539  return true;
4540  }
4541 
4542  bool leaveStruct(const CXXRecordDecl *RD, const CXXBaseSpecifier &BS,
4543  QualType) final {
4544  CurOffset -= offsetOf(RD, BS.getType()->getAsCXXRecordDecl());
4545  return true;
4546  }
4547 
4548  bool enterArray(FieldDecl *FD, QualType ArrayTy, QualType) final {
4549  ArrayBaseOffsets.push_back(CurOffset + offsetOf(FD, ArrayTy));
4550  return true;
4551  }
4552 
4553  bool enterArray(ParmVarDecl *PD, QualType ArrayTy, QualType) final {
4554  // TODO
4556  return true;
4557  }
4558 
4559  bool nextElement(QualType ET, uint64_t Index) final {
4560  int64_t Size =
4561  SemaSYCLRef.getASTContext().getTypeSizeInChars(ET).getQuantity();
4562  CurOffset = ArrayBaseOffsets.back() + Size * Index;
4563  return true;
4564  }
4565 
4566  bool leaveArray(FieldDecl *FD, QualType ArrayTy, QualType) final {
4567  CurOffset = ArrayBaseOffsets.pop_back_val();
4568  CurOffset -= offsetOf(FD, ArrayTy);
4569  return true;
4570  }
4571 
4572  bool leaveArray(ParmVarDecl *PD, QualType ArrayTy, QualType) final {
4573  // TODO
4575  return true;
4576  }
4577 
4578  using SyclKernelFieldHandler::enterStruct;
4579  using SyclKernelFieldHandler::leaveStruct;
4580 };
4581 
4582 class SyclKernelIntFooterCreator : public SyclKernelFieldHandler {
4583  SYCLIntegrationFooter &Footer;
4584 
4585 public:
4586  SyclKernelIntFooterCreator(SemaSYCL &S, SYCLIntegrationFooter &F)
4587  : SyclKernelFieldHandler(S), Footer(F) {
4588  (void)Footer; // workaround for unused field warning
4589  }
4590 };
4591 
4592 } // namespace
4593 
4595  : public TypeVisitor<SYCLKernelNameTypeVisitor>,
4596  public ConstTemplateArgumentVisitor<SYCLKernelNameTypeVisitor> {
4597  SemaSYCL &S;
4598  SourceLocation KernelInvocationFuncLoc;
4599  QualType KernelNameType;
4601  using InnerTemplArgVisitor =
4603  bool IsInvalid = false;
4604  bool IsUnnamedKernel = false;
4605 
4606  void VisitTemplateArgs(ArrayRef<TemplateArgument> Args) {
4607  for (auto &A : Args)
4608  Visit(A);
4609  }
4610 
4611 public:
4613  QualType KernelNameType, bool IsUnnamedKernel)
4614  : S(S), KernelInvocationFuncLoc(KernelInvocationFuncLoc),
4615  KernelNameType(KernelNameType), IsUnnamedKernel(IsUnnamedKernel) {}
4616 
4617  bool isValid() { return !IsInvalid; }
4618 
4619  void Visit(QualType T) {
4620  if (T.isNull())
4621  return;
4622 
4623  const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
4624  // If KernelNameType has template args visit each template arg via
4625  // ConstTemplateArgumentVisitor
4626  if (const auto *TSD =
4627  dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD)) {
4628  ArrayRef<TemplateArgument> Args = TSD->getTemplateArgs().asArray();
4629 
4630  VisitTemplateArgs(Args);
4631  } else {
4632  InnerTypeVisitor::Visit(T.getTypePtr());
4633  }
4634  }
4635 
4636  void Visit(const TemplateArgument &TA) {
4637  if (TA.isNull())
4638  return;
4639  InnerTemplArgVisitor::Visit(TA);
4640  }
4641 
4642  void VisitBuiltinType(const BuiltinType *TT) {
4643  if (TT->isNullPtrType()) {
4644  S.Diag(KernelInvocationFuncLoc, diag::err_nullptr_t_type_in_sycl_kernel)
4645  << KernelNameType;
4646 
4647  IsInvalid = true;
4648  }
4649  return;
4650  }
4651 
4652  void VisitTagType(const TagType *TT) {
4653  return DiagnoseKernelNameType(TT->getDecl());
4654  }
4655 
4656  void DiagnoseKernelNameType(const NamedDecl *DeclNamed) {
4657  /*
4658  This is a helper function which throws an error if the kernel name
4659  declaration is:
4660  * declared within namespace 'std' (at any level)
4661  e.g., namespace std { namespace literals { class Whatever; } }
4662  h.single_task<std::literals::Whatever>([]() {});
4663  * declared within a function
4664  e.g., void foo() { struct S { int i; };
4665  h.single_task<S>([]() {}); }
4666  * declared within another tag
4667  e.g., struct S { struct T { int i } t; };
4668  h.single_task<S::T>([]() {});
4669  */
4670 
4671  if (const auto *ED = dyn_cast<EnumDecl>(DeclNamed)) {
4672  if (!ED->isScoped() && !ED->isFixed()) {
4673  S.Diag(KernelInvocationFuncLoc, diag::err_sycl_kernel_incorrectly_named)
4674  << /* unscoped enum requires fixed underlying type */ 1
4675  << DeclNamed;
4676  IsInvalid = true;
4677  }
4678  }
4679 
4680  const DeclContext *DeclCtx = DeclNamed->getDeclContext();
4681  if (DeclCtx && !IsUnnamedKernel) {
4682 
4683  // Check if the kernel name declaration is declared within namespace
4684  // "std" (at any level).
4685  while (!DeclCtx->isTranslationUnit() && isa<NamespaceDecl>(DeclCtx)) {
4686  const auto *NSDecl = cast<NamespaceDecl>(DeclCtx);
4687  if (NSDecl->isStdNamespace()) {
4688  S.Diag(KernelInvocationFuncLoc,
4689  diag::err_invalid_std_type_in_sycl_kernel)
4690  << KernelNameType << DeclNamed;
4691  IsInvalid = true;
4692  return;
4693  }
4694  DeclCtx = DeclCtx->getParent();
4695  }
4696 
4697  // Check if the kernel name is a Tag declaration
4698  // local to a non-namespace scope (i.e. Inside a function or within
4699  // another Tag etc).
4700  if (!DeclCtx->isTranslationUnit() && !isa<NamespaceDecl>(DeclCtx)) {
4701  if (const auto *Tag = dyn_cast<TagDecl>(DeclNamed)) {
4702  bool UnnamedLambdaUsed = Tag->getIdentifier() == nullptr;
4703 
4704  if (UnnamedLambdaUsed) {
4705  S.Diag(KernelInvocationFuncLoc,
4706  diag::err_sycl_kernel_incorrectly_named)
4707  << /* unnamed type is invalid */ 2 << KernelNameType;
4708  IsInvalid = true;
4709  return;
4710  }
4711 
4712  // Diagnose used types without complete definition i.e.
4713  // int main() {
4714  // class KernelName1;
4715  // parallel_for<class KernelName1>(..);
4716  // }
4717  // This case can only be diagnosed during host compilation because the
4718  // integration header is required to distinguish between the invalid
4719  // code (above) and the following valid code:
4720  // int main() {
4721  // parallel_for<class KernelName2>(..);
4722  // }
4723  // The device compiler forward declares both KernelName1 and
4724  // KernelName2 in the integration header as ::KernelName1 and
4725  // ::KernelName2. The problem with the former case is the additional
4726  // declaration 'class KernelName1' in non-global scope. Lookup in this
4727  // case will resolve to ::main::KernelName1 (instead of
4728  // ::KernelName1). Since this is not visible to runtime code that
4729  // submits kernels, this is invalid.
4730  if (Tag->isCompleteDefinition() ||
4731  S.getLangOpts().SYCLEnableIntHeaderDiags) {
4732  S.Diag(KernelInvocationFuncLoc,
4733  diag::err_sycl_kernel_incorrectly_named)
4734  << /* kernel name should be forward declarable at namespace
4735  scope */
4736  0 << KernelNameType;
4737  IsInvalid = true;
4738  } else {
4739  S.Diag(KernelInvocationFuncLoc, diag::warn_sycl_implicit_decl);
4740  S.Diag(DeclNamed->getLocation(), diag::note_previous_decl)
4741  << DeclNamed->getName();
4742  }
4743  }
4744  }
4745  }
4746  }
4747 
4749  QualType T = TA.getAsType();
4750  if (const auto *ET = T->getAs<EnumType>())
4751  VisitTagType(ET);
4752  else
4753  Visit(T);
4754  }
4755 
4757  QualType T = TA.getIntegralType();
4758  if (const EnumType *ET = T->getAs<EnumType>())
4759  VisitTagType(ET);
4760  }
4761 
4764  assert(TD && "template declaration must be available");
4765  TemplateParameterList *TemplateParams = TD->getTemplateParameters();
4766  for (NamedDecl *P : *TemplateParams) {
4768  dyn_cast<NonTypeTemplateParmDecl>(P))
4769  if (const EnumType *ET = TemplateParam->getType()->getAs<EnumType>())
4770  VisitTagType(ET);
4771  }
4772  }
4773 
4775  VisitTemplateArgs(TA.getPackAsArray());
4776  }
4777 };
4778 
4780  ArrayRef<const Expr *> Args) {
4781  QualType KernelNameType =
4782  calculateKernelNameType(getASTContext(), KernelFunc);
4783  SYCLKernelNameTypeVisitor KernelNameTypeVisitor(
4784  *this, Args[0]->getExprLoc(), KernelNameType,
4785  IsSYCLUnnamedKernel(*this, KernelFunc));
4786  KernelNameTypeVisitor.Visit(KernelNameType.getCanonicalType());
4787 
4788  // FIXME: In place until the library works around its 'host' invocation
4789  // issues.
4790  if (!SemaRef.LangOpts.SYCLIsDevice)
4791  return;
4792 
4793  const CXXRecordDecl *KernelObj =
4795 
4796  if (!KernelObj || (KernelObj && !KernelObj->hasDefinition())) {
4797  Diag(Args[0]->getExprLoc(), diag::err_sycl_kernel_not_function_object);
4798  KernelFunc->setInvalidDecl();
4799  return;
4800  }
4801 
4802  if (KernelObj->isLambda()) {
4803  for (const LambdaCapture &LC : KernelObj->captures())
4804  if (LC.capturesThis() && LC.isImplicit()) {
4805  Diag(LC.getLocation(), diag::err_implicit_this_capture);
4806  KernelFunc->setInvalidDecl();
4807  }
4808  }
4809 
4810  // check that calling kernel conforms to spec
4811  QualType KernelParamTy = KernelFunc->getParamDecl(0)->getType();
4812  if (KernelParamTy->isReferenceType()) {
4813  // passing by reference, so emit warning if not using SYCL 2020
4814  if (SemaRef.LangOpts.getSYCLVersion() < LangOptions::SYCL_2020)
4815  Diag(KernelFunc->getLocation(), diag::warn_sycl_pass_by_reference_future);
4816  } else {
4817  // passing by value. emit warning if using SYCL 2020 or greater
4818  if (SemaRef.LangOpts.getSYCLVersion() > LangOptions::SYCL_2017)
4819  Diag(KernelFunc->getLocation(), diag::warn_sycl_pass_by_value_deprecated);
4820  }
4821 
4822  // Do not visit invalid kernel object.
4823  if (KernelObj->isInvalidDecl())
4824  return;
4825 
4826  SyclKernelDecompMarker DecompMarker(*this);
4827  SyclKernelFieldChecker FieldChecker(*this);
4828  SyclKernelUnionChecker UnionChecker(*this);
4829 
4830  KernelObjVisitor Visitor{*this};
4831 
4832  DiagnosingSYCLKernel = true;
4833 
4834  // Emit diagnostics for SYCL device kernels only
4835  Visitor.VisitRecordBases(KernelObj, FieldChecker, UnionChecker, DecompMarker);
4836  Visitor.VisitRecordFields(KernelObj, FieldChecker, UnionChecker,
4837  DecompMarker);
4838 
4839  DiagnosingSYCLKernel = false;
4840  // Set the kernel function as invalid, if any of the checkers fail validation.
4841  if (!FieldChecker.isValid() || !UnionChecker.isValid() ||
4842  !KernelNameTypeVisitor.isValid())
4843  KernelFunc->setInvalidDecl();
4844 }
4845 
4846 // For a wrapped parallel_for, copy attributes from original
4847 // kernel to wrapped kernel.
4849  // Get the operator() function of the wrapper.
4850  assert(CallOperator && "invalid kernel object");
4851 
4852  typedef std::pair<FunctionDecl *, FunctionDecl *> ChildParentPair;
4855  WorkList.push_back({CallOperator, nullptr});
4856  FunctionDecl *KernelBody = nullptr;
4857 
4858  CallGraph SYCLCG;
4859  SYCLCG.addToCallGraph(CallOperator);
4860  while (!WorkList.empty()) {
4861  FunctionDecl *FD = WorkList.back().first;
4862  FunctionDecl *ParentFD = WorkList.back().second;
4863 
4864  if ((ParentFD == CallOperator) && isSYCLKernelBodyFunction(FD)) {
4865  KernelBody = FD;
4866  break;
4867  }
4868 
4869  WorkList.pop_back();
4870  if (!Visited.insert(FD).second)
4871  continue; // We've already seen this Decl
4872 
4873  CallGraphNode *N = SYCLCG.getNode(FD);
4874  if (!N)
4875  continue;
4876 
4877  for (const CallGraphNode *CI : *N) {
4878  if (auto *Callee = dyn_cast<FunctionDecl>(CI->getDecl())) {
4879  Callee = Callee->getMostRecentDecl();
4880  if (!Visited.count(Callee))
4881  WorkList.push_back({Callee, FD});
4882  }
4883  }
4884  }
4885 
4886  assert(KernelBody && "improper parallel_for wrap");
4887  if (KernelBody) {
4889  collectSYCLAttributes(*this, KernelBody, Attrs, /*DirectlyCalled*/ true);
4890  if (!Attrs.empty())
4891  llvm::for_each(Attrs,
4892  [CallOperator](Attr *A) { CallOperator->addAttr(A); });
4893  }
4894 }
4895 
4897  std::unique_ptr<MangleContext> MangleCtx(
4898  getASTContext().createMangleContext());
4899  // We assume the list of KernelDescs is the complete list of kernels needing
4900  // to be rewritten.
4901  for (const std::pair<const FunctionDecl *, FunctionDecl *> &Pair :
4902  SyclKernelsToOpenCLKernels) {
4903  std::string CalculatedName, StableName;
4904  StringRef KernelName;
4905  if (isFreeFunction(*this, Pair.first)) {
4906  std::tie(CalculatedName, StableName) =
4907  constructFreeFunctionKernelName(*this, Pair.first, *MangleCtx);
4908  KernelName = CalculatedName;
4909  } else {
4910  std::tie(CalculatedName, StableName) =
4911  constructKernelName(*this, Pair.first, *MangleCtx);
4912  KernelName =
4913  IsSYCLUnnamedKernel(*this, Pair.first) ? StableName : CalculatedName;
4914  }
4915 
4916  getSyclIntegrationHeader().updateKernelNames(Pair.first, KernelName,
4917  StableName);
4918 
4919  // Set name of generated kernel.
4920  Pair.second->setDeclName(&getASTContext().Idents.get(KernelName));
4921  // Update the AsmLabel for this generated kernel.
4922  Pair.second->addAttr(
4923  AsmLabelAttr::CreateImplicit(getASTContext(), KernelName));
4924  }
4925 }
4926 
4927 // Generates the OpenCL kernel using KernelCallerFunc (kernel caller
4928 // function) defined is SYCL headers.
4929 // Generated OpenCL kernel contains the body of the kernel caller function,
4930 // receives OpenCL like parameters and additionally does some manipulation to
4931 // initialize captured lambda/functor fields with these parameters.
4932 // SYCL runtime marks kernel caller function with sycl_kernel attribute.
4933 // To be able to generate OpenCL kernel from KernelCallerFunc we put
4934 // the following requirements to the function which SYCL runtime can mark with
4935 // sycl_kernel attribute:
4936 // - Must be template function with at least two template parameters.
4937 // First parameter must represent "unique kernel name"
4938 // Second parameter must be the function object type
4939 // - Must have only one function parameter - function object.
4940 //
4941 // Example of kernel caller function:
4942 // template <typename KernelName, typename KernelType/*, ...*/>
4943 // __attribute__((sycl_kernel)) void kernel_caller_function(KernelType
4944 // KernelFuncObj) {
4945 // KernelFuncObj();
4946 // }
4947 //
4948 //
4950  MangleContext &MC) {
4951  // The first argument to the KernelCallerFunc is the lambda object.
4952  const CXXRecordDecl *KernelObj =
4953  GetSYCLKernelObjectType(KernelCallerFunc)->getAsCXXRecordDecl();
4954  assert(KernelObj && "invalid kernel caller");
4955 
4956  // Do not visit invalid kernel object.
4957  if (KernelObj->isInvalidDecl())
4958  return;
4959 
4960  KernelCallOperatorVisitor KernelCallOperator(KernelCallerFunc, KernelObj);
4961  CXXMethodDecl *CallOperator = nullptr;
4962 
4963  if (KernelObj->isLambda())
4964  CallOperator = KernelObj->getLambdaCallOperator();
4965  else
4966  CallOperator = KernelCallOperator.getCallOperator();
4967 
4968  {
4969  // Do enough to calculate the StableName for the purposes of the hackery
4970  // below for __pf_kernel_wrapper. Placed in a scope so that we don't
4971  // accidentially use these values below, before the names are stabililzed.
4972  std::string CalculatedName, StableName;
4973  std::tie(CalculatedName, StableName) =
4974  constructKernelName(*this, KernelCallerFunc, MC);
4975 
4976  // Attributes of a user-written SYCL kernel must be copied to the internally
4977  // generated alternative kernel, identified by a known string in its name.
4978  if (StableName.find("__pf_kernel_wrapper") != std::string::npos)
4979  copySYCLKernelAttrs(CallOperator);
4980  }
4981 
4982  bool IsSIMDKernel = isESIMDKernelType(CallOperator);
4983 
4984  SyclKernelArgsSizeChecker argsSizeChecker(*this, KernelObj->getLocation(),
4985  IsSIMDKernel);
4986  ESIMDKernelDiagnostics esimdKernel(*this, KernelObj->getLocation(),
4987  IsSIMDKernel);
4988 
4989  SyclKernelDeclCreator kernel_decl(*this, KernelObj->getLocation(),
4990  KernelCallerFunc->isInlined(), IsSIMDKernel,
4991  false /*IsFreeFunction*/, KernelCallerFunc);
4992  SyclKernelBodyCreator kernel_body(*this, kernel_decl, KernelObj,
4993  KernelCallerFunc, IsSIMDKernel,
4994  CallOperator);
4995  SyclKernelIntHeaderCreator int_header(
4996  IsSIMDKernel, *this, getSyclIntegrationHeader(), KernelObj,
4997  calculateKernelNameType(getASTContext(), KernelCallerFunc),
4998  KernelCallerFunc);
4999 
5000  SyclKernelIntFooterCreator int_footer(*this, getSyclIntegrationFooter());
5001  SyclOptReportCreator opt_report(*this, kernel_decl, KernelObj->getLocation());
5002 
5003  KernelObjVisitor Visitor{*this};
5004 
5005  // Visit handlers to generate information for optimization record only if
5006  // optimization record is saved.
5007  if (!getLangOpts().OptRecordFile.empty()) {
5008  Visitor.VisitRecordBases(KernelObj, argsSizeChecker, esimdKernel,
5009  kernel_decl, kernel_body, int_header, int_footer,
5010  opt_report);
5011  Visitor.VisitRecordFields(KernelObj, argsSizeChecker, esimdKernel,
5012  kernel_decl, kernel_body, int_header, int_footer,
5013  opt_report);
5014  } else {
5015  Visitor.VisitRecordBases(KernelObj, argsSizeChecker, esimdKernel,
5016  kernel_decl, kernel_body, int_header, int_footer);
5017  Visitor.VisitRecordFields(KernelObj, argsSizeChecker, esimdKernel,
5018  kernel_decl, kernel_body, int_header, int_footer);
5019  }
5020 
5021  if (ParmVarDecl *KernelHandlerArg =
5022  getSyclKernelHandlerArg(KernelCallerFunc)) {
5023  kernel_decl.handleSyclKernelHandlerType();
5024  kernel_body.handleSyclKernelHandlerType(KernelHandlerArg);
5025  int_header.handleSyclKernelHandlerType(KernelHandlerArg->getType());
5026 
5027  if (!getLangOpts().OptRecordFile.empty())
5028  opt_report.handleSyclKernelHandlerType();
5029  }
5030 }
5031 
5033  SyclKernelArgsSizeChecker argsSizeChecker(SemaSYCLRef, FD->getLocation(),
5034  false /*IsSIMDKernel*/);
5035  SyclKernelDeclCreator kernel_decl(SemaSYCLRef, FD->getLocation(),
5036  FD->isInlined(), false /*IsSIMDKernel */,
5037  true /*IsFreeFunction*/, FD);
5038 
5039  FreeFunctionKernelBodyCreator kernel_body(SemaSYCLRef, kernel_decl, FD);
5040 
5041  SyclKernelIntHeaderCreator int_header(
5042  SemaSYCLRef, SemaSYCLRef.getSyclIntegrationHeader(), FD->getType(), FD);
5043 
5044  SyclKernelIntFooterCreator int_footer(SemaSYCLRef,
5045  SemaSYCLRef.getSyclIntegrationFooter());
5046  KernelObjVisitor Visitor{SemaSYCLRef};
5047 
5048  Visitor.VisitFunctionParameters(FD, argsSizeChecker, kernel_decl, kernel_body,
5049  int_header, int_footer);
5050 };
5051 
5052 // Figure out the sub-group for the this function. First we check the
5053 // attributes, then the global settings.
5054 static std::pair<LangOptions::SubGroupSizeType, int64_t>
5056  const FunctionDecl *FD) {
5057  if (const auto *A = FD->getAttr<IntelReqdSubGroupSizeAttr>()) {
5058  int64_t Val = getIntExprValue(A->getValue(), Ctx);
5060  }
5061 
5062  if (const auto *A = FD->getAttr<IntelNamedSubGroupSizeAttr>()) {
5063  if (A->getType() == IntelNamedSubGroupSizeAttr::Primary)
5066  }
5067 
5068  // Return the global settings.
5069  return {LO.getDefaultSubGroupSizeType(),
5070  static_cast<uint64_t>(LO.DefaultSubGroupSize)};
5071 }
5072 
5074  if (const auto *A = FD->getAttr<IntelReqdSubGroupSizeAttr>())
5075  return A->getLocation();
5076  if (const auto *A = FD->getAttr<IntelNamedSubGroupSizeAttr>())
5077  return A->getLocation();
5078  return SourceLocation{};
5079 }
5080 
5082  const FunctionDecl *FD) {
5083  // If they are the same, no error.
5084  if (CalcEffectiveSubGroup(S.getASTContext(), S.getLangOpts(), SYCLKernel) ==
5086  return;
5087 
5088  // No need to validate __spirv routines here since they
5089  // are mapped to the equivalent SPIRV operations.
5090  const IdentifierInfo *II = FD->getIdentifier();
5091  if (II && II->getName().starts_with("__spirv_"))
5092  return;
5093 
5094  // Else we need to figure out why they don't match.
5095  SourceLocation FDAttrLoc = GetSubGroupLoc(FD);
5096  SourceLocation KernelAttrLoc = GetSubGroupLoc(SYCLKernel);
5097 
5098  if (FDAttrLoc.isValid()) {
5099  // This side was caused by an attribute.
5100  S.Diag(FDAttrLoc, diag::err_sycl_mismatch_group_size)
5101  << /*kernel called*/ 0;
5102 
5103  if (KernelAttrLoc.isValid()) {
5104  S.Diag(KernelAttrLoc, diag::note_conflicting_attribute);
5105  } else {
5106  // Kernel is 'default'.
5107  S.Diag(SYCLKernel->getLocation(), diag::note_sycl_kernel_declared_here);
5108  }
5109  return;
5110  }
5111 
5112  // Else this doesn't have an attribute, which can only be caused by this being
5113  // an undefined SYCL_EXTERNAL, and the kernel has an attribute that conflicts.
5114  if (const auto *A = SYCLKernel->getAttr<IntelReqdSubGroupSizeAttr>()) {
5115  // Don't diagnose this if the kernel got its size from the 'old' attribute
5116  // spelling.
5117  if (!A->isSYCL2020Spelling())
5118  return;
5119  }
5120 
5121  assert(KernelAttrLoc.isValid() && "Kernel doesn't have attribute either?");
5122  S.Diag(FD->getLocation(), diag::err_sycl_mismatch_group_size)
5123  << /*undefined SYCL_EXTERNAL*/ 1;
5124  S.Diag(KernelAttrLoc, diag::note_conflicting_attribute);
5125 }
5126 
5127 // Check SYCL2020 Attributes. 2020 attributes don't propogate, they are only
5128 // valid if they match the attribute on the kernel. Note that this is a slight
5129 // difference from what the spec says, which says these attributes are only
5130 // valid on SYCL Kernels and SYCL_EXTERNAL, but we felt that for
5131 // self-documentation purposes that it would be nice to be able to repeat these
5132 // on subsequent functions.
5134  SemaSYCL &S, FunctionDecl *SYCLKernel, FunctionDecl *KernelBody,
5135  const llvm::SmallPtrSetImpl<FunctionDecl *> &CalledFuncs) {
5136 
5137  if (KernelBody) {
5138  // Make sure the kernel itself has all the 2020 attributes, since we don't
5139  // do propagation of these.
5140  if (auto *A = KernelBody->getAttr<IntelReqdSubGroupSizeAttr>())
5141  if (A->isSYCL2020Spelling())
5142  SYCLKernel->addAttr(A);
5143  if (auto *A = KernelBody->getAttr<IntelNamedSubGroupSizeAttr>())
5144  SYCLKernel->addAttr(A);
5145 
5146  // If the kernel has a body, we should get the attributes for the kernel
5147  // from there instead, so that we get the functor object.
5148  SYCLKernel = KernelBody;
5149  }
5150 
5151  for (auto *FD : CalledFuncs) {
5152  if (FD == SYCLKernel || FD == KernelBody)
5153  continue;
5154  for (auto *Attr : FD->attrs()) {
5155  switch (Attr->getKind()) {
5156  case attr::Kind::IntelReqdSubGroupSize:
5157  // Pre SYCL2020 spellings handled during collection.
5158  if (!cast<IntelReqdSubGroupSizeAttr>(Attr)->isSYCL2020Spelling())
5159  break;
5160  LLVM_FALLTHROUGH;
5161  case attr::Kind::IntelNamedSubGroupSize:
5162  CheckSYCL2020SubGroupSizes(S, SYCLKernel, FD);
5163  break;
5164  case attr::Kind::SYCLDevice:
5165  // If a SYCL_EXTERNAL function is not defined in this TU, its necessary
5166  // that it has a compatible sub-group-size. Don't diagnose if it has a
5167  // sub-group attribute, we can count on the other checks to catch this.
5168  if (!FD->isDefined() && !FD->hasAttr<IntelReqdSubGroupSizeAttr>() &&
5169  !FD->hasAttr<IntelNamedSubGroupSizeAttr>())
5170  CheckSYCL2020SubGroupSizes(S, SYCLKernel, FD);
5171  break;
5172  default:
5173  break;
5174  }
5175  }
5176  }
5177 }
5178 
5180  SemaSYCL &S, const SingleDeviceFunctionTracker &Tracker, Attr *A,
5181  FunctionDecl *SYCLKernel, FunctionDecl *KernelBody) {
5182  switch (A->getKind()) {
5183  case attr::Kind::IntelReqdSubGroupSize: {
5184  auto *Attr = cast<IntelReqdSubGroupSizeAttr>(A);
5185 
5186  if (Attr->isSYCL2020Spelling())
5187  break;
5188  const auto *KBSimdAttr =
5189  KernelBody ? KernelBody->getAttr<SYCLSimdAttr>() : nullptr;
5190  if (auto *Existing = SYCLKernel->getAttr<IntelReqdSubGroupSizeAttr>()) {
5191  if (getIntExprValue(Existing->getValue(), S.getASTContext()) !=
5192  getIntExprValue(Attr->getValue(), S.getASTContext())) {
5193  S.Diag(SYCLKernel->getLocation(),
5194  diag::err_conflicting_sycl_kernel_attributes);
5195  S.Diag(Existing->getLocation(), diag::note_conflicting_attribute);
5196  S.Diag(Attr->getLocation(), diag::note_conflicting_attribute);
5197  SYCLKernel->setInvalidDecl();
5198  }
5199  } else if (KBSimdAttr &&
5200  (getIntExprValue(Attr->getValue(), S.getASTContext()) != 1)) {
5201  reportConflictingAttrs(S, KernelBody, KBSimdAttr, Attr);
5202  } else {
5203  SYCLKernel->addAttr(A);
5204  }
5205  break;
5206  }
5207  case attr::Kind::SYCLReqdWorkGroupSize: {
5208  auto *RWGSA = cast<SYCLReqdWorkGroupSizeAttr>(A);
5209  if (auto *Existing = SYCLKernel->getAttr<SYCLReqdWorkGroupSizeAttr>()) {
5211  Existing->getXDim(), Existing->getYDim(), Existing->getZDim(),
5212  RWGSA->getXDim(), RWGSA->getYDim(), RWGSA->getZDim())) {
5213  S.Diag(SYCLKernel->getLocation(),
5214  diag::err_conflicting_sycl_kernel_attributes);
5215  S.Diag(Existing->getLocation(), diag::note_conflicting_attribute);
5216  S.Diag(RWGSA->getLocation(), diag::note_conflicting_attribute);
5217  SYCLKernel->setInvalidDecl();
5218  }
5219  } else if (auto *Existing =
5220  SYCLKernel->getAttr<SYCLIntelMaxWorkGroupSizeAttr>()) {
5222  RWGSA->getXDim(), RWGSA->getYDim(), RWGSA->getZDim(),
5223  Existing->getXDim(), Existing->getYDim(), Existing->getZDim())) {
5224  S.Diag(SYCLKernel->getLocation(),
5225  diag::err_conflicting_sycl_kernel_attributes);
5226  S.Diag(Existing->getLocation(), diag::note_conflicting_attribute);
5227  S.Diag(RWGSA->getLocation(), diag::note_conflicting_attribute);
5228  SYCLKernel->setInvalidDecl();
5229  } else {
5230  SYCLKernel->addAttr(A);
5231  }
5232  } else {
5233  SYCLKernel->addAttr(A);
5234  }
5235  break;
5236  }
5237  case attr::Kind::SYCLWorkGroupSizeHint: {
5238  auto *WGSH = cast<SYCLWorkGroupSizeHintAttr>(A);
5239  if (auto *Existing = SYCLKernel->getAttr<SYCLWorkGroupSizeHintAttr>()) {
5241  Existing->getXDim(), Existing->getYDim(), Existing->getZDim(),
5242  WGSH->getXDim(), WGSH->getYDim(), WGSH->getZDim())) {
5243  S.Diag(SYCLKernel->getLocation(),
5244  diag::err_conflicting_sycl_kernel_attributes);
5245  S.Diag(Existing->getLocation(), diag::note_conflicting_attribute);
5246  S.Diag(WGSH->getLocation(), diag::note_conflicting_attribute);
5247  SYCLKernel->setInvalidDecl();
5248  }
5249  }
5250  SYCLKernel->addAttr(A);
5251  break;
5252  }
5253  case attr::Kind::SYCLIntelMaxWorkGroupSize: {
5254  auto *SIMWGSA = cast<SYCLIntelMaxWorkGroupSizeAttr>(A);
5255  if (auto *Existing = SYCLKernel->getAttr<SYCLReqdWorkGroupSizeAttr>()) {
5257  Existing->getXDim(), Existing->getYDim(), Existing->getZDim(),
5258  SIMWGSA->getXDim(), SIMWGSA->getYDim(), SIMWGSA->getZDim())) {
5259  S.Diag(SYCLKernel->getLocation(),
5260  diag::err_conflicting_sycl_kernel_attributes);
5261  S.Diag(Existing->getLocation(), diag::note_conflicting_attribute);
5262  S.Diag(SIMWGSA->getLocation(), diag::note_conflicting_attribute);
5263  SYCLKernel->setInvalidDecl();
5264  } else {
5265  SYCLKernel->addAttr(A);
5266  }
5267  } else {
5268  SYCLKernel->addAttr(A);
5269  }
5270  break;
5271  }
5272  case attr::Kind::SYCLSimd:
5273  if (KernelBody && !KernelBody->getAttr<SYCLSimdAttr>()) {
5274  // Usual kernel can't call ESIMD functions.
5275  S.Diag(KernelBody->getLocation(),
5276  diag::err_sycl_function_attribute_mismatch)
5277  << A;
5278  S.Diag(A->getLocation(), diag::note_attribute);
5279  KernelBody->setInvalidDecl();
5280  break;
5281  }
5282  LLVM_FALLTHROUGH;
5283  case attr::Kind::SYCLIntelKernelArgsRestrict:
5284  case attr::Kind::SYCLIntelNumSimdWorkItems:
5285  case attr::Kind::SYCLIntelSchedulerTargetFmaxMhz:
5286  case attr::Kind::SYCLIntelMaxGlobalWorkDim:
5287  case attr::Kind::SYCLIntelMinWorkGroupsPerComputeUnit:
5288  case attr::Kind::SYCLIntelMaxWorkGroupsPerMultiprocessor:
5289  case attr::Kind::SYCLIntelNoGlobalWorkOffset:
5290  case attr::Kind::SYCLIntelLoopFuse:
5291  case attr::Kind::SYCLIntelMaxConcurrency:
5292  case attr::Kind::SYCLIntelDisableLoopPipelining:
5293  case attr::Kind::SYCLIntelInitiationInterval:
5294  case attr::Kind::SYCLIntelUseStallEnableClusters:
5295  case attr::Kind::SYCLDeviceHas:
5296  case attr::Kind::SYCLAddIRAttributesFunction:
5297  SYCLKernel->addAttr(A);
5298  break;
5299  case attr::Kind::IntelNamedSubGroupSize:
5300  // Nothing to do here, handled in the SYCL2020 spelling.
5301  break;
5302  // TODO: vec_len_hint should be handled here
5303  default:
5304  // Seeing this means that CollectPossibleKernelAttributes was
5305  // updated while this switch wasn't...or something went wrong
5306  llvm_unreachable("Unexpected attribute was collected by "
5307  "CollectPossibleKernelAttributes");
5308  }
5309 }
5310 
5312  // This Tracker object ensures that the SyclDeviceDecls collection includes
5313  // the SYCL_EXTERNAL functions, and manages the diagnostics for all of the
5314  // functions in the kernel.
5315  DeviceFunctionTracker Tracker(*this);
5316 
5317  for (Decl *D : syclDeviceDecls()) {
5318  auto *SYCLKernel = cast<FunctionDecl>(D);
5319 
5320  // This type does the actual analysis on a per-kernel basis. It does this to
5321  // make sure that we're only ever dealing with the context of a single
5322  // kernel at a time.
5323  SingleDeviceFunctionTracker T{Tracker, SYCLKernel};
5324 
5325  CheckSYCL2020Attributes(*this, T.GetSYCLKernel(), T.GetKernelBody(),
5326  T.GetDeviceFunctions());
5327  for (auto *A : T.GetCollectedAttributes())
5328  PropagateAndDiagnoseDeviceAttr(*this, T, A, T.GetSYCLKernel(),
5329  T.GetKernelBody());
5331  }
5332 }
5333 
5335  if (isFreeFunction(*this, FD)) {
5336  SyclKernelFieldChecker FieldChecker(*this);
5337  SyclKernelUnionChecker UnionChecker(*this);
5338 
5339  KernelObjVisitor Visitor{*this};
5340 
5341  DiagnosingSYCLKernel = true;
5342 
5343  // Check parameters of free function.
5344  Visitor.VisitFunctionParameters(FD, FieldChecker, UnionChecker);
5345 
5346  DiagnosingSYCLKernel = false;
5347 
5348  // Ignore the free function if any of the checkers fail validation.
5349  if (!FieldChecker.isValid() || !UnionChecker.isValid())
5350  return;
5351 
5352  ConstructFreeFunctionKernel(*this, FD);
5353  }
5354 }
5355 
5356 // -----------------------------------------------------------------------------
5357 // SYCL device specific diagnostics implementation
5358 // -----------------------------------------------------------------------------
5359 
5362  DeviceDiagnosticReason Reason) {
5363  assert(getLangOpts().SYCLIsDevice &&
5364  "Should only be called during SYCL compilation");
5365  FunctionDecl *FD = dyn_cast<FunctionDecl>(SemaRef.getCurLexicalContext());
5366  SemaDiagnosticBuilder::Kind DiagKind = [this, FD, Reason] {
5367  if (DiagnosingSYCLKernel)
5369  if (!FD)
5371  if (SemaRef.getEmissionStatus(FD) ==
5373  // Skip the diagnostic if we know it won't be emitted.
5374  if ((SemaRef.getEmissionReason(FD) & Reason) ==
5377 
5379  }
5381  }();
5382  return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, FD, SemaRef, Reason);
5383 }
5384 
5387  ValueDecl *DeclToCheck) {
5388  assert(getLangOpts().SYCLIsDevice &&
5389  "Should only be called during SYCL compilation");
5390  // Emit notes only for the first discovered declaration of unsupported type
5391  // to avoid mess of notes. This flag is to track that error already happened.
5392  bool NeedToEmitNotes = true;
5393 
5394  auto Check = [&](QualType TypeToCheck, const ValueDecl *D) {
5395  bool ErrorFound = false;
5396  if (isZeroSizedArray(*this, TypeToCheck)) {
5397  DiagIfDeviceCode(UsedAt, diag::err_typecheck_zero_array_size) << 1;
5398  ErrorFound = true;
5399  }
5400  // Checks for other types can also be done here.
5401  if (ErrorFound) {
5402  if (NeedToEmitNotes) {
5403  if (auto *FD = dyn_cast<FieldDecl>(D))
5405  diag::note_illegal_field_declared_here)
5406  << FD->getType()->isPointerType() << FD->getType();
5407  else
5408  DiagIfDeviceCode(D->getLocation(), diag::note_declared_at);
5409  }
5410  }
5411 
5412  return ErrorFound;
5413  };
5414 
5415  // In case we have a Record used do the DFS for a bad field.
5416  SmallVector<const ValueDecl *, 4> StackForRecursion;
5417  StackForRecursion.push_back(DeclToCheck);
5418 
5419  // While doing DFS save how we get there to emit a nice set of notes.
5421  History.push_back(nullptr);
5422 
5423  do {
5424  const ValueDecl *Next = StackForRecursion.pop_back_val();
5425  if (!Next) {
5426  assert(!History.empty());
5427  // Found a marker, we have gone up a level.
5428  History.pop_back();
5429  continue;
5430  }
5431  QualType NextTy = Next->getType();
5432 
5433  if (!Visited.insert(NextTy).second)
5434  continue;
5435 
5436  auto EmitHistory = [&]() {
5437  // The first element is always nullptr.
5438  for (uint64_t Index = 1; Index < History.size(); ++Index) {
5439  DiagIfDeviceCode(History[Index]->getLocation(),
5440  diag::note_within_field_of_type)
5441  << History[Index]->getType();
5442  }
5443  };
5444 
5445  if (Check(NextTy, Next)) {
5446  if (NeedToEmitNotes)
5447  EmitHistory();
5448  NeedToEmitNotes = false;
5449  }
5450 
5451  // In case pointer/array/reference type is met get pointee type, then
5452  // proceed with that type.
5453  while (NextTy->isAnyPointerType() || NextTy->isArrayType() ||
5454  NextTy->isReferenceType()) {
5455  if (NextTy->isArrayType())
5456  NextTy = QualType{NextTy->getArrayElementTypeNoTypeQual(), 0};
5457  else
5458  NextTy = NextTy->getPointeeType();
5459  if (Check(NextTy, Next)) {
5460  if (NeedToEmitNotes)
5461  EmitHistory();
5462  NeedToEmitNotes = false;
5463  }
5464  }
5465 
5466  if (const auto *RecDecl = NextTy->getAsRecordDecl()) {
5467  if (auto *NextFD = dyn_cast<FieldDecl>(Next))
5468  History.push_back(NextFD);
5469  // When nullptr is discovered, this means we've gone back up a level, so
5470  // the history should be cleaned.
5471  StackForRecursion.push_back(nullptr);
5472  llvm::copy(RecDecl->fields(), std::back_inserter(StackForRecursion));
5473  }
5474  } while (!StackForRecursion.empty());
5475 }
5476 
5478  const FunctionDecl *Callee,
5480  DeviceDiagnosticReason Reason) {
5481  Callee = Callee->getMostRecentDecl();
5482 
5483  // If the reason for the emission of this diagnostic is not SYCL-specific,
5484  // and it is not known to be reachable from a routine on device, do not
5485  // issue a diagnostic.
5487  !isFDReachableFromSyclDevice(Callee, Caller))
5488  return;
5489 
5490  // If Callee has a SYCL attribute, no diagnostic needed.
5491  if (Callee->hasAttr<SYCLDeviceAttr>() || Callee->hasAttr<SYCLKernelAttr>())
5492  return;
5493 
5494  // If Callee has a CUDA device attribute, no diagnostic needed.
5495  if (getLangOpts().CUDA && Callee->hasAttr<CUDADeviceAttr>())
5496  return;
5497 
5498  // Diagnose if this is an undefined function and it is not a builtin.
5499  // Currently, there is an exception of "__failed_assertion" in libstdc++-11,
5500  // this undefined function is used to trigger a compiling error.
5501  if (!Callee->isDefined() && !Callee->getBuiltinID() &&
5502  !Callee->isReplaceableGlobalAllocationFunction() &&
5504  Diag(Loc, diag::err_sycl_restrict) << SemaSYCL::KernelCallUndefinedFunction;
5505  Diag(Callee->getLocation(), diag::note_previous_decl) << Callee;
5506  Diag(Caller->getLocation(), diag::note_called_by) << Caller;
5507  }
5508 }
5509 
5511  assert(getLangOpts().SYCLIsDevice &&
5512  "Should only be called during SYCL compilation");
5513 
5514  if (VD->isInvalidDecl() || !VD->hasInit() || !VD->hasGlobalStorage())
5515  return true;
5516 
5517  const Expr *Init = VD->getInit();
5518  bool ValueDependent = Init && Init->isValueDependent();
5519  bool isConstantInit = Init && !ValueDependent &&
5520  Init->isConstantInitializer(getASTContext(), false);
5521  if (!VD->isConstexpr() && Init && !ValueDependent && !isConstantInit)
5522  return false;
5523 
5524  return true;
5525 }
5526 
5527 // -----------------------------------------------------------------------------
5528 // Integration header functionality implementation
5529 // -----------------------------------------------------------------------------
5530 
5531 /// Returns a string ID of given parameter kind - used in header
5532 /// emission.
5533 static const char *paramKind2Str(KernelParamKind K) {
5534 #define CASE(x) \
5535  case SYCLIntegrationHeader::kind_##x: \
5536  return "kind_" #x
5537  switch (K) {
5538  CASE(accessor);
5539  CASE(std_layout);
5540  CASE(sampler);
5541  CASE(stream);
5542  CASE(specialization_constants_buffer);
5543  CASE(pointer);
5544  }
5545  return "<ERROR>";
5546 
5547 #undef CASE
5548 }
5549 
5550 // Emits forward declarations of classes and template classes on which
5551 // declaration of given type depends.
5552 // For example, consider SimpleVadd
5553 // class specialization in parallel_for below:
5554 //
5555 // template <typename T1, unsigned int N, typename ... T2>
5556 // class SimpleVadd;
5557 // ...
5558 // template <unsigned int N, typename T1, typename ... T2>
5559 // void simple_vadd(const std::array<T1, N>& VA, const std::array<T1, N>&
5560 // VB,
5561 // std::array<T1, N>& VC, int param, T2 ... varargs) {
5562 // ...
5563 // deviceQueue.submit([&](sycl::handler& cgh) {
5564 // ...
5565 // cgh.parallel_for<class SimpleVadd<T1, N, T2...>>(...)
5566 // ...
5567 // }
5568 // ...
5569 // }
5570 // ...
5571 // class MyClass {...};
5572 // template <typename T> class MyInnerTmplClass { ... }
5573 // template <typename T> class MyTmplClass { ... }
5574 // ...
5575 // MyClass *c = new MyClass();
5576 // MyInnerTmplClass<MyClass**> c1(&c);
5577 // simple_vadd(A, B, C, 5, 'a', 1.f,
5578 // new MyTmplClass<MyInnerTmplClass<MyClass**>>(c1));
5579 //
5580 // it will generate the following forward declarations:
5581 // class MyClass;
5582 // template <typename T> class MyInnerTmplClass;
5583 // template <typename T> class MyTmplClass;
5584 // template <typename T1, unsigned int N, typename ...T2> class SimpleVadd;
5585 //
5587  : public TypeVisitor<SYCLFwdDeclEmitter>,
5588  public ConstTemplateArgumentVisitor<SYCLFwdDeclEmitter> {
5591  raw_ostream &OS;
5593  PrintingPolicy Policy;
5594 
5595  void printForwardDecl(NamedDecl *D) {
5596  // wrap the declaration into namespaces if needed
5597  unsigned NamespaceCnt = 0;
5598  std::string NSStr = "";
5599  const DeclContext *DC = D->getDeclContext();
5600 
5601  while (DC) {
5602  if (const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
5603  ++NamespaceCnt;
5604  StringRef NSInlinePrefix = NS->isInline() ? "inline " : "";
5605  NSStr.insert(
5606  0,
5607  Twine(NSInlinePrefix + "namespace " + NS->getName() + " { ").str());
5608  DC = NS->getDeclContext();
5609  } else {
5610  // We should be able to handle a subset of the decl-context types to
5611  // make our namespaces for forward declarations as specific as possible,
5612  // so just skip them here. We can't use their names, since they would
5613  // not be forward declarable, but we can try to make them as specific as
5614  // possible.
5615  // This permits things such as:
5616  // namespace N1 { void foo() { kernel<class K>(...); }}
5617  // and
5618  // namespace N2 { void foo() { kernel<class K>(...); }}
5619  // to co-exist, despite technically being against the SYCL rules.
5620  // See SYCLKernelNameTypePrinter for the corresponding part that prints
5621  // the kernel information for this type. These two must match.
5622  if (isa<FunctionDecl, RecordDecl, LinkageSpecDecl>(DC)) {
5623  DC = cast<Decl>(DC)->getDeclContext();
5624  } else {
5625  break;
5626  }
5627  }
5628  }
5629  OS << NSStr;
5630  if (NamespaceCnt > 0)
5631  OS << "\n";
5632 
5633  D->print(OS, Policy);
5634 
5635  if (const auto *ED = dyn_cast<EnumDecl>(D)) {
5636  QualType T = ED->getIntegerType().getCanonicalType();
5637  // Backup since getIntegerType() returns null for enum forward
5638  // declaration with no fixed underlying type
5639  if (T.isNull())
5640  T = ED->getPromotionType();
5641  OS << " : " << T.getAsString();
5642  }
5643 
5644  OS << ";\n";
5645 
5646  // print closing braces for namespaces if needed
5647  for (unsigned I = 0; I < NamespaceCnt; ++I)
5648  OS << "}";
5649  if (NamespaceCnt > 0)
5650  OS << "\n";
5651  }
5652 
5653  // Checks if we've already printed forward declaration and prints it if not.
5654  void checkAndEmitForwardDecl(NamedDecl *D) {
5655  if (Printed.insert(D).second)
5656  printForwardDecl(D);
5657  }
5658 
5659  void VisitTemplateArgs(ArrayRef<TemplateArgument> Args) {
5660  for (size_t I = 0, E = Args.size(); I < E; ++I)
5661  Visit(Args[I]);
5662  }
5663 
5664 public:
5665  SYCLFwdDeclEmitter(raw_ostream &OS, const LangOptions &LO)
5666  : OS(OS), Policy(LO) {
5667  Policy.adjustForCPlusPlusFwdDecl();
5668  Policy.SuppressTypedefs = true;
5669  Policy.SuppressUnwrittenScope = true;
5670  Policy.PrintCanonicalTypes = true;
5672  Policy.SuppressFinalSpecifier = true;
5673  }
5674 
5675  void Visit(QualType T) {
5676  if (T.isNull())
5677  return;
5678  InnerTypeVisitor::Visit(T.getTypePtr());
5679  }
5680 
5682  // Our forward declarations don't care about references, so we should just
5683  // ignore the reference and continue on.
5684  Visit(RT->getPointeeType());
5685  }
5686 
5687  void Visit(const TemplateArgument &TA) {
5688  if (TA.isNull())
5689  return;
5690  InnerTemplArgVisitor::Visit(TA);
5691  }
5692 
5694  // Peel off the pointer types.
5695  QualType PT = T->getPointeeType();
5696  while (PT->isPointerType())
5697  PT = PT->getPointeeType();
5698  Visit(PT);
5699  }
5700 
5701  void VisitTagType(const TagType *T) {
5702  TagDecl *TD = T->getDecl();
5703  if (const auto *TSD = dyn_cast<ClassTemplateSpecializationDecl>(TD)) {
5704  // - first, recurse into template parameters and emit needed forward
5705  // declarations
5706  ArrayRef<TemplateArgument> Args = TSD->getTemplateArgs().asArray();
5707  VisitTemplateArgs(Args);
5708  // - second, emit forward declaration for the template class being
5709  // specialized
5710  ClassTemplateDecl *CTD = TSD->getSpecializedTemplate();
5711  assert(CTD && "template declaration must be available");
5712 
5713  checkAndEmitForwardDecl(CTD);
5714  return;
5715  }
5716  checkAndEmitForwardDecl(TD);
5717  }
5718 
5720  QualType T = TA.getAsType();
5721  Visit(T);
5722  }
5723 
5725  QualType T = TA.getIntegralType();
5726  if (const EnumType *ET = T->getAs<EnumType>())
5727  VisitTagType(ET);
5728  }
5729 
5731  // recursion is not required, since the maximum possible nesting level
5732  // equals two for template argument
5733  //
5734  // for example:
5735  // template <typename T> class Bar;
5736  // template <template <typename> class> class Baz;
5737  // template <template <template <typename> class> class T>
5738  // class Foo;
5739  //
5740  // The Baz is a template class. The Baz<Bar> is a class. The class Foo
5741  // should be specialized with template class, not a class. The correct
5742  // specialization of template class Foo is Foo<Baz>. The incorrect
5743  // specialization of template class Foo is Foo<Baz<Bar>>. In this case
5744  // template class Foo specialized by class Baz<Bar>, not a template
5745  // class template <template <typename> class> class T as it should.
5747  assert(TD && "template declaration must be available");
5748  TemplateParameterList *TemplateParams = TD->getTemplateParameters();
5749  for (NamedDecl *P : *TemplateParams) {
5750  // If template template parameter type has an enum value template
5751  // parameter, forward declaration of enum type is required. Only enum
5752  // values (not types) need to be handled. For example, consider the
5753  // following kernel name type:
5754  //
5755  // template <typename EnumTypeOut, template <EnumValueIn EnumValue,
5756  // typename TypeIn> class T> class Foo;
5757  //
5758  // The correct specialization for Foo (with enum type) is:
5759  // Foo<EnumTypeOut, Baz>, where Baz is a template class.
5760  //
5761  // Therefore the forward class declarations generated in the
5762  // integration header are:
5763  // template <EnumValueIn EnumValue, typename TypeIn> class Baz;
5764  // template <typename EnumTypeOut, template <EnumValueIn EnumValue,
5765  // typename EnumTypeIn> class T> class Foo;
5766  //
5767  // This requires the following enum forward declarations:
5768  // enum class EnumTypeOut : int; (Used to template Foo)
5769  // enum class EnumValueIn : int; (Used to template Baz)
5771  dyn_cast<NonTypeTemplateParmDecl>(P))
5772  if (const EnumType *ET = TemplateParam->getType()->getAs<EnumType>())
5773  VisitTagType(ET);
5774  }
5775  checkAndEmitForwardDecl(TD);
5776  }
5777 
5779  VisitTemplateArgs(TA.getPackAsArray());
5780  }
5781 };
5782 
5784  : public TypeVisitor<SYCLKernelNameTypePrinter>,
5785  public ConstTemplateArgumentVisitor<SYCLKernelNameTypePrinter> {
5787  using InnerTemplArgVisitor =
5789  raw_ostream &OS;
5790  PrintingPolicy &Policy;
5791 
5793  for (size_t I = 0, E = Args.size(); I < E; ++I) {
5794  const TemplateArgument &Arg = Args[I];
5795  // If argument is an empty pack argument, skip printing comma and
5796  // argument.
5797  if (Arg.getKind() == TemplateArgument::ArgKind::Pack && !Arg.pack_size())
5798  continue;
5799 
5800  if (I)
5801  OS << ", ";
5802 
5803  Visit(Arg);
5804  }
5805  }
5806 
5807  void VisitQualifiers(Qualifiers Quals) {
5808  Quals.print(OS, Policy, /*appendSpaceIfNotEmpty*/ true);
5809  }
5810 
5811  // Use recursion to print the namespace-qualified name for the purposes of the
5812  // canonical sycl example of a type being created in the kernel call.
5813  void PrintNamespaceScopes(const DeclContext *DC) {
5814  if (isa<NamespaceDecl, FunctionDecl, RecordDecl, LinkageSpecDecl>(DC)) {
5815  PrintNamespaceScopes(DC->getParent());
5816 
5817  const auto *NS = dyn_cast<NamespaceDecl>(DC);
5818  if (NS && !NS->isAnonymousNamespace())
5819  OS << NS->getName() << "::";
5820  }
5821  }
5822 
5823 public:
5824  SYCLKernelNameTypePrinter(raw_ostream &OS, PrintingPolicy &Policy)
5825  : OS(OS), Policy(Policy) {}
5826 
5827  void Visit(QualType T) {
5828  if (T.isNull())
5829  return;
5830 
5831  QualType CT = T.getCanonicalType();
5832  VisitQualifiers(CT.getQualifiers());
5833 
5834  InnerTypeVisitor::Visit(CT.getTypePtr());
5835  }
5836 
5837  void VisitType(const Type *T) {
5838  OS << QualType::getAsString(T, Qualifiers(), Policy);
5839  }
5840 
5841  void Visit(const TemplateArgument &TA) {
5842  if (TA.isNull())
5843  return;
5844  InnerTemplArgVisitor::Visit(TA);
5845  }
5846 
5847  void VisitTagType(const TagType *T) {
5848  TagDecl *RD = T->getDecl();
5849  if (const auto *TSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
5850 
5851  // Print template class name
5852  TSD->printQualifiedName(OS, Policy, /*WithGlobalNsPrefix*/ true);
5853 
5854  ArrayRef<TemplateArgument> Args = TSD->getTemplateArgs().asArray();
5855  OS << "<";
5856  printTemplateArgs(Args);
5857  OS << ">";
5858 
5859  return;
5860  }
5861 
5862  // Handle the canonical sycl example where the type is created for the first
5863  // time in the kernel naming. We want to qualify this as fully as we can,
5864  // but not in a way that won't be forward declarable. See
5865  // SYCLFwdDeclEmitter::printForwardDecl for the corresponding list for
5866  // printing the forward declaration, these two must match.
5867  DeclContext *DC = RD->getDeclContext();
5868  if (isa<FunctionDecl, RecordDecl, LinkageSpecDecl>(DC)) {
5869  PrintNamespaceScopes(DC);
5870  RD->printName(OS, Policy);
5871  return;
5872  }
5873 
5874  const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(RD->getDeclContext());
5875  RD->printQualifiedName(OS, Policy, !(NS && NS->isAnonymousNamespace()));
5876  }
5877 
5879  TA.print(Policy, OS, false /* IncludeType */);
5880  }
5881 
5883  Policy.SuppressTagKeyword = true;
5884  QualType T = TA.getAsType();
5885  Visit(T);
5886  Policy.SuppressTagKeyword = false;
5887  }
5888 
5890  QualType T = TA.getIntegralType();
5891  if (const EnumType *ET = T->getAs<EnumType>()) {
5892  const llvm::APSInt &Val = TA.getAsIntegral();
5893  OS << "static_cast<";
5894  ET->getDecl()->printQualifiedName(OS, Policy,
5895  /*WithGlobalNsPrefix*/ true);
5896  OS << ">(" << Val << ")";
5897  } else {
5898  TA.print(Policy, OS, false /* IncludeType */);
5899  }
5900  }
5901 
5904  TD->printQualifiedName(OS, Policy);
5905  }
5906 
5909  }
5910 };
5911 
5912 static void OutputStableNameChar(raw_ostream &O, char C) {
5913  // If it is reliably printable, print in the integration header as a
5914  // character. Else just print it as the integral representation.
5915  if (llvm::isPrint(C))
5916  O << '\'' << C << '\'';
5917  else
5918  O << static_cast<short>(C);
5919 }
5920 
5921 static void OutputStableNameInChars(raw_ostream &O, StringRef Name) {
5922  assert(!Name.empty() && "Expected a nonempty string!");
5923  OutputStableNameChar(O, Name[0]);
5924 
5925  for (char C : Name.substr(1)) {
5926  O << ", ";
5927  OutputStableNameChar(O, C);
5928  }
5929 }
5930 
5931 void SYCLIntegrationHeader::emit(raw_ostream &O) {
5932  O << "// This is auto-generated SYCL integration header.\n";
5933  O << "\n";
5934 
5935  O << "#include <sycl/detail/defines_elementary.hpp>\n";
5936  O << "#include <sycl/detail/kernel_desc.hpp>\n";
5937 
5938  O << "\n";
5939 
5940  LangOptions LO;
5941  PrintingPolicy Policy(LO);
5942  Policy.SuppressTypedefs = true;
5943  Policy.SuppressUnwrittenScope = true;
5944  // Disable printing anonymous tag locations because on Windows
5945  // file path separators are treated as escape sequences and cause errors
5946  // when integration header is compiled with host compiler.
5947  Policy.AnonymousTagLocations = 0;
5948  SYCLFwdDeclEmitter FwdDeclEmitter(O, S.getLangOpts());
5949 
5950  // Predefines which need to be set for custom host compilation
5951  // must be defined in integration header.
5952  for (const std::pair<StringRef, StringRef> &Macro :
5954  O << "#ifndef " << Macro.first << '\n';
5955  O << "#define " << Macro.first << " " << Macro.second << '\n';
5956  O << "#endif //" << Macro.first << "\n\n";
5957  }
5958 
5959  switch (S.getLangOpts().getSYCLRangeRounding()) {
5961  O << "#ifndef __SYCL_DISABLE_PARALLEL_FOR_RANGE_ROUNDING__ \n";
5962  O << "#define __SYCL_DISABLE_PARALLEL_FOR_RANGE_ROUNDING__ 1\n";
5963  O << "#endif //__SYCL_DISABLE_PARALLEL_FOR_RANGE_ROUNDING__\n\n";
5964  break;
5966  O << "#ifndef __SYCL_FORCE_PARALLEL_FOR_RANGE_ROUNDING__ \n";
5967  O << "#define __SYCL_FORCE_PARALLEL_FOR_RANGE_ROUNDING__ 1\n";
5968  O << "#endif //__SYCL_FORCE_PARALLEL_FOR_RANGE_ROUNDING__\n\n";
5969  break;
5970  default:
5971  break;
5972  }
5973 
5974  if (S.getLangOpts().SYCLExperimentalRangeRounding) {
5975  O << "#ifndef __SYCL_EXP_PARALLEL_FOR_RANGE_ROUNDING__ \n";
5976  O << "#define __SYCL_EXP_PARALLEL_FOR_RANGE_ROUNDING__ 1\n";
5977  O << "#endif //__SYCL_EXP_PARALLEL_FOR_RANGE_ROUNDING__\n\n";
5978  }
5979 
5980  if (SpecConsts.size() > 0) {
5981  O << "// Forward declarations of templated spec constant types:\n";
5982  for (const auto &SC : SpecConsts)
5983  FwdDeclEmitter.Visit(SC.first);
5984  O << "\n";
5985 
5986  // Remove duplicates.
5987  std::sort(SpecConsts.begin(), SpecConsts.end(),
5988  [](const SpecConstID &SC1, const SpecConstID &SC2) {
5989  // Sort by string IDs for stable spec consts order in the
5990  // header.
5991  return SC1.second.compare(SC2.second) < 0;
5992  });
5993  SpecConstID *End =
5994  std::unique(SpecConsts.begin(), SpecConsts.end(),
5995  [](const SpecConstID &SC1, const SpecConstID &SC2) {
5996  // Here can do faster comparison of types.
5997  return SC1.first == SC2.first;
5998  });
5999 
6000  O << "// Specialization constants IDs:\n";
6001  for (const auto &P : llvm::make_range(SpecConsts.begin(), End)) {
6002  O << "template <> struct sycl::detail::SpecConstantInfo<";
6003  SYCLKernelNameTypePrinter Printer(O, Policy);
6004  Printer.Visit(P.first);
6005  O << "> {\n";
6006  O << " static constexpr const char* getName() {\n";
6007  O << " return \"" << P.second << "\";\n";
6008  O << " }\n";
6009  O << "};\n";
6010  }
6011  }
6012 
6013  O << "// Forward declarations of templated kernel function types:\n";
6014  for (const KernelDesc &K : KernelDescs)
6015  if (!K.IsUnnamedKernel)
6016  FwdDeclEmitter.Visit(K.NameType);
6017  O << "\n";
6018 
6019  O << "namespace sycl {\n";
6020  O << "inline namespace _V1 {\n";
6021  O << "namespace detail {\n";
6022 
6023  // Generate declaration of variable of type __sycl_device_global_registration
6024  // whose sole purpose is to run its constructor before the application's
6025  // main() function.
6026 
6027  if (NeedToEmitDeviceGlobalRegistration) {
6028  O << "namespace {\n";
6029 
6030  O << "class __sycl_device_global_registration {\n";
6031  O << "public:\n";
6032  O << " __sycl_device_global_registration() noexcept;\n";
6033  O << "};\n";
6034  O << "__sycl_device_global_registration __sycl_device_global_registrar;\n";
6035 
6036  O << "} // namespace\n";
6037 
6038  O << "\n";
6039  }
6040 
6041  // Generate declaration of variable of type __sycl_host_pipe_registration
6042  // whose sole purpose is to run its constructor before the application's
6043  // main() function.
6044  if (NeedToEmitHostPipeRegistration) {
6045  O << "namespace {\n";
6046 
6047  O << "class __sycl_host_pipe_registration {\n";
6048  O << "public:\n";
6049  O << " __sycl_host_pipe_registration() noexcept;\n";
6050  O << "};\n";
6051  O << "__sycl_host_pipe_registration __sycl_host_pipe_registrar;\n";
6052 
6053  O << "} // namespace\n";
6054 
6055  O << "\n";
6056  }
6057 
6058 
6059  O << "// names of all kernels defined in the corresponding source\n";
6060  O << "static constexpr\n";
6061  O << "const char* const kernel_names[] = {\n";
6062 
6063  for (unsigned I = 0; I < KernelDescs.size(); I++) {
6064  O << " \"" << KernelDescs[I].Name << "\"";
6065 
6066  if (I < KernelDescs.size() - 1)
6067  O << ",";
6068  O << "\n";
6069  }
6070  O << "};\n\n";
6071 
6072  O << "// array representing signatures of all kernels defined in the\n";
6073  O << "// corresponding source\n";
6074  O << "static constexpr\n";
6075  O << "const kernel_param_desc_t kernel_signatures[] = {\n";
6076 
6077  for (unsigned I = 0; I < KernelDescs.size(); I++) {
6078  auto &K = KernelDescs[I];
6079  O << " //--- " << K.Name << "\n";
6080 
6081  for (const auto &P : K.Params) {
6082  std::string TyStr = paramKind2Str(P.Kind);
6083  O << " { kernel_param_kind_t::" << TyStr << ", ";
6084  O << P.Info << ", " << P.Offset << " },\n";
6085  }
6086  O << "\n";
6087  }
6088 
6089  // Sentinel in place for 2 reasons:
6090  // 1- to make sure we don't get a warning because this collection is empty.
6091  // 2- to provide an obvious value that we can use when debugging to see that
6092  // we have left valid kernel information.
6093  // integer-field values are negative, so they are obviously invalid, notable
6094  // enough to 'stick out' and 'negative enough' to not be easily reachable by a
6095  // mathematical error.
6096  O << " { kernel_param_kind_t::kind_invalid, -987654321, -987654321 }, \n";
6097  O << "};\n\n";
6098 
6099  O << "// Specializations of KernelInfo for kernel function types:\n";
6100  unsigned CurStart = 0;
6101 
6102  for (const KernelDesc &K : KernelDescs) {
6103  const size_t N = K.Params.size();
6105  S.getASTContext()
6106  .getSourceManager()
6107  .getExpansionRange(K.KernelLocation)
6108  .getEnd());
6109  if (K.IsUnnamedKernel) {
6110  O << "template <> struct KernelInfoData<";
6111  OutputStableNameInChars(O, K.StableName);
6112  O << "> {\n";
6113  } else {
6114  O << "template <> struct KernelInfo<";
6115  SYCLKernelNameTypePrinter Printer(O, Policy);
6116  Printer.Visit(K.NameType);
6117  O << "> {\n";
6118  }
6119 
6120  O << " __SYCL_DLL_LOCAL\n";
6121  O << " static constexpr const char* getName() { return \"" << K.Name
6122  << "\"; }\n";
6123  O << " __SYCL_DLL_LOCAL\n";
6124  O << " static constexpr unsigned getNumParams() { return " << N << "; }\n";
6125  O << " __SYCL_DLL_LOCAL\n";
6126  O << " static constexpr const kernel_param_desc_t& ";
6127  O << "getParamDesc(unsigned i) {\n";
6128  O << " return kernel_signatures[i+" << CurStart << "];\n";
6129  O << " }\n";
6130  O << " __SYCL_DLL_LOCAL\n";
6131  O << " static constexpr bool isESIMD() { return " << K.IsESIMDKernel
6132  << "; }\n";
6133  O << " __SYCL_DLL_LOCAL\n";
6134  O << " static constexpr const char* getFileName() {\n";
6135  O << "#ifndef NDEBUG\n";
6136  O << " return \""
6137  << std::string(PLoc.getFilename())
6138  .substr(std::string(PLoc.getFilename()).find_last_of("/\\") + 1);
6139  O << "\";\n";
6140  O << "#else\n";
6141  O << " return \"\";\n";
6142  O << "#endif\n";
6143  O << " }\n";
6144  O << " __SYCL_DLL_LOCAL\n";
6145  O << " static constexpr const char* getFunctionName() {\n";
6146  O << "#ifndef NDEBUG\n";
6147  O << " return \"";
6148  SYCLKernelNameTypePrinter Printer(O, Policy);
6149  Printer.Visit(K.NameType);
6150  O << "\";\n";
6151  O << "#else\n";
6152  O << " return \"\";\n";
6153  O << "#endif\n";
6154  O << " }\n";
6155  O << " __SYCL_DLL_LOCAL\n";
6156  O << " static constexpr unsigned getLineNumber() {\n";
6157  O << "#ifndef NDEBUG\n";
6158  O << " return " << PLoc.getLine() << ";\n";
6159  O << "#else\n";
6160  O << " return 0;\n";
6161  O << "#endif\n";
6162  O << " }\n";
6163  O << " __SYCL_DLL_LOCAL\n";
6164  O << " static constexpr unsigned getColumnNumber() {\n";
6165  O << "#ifndef NDEBUG\n";
6166  O << " return " << PLoc.getColumn() << ";\n";
6167  O << "#else\n";
6168  O << " return 0;\n";
6169  O << "#endif\n";
6170  O << " }\n";
6171  StringRef ReturnType = (S.getASTContext().getTargetInfo().getInt64Type() ==
6173  ? "long"
6174  : "long long";
6175  O << " // Returns the size of the kernel object in bytes.\n";
6176  O << " __SYCL_DLL_LOCAL\n";
6177  O << " static constexpr " << ReturnType << " getKernelSize() { return "
6178  << K.ObjSize << "; }\n";
6179  O << "};\n";
6180  CurStart += N;
6181  }
6182  O << "\n";
6183  O << "} // namespace detail\n";
6184  O << "} // namespace _V1\n";
6185  O << "} // namespace sycl\n";
6186  O << "\n";
6187 }
6188 
6189 bool SYCLIntegrationHeader::emit(StringRef IntHeaderName) {
6190  if (IntHeaderName.empty())
6191  return false;
6192  int IntHeaderFD = 0;
6193  std::error_code EC =
6194  llvm::sys::fs::openFileForWrite(IntHeaderName, IntHeaderFD);
6195  if (EC) {
6196  llvm::errs() << "Error: " << EC.message() << "\n";
6197  // compilation will fail on absent include file - don't need to fail here
6198  return false;
6199  }
6200  llvm::raw_fd_ostream Out(IntHeaderFD, true /*close in destructor*/);
6201  emit(Out);
6202  return true;
6203 }
6204 
6206  QualType KernelNameType,
6207  SourceLocation KernelLocation,
6208  bool IsESIMDKernel,
6209  bool IsUnnamedKernel, int64_t ObjSize) {
6210  KernelDescs.emplace_back(SyclKernel, KernelNameType, KernelLocation,
6211  IsESIMDKernel, IsUnnamedKernel, ObjSize);
6212 }
6213 
6215  unsigned Offset) {
6216  auto *K = getCurKernelDesc();
6217  assert(K && "no kernels");
6218  K->Params.push_back(KernelParamDesc());
6219  KernelParamDesc &PD = K->Params.back();
6220  PD.Kind = Kind;
6221  PD.Info = Info;
6222  PD.Offset = Offset;
6223 }
6224 
6226  // nop for now
6227 }
6228 
6229 void SYCLIntegrationHeader::addSpecConstant(StringRef IDName, QualType IDType) {
6230  SpecConsts.emplace_back(std::make_pair(IDType, IDName.str()));
6231 }
6232 
6234 
6236  // Variable template declaration can result in an error case of 'nullptr'
6237  // here.
6238  if (!VD)
6239  return;
6240  // Skip the dependent version of these variables, we only care about them
6241  // after instantiation.
6242  if (VD->getDeclContext()->isDependentContext())
6243  return;
6244 
6245  // Skip partial specializations of a variable template, treat other variable
6246  // template instantiations as a VarDecl.
6247  if (isa<VarTemplatePartialSpecializationDecl>(VD))
6248  return;
6249  // Step 1: ensure that this is of the correct type template specialization.
6250  if (!SemaSYCL::isSyclType(VD->getType(), SYCLTypeAttr::specialization_id) &&
6251  !SemaSYCL::isSyclType(VD->getType(), SYCLTypeAttr::host_pipe) &&
6252  !S.isTypeDecoratedWithDeclAttribute<SYCLDeviceGlobalAttr>(
6253  VD->getType())) {
6254  // Handle the case where this could be a deduced type, such as a deduction
6255  // guide. We have to do this here since this function, unlike most of the
6256  // rest of this file, is called during Sema instead of after it. We will
6257  // also have to filter out after deduction later.
6258  QualType Ty = VD->getType().getCanonicalType();
6259  if (!Ty->isUndeducedType())
6260  return;
6261  }
6262  // Step 2: ensure that this is a static member, or a namespace-scope.
6263  // Note that isLocalVarDeclorParm excludes thread-local and static-local
6264  // intentionally, as there is no way to 'spell' one of those in the
6265  // specialization. We just don't generate the specialization for those, and
6266  // let an error happen during host compilation. To avoid multiple entries for
6267  // redeclarations, variables with external storage are omitted.
6268  if (VD->hasLocalStorage() || VD->isLocalVarDeclOrParm() ||
6269  VD->hasExternalStorage())
6270  return;
6271 
6272  // Step 3: Add to collection.
6273  GlobalVars.push_back(VD);
6274 }
6275 
6276 // Post-compile integration header support.
6277 bool SYCLIntegrationFooter::emit(StringRef IntHeaderName) {
6278  if (IntHeaderName.empty())
6279  return false;
6280  int IntHeaderFD = 0;
6281  std::error_code EC =
6282  llvm::sys::fs::openFileForWrite(IntHeaderName, IntHeaderFD);
6283  if (EC) {
6284  llvm::errs() << "Error: " << EC.message() << "\n";
6285  // compilation will fail on absent include file - don't need to fail here
6286  return false;
6287  }
6288  llvm::raw_fd_ostream Out(IntHeaderFD, true /*close in destructor*/);
6289  return emit(Out);
6290 }
6291 
6292 template <typename BeforeFn, typename AfterFn>
6293 static void PrintNSHelper(BeforeFn Before, AfterFn After, raw_ostream &OS,
6294  const DeclContext *DC) {
6295  if (DC->isTranslationUnit())
6296  return;
6297 
6298  const auto *CurDecl = cast<Decl>(DC);
6299  // Ensure we are in the canonical version, so that we know we have the 'full'
6300  // name of the thing.
6301  CurDecl = CurDecl->getCanonicalDecl();
6302 
6303  // We are intentionally skipping linkage decls and record decls. Namespaces
6304  // can appear in a linkage decl, but not a record decl, so we don't have to
6305  // worry about the names getting messed up from that. We handle record decls
6306  // later when printing the name of the thing.
6307  const auto *NS = dyn_cast<NamespaceDecl>(CurDecl);
6308  if (NS)
6309  Before(OS, NS);
6310 
6311  if (const DeclContext *NewDC = CurDecl->getDeclContext())
6312  PrintNSHelper(Before, After, OS, NewDC);
6313 
6314  if (NS)
6315  After(OS, NS);
6316 }
6317 
6318 static void PrintNamespaces(raw_ostream &OS, const DeclContext *DC) {
6319  PrintNSHelper([](raw_ostream &OS, const NamespaceDecl *NS) {},
6320  [](raw_ostream &OS, const NamespaceDecl *NS) {
6321  if (NS->isInline())
6322  OS << "inline ";
6323  OS << "namespace ";
6324  if (!NS->isAnonymousNamespace())
6325  OS << NS->getName() << " ";
6326  OS << "{\n";
6327  },
6328  OS, DC);
6329 }
6330 
6331 static void PrintNSClosingBraces(raw_ostream &OS, const DeclContext *DC) {
6332  PrintNSHelper(
6333  [](raw_ostream &OS, const NamespaceDecl *NS) {
6334  OS << "} // ";
6335  if (NS->isInline())
6336  OS << "inline ";
6337 
6338  OS << "namespace ";
6339  if (!NS->isAnonymousNamespace())
6340  OS << NS->getName();
6341 
6342  OS << '\n';
6343  },
6344  [](raw_ostream &OS, const NamespaceDecl *NS) {}, OS, DC);
6345 }
6346 
6347 static std::string EmitShim(raw_ostream &OS, unsigned &ShimCounter,
6348  const std::string &LastShim,
6349  const NamespaceDecl *AnonNS) {
6350  std::string NewShimName =
6351  "__sycl_detail::__shim_" + std::to_string(ShimCounter) + "()";
6352  // Print opening-namespace
6354  OS << "namespace __sycl_detail {\n";
6355  OS << "static constexpr decltype(" << LastShim << ") &__shim_" << ShimCounter
6356  << "() {\n";
6357  OS << " return " << LastShim << ";\n";
6358  OS << "}\n";
6359  OS << "} // namespace __sycl_detail\n";
6361 
6362  ++ShimCounter;
6363  return NewShimName;
6364 }
6365 
6366 // Emit the list of shims required for a DeclContext, calls itself recursively.
6367 static void EmitShims(raw_ostream &OS, unsigned &ShimCounter,
6368  const DeclContext *DC, std::string &NameForLastShim,
6369  PrintingPolicy &Policy) {
6370  if (DC->isTranslationUnit()) {
6371  NameForLastShim = "::" + NameForLastShim;
6372  return;
6373  }
6374 
6375  const auto *CurDecl = cast<Decl>(DC)->getCanonicalDecl();
6376 
6377  // We skip linkage decls, since they don't modify the Qualified name.
6378  if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(CurDecl)) {
6379  std::string TemplatedName;
6380  llvm::raw_string_ostream Stream(TemplatedName);
6381  CTSD->getNameForDiagnostic(Stream, Policy, false);
6382  Stream.flush();
6383  NameForLastShim = TemplatedName + "::" + NameForLastShim;
6384  } else if (const auto *RD = dyn_cast<RecordDecl>(CurDecl)) {
6385  NameForLastShim = RD->getNameAsString() + "::" + NameForLastShim;
6386  } else if (const auto *ND = dyn_cast<NamespaceDecl>(CurDecl)) {
6387  if (ND->isAnonymousNamespace()) {
6388  // Print current shim, reset 'name for last shim'.
6389  NameForLastShim = EmitShim(OS, ShimCounter, NameForLastShim, ND);
6390  } else {
6391  NameForLastShim = ND->getNameAsString() + "::" + NameForLastShim;
6392  }
6393  } else {
6394  // FIXME: I don't believe there are other declarations that these variables
6395  // could possibly find themselves in. LinkageDecls don't change the
6396  // qualified name, so there is nothing to do here. At one point we should
6397  // probably convince ourselves that this is entire list and remove this
6398  // comment.
6399  assert((isa<LinkageSpecDecl, ExternCContextDecl>(CurDecl)) &&
6400  "Unhandled decl type");
6401  }
6402 
6403  EmitShims(OS, ShimCounter, CurDecl->getDeclContext(), NameForLastShim,
6404  Policy);
6405 }
6406 
6407 // Emit the list of shims required for a variable declaration.
6408 // Returns a string containing the FQN of the 'top most' shim, including its
6409 // function call parameters.
6410 static std::string EmitShims(raw_ostream &OS, unsigned &ShimCounter,
6411  PrintingPolicy &Policy, const VarDecl *VD) {
6412  if (!VD->isInAnonymousNamespace())
6413  return "";
6414  std::string RelativeName;
6415  llvm::raw_string_ostream stream(RelativeName);
6416  VD->getNameForDiagnostic(stream, Policy, false);
6417  stream.flush();
6418 
6419  EmitShims(OS, ShimCounter, VD->getDeclContext(), RelativeName, Policy);
6420  return RelativeName;
6421 }
6422 
6423 bool SYCLIntegrationFooter::emit(raw_ostream &OS) {
6424  PrintingPolicy Policy{S.getLangOpts()};
6425  Policy.adjustForCPlusPlusFwdDecl();
6426  Policy.SuppressTypedefs = true;
6427  Policy.SuppressUnwrittenScope = true;
6428 
6429  llvm::SmallSet<const VarDecl *, 8> Visited;
6430  bool EmittedFirstSpecConstant = false;
6431  bool DeviceGlobalsEmitted = false;
6432  bool HostPipesEmitted = false;
6433 
6434  // Used to uniquely name the 'shim's as we generate the names in each
6435  // anonymous namespace.
6436  unsigned ShimCounter = 0;
6437 
6438  std::string DeviceGlobalsBuf;
6439  llvm::raw_string_ostream DeviceGlobOS(DeviceGlobalsBuf);
6440  std::string HostPipesBuf;
6441  llvm::raw_string_ostream HostPipesOS(HostPipesBuf);
6442  for (const VarDecl *VD : GlobalVars) {
6443  VD = VD->getCanonicalDecl();
6444 
6445  // Skip if this isn't a SpecIdType, DeviceGlobal, or HostPipe. This
6446  // can happen if it was a deduced type.
6447  if (!SemaSYCL::isSyclType(VD->getType(), SYCLTypeAttr::specialization_id) &&
6448  !SemaSYCL::isSyclType(VD->getType(), SYCLTypeAttr::host_pipe) &&
6449  !S.isTypeDecoratedWithDeclAttribute<SYCLDeviceGlobalAttr>(
6450  VD->getType()))
6451  continue;
6452 
6453  // Skip if we've already visited this.
6454  if (llvm::find(Visited, VD) != Visited.end())
6455  continue;
6456 
6457  // We only want to emit the #includes if we have a variable that needs
6458  // them, so emit this one on the first time through the loop.
6459  if (!EmittedFirstSpecConstant && !DeviceGlobalsEmitted && !HostPipesEmitted)
6460  OS << "#include <sycl/detail/defines_elementary.hpp>\n";
6461 
6462  Visited.insert(VD);
6463  std::string TopShim = EmitShims(OS, ShimCounter, Policy, VD);
6464  if (S.isTypeDecoratedWithDeclAttribute<SYCLDeviceGlobalAttr>(
6465  VD->getType())) {
6466  DeviceGlobalsEmitted = true;
6467  DeviceGlobOS << "device_global_map::add(";
6468  DeviceGlobOS << "(void *)&";
6469  if (VD->isInAnonymousNamespace()) {
6470  DeviceGlobOS << TopShim;
6471  } else {
6472  DeviceGlobOS << "::";
6473  VD->getNameForDiagnostic(DeviceGlobOS, Policy, true);
6474  }
6475  DeviceGlobOS << ", \"";
6477  VD);
6478  DeviceGlobOS << "\");\n";
6479  } else if (SemaSYCL::isSyclType(VD->getType(), SYCLTypeAttr::host_pipe)) {
6480  HostPipesEmitted = true;
6481  HostPipesOS << "host_pipe_map::add(";
6482  HostPipesOS << "(void *)&";
6483  if (VD->isInAnonymousNamespace()) {
6484  HostPipesOS << TopShim;
6485  } else {
6486  HostPipesOS << "::";
6487  VD->getNameForDiagnostic(HostPipesOS, Policy, true);
6488  }
6489  HostPipesOS << ", \"";
6491  VD);
6492  HostPipesOS << "\");\n";
6493  } else {
6494  EmittedFirstSpecConstant = true;
6495  OS << "namespace sycl {\n";
6496  OS << "inline namespace _V1 {\n";
6497  OS << "namespace detail {\n";
6498  OS << "template<>\n";
6499  OS << "inline const char *get_spec_constant_symbolic_ID_impl<";
6500 
6501  if (VD->isInAnonymousNamespace()) {
6502  OS << TopShim;
6503  } else {
6504  OS << "::";
6505  VD->getNameForDiagnostic(OS, Policy, true);
6506  }
6507 
6508  OS << ">() {\n";
6509  OS << " return \"";
6511  OS << "\";\n";
6512  OS << "}\n";
6513  OS << "} // namespace detail\n";
6514  OS << "} // namespace _V1\n";
6515  OS << "} // namespace sycl\n";
6516  }
6517  }
6518 
6519  if (EmittedFirstSpecConstant)
6520  OS << "#include <sycl/detail/spec_const_integration.hpp>\n";
6521 
6522  if (DeviceGlobalsEmitted) {
6523  OS << "#include <sycl/detail/device_global_map.hpp>\n";
6524  DeviceGlobOS.flush();
6525  OS << "namespace sycl::detail {\n";
6526  OS << "namespace {\n";
6527  OS << "__sycl_device_global_registration::__sycl_device_global_"
6528  "registration() noexcept {\n";
6529  OS << DeviceGlobalsBuf;
6530  OS << "}\n";
6531  OS << "} // namespace (unnamed)\n";
6532  OS << "} // namespace sycl::detail\n";
6533 
6534  S.getSyclIntegrationHeader().addDeviceGlobalRegistration();
6535  }
6536 
6537  if (HostPipesEmitted) {
6538  OS << "#include <sycl/detail/host_pipe_map.hpp>\n";
6539  HostPipesOS.flush();
6540  OS << "namespace sycl::detail {\n";
6541  OS << "namespace {\n";
6542  OS << "__sycl_host_pipe_registration::__sycl_host_pipe_"
6543  "registration() noexcept {\n";
6544  OS << HostPipesBuf;
6545  OS << "}\n";
6546  OS << "} // namespace (unnamed)\n";
6547  OS << "} // namespace sycl::detail\n";
6548 
6549  S.getSyclIntegrationHeader().addHostPipeRegistration();
6550  }
6551 
6552  return true;
6553 }
6554 
6556  SourceLocation LParen,
6557  SourceLocation RParen, Expr *E) {
6558  if (!E->isInstantiationDependent()) {
6559  // Special handling to get us better error messages for a member variable.
6560  if (auto *ME = dyn_cast<MemberExpr>(E->IgnoreUnlessSpelledInSource())) {
6561  if (isa<FieldDecl>(ME->getMemberDecl()))
6562  Diag(E->getExprLoc(), diag::err_unique_stable_id_global_storage);
6563  else
6564  Diag(E->getExprLoc(), diag::err_unique_stable_id_expected_var);
6565  return ExprError();
6566  }
6567 
6568  auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreUnlessSpelledInSource());
6569 
6570  if (!DRE || !isa_and_nonnull<VarDecl>(DRE->getDecl())) {
6571  Diag(E->getExprLoc(), diag::err_unique_stable_id_expected_var);
6572  return ExprError();
6573  }
6574 
6575  auto *Var = cast<VarDecl>(DRE->getDecl());
6576 
6577  if (!Var->hasGlobalStorage()) {
6578  Diag(E->getExprLoc(), diag::err_unique_stable_id_global_storage);
6579  return ExprError();
6580  }
6581  }
6582 
6583  return SYCLUniqueStableIdExpr::Create(getASTContext(), OpLoc, LParen, RParen,
6584  E);
6585 }
6586 
6588  SourceLocation LParen,
6589  SourceLocation RParen, Expr *E) {
6590  return BuildUniqueStableIdExpr(OpLoc, LParen, RParen, E);
6591 }
6592 
6594  SourceLocation LParen,
6595  SourceLocation RParen,
6596  TypeSourceInfo *TSI) {
6597  return SYCLUniqueStableNameExpr::Create(getASTContext(), OpLoc, LParen,
6598  RParen, TSI);
6599 }
6600 
6602  SourceLocation LParen,
6603  SourceLocation RParen,
6604  ParsedType ParsedTy) {
6605  TypeSourceInfo *TSI = nullptr;
6606  QualType Ty = SemaRef.GetTypeFromParser(ParsedTy, &TSI);
6607 
6608  if (Ty.isNull())
6609  return ExprError();
6610  if (!TSI)
6611  TSI = getASTContext().getTrivialTypeSourceInfo(Ty, LParen);
6612 
6613  return BuildUniqueStableNameExpr(OpLoc, LParen, RParen, TSI);
6614 }
NodeId Parent
Definition: ASTDiff.cpp:191
int Id
Definition: ASTDiff.cpp:190
MatchType Type
DynTypedNode Node
StringRef P
Defines the Diagnostic-related interfaces.
Defines enum values for all the target-independent builtin functions.
llvm::APSInt APSInt
unsigned Offset
Definition: Format.cpp:2978
llvm::DenseSet< const void * > Visited
Definition: HTMLLogger.cpp:146
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::Record Record
Definition: MachO.h:31
static std::string printTemplateArgs(const PrintingPolicy &PrintingPolicy, TemplateArgumentListInfo &Args, const TemplateParameterList *Params)
SourceLocation Loc
Definition: SemaObjC.cpp:755
static constexpr llvm::StringLiteral InitSpecConstantsBuffer
Definition: SemaSYCL.cpp:66
static bool isDeclaredInSYCLNamespace(const Decl *D)
This function checks whether given DeclContext contains a topmost namespace with name "sycl".
Definition: SemaSYCL.cpp:738
KernelInvocationKind
Definition: SemaSYCL.cpp:57
@ InvokeParallelFor
Definition: SemaSYCL.cpp:60
@ InvokeParallelForWorkGroup
Definition: SemaSYCL.cpp:61
@ InvokeUnknown
Definition: SemaSYCL.cpp:58
@ InvokeSingleTask
Definition: SemaSYCL.cpp:59
static void PrintNSHelper(BeforeFn Before, AfterFn After, raw_ostream &OS, const DeclContext *DC)
Definition: SemaSYCL.cpp:6293
static bool isSYCLKernelBodyFunction(FunctionDecl *FD)
Definition: SemaSYCL.cpp:487
constexpr unsigned MaxKernelArgsSize
Definition: SemaSYCL.cpp:71
static bool isSyclAccessorType(QualType Ty)
Definition: SemaSYCL.cpp:90
#define KP_FOR_EACH(FUNC, Item, Qt)
Definition: SemaSYCL.cpp:1276
static void CheckSYCL2020SubGroupSizes(SemaSYCL &S, FunctionDecl *SYCLKernel, const FunctionDecl *FD)
Definition: SemaSYCL.cpp:5081
void ConstructFreeFunctionKernel(SemaSYCL &SemaSYCLRef, FunctionDecl *FD)
Definition: SemaSYCL.cpp:5032
static void OutputStableNameInChars(raw_ostream &O, StringRef Name)
Definition: SemaSYCL.cpp:5921
static SourceLocation GetSubGroupLoc(const FunctionDecl *FD)
Definition: SemaSYCL.cpp:5073
std::tuple< QualType, IdentifierInfo *, TypeSourceInfo * > ParamDesc
Definition: SemaSYCL.cpp:55
static KernelInvocationKind getKernelInvocationKind(FunctionDecl *KernelCallerFunc)
Definition: SemaSYCL.cpp:1039
static bool IsSyclMathFunc(unsigned BuiltinID)
Definition: SemaSYCL.cpp:320
target
Definition: SemaSYCL.cpp:45
@ host_image
Definition: SemaSYCL.cpp:51
@ local
Definition: SemaSYCL.cpp:48
@ global_buffer
Definition: SemaSYCL.cpp:46
@ constant_buffer
Definition: SemaSYCL.cpp:47
@ host_buffer
Definition: SemaSYCL.cpp:50
@ image
Definition: SemaSYCL.cpp:49
@ image_array
Definition: SemaSYCL.cpp:52
#define KF_FOR_EACH(FUNC, Item, Qt)
Definition: SemaSYCL.cpp:1253
#define CASE(x)
static constexpr llvm::StringLiteral InitESIMDMethodName
Definition: SemaSYCL.cpp:65
static void OutputStableNameChar(raw_ostream &O, char C)
Definition: SemaSYCL.cpp:5912
static int64_t getIntExprValue(const Expr *E, ASTContext &Ctx)
Returns the signed constant integer value represented by given expression.
Definition: SemaSYCL.cpp:522
static std::pair< LangOptions::SubGroupSizeType, int64_t > CalcEffectiveSubGroup(ASTContext &Ctx, const LangOptions &LO, const FunctionDecl *FD)
Definition: SemaSYCL.cpp:5055
static bool isSyclSpecialType(QualType Ty, SemaSYCL &S)
Definition: SemaSYCL.cpp:109
static std::pair< std::string, std::string > constructKernelName(SemaSYCL &S, const FunctionDecl *KernelCallerFunc, MangleContext &MC)
Definition: SemaSYCL.cpp:1143
static bool isFreeFunction(SemaSYCL &SemaSYCLRef, const FunctionDecl *FD)
Definition: SemaSYCL.cpp:1077
static bool isZeroSizedArray(SemaSYCL &S, QualType Ty)
Definition: SemaSYCL.cpp:399
static void checkSYCLType(SemaSYCL &S, QualType Ty, SourceRange Loc, llvm::DenseSet< QualType > Visited, SourceRange UsedAtLoc=SourceRange())
Definition: SemaSYCL.cpp:405
static CXXMethodDecl * getMethodByName(const CXXRecordDecl *CRD, StringRef MethodName)
Return method by name.
Definition: SemaSYCL.cpp:1027
static void CheckSYCL2020Attributes(SemaSYCL &S, FunctionDecl *SYCLKernel, FunctionDecl *KernelBody, const llvm::SmallPtrSetImpl< FunctionDecl * > &CalledFuncs)
Definition: SemaSYCL.cpp:5133
static bool isSYCLUndefinedAllowed(const FunctionDecl *Callee, const SourceManager &SrcMgr)
Definition: SemaSYCL.cpp:491
static bool isReadOnlyAccessor(const TemplateArgument &AccessModeArg)
Definition: SemaSYCL.cpp:1196
static QualType calculateKernelNameType(ASTContext &Ctx, const FunctionDecl *KernelCallerFunc)
Definition: SemaSYCL.cpp:1132
static void PropagateAndDiagnoseDeviceAttr(SemaSYCL &S, const SingleDeviceFunctionTracker &Tracker, Attr *A, FunctionDecl *SYCLKernel, FunctionDecl *KernelBody)
Definition: SemaSYCL.cpp:5179
static const char * paramKind2Str(KernelParamKind K)
Returns a string ID of given parameter kind - used in header emission.
Definition: SemaSYCL.cpp:5533
static void collectSYCLAttributes(SemaSYCL &S, FunctionDecl *FD, llvm::SmallVectorImpl< Attr * > &Attrs, bool DirectlyCalled)
Definition: SemaSYCL.cpp:527
static bool isDefaultSPIRArch(ASTContext &Context)
Definition: SemaSYCL.cpp:1174
static bool isSYCLPrivateMemoryVar(VarDecl *VD)
Definition: SemaSYCL.cpp:1002
static void addScopeAttrToLocalVars(CXXMethodDecl &F)
Definition: SemaSYCL.cpp:1006
static std::pair< std::string, std::string > constructFreeFunctionKernelName(SemaSYCL &SemaSYCLRef, const FunctionDecl *FreeFunc, MangleContext &MC)
Definition: SemaSYCL.cpp:1110
static QualType GetSYCLKernelObjectType(const FunctionDecl *KernelCaller)
Definition: SemaSYCL.cpp:1051
static ParmVarDecl * getSyclKernelHandlerArg(FunctionDecl *KernelCallerFunc)
Definition: SemaSYCL.cpp:1181
static target getAccessTarget(QualType FieldTy, const ClassTemplateSpecializationDecl *AccTy)
Definition: SemaSYCL.cpp:1064
static std::string EmitShim(raw_ostream &OS, unsigned &ShimCounter, const std::string &LastShim, const NamespaceDecl *AnonNS)
Definition: SemaSYCL.cpp:6347
static void unsupportedFreeFunctionParamType()
Definition: SemaSYCL.cpp:969
static ParamDesc makeParamDesc(const FieldDecl *Src, QualType Ty)
Creates a kernel parameter descriptor.
Definition: SemaSYCL.cpp:951
static void EmitShims(raw_ostream &OS, unsigned &ShimCounter, const DeclContext *DC, std::string &NameForLastShim, PrintingPolicy &Policy)
Definition: SemaSYCL.cpp:6367
static constexpr llvm::StringLiteral LibstdcxxFailedAssertion
Definition: SemaSYCL.cpp:69
static void PrintNSClosingBraces(raw_ostream &OS, const DeclContext *DC)
Definition: SemaSYCL.cpp:6331
static void PrintNamespaces(raw_ostream &OS, const DeclContext *DC)
Definition: SemaSYCL.cpp:6318
static bool isAccessorPropertyType(QualType Ty, SYCLTypeAttr::SYCLType TypeName)
Definition: SemaSYCL.cpp:99
static constexpr llvm::StringLiteral FinalizeMethodName
Definition: SemaSYCL.cpp:68
static void reportConflictingAttrs(SemaSYCL &S, FunctionDecl *F, const Attr *A1, const Attr *A2)
Definition: SemaSYCL.cpp:513
static constexpr llvm::StringLiteral InitMethodName
Definition: SemaSYCL.cpp:64
This file declares semantic analysis for SYCL constructs.
SourceLocation End
Defines version macros and version-related utility functions for Clang.
DeviceFunctionTracker(SemaSYCL &S)
Definition: SemaSYCL.cpp:722
DiagDeviceFunction(SemaSYCL &S, const llvm::SmallPtrSetImpl< const FunctionDecl * > &RecursiveFuncs)
Definition: SemaSYCL.cpp:568
bool TraverseStaticAssertDecl(StaticAssertDecl *D)
Definition: SemaSYCL.cpp:661
bool VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E)
Definition: SemaSYCL.cpp:640
bool VisitCallExpr(CallExpr *e)
Definition: SemaSYCL.cpp:575
bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc)
Definition: SemaSYCL.cpp:655
bool TraverseConstantArrayTypeLoc(const ConstantArrayTypeLoc &ArrLoc)
Definition: SemaSYCL.cpp:671
void CheckBody(Stmt *ToBeDiagnosed)
Definition: SemaSYCL.cpp:573
bool TraverseVarDecl(VarDecl *VD)
Definition: SemaSYCL.cpp:647
bool TraverseIfStmt(IfStmt *S)
Definition: SemaSYCL.cpp:675
bool TraverseCaseStmt(CaseStmt *S)
Definition: SemaSYCL.cpp:665
bool VisitCXXTypeidExpr(CXXTypeidExpr *E)
Definition: SemaSYCL.cpp:634
ExprResult TransformDeclRefExpr(DeclRefExpr *DRE)
Definition: SemaSYCL.cpp:930
KernelBodyTransform(std::pair< DeclaratorDecl *, DeclaratorDecl * > &MPair, Sema &S)
Definition: SemaSYCL.cpp:925
bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call)
Definition: SemaSYCL.cpp:978
MarkWIScopeFnVisitor(ASTContext &Ctx)
Definition: SemaSYCL.cpp:976
void Visit(const TemplateArgument &TA)
Definition: SemaSYCL.cpp:5687
void VisitPointerType(const PointerType *T)
Definition: SemaSYCL.cpp:5693
void VisitTemplateTemplateArgument(const TemplateArgument &TA)
Definition: SemaSYCL.cpp:5730
void Visit(QualType T)
Definition: SemaSYCL.cpp:5675
void VisitReferenceType(const ReferenceType *RT)
Definition: SemaSYCL.cpp:5681
void VisitTypeTemplateArgument(const TemplateArgument &TA)
Definition: SemaSYCL.cpp:5719
void VisitPackTemplateArgument(const TemplateArgument &TA)
Definition: SemaSYCL.cpp:5778
SYCLFwdDeclEmitter(raw_ostream &OS, const LangOptions &LO)
Definition: SemaSYCL.cpp:5665
void VisitTagType(const TagType *T)
Definition: SemaSYCL.cpp:5701
void VisitIntegralTemplateArgument(const TemplateArgument &TA)
Definition: SemaSYCL.cpp:5724
void VisitPackTemplateArgument(const TemplateArgument &TA)
Definition: SemaSYCL.cpp:5907
void VisitTagType(const TagType *T)
Definition: SemaSYCL.cpp:5847
void VisitTemplateArgument(const TemplateArgument &TA)
Definition: SemaSYCL.cpp:5878
void VisitIntegralTemplateArgument(const TemplateArgument &TA)
Definition: SemaSYCL.cpp:5889
void Visit(QualType T)
Definition: SemaSYCL.cpp:5827
void Visit(const TemplateArgument &TA)
Definition: SemaSYCL.cpp:5841
SYCLKernelNameTypePrinter(raw_ostream &OS, PrintingPolicy &Policy)
Definition: SemaSYCL.cpp:5824
void VisitType(const Type *T)
Definition: SemaSYCL.cpp:5837
void VisitTemplateTemplateArgument(const TemplateArgument &TA)
Definition: SemaSYCL.cpp:5902
void VisitTypeTemplateArgument(const TemplateArgument &TA)
Definition: SemaSYCL.cpp:5882
void Visit(const TemplateArgument &TA)
Definition: SemaSYCL.cpp:4636
void VisitIntegralTemplateArgument(const TemplateArgument &TA)
Definition: SemaSYCL.cpp:4756
void VisitTemplateTemplateArgument(const TemplateArgument &TA)
Definition: SemaSYCL.cpp:4762
void VisitBuiltinType(const BuiltinType *TT)
Definition: SemaSYCL.cpp:4642
SYCLKernelNameTypeVisitor(SemaSYCL &S, SourceLocation KernelInvocationFuncLoc, QualType KernelNameType, bool IsUnnamedKernel)
Definition: SemaSYCL.cpp:4612
void VisitTagType(const TagType *TT)
Definition: SemaSYCL.cpp:4652
void Visit(QualType T)
Definition: SemaSYCL.cpp:4619
void VisitTypeTemplateArgument(const TemplateArgument &TA)
Definition: SemaSYCL.cpp:4748
void VisitPackTemplateArgument(const TemplateArgument &TA)
Definition: SemaSYCL.cpp:4774
void DiagnoseKernelNameType(const NamedDecl *DeclNamed)
Definition: SemaSYCL.cpp:4656
llvm::SmallPtrSetImpl< FunctionDecl * > & GetDeviceFunctions()
Definition: SemaSYCL.cpp:914
SingleDeviceFunctionTracker(DeviceFunctionTracker &P, Decl *Kernel)
Definition: SemaSYCL.cpp:901
FunctionDecl * GetKernelBody()
Definition: SemaSYCL.cpp:908
FunctionDecl * GetSYCLKernel()
Definition: SemaSYCL.cpp:906
llvm::SmallVectorImpl< Attr * > & GetCollectedAttributes()
Definition: SemaSYCL.cpp:910
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:185
SourceManager & getSourceManager()
Definition: ASTContext.h:708
uint64_t getFieldOffset(const ValueDecl *FD) const
Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
QualType getRecordType(const RecordDecl *Decl) const
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2605
RecordDecl * buildImplicitRecord(StringRef Name, RecordDecl::TagKind TK=RecordDecl::TagKind::Struct) const
Create a new implicit TU-level CXXRecordDecl or RecordDecl declaration.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
IdentifierTable & Idents
Definition: ASTContext.h:647
Builtin::Context & BuiltinInfo
Definition: ASTContext.h:649
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
const ConstantArrayType * getAsConstantArrayType(QualType T) const
Definition: ASTContext.h:2782
const LangOptions & getLangOpts() const
Definition: ASTContext.h:778
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
CanQualType CharTy
Definition: ASTContext.h:1096
QualType getQualifiedType(SplitQualType split) const
Un-split a SplitQualType.
Definition: ASTContext.h:2171
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2355
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType VoidTy
Definition: ASTContext.h:1094
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
Definition: ASTContext.h:1583
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:760
QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const
Return the uniqued reference to the type for an address space qualified type with the specified type ...
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:1076
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
Definition: RecordLayout.h:38
unsigned getFieldCount() const
getFieldCount - Get the number of fields in the layout.
Definition: RecordLayout.h:196
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
Definition: RecordLayout.h:249
PtrTy get() const
Definition: Ownership.h:170
bool isInvalid() const
Definition: Ownership.h:166
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2716
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: Type.h:3530
ArraySizeModifier getSizeModifier() const
Definition: Type.h:3544
QualType getElementType() const
Definition: Type.h:3542
unsigned getIndexTypeCVRQualifiers() const
Definition: Type.h:3552
Attr - This represents one attribute.
Definition: Attr.h:46
attr::Kind getKind() const
Definition: Attr.h:92
SourceLocation getLocation() const
Definition: Attr.h:99
This class is used for builtin types like 'int'.
Definition: Type.h:2989
llvm::StringRef getName(unsigned ID) const
Return the identifier name for the specified builtin, e.g.
Definition: Builtins.h:103
Represents a base class of a C++ class.
Definition: DeclCXX.h:146
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclCXX.h:194
bool isVirtual() const
Determines whether the base class is a virtual base class (or not).
Definition: DeclCXX.h:203
QualType getType() const
Retrieves the type of the base class.
Definition: DeclCXX.h:249
AccessSpecifier getAccessSpecifier() const
Returns the access specifier for this base specifier.
Definition: DeclCXX.h:230
A C++ dynamic_cast expression (C++ [expr.dynamic.cast]).
Definition: ExprCXX.h:478
Represents a call to a member function that may be written either with member call syntax (e....
Definition: ExprCXX.h:176
static CXXMemberCallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RP, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0)
Definition: ExprCXX.cpp:626
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2060
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition: DeclCXX.h:2186
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
void setBases(CXXBaseSpecifier const *const *Bases, unsigned NumBases)
Sets the base classes of this struct or class.
Definition: DeclCXX.cpp:195
void completeDefinition() override
Indicates that the definition of this class is now complete.
Definition: DeclCXX.cpp:2055
base_class_range bases()
Definition: DeclCXX.h:619
TypeSourceInfo * getLambdaTypeInfo() const
Definition: DeclCXX.h:1862
bool isLambda() const
Determine whether this class describes a lambda function object.
Definition: DeclCXX.h:1022
method_range methods() const
Definition: DeclCXX.h:661
unsigned getNumBases() const
Retrieves the number of base classes of this class.
Definition: DeclCXX.h:613
static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr, bool DelayTypeCreation=false)
Definition: DeclCXX.cpp:132
base_class_iterator bases_begin()
Definition: DeclCXX.h:626
capture_const_range captures() const
Definition: DeclCXX.h:1101
bool hasDefinition() const
Definition: DeclCXX.h:571
llvm::iterator_range< base_class_const_iterator > base_class_const_range
Definition: DeclCXX.h:617
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
Definition: DeclCXX.cpp:1594
static CXXReinterpretCastExpr * Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind Kind, Expr *Op, const CXXCastPath *Path, TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation RParenLoc, SourceRange AngleBrackets)
Definition: ExprCXX.cpp:803
A C++ typeid expression (C++ [expr.typeid]), which gets the type_info that corresponds to the supplie...
Definition: ExprCXX.h:845
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2872
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
Definition: Expr.cpp:1549
Expr * getCallee()
Definition: Expr.h:3022
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:3042
Decl * getCalleeDecl()
Definition: Expr.h:3036
llvm::iterator_range< iterator > callees()
Iterator access to callees/children of the node.
Definition: CallGraph.h:199
The AST-based call graph.
Definition: CallGraph.h:43
CallGraphNode * getRoot() const
Get the virtual root of the graph, all the functions available externally are represented as callees ...
Definition: CallGraph.h:103
void addToCallGraph(Decl *D)
Populate the call graph with the functions in the given declaration.
Definition: CallGraph.h:69
CallGraphNode * getNode(const Decl *) const
Lookup the node for the given declaration.
Definition: CallGraph.cpp:219
void setSkipConstantExpressions(ASTContext &Context)
Definition: CallGraph.h:149
CaseStmt - Represent a case statement.
Definition: Stmt.h:1801
SourceLocation getEnd() const
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition: CharUnits.h:185
Declaration of a class template.
Represents a class template specialization, which refers to a class template with a given set of temp...
const TemplateArgumentList & getTemplateArgs() const
Retrieve the template arguments of the class template specialization.
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1606
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition: Stmt.cpp:383
A simple visitor class that helps create template argument visitors.
Represents the canonical version of C arrays with a specified constant size.
Definition: Type.h:3568
const Expr * getSizeExpr() const
Return a pointer to the size expression.
Definition: Type.h:3664
llvm::APInt getSize() const
Return the constant array size as an APInt.
Definition: Type.h:3624
A POD class for pairing a NamedDecl* with an access specifier.
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1436
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1282
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2066
bool isTranslationUnit() const
Definition: DeclBase.h:2142
void addDecl(Decl *D)
Add the declaration D into this context.
Definition: DeclBase.cpp:1716
DeclContext * getEnclosingNamespaceContext()
Retrieve the nearest enclosing namespace context.
Definition: DeclBase.cpp:1956
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition: DeclBase.h:2322
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1260
ValueDecl * getDecl()
Definition: Expr.h:1328
DeclarationNameInfo getNameInfo() const
Definition: Expr.h:1332
SourceLocation getTemplateKeywordLoc() const
Retrieve the location of the template keyword preceding this name, if any.
Definition: Expr.h:1381
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Definition: Expr.cpp:488
NestedNameSpecifierLoc getQualifierLoc() const
If the name was qualified, retrieves the nested-name-specifier that precedes the name,...
Definition: Expr.h:1347
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1497
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
bool hasAttrs() const
Definition: DeclBase.h:524
ASTContext & getASTContext() const LLVM_READONLY
Definition: DeclBase.cpp:501
void addAttr(Attr *A)
Definition: DeclBase.cpp:991
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition: DeclBase.cpp:132
Kind
Lists the kind of concrete classes of Decl.
Definition: DeclBase.h:89
AttrVec & getAttrs()
Definition: DeclBase.h:530
static DeclContext * castToDeclContext(const Decl *)
Definition: DeclBase.cpp:1032
bool isInvalidDecl() const
Definition: DeclBase.h:594
SourceLocation getLocation() const
Definition: DeclBase.h:445
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition: DeclBase.h:565
void setIsUsed()
Set whether the declaration is used, in the sense of odr-use.
Definition: DeclBase.h:614
attr_range attrs() const
Definition: DeclBase.h:541
AccessSpecifier getAccess() const
Definition: DeclBase.h:513
bool isInAnonymousNamespace() const
Definition: DeclBase.cpp:393
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
bool hasAttr() const
Definition: DeclBase.h:583
T * getAttr() const
Definition: DeclBase.h:579
DeclContext * getDeclContext()
Definition: DeclBase.h:454
The name of a declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Decl.h:823
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:193
SyclOptReportHandler & getSYCLOptReport()
Retrieve the SyclOptReport info.
Definition: Diagnostic.h:560
An instance of this object exists for each enum constant that is defined.
Definition: Decl.h:3300
Represents an enum.
Definition: Decl.h:3870
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
Definition: Type.h:5587
This represents one expression.
Definition: Expr.h:110
void setType(QualType t)
Definition: Expr.h:143
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition: Expr.h:175
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition: Expr.h:437
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition: Expr.h:192
Expr * IgnoreUnlessSpelledInSource()
Skip past any invisible AST nodes which might surround this statement, such as ExprWithCleanups or Im...
Definition: Expr.cpp:3164
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition: Expr.h:221
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
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
QualType getType() const
Definition: Expr.h:142
static ExprValueKind getValueKindForType(QualType T)
getValueKindForType - Given a formal return or parameter type, give its value kind.
Definition: Expr.h:427
bool isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result=nullptr, SourceLocation *Loc=nullptr) const
isCXX11ConstantExpr - Return true if this expression is a constant expression in C++11.
Represents difference between two FPOptions values.
Definition: LangOptions.h:956
Represents a member of a struct/union/class.
Definition: Decl.h:3060
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
Definition: Decl.cpp:4549
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition: Decl.h:3273
Represents a function declaration or definition.
Definition: Decl.h:1972
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition: Decl.cpp:3240
param_iterator param_end()
Definition: Decl.h:2699
bool isInlined() const
Determine whether this function should be inlined, because it is either marked "inline" or "constexpr...
Definition: Decl.h:2833
QualType getReturnType() const
Definition: Decl.h:2757
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition: Decl.cpp:3621
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition: Decl.cpp:4182
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, Expr *TrailingRequiresClause=nullptr)
Definition: Decl.h:2161
void setImplicitlyInline(bool I=true)
Flag that this function is implicitly inline.
Definition: Decl.h:2828
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2686
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any.
Definition: Decl.cpp:3983
void setBody(Stmt *B)
Definition: Decl.cpp:3252
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3696
FunctionDecl * getDefinition()
Get the definition for this declaration.
Definition: Decl.h:2254
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
Definition: Decl.cpp:3207
const ParmVarDecl * getParamDecl(unsigned i) const
Definition: Decl.h:2709
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.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
Definition: Stmt.h:2138
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition: Expr.cpp:2129
Describes an C or C++ initializer list.
Definition: Expr.h:4888
unsigned getNumInits() const
Definition: Expr.h:4918
Expr * updateInit(const ASTContext &C, unsigned Init, Expr *expr)
Updates the initializer at index Init with the new expression expr, and returns the old expression at...
Definition: Expr.cpp:2448
void reserveInits(const ASTContext &C, unsigned NumInits)
Reserve space for some number of initializers.
Definition: Expr.cpp:2439
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateDefault(SourceLocation InitLoc)
Create a default initialization.
static InitializationKind CreateDirect(SourceLocation InitLoc, SourceLocation LParenLoc, SourceLocation RParenLoc)
Create a direct initialization.
static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)
Create a copy initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
Describes an entity that is being initialized.
static InitializedEntity InitializeBase(ASTContext &Context, const CXXBaseSpecifier *Base, bool IsInheritedVirtualBase, const InitializedEntity *Parent=nullptr)
Create the initialization entity for a base class subobject.
Definition: SemaInit.cpp:3471
static InitializedEntity InitializeMember(FieldDecl *Member, const InitializedEntity *Parent=nullptr, bool Implicit=false)
Create the initialization entity for a member subobject.
static InitializedEntity InitializeElement(ASTContext &Context, unsigned Index, const InitializedEntity &Parent)
Create the initialization entity for an array element.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
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
Describes the capture of a variable or of this, or of a C++1y init-capture.
Definition: LambdaCapture.h:25
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:482
MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...
Definition: Mangle.h:45
void mangleName(GlobalDecl GD, raw_ostream &)
Definition: Mangle.cpp:139
virtual void mangleCanonicalTypeName(QualType T, raw_ostream &, bool NormalizeIntegers=false)=0
Generates a unique string for an externally visible type for use with TBAA or type uniquing.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3224
This represents a decl that may have a name.
Definition: Decl.h:249
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:276
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Definition: Decl.h:292
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:270
virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const
Appends a human-readable name for this declaration into the given stream.
Definition: Decl.cpp:1830
void printQualifiedName(raw_ostream &OS) const
Returns a human-readable qualified name for this declaration, like A::B::i, for i being member of nam...
Definition: Decl.cpp:1691
Represent a C++ namespace.
Definition: Decl.h:548
bool isAnonymousNamespace() const
Returns true if this is an anonymous namespace declaration.
Definition: Decl.h:606
bool isInline() const
Returns true if this is an inline namespace declaration.
Definition: Decl.h:611
A C++ nested-name-specifier augmented with source location information.
NonTypeTemplateParmDecl - Declares a non-type template parameter, e.g., "Size" in.
Represents a parameter to a function.
Definition: Decl.h:1762
QualType getOriginalType() const
Definition: Decl.cpp:2928
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
Definition: Decl.cpp:2919
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:3151
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
A (possibly-)qualified type.
Definition: Type.h:940
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
Definition: Type.cpp:3493
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:1007
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:7371
LangAS getAddressSpace() const
Return the address space of this type.
Definition: Type.h:7497
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition: Type.h:7411
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition: Type.h:7572
QualType getCanonicalType() const
Definition: Type.h:7423
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:7465
std::string getAsString() const
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition: Type.h:1327
The collection of all-type qualifiers we support.
Definition: Type.h:318
void print(raw_ostream &OS, const PrintingPolicy &Policy, bool appendSpaceIfNonEmpty=false) const
void setAddressSpace(LangAS space)
Definition: Type.h:577
LangAS getAddressSpace() const
Definition: Type.h:557
Represents a struct/union/class.
Definition: Decl.h:4171
field_iterator field_end() const
Definition: Decl.h:4380
field_range fields() const
Definition: Decl.h:4377
virtual void completeDefinition()
Note that the definition of this type is now complete.
Definition: Decl.cpp:5085
llvm::iterator_range< specific_decl_iterator< FieldDecl > > field_range
Definition: Decl.h:4375
field_iterator field_begin() const
Definition: Decl.cpp:5073
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
Definition: Redeclarable.h:226
Base for LValueReferenceType and RValueReferenceType.
Definition: Type.h:3392
QualType getPointeeType() const
Definition: Type.h:3410
Represents a __builtin_base_type expression.
Definition: ExprCXX.h:5459
Represents a __builtin_field_type expression.
Definition: ExprCXX.h:5372
Represents a __builtin_num_bases expression.
Definition: ExprCXX.h:5413
Represents a __builtin_num_fields expression.
Definition: ExprCXX.h:5320
void addVarDecl(const VarDecl *VD)
Definition: SemaSYCL.cpp:6235
bool emit(StringRef MainSrc)
Definition: SemaSYCL.cpp:6277
void emit(raw_ostream &Out)
Emits contents of the header into given stream.
Definition: SemaSYCL.cpp:5931
void addParamDesc(kernel_param_kind_t Kind, int Info, unsigned Offset)
Adds a kernel parameter descriptor to current kernel invocation descriptor.
Definition: SemaSYCL.cpp:6214
void startKernel(const FunctionDecl *SyclKernel, QualType KernelNameType, SourceLocation Loc, bool IsESIMD, bool IsUnnamedKernel, int64_t ObjSize)
Signals that subsequent parameter descriptor additions will go to the kernel with given name.
Definition: SemaSYCL.cpp:6205
void endKernel()
Signals that addition of parameter descriptors to current kernel invocation descriptor has finished.
Definition: SemaSYCL.cpp:6225
SYCLIntegrationHeader(SemaSYCL &S)
Definition: SemaSYCL.cpp:6233
void addSpecConstant(StringRef IDName, QualType IDType)
Registers a specialization constant to emit info for it into the header.
Definition: SemaSYCL.cpp:6229
void updateKernelNames(const FunctionDecl *SyclKernel, StringRef Name, StringRef StableName)
Update the names of a kernel description based on its SyclKernel.
Definition: SemaSYCL.h:92
std::string ComputeName(ASTContext &Context) const
Definition: Expr.cpp:646
static SYCLUniqueStableIdExpr * Create(const ASTContext &Ctx, SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, Expr *E)
Definition: Expr.cpp:631
static SYCLUniqueStableNameExpr * Create(const ASTContext &Ctx, SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, TypeSourceInfo *TSI)
Definition: Expr.cpp:578
std::string ComputeName(ASTContext &Context) const
Definition: Expr.cpp:592
A generic diagnostic builder for errors which may or may not be deferred.
Definition: SemaBase.h:175
@ K_Deferred
Create a deferred diagnostic, which is emitted only if the function it's attached to is codegen'ed.
Definition: SemaBase.h:189
@ K_ImmediateWithCallStack
Emit the diagnostic immediately, and, if it's a warning or error, also emit a call stack showing how ...
Definition: SemaBase.h:185
bool isFDReachableFromSyclDevice(const FunctionDecl *Callee, const FunctionDecl *Caller)
Definition: SemaBase.h:139
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:57
DeviceDiagnosticReason
Bitmask to contain the list of reasons a single diagnostic should be emitted, based on its language.
Definition: SemaBase.h:99
@ Sycl
SYCL specific diagnostic.
@ None
Diagnostic doesn't apply to anything.
ASTContext & getASTContext() const
Definition: SemaBase.cpp:9
Sema & SemaRef
Definition: SemaBase.h:40
const LangOptions & getLangOpts() const
Definition: SemaBase.cpp:11
DiagnosticsEngine & getDiagnostics() const
Definition: SemaBase.cpp:10
void ConstructOpenCLKernel(FunctionDecl *KernelCallerFunc, MangleContext &MC)
Definition: SemaSYCL.cpp:4949
bool isDeclAllowedInSYCLDeviceCode(const Decl *D)
Definition: SemaSYCL.cpp:375
void finalizeSYCLDelayedAnalysis(const FunctionDecl *Caller, const FunctionDecl *Callee, SourceLocation Loc, DeviceDiagnosticReason Reason)
Finishes analysis of the deferred functions calls that may be not properly declared for device compil...
Definition: SemaSYCL.cpp:5477
ExprResult BuildUniqueStableIdExpr(SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, Expr *E)
Definition: SemaSYCL.cpp:6555
ExprResult ActOnSYCLBuiltinFieldTypeExpr(ParsedType PT, Expr *Idx)
Get a value based on the type of the given field number so that callers can wrap it in a decltype() t...
Definition: SemaSYCL.cpp:140
void CheckSYCLKernelCall(FunctionDecl *CallerFunc, ArrayRef< const Expr * > Args)
Definition: SemaSYCL.cpp:4779
ExprResult ActOnUniqueStableIdExpr(SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, Expr *E)
Definition: SemaSYCL.cpp:6587
SYCLIntegrationFooter & getSyclIntegrationFooter()
Definition: SemaSYCL.h:285
SYCLIntegrationHeader & getSyclIntegrationHeader()
Lazily creates and returns SYCL integration header instance.
Definition: SemaSYCL.h:279
ExprResult BuildSYCLBuiltinFieldTypeExpr(SourceLocation Loc, QualType SourceTy, Expr *Idx)
Definition: SemaSYCL.cpp:149
@ KernelCallFunctionPointer
Definition: SemaSYCL.h:306
@ KernelCallVirtualFunction
Definition: SemaSYCL.h:303
@ KernelCallUndefinedFunction
Definition: SemaSYCL.h:311
@ KernelCallRecursiveFunction
Definition: SemaSYCL.h:305
@ KernelCallDllimportFunction
Definition: SemaSYCL.h:309
ExprResult ActOnSYCLBuiltinNumBasesExpr(ParsedType PT)
Get the number of base classes within the parsed type.
Definition: SemaSYCL.cpp:219
ExprResult ActOnSYCLBuiltinNumFieldsExpr(ParsedType PT)
Get the number of fields or captures within the parsed type.
Definition: SemaSYCL.cpp:113
void copySYCLKernelAttrs(CXXMethodDecl *CallOperator)
Definition: SemaSYCL.cpp:4848
void checkSYCLDeviceVarDecl(VarDecl *Var)
Definition: SemaSYCL.cpp:473
ExprResult BuildUniqueStableNameExpr(SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, TypeSourceInfo *TSI)
Definition: SemaSYCL.cpp:6593
void SetSYCLKernelNames()
Definition: SemaSYCL.cpp:4896
llvm::SetVector< Decl * > & syclDeviceDecls()
Definition: SemaSYCL.h:276
ExprResult BuildSYCLBuiltinNumFieldsExpr(SourceLocation Loc, QualType SourceTy)
Definition: SemaSYCL.cpp:122
void addSyclDeviceDecl(Decl *d)
Definition: SemaSYCL.h:275
void MarkDevices()
Definition: SemaSYCL.cpp:5311
void deepTypeCheckForDevice(SourceLocation UsedAt, llvm::DenseSet< QualType > Visited, ValueDecl *DeclToCheck)
Definition: SemaSYCL.cpp:5385
ExprResult BuildSYCLBuiltinNumBasesExpr(SourceLocation Loc, QualType SourceTy)
Definition: SemaSYCL.cpp:228
SemaSYCL(Sema &S)
Definition: SemaSYCL.cpp:396
bool checkAllowedSYCLInitializer(VarDecl *VD)
Definition: SemaSYCL.cpp:5510
ExprResult ActOnSYCLBuiltinBaseTypeExpr(ParsedType PT, Expr *Idx)
Get a value based on the type of the given base number so that callers can wrap it in a decltype() to...
Definition: SemaSYCL.cpp:246
ExprResult BuildSYCLBuiltinBaseTypeExpr(SourceLocation Loc, QualType SourceTy, Expr *Idx)
Definition: SemaSYCL.cpp:255
void ProcessFreeFunction(FunctionDecl *FD)
Definition: SemaSYCL.cpp:5334
static bool isSyclType(QualType Ty, SYCLTypeAttr::SYCLType TypeName)
Check whether Ty corresponds to a SYCL type of name TypeName.
Definition: SemaSYCL.cpp:73
SemaDiagnosticBuilder DiagIfDeviceCode(SourceLocation Loc, unsigned DiagID, DeviceDiagnosticReason Reason=DeviceDiagnosticReason::Sycl|DeviceDiagnosticReason::Esimd)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...
Definition: SemaSYCL.cpp:5361
ExprResult ActOnUniqueStableNameExpr(SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, ParsedType ParsedTy)
Definition: SemaSYCL.cpp:6601
A RAII object to temporarily push a declaration context.
Definition: Sema.h:2558
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:462
FPOptionsOverride CurFPFeatureOverrides()
Definition: Sema.h:1449
bool AnyWorkGroupSizesDiffer(const Expr *LHSXDim, const Expr *LHSYDim, const Expr *LHSZDim, const Expr *RHSXDim, const Expr *RHSYDim, const Expr *RHSZDim)
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
Definition: SemaExpr.cpp:2277
void PushFunctionScope()
Enter a new function scope.
Definition: Sema.cpp:2238
DeviceDiagnosticReason getEmissionReason(const FunctionDecl *Decl)
Definition: SemaDecl.cpp:20546
const LangOptions & LangOpts
Definition: Sema.h:855
const LangOptions & getLangOpts() const
Definition: Sema.h:519
void CheckSYCLAddIRAttributesFunctionAttrConflicts(Decl *D)
CXXBaseSpecifier * CheckBaseSpecifier(CXXRecordDecl *Class, SourceRange SpecifierRange, bool Virtual, AccessSpecifier Access, TypeSourceInfo *TInfo, SourceLocation EllipsisLoc)
ActOnBaseSpecifier - Parsed a base specifier.
ExprResult DefaultLvalueConversion(Expr *E)
Definition: SemaExpr.cpp:721
bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, SourceLocation Loc, SourceRange Range, CXXCastPath *BasePath=nullptr, bool IgnoreAccess=false)
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
Definition: SemaDecl.cpp:20563
SourceManager & getSourceManager() const
Definition: Sema.h:524
ASTContext & getASTContext() const
Definition: Sema.h:526
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
Definition: SemaExpr.cpp:5237
Expr * MaybeCreateExprWithCleanups(Expr *SubExpr)
MaybeCreateExprWithCleanups - If the current full-expression requires any cleanups,...
bool CheckMaxAllowedWorkGroupSize(const Expr *RWGSXDim, const Expr *RWGSYDim, const Expr *RWGSZDim, const Expr *MWGSXDim, const Expr *MWGSYDim, const Expr *MWGSZDim)
MemberExpr * BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK, ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs=nullptr)
bool GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, const FunctionProtoType *Proto, unsigned FirstParam, ArrayRef< Expr * > Args, SmallVectorImpl< Expr * > &AllArgs, VariadicCallType CallType=VariadicDoesNotApply, bool AllowExplicit=false, bool IsListInitialization=false)
GatherArgumentsForCall - Collector argument expressions for various form of call prototypes.
Definition: SemaExpr.cpp:6029
DeclContext * getCurLexicalContext() const
Definition: Sema.h:701
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)
Definition: SemaType.cpp:2820
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
CharSourceRange getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
A trivial tuple used to represent a source range.
Represents a C++11 static_assert declaration.
Definition: DeclCXX.h:4058
Stmt - This represents one statement.
Definition: Stmt.h:84
void AddKernelArgs(const FunctionDecl *FD, StringRef ArgDescName, StringRef ArgType, SourceLocation ArgLoc, unsigned ArgSize, StringRef ArgDesc, StringRef ArgDecomposedField)
Represents the declaration of a struct/union/class/enum.
Definition: Decl.h:3587
void startDefinition()
Starts the definition of this tag declaration.
Definition: Decl.cpp:4741
void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override
Pretty-print the unqualified name of this declaration.
Definition: Decl.cpp:4807
TagKind getTagKind() const
Definition: Decl.h:3782
TagDecl * getDecl() const
Definition: Type.cpp:4032
IntType getInt64Type() const
Definition: TargetInfo.h:405
virtual bool hasFloat128Type() const
Determine whether the __float128 type is supported on this target.
Definition: TargetInfo.h:693
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1256
A template argument list.
Definition: DeclTemplate.h:244
unsigned size() const
Retrieve the number of template arguments in this template argument list.
Definition: DeclTemplate.h:280
const TemplateArgument & get(unsigned Idx) const
Retrieve the template argument at a given index.
Definition: DeclTemplate.h:265
Location wrapper for a TemplateArgument.
Definition: TemplateBase.h:524
Represents a template argument.
Definition: TemplateBase.h:61
pack_iterator pack_end() const
Iterator referencing one past the last argument of a template argument pack.
Definition: TemplateBase.h:425
pack_iterator pack_begin() const
Iterator referencing the first argument of a template argument pack.
Definition: TemplateBase.h:418
QualType getAsType() const
Retrieve the type for a type template argument.
Definition: TemplateBase.h:319
ArrayRef< TemplateArgument > getPackAsArray() const
Return the array of arguments in this template argument pack.
Definition: TemplateBase.h:444
llvm::APSInt getAsIntegral() const
Retrieve the template argument as an integral value.
Definition: TemplateBase.h:363
TemplateName getAsTemplate() const
Retrieve the template name for a template name argument.
Definition: TemplateBase.h:343
bool isNull() const
Determine whether this template argument has no value.
Definition: TemplateBase.h:298
unsigned pack_size() const
The number of template arguments in the given template argument pack.
Definition: TemplateBase.h:438
void print(const PrintingPolicy &Policy, raw_ostream &Out, bool IncludeType) const
Print this template argument to the given output stream.
QualType getIntegralType() const
Retrieve the type of the integral value.
Definition: TemplateBase.h:377
@ Pack
The template argument is actually a parameter pack.
Definition: TemplateBase.h:107
ArgKind getKind() const
Return the kind of stored template argument.
Definition: TemplateBase.h:295
The base class of all kinds of template declarations (e.g., class, function, etc.).
Definition: DeclTemplate.h:394
NamedDecl * getTemplatedDecl() const
Get the underlying, templated declaration.
Definition: DeclTemplate.h:426
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Definition: DeclTemplate.h:413
TemplateDecl * getAsTemplateDecl() const
Retrieve the underlying template declaration that this template name refers to, if known.
Stores a list of template parameters for a TemplateDecl and its derived classes.
Definition: DeclTemplate.h:73
A semantic tree transformation that allows one to transform one abstract syntax tree into another.
const Type * getTypeForDecl() const
Definition: Decl.h:3417
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:59
SourceLocation getBeginLoc() const
Get the begin source location.
Definition: TypeLoc.cpp:192
A container of type source information.
Definition: Type.h:7342
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition: TypeLoc.h:256
An operation on a type.
Definition: TypeVisitor.h:64
The base class of the type hierarchy.
Definition: Type.h:1813
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1881
bool isVoidType() const
Definition: Type.h:7939
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
Definition: Type.h:8117
bool isRValueReferenceType() const
Definition: Type.h:7644
bool isArrayType() const
Definition: Type.h:7690
bool isPointerType() const
Definition: Type.h:7624
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:8227
bool isReferenceType() const
Definition: Type.h:7636
bool isScalarType() const
Definition: Type.h:8038
bool isVariableArrayType() const
Definition: Type.h:7702
const Type * getArrayElementTypeNoTypeQual() const
If this is an array type, return the element type of the array, potentially with type qualifiers miss...
Definition: Type.cpp:427
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:705
bool isLValueReferenceType() const
Definition: Type.h:7640
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition: Type.h:7908
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2661
bool isUndeducedType() const
Determine whether this type is an undeduced type, meaning that it somehow involves a C++11 'auto' typ...
Definition: Type.h:8073
bool isFunctionType() const
Definition: Type.h:7620
bool isStructureOrClassType() const
Definition: Type.cpp:657
bool isVectorType() const
Definition: Type.h:7730
bool isAnyPointerType() const
Definition: Type.h:7628
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8160
bool isNullPtrType() const
Definition: Type.h:7972
bool isRecordType() const
Definition: Type.h:7718
bool isUnionType() const
Definition: Type.cpp:671
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition: Type.cpp:1885
static UnaryOperator * Create(const ASTContext &C, Expr *input, Opcode opc, QualType type, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, bool CanOverflow, FPOptionsOverride FPFeatures)
Definition: Expr.cpp:4900
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:707
void setType(QualType newType)
Definition: Decl.h:719
QualType getType() const
Definition: Decl.h:718
Represents a variable declaration or definition.
Definition: Decl.h:919
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition: Decl.cpp:2152
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition: Decl.h:1550
bool hasInit() const
Definition: Decl.cpp:2399
void setInitStyle(InitializationStyle Style)
Definition: Decl.h:1433
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition: Decl.cpp:2258
@ CallInit
Call-style initialization (C++98)
Definition: Decl.h:927
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition: Decl.h:1214
const Expr * getInit() const
Definition: Decl.h:1356
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
Definition: Decl.h:1205
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition: Decl.h:1172
void setInit(Expr *I)
Definition: Decl.cpp:2458
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
Definition: Decl.h:1217
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
Definition: Decl.h:1250
Defines the clang::TargetInfo interface.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
@ After
Like System, but searched after the system directories.
llvm::APInt APInt
Definition: Integral.h:29
bool Init(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1472
bool Cast(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1717
std::string toString(const til::SExpr *E)
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ ICIS_NoInit
No in-class initializer.
Definition: Specifiers.h:269
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition: Specifiers.h:148
llvm::SmallVector< std::pair< llvm::StringRef, llvm::StringRef >, 2 > getSYCLVersionMacros(const LangOptions &LangOpts)
Retrieves a string representing the SYCL standard version for use in the CL_SYCL_LANGUAGE_VERSION and...
Definition: Version.cpp:129
@ CXXLanguageLinkage
Definition: Linkage.h:65
@ SC_None
Definition: Specifiers.h:247
@ SD_Automatic
Automatic storage duration (most local variables).
Definition: Specifiers.h:326
ExprResult ExprError()
Definition: Ownership.h:264
LangAS
Defines the address space values used by the address space qualifier of QualType.
Definition: AddressSpaces.h:25
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
Definition: Specifiers.h:129
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition: Specifiers.h:132
@ VK_XValue
An x-value expression is a reference to an object with independent storage but which can be "moved",...
Definition: Specifiers.h:141
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:136
const FunctionProtoType * T
@ CC_OpenCLKernel
Definition: Specifiers.h:289
@ AS_public
Definition: Specifiers.h:121
@ AS_none
Definition: Specifiers.h:124
unsigned long uint64_t
long int64_t
float __ovld __cnfn distance(float, float)
Returns the distance between p0 and p1.
#define true
Definition: stdbool.h:25
#define false
Definition: stdbool.h:26
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
Extra information about a function prototype.
Definition: Type.h:4747
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:57
unsigned SuppressUnwrittenScope
Suppress printing parts of scope specifiers that are never written, e.g., for anonymous namespaces.
void adjustForCPlusPlusFwdDecl()
Adjust this printing policy to print C++ forward declaration for a given Decl.
Definition: PrettyPrinter.h:98
unsigned PrintCanonicalTypes
Whether to print types as written or canonically.
unsigned SkipCanonicalizationOfTemplateTypeParms
Whether to skip the canonicalization (when PrintCanonicalTypes is set) for TemplateTypeParmTypes.
unsigned AnonymousTagLocations
When printing an anonymous tag name, also print the location of that entity (e.g.,...
unsigned SuppressTagKeyword
Whether type printing should skip printing the tag keyword.
unsigned SuppressTypedefs
When true prints a canonical type instead of an alias.
unsigned SuppressFinalSpecifier
When true, suppress printing final specifier.