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"
38 #include <initializer_list>
40 using namespace clang;
41 using namespace std::placeholders;
55 using ParamDesc = std::tuple<QualType, IdentifierInfo *, TypeSourceInfo *>;
67 "__init_specialization_constants_buffer";
78 if (
const auto *
Attr = RD->getAttr<SYCLTypeAttr>())
81 if (
const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
100 SYCLTypeAttr::SYCLType TypeName) {
102 if (
const auto *
Parent = dyn_cast<CXXRecordDecl>(RD->getParent()))
103 if (
const auto *
Attr =
Parent->getAttr<SYCLTypeAttr>())
110 return S.isTypeDecoratedWithDeclAttribute<SYCLSpecialClassAttr>(Ty);
116 assert(TInfo &&
"couldn't get type info from a type from the parser?");
119 return BuildSYCLBuiltinNumFieldsExpr(
TypeLoc, QT);
125 if (SemaRef.RequireCompleteType(
126 Loc, SourceTy, diag::err_sycl_type_trait_requires_complete_type,
131 Diag(
Loc, diag::err_sycl_type_trait_requires_record_type)
136 return new (getASTContext())
143 assert(TInfo &&
"couldn't get type info from a type from the parser?");
146 return BuildSYCLBuiltinFieldTypeExpr(
TypeLoc, QT, Idx);
154 if (!SemaRef.isUnevaluatedContext()) {
155 Diag(
Loc, diag::err_sycl_builtin_type_trait_evaluated)
167 if (SemaRef.RequireCompleteType(
168 Loc, SourceTy, diag::err_sycl_type_trait_requires_complete_type,
173 Diag(
Loc, diag::err_sycl_type_trait_requires_record_type)
179 std::optional<llvm::APSInt> IdxVal =
183 assert(RD &&
"Record type but no record decl?");
184 int64_t Index = IdxVal->getExtValue();
188 diag::err_sycl_type_trait_requires_nonnegative_index)
195 if (Index >= NumFields) {
197 diag::err_sycl_builtin_type_trait_index_out_of_range)
198 <<
toString(*IdxVal, 10) << SourceTy << 0;
215 return new (getASTContext())
222 assert(TInfo &&
"couldn't get type info from a type from the parser?");
225 return BuildSYCLBuiltinNumBasesExpr(
TypeLoc, QT);
231 if (SemaRef.RequireCompleteType(
232 Loc, SourceTy, diag::err_sycl_type_trait_requires_complete_type,
237 Diag(
Loc, diag::err_sycl_type_trait_requires_record_type)
242 return new (getASTContext())
248 QualType QT = SemaRef.GetTypeFromParser(PT, &TInfo);
249 assert(TInfo &&
"couldn't get type info from a type from the parser?");
252 return BuildSYCLBuiltinBaseTypeExpr(
TypeLoc, QT, Idx);
260 if (!SemaRef.isUnevaluatedContext()) {
261 Diag(
Loc, diag::err_sycl_builtin_type_trait_evaluated)
272 if (SemaRef.RequireCompleteType(
273 Loc, SourceTy, diag::err_sycl_type_trait_requires_complete_type,
278 Diag(
Loc, diag::err_sycl_type_trait_requires_record_type)
284 std::optional<llvm::APSInt> IdxVal =
288 assert(RD &&
"Record type but no record decl?");
289 int64_t Index = IdxVal->getExtValue();
293 diag::err_sycl_type_trait_requires_nonnegative_index)
301 diag::err_sycl_builtin_type_trait_index_out_of_range)
302 <<
toString(*IdxVal, 10) << SourceTy << 1;
311 return new (getASTContext())
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:
376 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
381 if (FD->getBuiltinID() &&
382 (FD->getBuiltinID() == Builtin::BI__builtin_assume_aligned ||
383 FD->getBuiltinID() == Builtin::BI__builtin_printf))
387 if (II && II->
isStr(
"__spirv_ocl_printf") &&
397 :
SemaBase(S), SyclIntHeader(nullptr), SyclIntFooter(nullptr) {}
401 return CAT->isZeroSize();
418 bool Emitting =
false;
424 S.DiagIfDeviceCode(
Loc.getBegin(), diag::err_typecheck_zero_array_size)
431 S.DiagIfDeviceCode(
Loc.getBegin(), diag::err_vla_unsupported) << 0;
446 S.DiagIfDeviceCode(
Loc.getBegin(), diag::err_type_unsupported)
451 if (Emitting && UsedAtLoc.isValid())
452 S.DiagIfDeviceCode(UsedAtLoc.getBegin(), diag::note_used_here);
457 if (!
Visited.insert(Ty).second)
460 if (
const auto *ATy = dyn_cast<AttributedType>(Ty))
464 for (
const auto &Field : RD->fields())
466 }
else if (
const auto *FPTy = dyn_cast<FunctionProtoType>(Ty)) {
467 for (
const auto &ParamTy : FPTy->param_types())
475 "Should only be called during SYCL compilation");
497 if (!Callee->getIdentifier())
506 Callee->getNumParams() == 0 && Callee->getReturnType()->isVoidType() &&
515 S.
Diag(F->
getLocation(), diag::err_conflicting_sycl_kernel_attributes);
529 bool DirectlyCalled) {
538 llvm::copy_if(FD->
getAttrs(), std::back_inserter(Attrs), [](
Attr *A) {
540 return isa<IntelReqdSubGroupSizeAttr, IntelNamedSubGroupSizeAttr,
541 SYCLReqdWorkGroupSizeAttr, SYCLWorkGroupSizeHintAttr,
542 SYCLIntelKernelArgsRestrictAttr, SYCLIntelNumSimdWorkItemsAttr,
543 SYCLIntelSchedulerTargetFmaxMhzAttr,
544 SYCLIntelMaxWorkGroupSizeAttr, SYCLIntelMaxGlobalWorkDimAttr,
545 SYCLIntelMinWorkGroupsPerComputeUnitAttr,
546 SYCLIntelMaxWorkGroupsPerMultiprocessorAttr,
547 SYCLIntelNoGlobalWorkOffsetAttr, SYCLSimdAttr>(A);
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);
565 const llvm::SmallPtrSetImpl<const FunctionDecl *> &RecursiveFuncs;
570 const llvm::SmallPtrSetImpl<const FunctionDecl *> &RecursiveFuncs)
577 Callee = Callee->getCanonicalDecl();
578 assert(Callee &&
"Device function canonical decl must be available");
584 if (RecursiveFuncs.count(Callee)) {
587 SemaSYCLRef.
Diag(Callee->getSourceRange().getBegin(),
588 diag::note_sycl_recursive_function_declared_here)
592 if (
const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Callee))
593 if (Method->isVirtual() &&
594 !SemaSYCLRef.
getLangOpts().SYCLAllowVirtualFunctions)
598 if (
auto const *FD = dyn_cast<FunctionDecl>(Callee)) {
604 if (FD->hasAttr<DLLImportAttr>()) {
607 SemaSYCLRef.
Diag(FD->getLocation(), diag::note_callee_decl) << FD;
612 unsigned BuiltinID = Callee->getBuiltinID();
616 SemaSYCLRef.
Diag(e->
getExprLoc(), diag::err_builtin_target_unsupported)
617 << Name <<
"SYCL device";
619 }
else if (!SemaSYCLRef.
getLangOpts().SYCLAllowFuncPtr &&
621 !isa<CXXPseudoDestructorExpr>(e->
getCallee())) {
622 bool MaybeConstantExpr =
false;
627 if (!MaybeConstantExpr)
650 return RecursiveASTVisitor::TraverseVarDecl(VD);
666 return TraverseStmt(S->getSubStmt());
676 if (std::optional<Stmt *> ActiveStmt =
679 return TraverseStmt(*ActiveStmt);
682 return RecursiveASTVisitor::TraverseIfStmt(S);
702 void CollectSyclExternalFuncs() {
704 if (
auto *FD = dyn_cast<FunctionDecl>(
Record.Callee->getDecl()))
705 if (FD->hasBody() && FD->hasAttr<SYCLDeviceAttr>())
710 assert(CG.
getNode(Kernel) &&
"No call graph entry for a kernel?");
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());
725 CollectSyclExternalFuncs();
732 Diagnoser.CheckBody(Def->getBody());
740 const auto *ND = dyn_cast<NamespaceDecl>(DC);
747 if (!isa<NamespaceDecl>(
Parent))
749 ND = cast<NamespaceDecl>(
Parent);
752 return ND && ND->getName() ==
"sycl";
785 if (llvm::is_contained(CallStack, CurrentDecl)) {
795 !CurrentDecl->
hasAttr<SYCLDeviceAttr>())
796 Parent.SemaSYCLRef.addFDToReachableFromSyclDevice(CurrentDecl,
807 !CurrentDecl->
hasAttr<SYCLScopeAttr>()) {
808 CurrentDecl->
addAttr(SYCLScopeAttr::CreateImplicit(
809 Parent.SemaSYCLRef.getASTContext(), SYCLScopeAttr::Level::WorkItem));
828 DeviceFunctions.insert(CurrentDecl);
831 if (!CallStack.empty()) {
832 bool DirectlyCalled = CallStack.size() == 1;
834 CollectedAttributes, DirectlyCalled);
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()) {
862 KernelBody = CurrentDecl;
867 CallStack.push_back(CurrentDecl);
874 if (!llvm::is_contained(SeenCallees, CurFD)) {
875 VisitCallNode(CI, CurFD, CallStack);
876 SeenCallees.insert(CurFD);
879 CallStack.pop_back();
886 VisitCallNode(KernelNode, GetFDFromNode(KernelNode), CallStack);
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));
911 return CollectedAttributes;
915 return DeviceFunctions;
919 Parent.AddSingleFunction(DeviceFunctions, RecursiveFunctions);
931 auto Ref = dyn_cast<DeclaratorDecl>(DRE->
getDecl());
932 if (Ref && Ref == MappingPair.first) {
933 auto NewDecl = MappingPair.second;
943 std::pair<DeclaratorDecl *, DeclaratorDecl *> MappingPair;
953 std::string Name = (Twine(
"_arg_") + Src->
getName()).str();
954 return std::make_tuple(Ty, &Ctx.
Idents.
get(Name),
959 std::string Name = (Twine(
"__arg_") + Src->
getName()).str();
960 return std::make_tuple(Ty, &Ctx.
Idents.
get(Name),
965 return std::make_tuple(Ty, &Ctx.
Idents.
get(Name),
970 llvm::report_fatal_error(
"Only scalars and pointers are permitted as "
971 "free function parameters");
983 QualType Ty = Ctx.getRecordType(Call->getRecordDecl());
987 auto Name = Callee->getName();
988 if (Name !=
"wait_for" ||
989 Callee->hasAttr<SYCLScopeAttr>())
993 SYCLScopeAttr::CreateImplicit(Ctx, SYCLScopeAttr::Level::WorkItem));
1008 VarDecl *VD = dyn_cast<VarDecl>(D);
1010 if (!VD || isa<ParmVarDecl>(VD) ||
1020 ? SYCLScopeAttr::Level::WorkItem
1021 : SYCLScopeAttr::Level::WorkGroup;
1028 StringRef MethodName) {
1030 auto It = std::find_if(CRD->
methods().begin(), CRD->
methods().end(),
1032 return Method->getNameAsString() == MethodName;
1034 Method = (It != CRD->
methods().end()) ? *It :
nullptr;
1040 return llvm::StringSwitch<KernelInvocationKind>(KernelCallerFunc->
getName())
1052 assert(KernelCaller->
getNumParams() > 0 &&
"Insufficient kernel parameters");
1069 return static_cast<target>(
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") {
1085 llvm::report_fatal_error(
1086 "Only functions at file scope with void return "
1087 "type are permitted as free functions");
1113 llvm::raw_svector_ostream Out(Result);
1114 std::string StableName;
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);
1121 std::stoi(MangledName.substr(StartNums, EndNums - StartNums));
1122 size_t NewNameLength = 14 + 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};
1136 assert(TAL &&
"No template argument info");
1142 static std::pair<std::string, std::string>
1149 llvm::raw_svector_ostream Out(Result);
1152 std::string MangledName(Out.str());
1154 std::string StableName =
1168 MangledName = StableName;
1171 return {MangledName, StableName};
1176 if (
T.isSPIR() &&
T.getSubArch() == llvm::Triple::NoSubArch)
1188 assert(llvm::count_if(KernelCallerFunc->
parameters(), IsHandlerLambda) <= 1 &&
1189 "Multiple kernel_handler parameters");
1191 auto KHArg = llvm::find_if(KernelCallerFunc->
parameters(), IsHandlerLambda);
1193 return (KHArg != KernelCallerFunc->
param_end()) ? *KHArg :
nullptr;
1197 const auto *AccessModeArgEnumType =
1199 const EnumDecl *ED = AccessModeArgEnumType->getDecl();
1203 return E->getName() ==
"read";
1206 return ReadOnly != ED->enumerator_end() &&
1213 template <
typename T>
struct bind_param {
using type =
T; };
1223 template <
typename T>
using bind_param_t =
typename bind_param<T>::type;
1225 class KernelObjVisitor {
1228 template <
typename ParentTy,
typename... HandlerTys>
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)...};
1239 template <
typename... Tn>
1242 (void)std::initializer_list<int>{(result = result && tn(FD, FDTy), 0)...};
1245 template <
typename... Tn>
1248 std::initializer_list<int>{(result = result && tn(BD, BDTy), 0)...};
1253 #define KF_FOR_EACH(FUNC, 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)...)
1268 template <
typename... Tn>
1271 (void)std::initializer_list<int>{(result = result && tn(PD, PDTy), 0)...};
1276 #define KP_FOR_EACH(FUNC, 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)...)
1288 template <
typename ParentTy,
typename... HandlerTys>
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)...};
1300 template <
typename ParentTy,
typename... HandlerTys>
1303 HandlerTys &... Handlers) {
1304 (void)std::initializer_list<int>{
1305 (Handlers.handleNonDecompStruct(Owner,
Parent, RecordTy), 0)...};
1308 template <
typename ParentTy,
typename... HandlerTys>
1311 HandlerTys &... Handlers);
1313 template <
typename ParentTy,
typename... HandlerTys>
1317 template <
typename... HandlerTys>
1320 HandlerTys &... Handlers) {
1321 for (
const auto &
Base : Range) {
1325 (void)std::initializer_list<int>{
1326 (Handlers.handleSyclSpecialType(Owner,
Base, BaseTy), 0)...};
1334 template <
typename... HandlerTys>
1337 HandlerTys &... Handlers) {
1338 VisitRecordFields(Owner, Handlers...);
1341 template <
typename... HandlerTys>
1344 HandlerTys &... Handlers) {
1345 (void)std::initializer_list<int>{
1346 (Handlers.nextElement(ElementTy, Index), 0)...};
1347 visitField(Owner, ArrayField, ElementTy, Handlers...);
1350 template <
typename... HandlerTys>
1352 QualType ElementTy, HandlerTys &... Handlers) {
1353 visitArrayElementImpl(Owner, ArrayField, ElementTy, 0, Handlers...);
1355 template <
typename... HandlerTys>
1358 HandlerTys &... Handlers);
1360 template <
typename... HandlerTys>
1362 QualType ArrayTy, HandlerTys &... Handlers) {
1363 (void)std::initializer_list<int>{
1364 (Handlers.handleSimpleArrayType(Field, ArrayTy), 0)...};
1367 template <
typename... HandlerTys>
1369 QualType ArrayTy, HandlerTys &... Handlers) {
1379 if (!
KF_FOR_EACH(handleArrayType, Field, ArrayTy))
1384 assert(CAT &&
"Should only be called on constant-size array.");
1388 (void)std::initializer_list<int>{
1389 (Handlers.enterArray(Field, ArrayTy, ET), 0)...};
1391 visitFirstArrayElement(Owner, Field, ET, Handlers...);
1392 for (
uint64_t Index = 1; Index < ElemCount; ++Index)
1393 visitNthArrayElement(Owner, Field, ET, Index, Handlers...);
1395 (void)std::initializer_list<int>{
1396 (Handlers.leaveArray(Field, ArrayTy, ET), 0)...};
1399 template <
typename... HandlerTys>
1401 QualType FieldTy, HandlerTys &... Handlers) {
1403 KF_FOR_EACH(handleSyclSpecialType, Field, FieldTy);
1405 if (
KF_FOR_EACH(handleStructType, Field, FieldTy)) {
1407 visitRecord(Owner, Field, RD, FieldTy, Handlers...);
1410 if (
KF_FOR_EACH(handleUnionType, Field, FieldTy)) {
1412 VisitUnion(Owner, Field, RD, Handlers...);
1419 visitArray(Owner, Field, FieldTy, Handlers...);
1426 template <
typename... HandlerTys>
1428 HandlerTys &...Handlers) {
1448 KernelObjVisitor(
SemaSYCL &S) : SemaSYCLRef(S) {}
1450 template <
typename... HandlerTys>
1452 HandlerTys &... Handlers) {
1453 VisitRecordHelper(KernelFunctor, KernelFunctor->
bases(), Handlers...);
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...);
1464 template <
typename... HandlerTys>
1466 QualType ArrayTy, HandlerTys &...Handlers);
1470 template <
typename... HandlerTys>
1472 HandlerTys &...Handlers) {
1474 visitParam(Param, Param->
getType(), Handlers...);
1483 class SyclKernelFieldHandlerBase {
1485 static constexpr
const bool VisitUnionBody =
false;
1486 static constexpr
const bool VisitNthArrayElement =
true;
1490 static constexpr
const bool VisitInsideSimpleContainers =
true;
1491 static constexpr
const bool VisitInsideSimpleContainersWithPointer =
false;
1588 virtual ~SyclKernelFieldHandlerBase() =
default;
1594 class SyclKernelFieldHandler :
public SyclKernelFieldHandlerBase {
1597 SyclKernelFieldHandler(
SemaSYCL &S) : SemaSYCLRef(S) {}
1609 class SyclEmptyHandler final :
public SyclKernelFieldHandlerBase {};
1610 SyclEmptyHandler GlobalEmptyHandler;
1612 template <
bool Keep,
typename H>
struct HandlerFilter;
1613 template <
typename H>
struct HandlerFilter<
true, H> {
1615 HandlerFilter(H &Handler) : Handler(Handler) {}
1617 template <
typename H>
struct HandlerFilter<
false, H> {
1618 SyclEmptyHandler &Handler = GlobalEmptyHandler;
1619 HandlerFilter(H &Handler) {}
1622 template <
bool B,
bool... Rest>
struct AnyTrue;
1624 template <
bool B>
struct AnyTrue<B> {
static constexpr
bool Value = B; };
1626 template <
bool B,
bool... Rest>
struct AnyTrue {
1627 static constexpr
bool Value = B || AnyTrue<Rest...>
::Value;
1630 template <
bool B,
bool... Rest>
struct AllTrue;
1632 template <
bool B>
struct AllTrue<B> {
static constexpr
bool Value = B; };
1634 template <
bool B,
bool... Rest>
struct AllTrue {
1635 static constexpr
bool Value = B && AllTrue<Rest...>
::Value;
1638 template <
typename ParentTy,
typename... Handlers>
1641 Handlers &... handlers) {
1648 HandlerFilter<Handlers::VisitUnionBody, Handlers>(handlers).Handler...);
1651 template <
typename... Handlers>
1652 void KernelObjVisitor::visitNthArrayElement(
const CXXRecordDecl *Owner,
1655 Handlers &... handlers) {
1660 visitArrayElementImpl(
1661 Owner, ArrayField, ElementTy, Index,
1662 HandlerFilter<Handlers::VisitNthArrayElement, Handlers>(handlers)
1666 template <
typename ParentTy,
typename... HandlerTys>
1670 HandlerTys &... Handlers) {
1672 assert(RD &&
"should not be null.");
1673 if (RD->
hasAttr<SYCLRequiresDecompositionAttr>()) {
1677 visitComplexRecord(Owner,
Parent, Wrapper, RecordTy, Handlers...);
1678 }
else if (AnyTrue<HandlerTys::VisitInsideSimpleContainersWithPointer...>::
1681 if (RD->
hasAttr<SYCLGenerateNewTypeAttr>()) {
1683 visitComplexRecord(Owner,
Parent, Wrapper, RecordTy, Handlers...);
1686 visitSimpleRecord(Owner,
Parent, Wrapper, RecordTy, Handlers...);
1696 Owner,
Parent, Wrapper, RecordTy,
1697 HandlerFilter<!HandlerTys::VisitInsideSimpleContainers, HandlerTys>(
1706 Owner,
Parent, Wrapper, RecordTy,
1707 HandlerFilter<HandlerTys::VisitInsideSimpleContainers, HandlerTys>(
1713 template <
typename... HandlerTys>
1715 QualType ArrayTy, HandlerTys &... Handlers) {
1717 if (
Field->hasAttr<SYCLRequiresDecompositionAttr>()) {
1718 visitComplexArray(Owner, Field, ArrayTy, Handlers...);
1719 }
else if (AnyTrue<HandlerTys::VisitInsideSimpleContainersWithPointer...>::
1722 if (
Field->hasAttr<SYCLGenerateNewTypeAttr>()) {
1725 visitComplexArray(Owner, Field, ArrayTy, Handlers...);
1728 visitSimpleArray(Owner, Field, ArrayTy, Handlers...);
1733 Owner, Field, ArrayTy,
1734 HandlerFilter<!HandlerTys::VisitInsideSimpleContainers, HandlerTys>(
1740 Owner, Field, ArrayTy,
1741 HandlerFilter<HandlerTys::VisitInsideSimpleContainers, HandlerTys>(
1748 class SyclKernelFieldChecker :
public SyclKernelFieldHandler {
1749 bool IsInvalid =
false;
1753 int StructFieldDepth = 0;
1757 int StructBaseDepth = -1;
1763 if (
const auto *CAT =
1766 return checkNotCopyableToKernel(FD, ET);
1769 diag::err_sycl_non_constant_array_type)
1778 return SemaSYCLRef.
Diag(
1779 Loc, diag::err_sycl_invalid_accessor_property_template_param);
1783 return SemaSYCLRef.
Diag(
1784 Loc, diag::err_sycl_invalid_accessor_property_template_param);
1786 const auto *AccPropListDecl =
1788 if (AccPropListDecl->getTemplateArgs().size() != 1)
1790 diag::err_sycl_invalid_property_list_param_number)
1791 <<
"accessor_property_list";
1793 const auto TemplArg = AccPropListDecl->getTemplateArgs()[0];
1794 if (TemplArg.getKind() != TemplateArgument::ArgKind::Pack)
1795 return SemaSYCLRef.
Diag(
1797 diag::err_sycl_invalid_accessor_property_list_template_param)
1801 Prop != TemplArg.
pack_end(); ++Prop) {
1803 return SemaSYCLRef.
Diag(
1805 diag::err_sycl_invalid_accessor_property_list_template_param)
1807 QualType PropTy = Prop->getAsType();
1809 checkBufferLocationType(PropTy,
Loc))
1816 const auto *PropDecl =
1818 if (PropDecl->getTemplateArgs().size() != 1)
1820 diag::err_sycl_invalid_property_list_param_number)
1821 <<
"buffer_location";
1823 const auto BufferLoc = PropDecl->getTemplateArgs()[0];
1824 if (BufferLoc.getKind() != TemplateArgument::ArgKind::Integral)
1825 return SemaSYCLRef.
Diag(
1827 diag::err_sycl_invalid_accessor_property_list_template_param)
1830 int LocationID =
static_cast<int>(BufferLoc.getAsIntegral().getExtValue());
1832 return SemaSYCLRef.
Diag(
1834 diag::err_sycl_invalid_accessor_property_list_template_param)
1842 "Should only be called on sycl special class types.");
1848 (StructFieldDepth > 0 || StructBaseDepth > 0))
1849 return SemaSYCLRef.
Diag(
Loc.getBegin(),
1850 diag::err_bad_kernel_param_data_members)
1855 dyn_cast<ClassTemplateSpecializationDecl>(RecD)) {
1866 return checkPropertyListType(TAL.
get(5),
Loc.getBegin());
1872 SyclKernelFieldChecker(
SemaSYCL &S)
1873 : SyclKernelFieldHandler(S),
Diag(S.getASTContext().getDiagnostics()) {}
1874 static constexpr
const bool VisitNthArrayElement =
false;
1875 bool isValid() {
return !IsInvalid; }
1878 Diag.Report(FD->
getLocation(), diag::err_bad_kernel_param_type) << FieldTy;
1884 Diag.Report(PD->getLocation(), diag::err_bad_kernel_param_type) << ParamTy;
1891 assert(RD &&
"Not a RecordDecl inside the handler for struct type");
1894 if (LC.capturesThis() && LC.isImplicit()) {
1895 SemaSYCLRef.
Diag(LC.getLocation(), diag::err_implicit_this_capture);
1903 Diag.Report(PD->getLocation(), diag::err_bad_kernel_param_type) << ParamTy;
1910 IsInvalid |= checkSyclSpecialType(FieldTy, BS.getBeginLoc());
1915 IsInvalid |= checkSyclSpecialType(FieldTy, FD->
getLocation());
1920 Diag.Report(PD->getLocation(), diag::err_bad_kernel_param_type) << ParamTy;
1926 IsInvalid |= checkNotCopyableToKernel(FD, FieldTy);
1931 Diag.Report(PD->getLocation(), diag::err_bad_kernel_param_type) << ParamTy;
1952 Diag.Report(PD->getLocation(), diag::err_vla_unsupported) << 0;
1961 Diag.Report(FD->
getLocation(), diag::err_bad_kernel_param_type) << FieldTy;
1967 Diag.Report(PD->getLocation(), diag::err_bad_kernel_param_type) << ParamTy;
2009 class SyclKernelUnionChecker :
public SyclKernelFieldHandler {
2011 bool IsInvalid =
false;
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;
2024 Diag.Report(
Loc, diag::err_bad_kernel_param_data_members)
2064 return checkType(BS.getBeginLoc(), FieldTy);
2072 class SyclKernelDecompMarker :
public SyclKernelFieldHandler {
2077 static constexpr
const bool VisitUnionBody =
false;
2078 static constexpr
const bool VisitNthArrayElement =
false;
2080 SyclKernelDecompMarker(
SemaSYCL &S) : SyclKernelFieldHandler(S) {
2083 CollectionStack.push_back(
true);
2084 PointerStack.push_back(
true);
2089 CollectionStack.back() =
true;
2093 CollectionStack.back() =
true;
2104 PointerStack.back() =
true;
2115 CollectionStack.push_back(
false);
2116 PointerStack.push_back(
false);
2132 assert(RD &&
"should not be null.");
2133 if (CollectionStack.pop_back_val()) {
2134 if (!RD->
hasAttr<SYCLRequiresDecompositionAttr>())
2135 RD->
addAttr(SYCLRequiresDecompositionAttr::CreateImplicit(
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(
2157 CollectionStack.push_back(
false);
2158 PointerStack.push_back(
false);
2169 assert(RD &&
"should not be null.");
2170 if (CollectionStack.pop_back_val()) {
2171 if (!RD->
hasAttr<SYCLRequiresDecompositionAttr>())
2172 RD->
addAttr(SYCLRequiresDecompositionAttr::CreateImplicit(
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(
2186 CollectionStack.push_back(
false);
2187 PointerStack.push_back(
false);
2203 if (CollectionStack.pop_back_val()) {
2206 if (!FD->
hasAttr<SYCLRequiresDecompositionAttr>())
2207 FD->
addAttr(SYCLRequiresDecompositionAttr::CreateImplicit(
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(
2215 PointerStack.back() =
true;
2249 class SyclKernelPointerHandler :
public SyclKernelFieldHandler {
2256 Id ? (Twine(
"__generated_") +
Id->getName()).str() :
"__generated_";
2268 ModifiedRD->startDefinition();
2270 ModifiedRD->setAttrs(RD->
getAttrs());
2271 ModifiedRecords.push_back(ModifiedRD);
2276 assert(!ModifiedRecords.empty() &&
2277 "ModifiedRecords should have at least 1 record");
2288 ModifiedRecords.back()->addDecl(Field);
2299 ModifiedBases.push_back(ModifiedBase);
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(),
2322 static constexpr
const bool VisitInsideSimpleContainersWithPointer =
true;
2323 static constexpr
const bool VisitNthArrayElement =
false;
2325 : SyclKernelFieldHandler(S) {
2329 SyclKernelPointerHandler(
SemaSYCL &S) : SyclKernelFieldHandler(S) {}
2348 if (!isArrayElement(FD, Ty))
2351 ModifiedArrayElementsOrArray.push_back(
2375 createBaseSpecifier(
Parent, ModifiedRD, BS);
2380 QualType ModifiedArrayElement = ModifiedArrayElementsOrArray.pop_back_val();
2384 assert(CAT &&
"Should only be called on constant-size array.");
2386 ModifiedArrayElement, CAT->
getSize(),
2390 if (ModifiedRecords.empty()) {
2392 ModifiedArrayElementsOrArray.push_back(ModifiedArray);
2393 }
else if (!isArrayElement(FD, ArrayTy)) {
2395 addField(FD, ModifiedArray);
2398 ModifiedArrayElementsOrArray.push_back(ModifiedArray);
2411 QualType ModifiedPointerType = ModifyAddressSpace(SemaSYCLRef, FieldTy);
2412 if (!isArrayElement(FD, FieldTy))
2413 addField(FD, ModifiedPointerType);
2415 ModifiedArrayElementsOrArray.push_back(ModifiedPointerType);
2428 addField(FD, FieldTy);
2439 return handleScalarType(FD, FieldTy);
2477 if (!ModifiedBases.empty())
2478 ModifiedRD->
setBases(ModifiedBases.data(), ModifiedBases.size());
2483 return ModifiedArrayElementsOrArray.pop_back_val();
2488 class SyclKernelDeclCreator :
public SyclKernelFieldHandler {
2489 bool IsFreeFunction =
false;
2495 size_t LastParamIndex = 0;
2497 int StructDepth = 0;
2501 addParam(newParamDesc, FieldTy);
2506 addParam(newParamDesc, ParamTy);
2513 StringRef Name =
"_arg__base";
2516 addParam(newParamDesc, FieldTy);
2519 void addParam(StringRef Name,
QualType ParamTy) {
2522 addParam(newParamDesc, ParamTy);
2530 std::get<1>(newParamDesc), std::get<0>(newParamDesc),
2531 std::get<2>(newParamDesc),
SC_None,
nullptr);
2532 NewParam->setScopeInfo(0, Params.size());
2533 NewParam->setIsUsed();
2535 LastParamIndex = Params.size();
2536 Params.push_back(NewParam);
2541 void handleAccessorPropertyList(
ParmVarDecl *Param,
2544 const auto *AccTy = cast<ClassTemplateSpecializationDecl>(
RecordDecl);
2545 if (AccTy->getTemplateArgs().size() < 6)
2547 const auto PropList = cast<TemplateArgument>(AccTy->getTemplateArgs()[5]);
2549 const auto *AccPropListDecl =
2551 const auto TemplArg = AccPropListDecl->getTemplateArgs()[0];
2555 Prop != TemplArg.
pack_end(); ++Prop) {
2556 QualType PropTy = Prop->getAsType();
2558 handleNoAliasProperty(Param, PropTy,
Loc);
2560 handleBufferLocationProperty(Param, PropTy,
Loc);
2567 Param->
addAttr(RestrictAttr::CreateImplicit(Ctx,
Loc));
2576 if (Param->
hasAttr<SYCLIntelBufferLocationAttr>()) {
2577 SemaSYCLRef.
Diag(
Loc, diag::err_sycl_compiletime_property_duplication)
2578 <<
"buffer_location";
2582 const auto *PropDecl =
2584 const auto BufferLoc = PropDecl->getTemplateArgs()[0];
2585 int LocationID =
static_cast<int>(BufferLoc.getAsIntegral().getExtValue());
2587 SYCLIntelBufferLocationAttr::CreateImplicit(Ctx, LocationID));
2598 const auto *AccessorSpecializationDecl =
2599 cast<ClassTemplateSpecializationDecl>(
RecordDecl);
2601 AccessorSpecializationDecl->getTemplateArgs().get(2);
2603 Params.back()->addAttr(SYCLAccessorReadonlyAttr::CreateImplicit(
2609 Params.back()->addAttr(
2610 SYCLAccessorPtrAttr::CreateImplicit(SemaSYCLRef.
getASTContext()));
2619 assert(
RecordDecl &&
"The type must be a RecordDecl");
2620 llvm::StringLiteral MethodName =
2625 assert(InitMethod &&
"The type must have the __init method");
2629 size_t ParamIndex = Params.size();
2635 if (
const auto *AddIRAttr =
2636 Param->
getAttr<SYCLAddIRAttributesKernelParameterAttr>())
2637 Params.back()->addAttr(AddIRAttr->clone(SemaSYCLRef.
getASTContext()));
2648 LastParamIndex = ParamIndex;
2653 bool IsSIMDKernel) {
2655 FD->
addAttr(OpenCLKernelAttr::CreateImplicit(Context));
2656 FD->
addAttr(ArtificialAttr::CreateImplicit(Context));
2658 FD->
addAttr(SYCLSimdAttr::CreateImplicit(Context));
2662 bool IsInline,
bool IsSIMDKernel) {
2672 setKernelImplicitAttrs(Ctx, FD, IsSIMDKernel);
2687 SyclKernelPointerHandler PointerHandler(SemaSYCLRef, RD);
2688 KernelObjVisitor Visitor{SemaSYCLRef};
2689 Visitor.VisitRecordBases(RD, PointerHandler);
2690 Visitor.VisitRecordFields(RD, PointerHandler);
2691 return PointerHandler.getNewRecordType();
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();
2707 static constexpr
const bool VisitInsideSimpleContainers =
false;
2709 bool IsSIMDKernel,
bool IsFreeFunction,
2711 : SyclKernelFieldHandler(S), IsFreeFunction(IsFreeFunction),
2713 createKernelDecl(S.getASTContext(),
Loc, IsInline, IsSIMDKernel)),
2714 FuncContext(SemaSYCLRef.SemaRef, KernelDecl) {
2715 S.addSyclOpenCLKernel(SYCLKernel, KernelDecl);
2716 for (
const auto *IRAttr :
2722 ~SyclKernelDeclCreator() {
2727 std::transform(std::begin(Params), std::end(Params),
2728 std::back_inserter(ArgTys),
2732 KernelDecl->
setType(FuncType);
2733 KernelDecl->setParams(Params);
2740 SYCLKernelAttr::CreateImplicit(SemaSYCLRef.
getASTContext()));
2782 assert(
RecordDecl &&
"The type must be a RecordDecl");
2783 llvm::StringLiteral MethodName =
2788 assert(InitMethod &&
"The type must have the __init method");
2792 size_t ParamIndex = Params.size();
2805 LastParamIndex = ParamIndex;
2810 return handleSpecialType(FD, FieldTy);
2832 return WrapperClass;
2836 QualType ModTy = ModifyAddressSpace(SemaSYCLRef, FieldTy);
2844 RecordDecl *WrappedPointer = wrapField(FD, ModTy);
2848 addParam(FD, ModTy);
2853 QualType ModTy = ModifyAddressSpace(SemaSYCLRef, ParamTy);
2854 addParam(PD, ModTy);
2862 if (FD->
hasAttr<SYCLGenerateNewTypeAttr>())
2863 ArrayTy = GenerateNewArrayType(FD, FieldTy);
2866 RecordDecl *WrappedArray = wrapField(FD, ArrayTy);
2872 addParam(FD, FieldTy);
2877 addParam(PD, ParamTy);
2885 assert(FieldRecordDecl &&
"Type must be a C++ record type");
2888 if (FieldRecordDecl->
hasAttr<SYCLGenerateNewTypeAttr>())
2889 addParam(FD, GenerateNewRecordType(FieldRecordDecl));
2906 assert(BaseRecordDecl &&
"Type must be a C++ record type");
2909 if (BaseRecordDecl->
hasAttr<SYCLGenerateNewTypeAttr>())
2910 addParam(BS, GenerateNewRecordType(BaseRecordDecl));
2917 return handleScalarType(FD, FieldTy);
2927 void handleSyclKernelHandlerType() {
2929 StringRef Name =
"_arg__specialization_constants_buffer";
2974 class KernelCallOperatorVisitor
2983 KernelCallOperatorVisitor(
FunctionDecl *KernelCallerFunc,
2985 : KernelCallerFunc(KernelCallerFunc), KernelObj(KernelObj) {}
2989 if (isa_and_nonnull<CXXMethodDecl>(CalleeDecl)) {
3001 return CallOperator;
3003 TraverseDecl(KernelCallerFunc);
3004 return CallOperator;
3008 class ESIMDKernelDiagnostics :
public SyclKernelFieldHandler {
3011 bool IsESIMD =
false;
3013 bool handleSpecialType(
QualType FieldTy) {
3017 return SemaSYCLRef.
Diag(KernelLoc,
3018 diag::err_sycl_esimd_not_supported_for_type)
3025 : SyclKernelFieldHandler(S), KernelLoc(
Loc), IsESIMD(IsESIMD) {}
3028 return handleSpecialType(FieldTy);
3033 return handleSpecialType(FieldTy);
3036 using SyclKernelFieldHandler::handleSyclSpecialType;
3039 class SyclKernelArgsSizeChecker :
public SyclKernelFieldHandler {
3041 unsigned SizeOfParams = 0;
3042 bool IsESIMD =
false;
3049 bool handleSpecialType(
QualType FieldTy) {
3051 assert(
RecordDecl &&
"The type must be a RecordDecl");
3056 assert(InitMethod &&
"The type must have the __init method");
3063 static constexpr
const bool VisitInsideSimpleContainers =
false;
3065 : SyclKernelFieldHandler(S), KernelLoc(
Loc), IsESIMD(IsESIMD) {}
3067 ~SyclKernelArgsSizeChecker() {
3069 SemaSYCLRef.
Diag(KernelLoc, diag::warn_sycl_kernel_too_big_args)
3074 return handleSpecialType(FieldTy);
3085 return handleSpecialType(FieldTy);
3133 return handleScalarType(FD, FieldTy);
3143 std::string getKernelArgDesc(StringRef KernelArgDescription) {
3144 if (KernelArgDescription ==
"")
3146 return (
"Compiler generated argument for " + KernelArgDescription +
",")
3150 class SyclOptReportCreator :
public SyclKernelFieldHandler {
3151 SyclKernelDeclCreator &DC;
3155 StringRef KernelArgDescription,
3156 bool IsCompilerGeneratedType =
false) {
3157 StringRef NameToEmitInDescription = KernelArg->
getName();
3159 if (KernelArgParent && KernelArgDescription ==
"decomposed struct/class")
3160 NameToEmitInDescription = KernelArgParent->
getName();
3167 DC.getKernelDecl(), NameToEmitInDescription,
3168 IsCompilerGeneratedType ?
"Compiler generated"
3170 KernelInvocationLoc, KernelArgSize,
3171 getKernelArgDesc(KernelArgDescription),
3172 (KernelArgDescription ==
"decomposed struct/class")
3173 ? (
"Field:" + KernelArg->
getName().str() +
", ")
3178 std::string KernelArgDescription =
"";
3180 if (RD && RD->
hasAttr<SYCLRequiresDecompositionAttr>())
3181 KernelArgDescription =
"decomposed struct/class";
3183 addParam(FD, FieldTy, KernelArgDescription);
3188 StringRef KernelArgDescription,
3189 bool IsCompilerGeneratedType =
false) {
3195 IsCompilerGeneratedType ?
"Compiler generated"
3197 KernelInvocationLoc, KernelArgSize,
3198 getKernelArgDesc(KernelArgDescription),
"");
3202 void addParam(
QualType KernelArgType, std::string KernelArgDescription) {
3207 DC.getKernelDecl(),
"", KernelArgType.
getAsString(),
3208 KernelInvocationLoc, KernelArgSize,
3209 getKernelArgDesc(KernelArgDescription),
"");
3213 static constexpr
const bool VisitInsideSimpleContainers =
false;
3214 SyclOptReportCreator(
SemaSYCL &S, SyclKernelDeclCreator &DC,
3216 : SyclKernelFieldHandler(S), DC(DC), KernelInvocationLoc(
Loc) {}
3218 using SyclKernelFieldHandler::handleSyclSpecialType;
3220 for (
const auto *Param : DC.getParamVarDeclsForCurrentField())
3227 std::string KernelArgDescription =
"base class " + FieldTy.
getAsString();
3228 for (
const auto *Param : DC.getParamVarDeclsForCurrentField()) {
3235 KernelArgType.
getAsString(), KernelInvocationLoc, KernelArgSize,
3236 getKernelArgDesc(KernelArgDescription),
"");
3241 using SyclKernelFieldHandler::handlePointerType;
3243 std::string KernelArgDescription =
"";
3244 bool IsCompilerGeneratedType =
false;
3245 ParmVarDecl *KernelParameter = DC.getParamVarDeclsForCurrentField()[0];
3250 KernelArgDescription =
"nested pointer";
3251 IsCompilerGeneratedType =
true;
3254 for (
const auto *Param : DC.getParamVarDeclsForCurrentField())
3255 addParam(FD, Param->
getType(), KernelArgDescription,
3256 IsCompilerGeneratedType);
3260 using SyclKernelFieldHandler::handleScalarType;
3262 addParam(FD, FieldTy);
3266 using SyclKernelFieldHandler::handleSimpleArrayType;
3269 for (
const auto *Param : DC.getParamVarDeclsForCurrentField())
3270 addParam(FD, Param->
getType(),
"array",
true);
3274 using SyclKernelFieldHandler::handleNonDecompStruct;
3278 assert(RD &&
"Type must be a C++ record type");
3279 if (RD->
hasAttr<SYCLGenerateNewTypeAttr>())
3280 addParam(FD, Ty,
"object with pointer",
true);
3289 assert(RD &&
"Type must be a C++ record type");
3290 if (RD->
hasAttr<SYCLGenerateNewTypeAttr>())
3291 addParam(BS, Ty,
"base class with pointer",
3294 addParam(BS, Ty,
"base class");
3298 using SyclKernelFieldHandler::handleUnionType;
3300 return handleScalarType(FD, FieldTy);
3303 void handleSyclKernelHandlerType() {
3304 addParam(DC.getParamVarDeclsForCurrentField()[0]->getType(),
3305 "SYCL2020 specialization constant");
3309 static bool isESIMDKernelType(
CXXMethodDecl *CallOperator) {
3310 return (CallOperator !=
nullptr) && CallOperator->
hasAttr<SYCLSimdAttr>();
3313 class SyclKernelBodyCreator :
public SyclKernelFieldHandler {
3314 SyclKernelDeclCreator &DeclCreator;
3334 VarDecl *KernelHandlerClone =
nullptr;
3335 bool IsESIMD =
false;
3339 Stmt *FunctionBody) {
3343 std::pair<DeclaratorDecl *, DeclaratorDecl *> MappingPair =
3344 std::make_pair(OriginalParam, LocalClone);
3346 return KBT.TransformStmt(FunctionBody).get();
3357 assert(CollectionInitExprs.size() == 1 &&
3358 "Should have been popped down to just the first one");
3359 KernelObjClone->
setInit(CollectionInitExprs.back());
3364 replaceWithLocalClone(KernelCallerFunc->
getParamDecl(0), KernelObjClone,
3372 NewBody = replaceWithLocalClone(KernelHandlerParam, KernelHandlerClone,
3376 BodyStmts.push_back(NewBody);
3378 BodyStmts.insert(BodyStmts.end(), FinalizeStmts.begin(),
3379 FinalizeStmts.end());
3385 void annotateHierarchicalParallelismAPICalls() {
3392 KernelObjClone->
addAttr(SYCLScopeAttr::CreateImplicit(
3393 SemaSYCLRef.
getASTContext(), SYCLScopeAttr::Level::WorkGroup));
3395 assert(CallOperator &&
"non callable object is passed as kernel obj");
3405 if (!CallOperator->
hasAttr<SYCLScopeAttr>()) {
3406 CallOperator->
addAttr(SYCLScopeAttr::CreateImplicit(
3407 SemaSYCLRef.
getASTContext(), SYCLScopeAttr::Level::WorkGroup));
3410 MarkWIScope.TraverseDecl(CallOperator);
3418 Expr *createParamReferenceExpr() {
3420 DeclCreator.getParamVarDeclsForCurrentField()[0];
3424 KernelParameter, ParamType,
VK_LValue, KernelCallerSrcLoc);
3430 Expr *createPointerParamReferenceExpr(
QualType PointerTy,
bool Wrapped) {
3432 DeclCreator.getParamVarDeclsForCurrentField()[0];
3436 KernelParameter, ParamType,
VK_LValue, KernelCallerSrcLoc);
3445 DRE = buildMemberExpr(DRE, Pointer);
3446 ParamType =
Pointer->getType();
3450 CK_LValueToRValue, DRE,
nullptr,
3456 CK_AddressSpaceConversion, DRE,
nullptr,
3462 Expr *createSimpleArrayParamReferenceExpr(
QualType ArrayTy) {
3464 DeclCreator.getParamVarDeclsForCurrentField()[0];
3467 KernelParameter, ParamType,
VK_LValue, KernelCallerSrcLoc);
3472 return buildMemberExpr(DRE, ArrayField);
3479 if (isArrayElement(FD, Ty))
3481 ArrayInfos.back().second,
3482 ArrayInfos.back().first);
3489 addFieldInit(FD, Ty, ParamRef, InitKind);
3494 addFieldInit(FD, Ty, ParamRef, InitKind, getFieldEntity(FD, Ty));
3502 InitSeq.Perform(SemaSYCLRef.
SemaRef, Entity, InitKind, ParamRef);
3517 InitSeq.Perform(SemaSYCLRef.
SemaRef, Entity, InitKind, std::nullopt);
3531 InitSeq.Perform(SemaSYCLRef.
SemaRef, Entity, InitKind, Args);
3546 Expr *ParamRef = createParamReferenceExpr();
3550 InitSeq.Perform(SemaSYCLRef.
SemaRef, Entity, InitKind, ParamRef);
3559 Expr *ParamRef = createParamReferenceExpr();
3560 addFieldInit(FD, Ty, ParamRef);
3563 Expr *createGetAddressOf(
Expr *E) {
3592 Expr *RCE = createReinterpretCastExpr(
3593 createGetAddressOf(createParamReferenceExpr()),
3596 addFieldInit(FD, Ty, Initializer);
3605 Expr *RCE = createReinterpretCastExpr(
3606 createGetAddressOf(createParamReferenceExpr()),
3611 addBaseInit(BS, Ty, InitKind, Initializer);
3618 KernelCallerSrcLoc, Member, MemberDAP,
3626 if (!isArrayElement(FD, Ty))
3627 MemberExprBases.push_back(buildMemberExpr(MemberExprBases.back(), FD));
3631 if (!isArrayElement(FD, Ty))
3632 MemberExprBases.pop_back();
3635 void createSpecialMethodCall(
const CXXRecordDecl *RD, StringRef MethodName,
3644 DeclCreator.getParamVarDeclsForCurrentField();
3645 for (
size_t I = 0; I < NumParams; ++I) {
3646 QualType ParamType = KernelParameters[I]->getOriginalType();
3648 KernelParameters[I], ParamType,
VK_LValue, KernelCallerSrcLoc);
3651 MemberExpr *MethodME = buildMemberExpr(MemberExprBases.back(), Method);
3657 const auto *Proto = cast<FunctionProtoType>(Method->
getType());
3659 Proto, 0, ParamDREs, ParamStmts);
3663 SemaSYCLRef.
getASTContext(), MethodME, ParamStmts, ResultTy, VK,
3686 KernelCallerSrcLoc);
3697 InitListExpr *ILE = createInitListExpr(InitTy, NumChildInits);
3702 CollectionInitExprs.push_back(ILE);
3711 Ident = &Ctx.
Idents.
get(
"__SYCLKernel");
3719 const llvm::StringLiteral getInitMethodName()
const {
3725 addFieldInit(FD, Ty, std::nullopt,
3728 addFieldMemberExpr(FD, Ty);
3731 createSpecialMethodCall(
RecordDecl, getInitMethodName(), BodyStmts);
3738 removeFieldMemberExpr(FD, Ty);
3746 createSpecialMethodCall(
RecordDecl, getInitMethodName(), BodyStmts);
3751 void handleSpecialType(
QualType KernelHandlerTy) {
3758 MemberExprBases.push_back(KernelHandlerCloneRef);
3760 MemberExprBases.pop_back();
3767 KernelHandlerClone =
3779 InitSeq.Perform(SemaSYCLRef.
SemaRef, VarEntity, InitKind, std::nullopt);
3789 Index,
SizeT->isSignedIntegerType()};
3791 SemaSYCLRef.
getASTContext(), IndexVal, SizeT, KernelCallerSrcLoc);
3793 ArrayRef, KernelCallerSrcLoc, IndexLiteral, KernelCallerSrcLoc);
3795 return IndexExpr.
get();
3799 Expr *
ArrayRef = createSimpleArrayParamReferenceExpr(FieldTy);
3805 addFieldInit(FD, FieldTy,
ArrayRef, InitKind, Entity);
3809 Expr *RCE = createReinterpretCastExpr(
3810 createGetAddressOf(ArrayParamBases.pop_back_val()),
3813 addFieldInit(FD,
T, Initializer);
3826 addArrayElementInit(FD,
T);
3832 enterArray(FD,
T, ET);
3834 for (
uint64_t Index = 0; Index < ElemCount; ++Index) {
3835 ArrayInfos.back().second = Index;
3837 createArraySubscriptExpr(Index, ArrayParamBases.back());
3839 createArrayInit(FD, ET);
3842 leaveArray(FD,
T, ET);
3858 ArrayParamBases.push_back(createSimpleArrayParamReferenceExpr(FieldTy));
3859 createArrayInit(FD, FieldTy);
3863 static constexpr
const bool VisitInsideSimpleContainers =
false;
3864 SyclKernelBodyCreator(
SemaSYCL &S, SyclKernelDeclCreator &DC,
3868 : SyclKernelFieldHandler(S), DeclCreator(DC),
3869 KernelObjClone(createKernelObjClone(S.getASTContext(),
3870 DC.getKernelDecl(), KernelObj)),
3872 KernelCallerFunc(KernelCallerFunc),
3873 KernelCallerSrcLoc(KernelCallerFunc->getLocation()),
3874 IsESIMD(IsSIMDKernel), CallOperator(CallOperator) {
3875 CollectionInitExprs.push_back(createInitListExpr(KernelObj));
3876 annotateHierarchicalParallelismAPICalls();
3879 DeclGroupRef(KernelObjClone), KernelCallerSrcLoc, KernelCallerSrcLoc);
3880 BodyStmts.push_back(DS);
3885 MemberExprBases.push_back(KernelObjCloneRef);
3888 ~SyclKernelBodyCreator() {
3890 DeclCreator.setBody(KernelBody);
3894 return handleSpecialType(FD, Ty);
3899 return handleSpecialType(BS, Ty);
3904 createPointerParamReferenceExpr(FieldTy, StructDepth != 0);
3905 addFieldInit(FD, FieldTy, PointerRef);
3910 if (FD->
hasAttr<SYCLGenerateNewTypeAttr>())
3911 handleGeneratedArrayType(FD, FieldTy);
3913 addSimpleArrayInit(FD, FieldTy);
3920 assert(RD &&
"Type must be a C++ record type");
3921 if (RD->
hasAttr<SYCLGenerateNewTypeAttr>())
3922 handleGeneratedType(FD, Ty);
3924 addSimpleFieldInit(FD, Ty);
3931 assert(BaseDecl &&
"Type must be a C++ record type");
3932 if (BaseDecl->
hasAttr<SYCLGenerateNewTypeAttr>())
3933 handleGeneratedType(RD, BS, Ty);
3935 addSimpleBaseInit(BS, Ty);
3940 addSimpleFieldInit(FD, FieldTy);
3945 addSimpleFieldInit(FD, FieldTy);
3950 void handleSyclKernelHandlerType(
ParmVarDecl *KernelHandlerArg) {
3954 DeclCreator.getKernelDecl(), KernelHandlerArg);
3959 KernelCallerSrcLoc);
3960 BodyStmts.push_back(DS);
3968 handleSpecialType(KernelHandlerArg->
getType());
3975 addFieldMemberExpr(FD, Ty);
3981 CollectionInitExprs.pop_back();
3983 removeFieldMemberExpr(FD, Ty);
3995 DerivedTy, BaseTy, KernelCallerSrcLoc,
SourceRange(), &BasePath,
3999 MemberExprBases.back(),
4001 MemberExprBases.push_back(
Cast);
4009 MemberExprBases.pop_back();
4010 CollectionInitExprs.pop_back();
4018 assert(CAT &&
"Should only be called on constant-size array.");
4020 addCollectionInitListExpr(
ArrayType, ArraySize);
4021 ArrayInfos.emplace_back(getFieldEntity(FD,
ArrayType), 0);
4030 ArrayInfos.back().second = Index;
4034 MemberExprBases.pop_back();
4036 MemberExprBases.push_back(
4037 createArraySubscriptExpr(Index, MemberExprBases.back()));
4043 CollectionInitExprs.pop_back();
4044 ArrayInfos.pop_back();
4047 if (!FD->
hasAttr<SYCLGenerateNewTypeAttr>())
4048 MemberExprBases.pop_back();
4050 ArrayParamBases.pop_back();
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;
4067 class FreeFunctionKernelBodyCreator :
public SyclKernelFieldHandler {
4068 SyclKernelDeclCreator &DeclCreator;
4076 Expr *createParamReferenceExpr() {
4078 DeclCreator.getParamVarDeclsForCurrentField()[0];
4082 FreeFunctionParameter, FreeFunctionParamType,
VK_LValue,
4083 FreeFunctionSrcLoc);
4090 Expr *createPointerParamReferenceExpr(
QualType PointerTy,
bool Wrapped) {
4092 DeclCreator.getParamVarDeclsForCurrentField()[0];
4096 FreeFunctionParameter, FreeFunctionParamType,
VK_LValue,
4097 FreeFunctionSrcLoc);
4103 CK_AddressSpaceConversion, DRE,
nullptr,
4129 CK_FunctionToPointerDecay, Fn,
nullptr,
4139 static constexpr
const bool VisitInsideSimpleContainers =
false;
4141 FreeFunctionKernelBodyCreator(
SemaSYCL &S, SyclKernelDeclCreator &DC,
4143 : SyclKernelFieldHandler(S), DeclCreator(DC), FreeFunc(FF),
4144 FreeFunctionSrcLoc(FF->getLocation()) {}
4146 ~FreeFunctionKernelBodyCreator() {
4147 CompoundStmt *KernelBody = createFreeFunctionKernelBody();
4148 DeclCreator.setBody(KernelBody);
4177 Expr *PointerRef = createPointerParamReferenceExpr(ParamTy,
false);
4178 ArgExprs.push_back(PointerRef);
4216 Expr *ParamRef = createParamReferenceExpr();
4217 ArgExprs.push_back(ParamRef);
4312 class SyclKernelIntHeaderCreator :
public SyclKernelFieldHandler {
4316 int StructDepth = 0;
4320 return isArrayElement(FD, ArgTy)
4337 addParam(ArgTy,
Kind, offsetOf(FD, ArgTy));
4344 addParam(ParamTy,
Kind, offsetOf(PD, ParamTy));
4356 static_cast<unsigned>(CurOffset + OffsetAdj));
4360 static constexpr
const bool VisitInsideSimpleContainers =
false;
4361 SyclKernelIntHeaderCreator(
bool IsESIMD,
SemaSYCL &S,
4365 : SyclKernelFieldHandler(S), Header(H) {
4372 IsSYCLUnnamedKernel(S, KernelFunc), ObjSize);
4377 : SyclKernelFieldHandler(S), Header(H) {
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());
4395 offsetOf(RD, BC.getType()->getAsCXXRecordDecl()));
4401 assert(ClassTy &&
"Type must be a C++ record type");
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());
4412 CurOffset + offsetOf(FD, FieldTy));
4419 assert(InitMethod &&
"type must have __init method");
4421 assert(InitArg &&
"Init method must have arguments");
4428 addParam(
T, ParamKind, offsetOf(FD, FieldTy));
4431 "Unexpected SYCL special class when generating integration header");
4443 addParam(FD, FieldTy,
4492 return handleScalarType(FD, FieldTy);
4501 void handleSyclKernelHandlerType(
QualType Ty) {
4514 CurOffset += offsetOf(FD, Ty);
4526 CurOffset -= offsetOf(FD, Ty);
4549 ArrayBaseOffsets.push_back(CurOffset + offsetOf(FD, ArrayTy));
4562 CurOffset = ArrayBaseOffsets.back() +
Size * Index;
4567 CurOffset = ArrayBaseOffsets.pop_back_val();
4568 CurOffset -= offsetOf(FD, ArrayTy);
4578 using SyclKernelFieldHandler::enterStruct;
4579 using SyclKernelFieldHandler::leaveStruct;
4582 class SyclKernelIntFooterCreator :
public SyclKernelFieldHandler {
4587 : SyclKernelFieldHandler(S), Footer(F) {
4603 bool IsInvalid =
false;
4604 bool IsUnnamedKernel =
false;
4607 for (
auto &A : Args)
4613 QualType KernelNameType,
bool IsUnnamedKernel)
4614 : S(S), KernelInvocationFuncLoc(KernelInvocationFuncLoc),
4615 KernelNameType(KernelNameType), IsUnnamedKernel(IsUnnamedKernel) {}
4626 if (
const auto *TSD =
4627 dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD)) {
4630 VisitTemplateArgs(Args);
4632 InnerTypeVisitor::Visit(
T.getTypePtr());
4639 InnerTemplArgVisitor::Visit(TA);
4644 S.
Diag(KernelInvocationFuncLoc, diag::err_nullptr_t_type_in_sycl_kernel)
4653 return DiagnoseKernelNameType(TT->
getDecl());
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)
4681 if (DeclCtx && !IsUnnamedKernel) {
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;
4701 if (
const auto *Tag = dyn_cast<TagDecl>(DeclNamed)) {
4702 bool UnnamedLambdaUsed = Tag->getIdentifier() ==
nullptr;
4704 if (UnnamedLambdaUsed) {
4705 S.
Diag(KernelInvocationFuncLoc,
4706 diag::err_sycl_kernel_incorrectly_named)
4707 << 2 << KernelNameType;
4730 if (Tag->isCompleteDefinition() ||
4732 S.
Diag(KernelInvocationFuncLoc,
4733 diag::err_sycl_kernel_incorrectly_named)
4736 0 << KernelNameType;
4739 S.
Diag(KernelInvocationFuncLoc, diag::warn_sycl_implicit_decl);
4764 assert(TD &&
"template declaration must be available");
4768 dyn_cast<NonTypeTemplateParmDecl>(
P))
4784 *
this, Args[0]->getExprLoc(), KernelNameType,
4785 IsSYCLUnnamedKernel(*
this, KernelFunc));
4796 if (!KernelObj || (KernelObj && !KernelObj->
hasDefinition())) {
4797 Diag(Args[0]->getExprLoc(), diag::err_sycl_kernel_not_function_object);
4804 if (LC.capturesThis() && LC.isImplicit()) {
4805 Diag(LC.getLocation(), diag::err_implicit_this_capture);
4815 Diag(KernelFunc->
getLocation(), diag::warn_sycl_pass_by_reference_future);
4819 Diag(KernelFunc->
getLocation(), diag::warn_sycl_pass_by_value_deprecated);
4826 SyclKernelDecompMarker DecompMarker(*
this);
4827 SyclKernelFieldChecker FieldChecker(*
this);
4828 SyclKernelUnionChecker UnionChecker(*
this);
4830 KernelObjVisitor Visitor{*
this};
4832 DiagnosingSYCLKernel =
true;
4835 Visitor.VisitRecordBases(KernelObj, FieldChecker, UnionChecker, DecompMarker);
4836 Visitor.VisitRecordFields(KernelObj, FieldChecker, UnionChecker,
4839 DiagnosingSYCLKernel =
false;
4841 if (!FieldChecker.isValid() || !UnionChecker.isValid() ||
4842 !KernelNameTypeVisitor.
isValid())
4850 assert(CallOperator &&
"invalid kernel object");
4852 typedef std::pair<FunctionDecl *, FunctionDecl *> ChildParentPair;
4855 WorkList.push_back({CallOperator,
nullptr});
4860 while (!WorkList.empty()) {
4869 WorkList.pop_back();
4870 if (!
Visited.insert(FD).second)
4878 if (
auto *Callee = dyn_cast<FunctionDecl>(CI->getDecl())) {
4879 Callee = Callee->getMostRecentDecl();
4881 WorkList.push_back({Callee, FD});
4886 assert(KernelBody &&
"improper parallel_for wrap");
4891 llvm::for_each(Attrs,
4892 [CallOperator](
Attr *A) { CallOperator->
addAttr(A); });
4897 std::unique_ptr<MangleContext> MangleCtx(
4901 for (
const std::pair<const FunctionDecl *, FunctionDecl *> &Pair :
4902 SyclKernelsToOpenCLKernels) {
4903 std::string CalculatedName, StableName;
4904 StringRef KernelName;
4906 std::tie(CalculatedName, StableName) =
4908 KernelName = CalculatedName;
4910 std::tie(CalculatedName, StableName) =
4913 IsSYCLUnnamedKernel(*
this, Pair.first) ? StableName : CalculatedName;
4920 Pair.second->setDeclName(&
getASTContext().Idents.get(KernelName));
4922 Pair.second->addAttr(
4954 assert(KernelObj &&
"invalid kernel caller");
4960 KernelCallOperatorVisitor KernelCallOperator(KernelCallerFunc, KernelObj);
4966 CallOperator = KernelCallOperator.getCallOperator();
4972 std::string CalculatedName, StableName;
4973 std::tie(CalculatedName, StableName) =
4978 if (StableName.find(
"__pf_kernel_wrapper") != std::string::npos)
4982 bool IsSIMDKernel = isESIMDKernelType(CallOperator);
4984 SyclKernelArgsSizeChecker argsSizeChecker(*
this, KernelObj->
getLocation(),
4986 ESIMDKernelDiagnostics esimdKernel(*
this, KernelObj->
getLocation(),
4989 SyclKernelDeclCreator kernel_decl(*
this, KernelObj->
getLocation(),
4990 KernelCallerFunc->
isInlined(), IsSIMDKernel,
4991 false , KernelCallerFunc);
4992 SyclKernelBodyCreator kernel_body(*
this, kernel_decl, KernelObj,
4993 KernelCallerFunc, IsSIMDKernel,
4995 SyclKernelIntHeaderCreator int_header(
5001 SyclOptReportCreator opt_report(*
this, kernel_decl, KernelObj->
getLocation());
5003 KernelObjVisitor Visitor{*
this};
5008 Visitor.VisitRecordBases(KernelObj, argsSizeChecker, esimdKernel,
5009 kernel_decl, kernel_body, int_header, int_footer,
5011 Visitor.VisitRecordFields(KernelObj, argsSizeChecker, esimdKernel,
5012 kernel_decl, kernel_body, int_header, int_footer,
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);
5023 kernel_decl.handleSyclKernelHandlerType();
5024 kernel_body.handleSyclKernelHandlerType(KernelHandlerArg);
5025 int_header.handleSyclKernelHandlerType(KernelHandlerArg->
getType());
5028 opt_report.handleSyclKernelHandlerType();
5033 SyclKernelArgsSizeChecker argsSizeChecker(SemaSYCLRef, FD->
getLocation(),
5035 SyclKernelDeclCreator kernel_decl(SemaSYCLRef, FD->
getLocation(),
5039 FreeFunctionKernelBodyCreator kernel_body(SemaSYCLRef, kernel_decl, FD);
5041 SyclKernelIntHeaderCreator int_header(
5044 SyclKernelIntFooterCreator int_footer(SemaSYCLRef,
5046 KernelObjVisitor Visitor{SemaSYCLRef};
5048 Visitor.VisitFunctionParameters(FD, argsSizeChecker, kernel_decl, kernel_body,
5049 int_header, int_footer);
5054 static std::pair<LangOptions::SubGroupSizeType, int64_t>
5057 if (
const auto *A = FD->
getAttr<IntelReqdSubGroupSizeAttr>()) {
5062 if (
const auto *A = FD->
getAttr<IntelNamedSubGroupSizeAttr>()) {
5063 if (A->getType() == IntelNamedSubGroupSizeAttr::Primary)
5069 return {LO.getDefaultSubGroupSizeType(),
5070 static_cast<uint64_t>(LO.DefaultSubGroupSize)};
5074 if (
const auto *A = FD->
getAttr<IntelReqdSubGroupSizeAttr>())
5075 return A->getLocation();
5076 if (
const auto *A = FD->
getAttr<IntelNamedSubGroupSizeAttr>())
5077 return A->getLocation();
5091 if (II && II->
getName().starts_with(
"__spirv_"))
5100 S.
Diag(FDAttrLoc, diag::err_sycl_mismatch_group_size)
5103 if (KernelAttrLoc.
isValid()) {
5104 S.
Diag(KernelAttrLoc, diag::note_conflicting_attribute);
5107 S.
Diag(SYCLKernel->
getLocation(), diag::note_sycl_kernel_declared_here);
5114 if (
const auto *A = SYCLKernel->
getAttr<IntelReqdSubGroupSizeAttr>()) {
5117 if (!A->isSYCL2020Spelling())
5121 assert(KernelAttrLoc.
isValid() &&
"Kernel doesn't have attribute either?");
5124 S.
Diag(KernelAttrLoc, diag::note_conflicting_attribute);
5135 const llvm::SmallPtrSetImpl<FunctionDecl *> &CalledFuncs) {
5140 if (
auto *A = KernelBody->
getAttr<IntelReqdSubGroupSizeAttr>())
5141 if (A->isSYCL2020Spelling())
5143 if (
auto *A = KernelBody->
getAttr<IntelNamedSubGroupSizeAttr>())
5148 SYCLKernel = KernelBody;
5151 for (
auto *FD : CalledFuncs) {
5152 if (FD == SYCLKernel || FD == KernelBody)
5156 case attr::Kind::IntelReqdSubGroupSize:
5158 if (!cast<IntelReqdSubGroupSizeAttr>(
Attr)->isSYCL2020Spelling())
5161 case attr::Kind::IntelNamedSubGroupSize:
5164 case attr::Kind::SYCLDevice:
5168 if (!FD->isDefined() && !FD->
hasAttr<IntelReqdSubGroupSizeAttr>() &&
5169 !FD->
hasAttr<IntelNamedSubGroupSizeAttr>())
5183 case attr::Kind::IntelReqdSubGroupSize: {
5184 auto *
Attr = cast<IntelReqdSubGroupSizeAttr>(A);
5186 if (
Attr->isSYCL2020Spelling())
5188 const auto *KBSimdAttr =
5189 KernelBody ? KernelBody->
getAttr<SYCLSimdAttr>() :
nullptr;
5190 if (
auto *Existing = SYCLKernel->
getAttr<IntelReqdSubGroupSizeAttr>()) {
5194 diag::err_conflicting_sycl_kernel_attributes);
5195 S.
Diag(Existing->getLocation(), diag::note_conflicting_attribute);
5199 }
else if (KBSimdAttr &&
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())) {
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);
5219 }
else if (
auto *Existing =
5220 SYCLKernel->
getAttr<SYCLIntelMaxWorkGroupSizeAttr>()) {
5222 RWGSA->getXDim(), RWGSA->getYDim(), RWGSA->getZDim(),
5223 Existing->getXDim(), Existing->getYDim(), Existing->getZDim())) {
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);
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())) {
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);
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())) {
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);
5272 case attr::Kind::SYCLSimd:
5273 if (KernelBody && !KernelBody->
getAttr<SYCLSimdAttr>()) {
5276 diag::err_sycl_function_attribute_mismatch)
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:
5299 case attr::Kind::IntelNamedSubGroupSize:
5306 llvm_unreachable(
"Unexpected attribute was collected by "
5307 "CollectPossibleKernelAttributes");
5318 auto *SYCLKernel = cast<FunctionDecl>(D);
5326 T.GetDeviceFunctions());
5327 for (
auto *A :
T.GetCollectedAttributes())
5336 SyclKernelFieldChecker FieldChecker(*
this);
5337 SyclKernelUnionChecker UnionChecker(*
this);
5339 KernelObjVisitor Visitor{*
this};
5341 DiagnosingSYCLKernel =
true;
5344 Visitor.VisitFunctionParameters(FD, FieldChecker, UnionChecker);
5346 DiagnosingSYCLKernel =
false;
5349 if (!FieldChecker.isValid() || !UnionChecker.isValid())
5364 "Should only be called during SYCL compilation");
5367 if (DiagnosingSYCLKernel)
5389 "Should only be called during SYCL compilation");
5392 bool NeedToEmitNotes =
true;
5395 bool ErrorFound =
false;
5402 if (NeedToEmitNotes) {
5403 if (
auto *FD = dyn_cast<FieldDecl>(D))
5405 diag::note_illegal_field_declared_here)
5417 StackForRecursion.push_back(DeclToCheck);
5421 History.push_back(
nullptr);
5424 const ValueDecl *Next = StackForRecursion.pop_back_val();
5426 assert(!History.empty());
5433 if (!
Visited.insert(NextTy).second)
5436 auto EmitHistory = [&]() {
5438 for (
uint64_t Index = 1; Index < History.size(); ++Index) {
5440 diag::note_within_field_of_type)
5441 << History[Index]->getType();
5445 if (Check(NextTy, Next)) {
5446 if (NeedToEmitNotes)
5448 NeedToEmitNotes =
false;
5459 if (Check(NextTy, Next)) {
5460 if (NeedToEmitNotes)
5462 NeedToEmitNotes =
false;
5467 if (
auto *NextFD = dyn_cast<FieldDecl>(Next))
5468 History.push_back(NextFD);
5471 StackForRecursion.push_back(
nullptr);
5472 llvm::copy(RecDecl->fields(), std::back_inserter(StackForRecursion));
5474 }
while (!StackForRecursion.empty());
5481 Callee = Callee->getMostRecentDecl();
5491 if (Callee->hasAttr<SYCLDeviceAttr>() || Callee->hasAttr<SYCLKernelAttr>())
5501 if (!Callee->isDefined() && !Callee->getBuiltinID() &&
5502 !Callee->isReplaceableGlobalAllocationFunction() &&
5505 Diag(Callee->getLocation(), diag::note_previous_decl) << Callee;
5512 "Should only be called during SYCL compilation");
5518 bool ValueDependent = Init && Init->isValueDependent();
5519 bool isConstantInit = Init && !ValueDependent &&
5521 if (!VD->
isConstexpr() && Init && !ValueDependent && !isConstantInit)
5535 case SYCLIntegrationHeader::kind_##x: \
5542 CASE(specialization_constants_buffer);
5597 unsigned NamespaceCnt = 0;
5598 std::string NSStr =
"";
5602 if (
const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
5604 StringRef NSInlinePrefix = NS->isInline() ?
"inline " :
"";
5607 Twine(NSInlinePrefix +
"namespace " + NS->getName() +
" { ").str());
5608 DC = NS->getDeclContext();
5622 if (isa<FunctionDecl, RecordDecl, LinkageSpecDecl>(DC)) {
5623 DC = cast<Decl>(DC)->getDeclContext();
5630 if (NamespaceCnt > 0)
5633 D->
print(OS, Policy);
5635 if (
const auto *ED = dyn_cast<EnumDecl>(D)) {
5636 QualType T = ED->getIntegerType().getCanonicalType();
5640 T = ED->getPromotionType();
5641 OS <<
" : " <<
T.getAsString();
5647 for (
unsigned I = 0; I < NamespaceCnt; ++I)
5649 if (NamespaceCnt > 0)
5654 void checkAndEmitForwardDecl(
NamedDecl *D) {
5655 if (Printed.insert(D).second)
5656 printForwardDecl(D);
5660 for (
size_t I = 0, E = Args.size(); I < E; ++I)
5666 : OS(OS), Policy(LO) {
5678 InnerTypeVisitor::Visit(
T.getTypePtr());
5690 InnerTemplArgVisitor::Visit(TA);
5703 if (
const auto *TSD = dyn_cast<ClassTemplateSpecializationDecl>(TD)) {
5707 VisitTemplateArgs(Args);
5711 assert(CTD &&
"template declaration must be available");
5713 checkAndEmitForwardDecl(CTD);
5716 checkAndEmitForwardDecl(TD);
5747 assert(TD &&
"template declaration must be available");
5771 dyn_cast<NonTypeTemplateParmDecl>(
P))
5775 checkAndEmitForwardDecl(TD);
5793 for (
size_t I = 0, E = Args.size(); I < E; ++I) {
5808 Quals.
print(OS, Policy,
true);
5813 void PrintNamespaceScopes(
const DeclContext *DC) {
5814 if (isa<NamespaceDecl, FunctionDecl, RecordDecl, LinkageSpecDecl>(DC)) {
5817 const auto *NS = dyn_cast<NamespaceDecl>(DC);
5818 if (NS && !NS->isAnonymousNamespace())
5819 OS << NS->getName() <<
"::";
5825 : OS(OS), Policy(Policy) {}
5844 InnerTemplArgVisitor::Visit(TA);
5849 if (
const auto *TSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
5852 TSD->printQualifiedName(OS, Policy,
true);
5868 if (isa<FunctionDecl, RecordDecl, LinkageSpecDecl>(DC)) {
5869 PrintNamespaceScopes(DC);
5879 TA.
print(Policy, OS,
false );
5893 OS <<
"static_cast<";
5894 ET->getDecl()->printQualifiedName(OS, Policy,
5896 OS <<
">(" << Val <<
")";
5898 TA.
print(Policy, OS,
false );
5915 if (llvm::isPrint(C))
5916 O <<
'\'' << C <<
'\'';
5918 O << static_cast<short>(C);
5922 assert(!Name.empty() &&
"Expected a nonempty string!");
5925 for (
char C : Name.substr(1)) {
5932 O <<
"// This is auto-generated SYCL integration header.\n";
5935 O <<
"#include <sycl/detail/defines_elementary.hpp>\n";
5936 O <<
"#include <sycl/detail/kernel_desc.hpp>\n";
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";
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";
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";
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";
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);
5987 std::sort(SpecConsts.begin(), SpecConsts.end(),
5988 [](
const SpecConstID &SC1,
const SpecConstID &SC2) {
5991 return SC1.second.compare(SC2.second) < 0;
5994 std::unique(SpecConsts.begin(), SpecConsts.end(),
5995 [](
const SpecConstID &SC1,
const SpecConstID &SC2) {
5997 return SC1.first == SC2.first;
6000 O <<
"// Specialization constants IDs:\n";
6001 for (
const auto &
P : llvm::make_range(SpecConsts.begin(),
End)) {
6002 O <<
"template <> struct sycl::detail::SpecConstantInfo<";
6006 O <<
" static constexpr const char* getName() {\n";
6007 O <<
" return \"" <<
P.second <<
"\";\n";
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);
6019 O <<
"namespace sycl {\n";
6020 O <<
"inline namespace _V1 {\n";
6021 O <<
"namespace detail {\n";
6027 if (NeedToEmitDeviceGlobalRegistration) {
6028 O <<
"namespace {\n";
6030 O <<
"class __sycl_device_global_registration {\n";
6032 O <<
" __sycl_device_global_registration() noexcept;\n";
6034 O <<
"__sycl_device_global_registration __sycl_device_global_registrar;\n";
6036 O <<
"} // namespace\n";
6044 if (NeedToEmitHostPipeRegistration) {
6045 O <<
"namespace {\n";
6047 O <<
"class __sycl_host_pipe_registration {\n";
6049 O <<
" __sycl_host_pipe_registration() noexcept;\n";
6051 O <<
"__sycl_host_pipe_registration __sycl_host_pipe_registrar;\n";
6053 O <<
"} // namespace\n";
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";
6063 for (
unsigned I = 0; I < KernelDescs.size(); I++) {
6064 O <<
" \"" << KernelDescs[I].Name <<
"\"";
6066 if (I < KernelDescs.size() - 1)
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";
6077 for (
unsigned I = 0; I < KernelDescs.size(); I++) {
6078 auto &K = KernelDescs[I];
6079 O <<
" //--- " << K.Name <<
"\n";
6081 for (
const auto &
P : K.Params) {
6083 O <<
" { kernel_param_kind_t::" << TyStr <<
", ";
6084 O <<
P.Info <<
", " <<
P.Offset <<
" },\n";
6096 O <<
" { kernel_param_kind_t::kind_invalid, -987654321, -987654321 }, \n";
6099 O <<
"// Specializations of KernelInfo for kernel function types:\n";
6100 unsigned CurStart = 0;
6102 for (
const KernelDesc &K : KernelDescs) {
6103 const size_t N = K.Params.size();
6109 if (K.IsUnnamedKernel) {
6110 O <<
"template <> struct KernelInfoData<";
6114 O <<
"template <> struct KernelInfo<";
6116 Printer.
Visit(K.NameType);
6120 O <<
" __SYCL_DLL_LOCAL\n";
6121 O <<
" static constexpr const char* getName() { return \"" << K.Name
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";
6130 O <<
" __SYCL_DLL_LOCAL\n";
6131 O <<
" static constexpr bool isESIMD() { return " << K.IsESIMDKernel
6133 O <<
" __SYCL_DLL_LOCAL\n";
6134 O <<
" static constexpr const char* getFileName() {\n";
6135 O <<
"#ifndef NDEBUG\n";
6138 .substr(std::string(PLoc.
getFilename()).find_last_of(
"/\\") + 1);
6141 O <<
" return \"\";\n";
6144 O <<
" __SYCL_DLL_LOCAL\n";
6145 O <<
" static constexpr const char* getFunctionName() {\n";
6146 O <<
"#ifndef NDEBUG\n";
6149 Printer.
Visit(K.NameType);
6152 O <<
" return \"\";\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";
6160 O <<
" return 0;\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";
6168 O <<
" return 0;\n";
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";
6183 O <<
"} // namespace detail\n";
6184 O <<
"} // namespace _V1\n";
6185 O <<
"} // namespace sycl\n";
6190 if (IntHeaderName.empty())
6192 int IntHeaderFD = 0;
6193 std::error_code EC =
6194 llvm::sys::fs::openFileForWrite(IntHeaderName, IntHeaderFD);
6196 llvm::errs() <<
"Error: " << EC.message() <<
"\n";
6200 llvm::raw_fd_ostream Out(IntHeaderFD,
true );
6209 bool IsUnnamedKernel,
int64_t ObjSize) {
6210 KernelDescs.emplace_back(SyclKernel, KernelNameType, KernelLocation,
6211 IsESIMDKernel, IsUnnamedKernel, ObjSize);
6216 auto *K = getCurKernelDesc();
6217 assert(K &&
"no kernels");
6218 K->Params.push_back(KernelParamDesc());
6219 KernelParamDesc &PD = K->Params.back();
6230 SpecConsts.emplace_back(std::make_pair(IDType, IDName.str()));
6247 if (isa<VarTemplatePartialSpecializationDecl>(VD))
6252 !S.isTypeDecoratedWithDeclAttribute<SYCLDeviceGlobalAttr>(
6273 GlobalVars.push_back(VD);
6278 if (IntHeaderName.empty())
6280 int IntHeaderFD = 0;
6281 std::error_code EC =
6282 llvm::sys::fs::openFileForWrite(IntHeaderName, IntHeaderFD);
6284 llvm::errs() <<
"Error: " << EC.message() <<
"\n";
6288 llvm::raw_fd_ostream Out(IntHeaderFD,
true );
6292 template <
typename BeforeFn,
typename AfterFn>
6298 const auto *CurDecl = cast<Decl>(DC);
6301 CurDecl = CurDecl->getCanonicalDecl();
6307 const auto *NS = dyn_cast<NamespaceDecl>(CurDecl);
6311 if (
const DeclContext *NewDC = CurDecl->getDeclContext())
6347 static std::string
EmitShim(raw_ostream &OS,
unsigned &ShimCounter,
6348 const std::string &LastShim,
6350 std::string NewShimName =
6351 "__sycl_detail::__shim_" + std::to_string(ShimCounter) +
"()";
6354 OS <<
"namespace __sycl_detail {\n";
6355 OS <<
"static constexpr decltype(" << LastShim <<
") &__shim_" << ShimCounter
6357 OS <<
" return " << LastShim <<
";\n";
6359 OS <<
"} // namespace __sycl_detail\n";
6367 static void EmitShims(raw_ostream &OS,
unsigned &ShimCounter,
6368 const DeclContext *DC, std::string &NameForLastShim,
6371 NameForLastShim =
"::" + NameForLastShim;
6375 const auto *CurDecl = cast<Decl>(DC)->getCanonicalDecl();
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);
6383 NameForLastShim = TemplatedName +
"::" + NameForLastShim;
6384 }
else if (
const auto *RD = dyn_cast<RecordDecl>(CurDecl)) {
6386 }
else if (
const auto *ND = dyn_cast<NamespaceDecl>(CurDecl)) {
6387 if (ND->isAnonymousNamespace()) {
6389 NameForLastShim =
EmitShim(OS, ShimCounter, NameForLastShim, ND);
6391 NameForLastShim = ND->getNameAsString() +
"::" + NameForLastShim;
6399 assert((isa<LinkageSpecDecl, ExternCContextDecl>(CurDecl)) &&
6400 "Unhandled decl type");
6403 EmitShims(OS, ShimCounter, CurDecl->getDeclContext(), NameForLastShim,
6410 static std::string
EmitShims(raw_ostream &OS,
unsigned &ShimCounter,
6414 std::string RelativeName;
6415 llvm::raw_string_ostream stream(RelativeName);
6420 return RelativeName;
6425 Policy.adjustForCPlusPlusFwdDecl();
6426 Policy.SuppressTypedefs =
true;
6427 Policy.SuppressUnwrittenScope =
true;
6429 llvm::SmallSet<const VarDecl *, 8>
Visited;
6430 bool EmittedFirstSpecConstant =
false;
6431 bool DeviceGlobalsEmitted =
false;
6432 bool HostPipesEmitted =
false;
6436 unsigned ShimCounter = 0;
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) {
6449 !S.isTypeDecoratedWithDeclAttribute<SYCLDeviceGlobalAttr>(
6459 if (!EmittedFirstSpecConstant && !DeviceGlobalsEmitted && !HostPipesEmitted)
6460 OS <<
"#include <sycl/detail/defines_elementary.hpp>\n";
6463 std::string TopShim =
EmitShims(OS, ShimCounter, Policy, VD);
6464 if (S.isTypeDecoratedWithDeclAttribute<SYCLDeviceGlobalAttr>(
6466 DeviceGlobalsEmitted =
true;
6467 DeviceGlobOS <<
"device_global_map::add(";
6468 DeviceGlobOS <<
"(void *)&";
6470 DeviceGlobOS << TopShim;
6472 DeviceGlobOS <<
"::";
6475 DeviceGlobOS <<
", \"";
6478 DeviceGlobOS <<
"\");\n";
6480 HostPipesEmitted =
true;
6481 HostPipesOS <<
"host_pipe_map::add(";
6482 HostPipesOS <<
"(void *)&";
6484 HostPipesOS << TopShim;
6486 HostPipesOS <<
"::";
6489 HostPipesOS <<
", \"";
6492 HostPipesOS <<
"\");\n";
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<";
6513 OS <<
"} // namespace detail\n";
6514 OS <<
"} // namespace _V1\n";
6515 OS <<
"} // namespace sycl\n";
6519 if (EmittedFirstSpecConstant)
6520 OS <<
"#include <sycl/detail/spec_const_integration.hpp>\n";
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;
6531 OS <<
"} // namespace (unnamed)\n";
6532 OS <<
"} // namespace sycl::detail\n";
6534 S.getSyclIntegrationHeader().addDeviceGlobalRegistration();
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";
6546 OS <<
"} // namespace (unnamed)\n";
6547 OS <<
"} // namespace sycl::detail\n";
6549 S.getSyclIntegrationHeader().addHostPipeRegistration();
6561 if (isa<FieldDecl>(ME->getMemberDecl()))
6562 Diag(E->
getExprLoc(), diag::err_unique_stable_id_global_storage);
6570 if (!DRE || !isa_and_nonnull<VarDecl>(DRE->getDecl())) {
6575 auto *Var = cast<VarDecl>(DRE->getDecl());
6577 if (!Var->hasGlobalStorage()) {
6578 Diag(E->
getExprLoc(), diag::err_unique_stable_id_global_storage);
Defines the Diagnostic-related interfaces.
Defines enum values for all the target-independent builtin functions.
llvm::DenseSet< const void * > Visited
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
static std::string printTemplateArgs(const PrintingPolicy &PrintingPolicy, TemplateArgumentListInfo &Args, const TemplateParameterList *Params)
static constexpr llvm::StringLiteral InitSpecConstantsBuffer
static bool isDeclaredInSYCLNamespace(const Decl *D)
This function checks whether given DeclContext contains a topmost namespace with name "sycl".
@ InvokeParallelForWorkGroup
static void PrintNSHelper(BeforeFn Before, AfterFn After, raw_ostream &OS, const DeclContext *DC)
static bool isSYCLKernelBodyFunction(FunctionDecl *FD)
constexpr unsigned MaxKernelArgsSize
static bool isSyclAccessorType(QualType Ty)
#define KP_FOR_EACH(FUNC, Item, Qt)
static void CheckSYCL2020SubGroupSizes(SemaSYCL &S, FunctionDecl *SYCLKernel, const FunctionDecl *FD)
void ConstructFreeFunctionKernel(SemaSYCL &SemaSYCLRef, FunctionDecl *FD)
static void OutputStableNameInChars(raw_ostream &O, StringRef Name)
static SourceLocation GetSubGroupLoc(const FunctionDecl *FD)
std::tuple< QualType, IdentifierInfo *, TypeSourceInfo * > ParamDesc
static KernelInvocationKind getKernelInvocationKind(FunctionDecl *KernelCallerFunc)
static bool IsSyclMathFunc(unsigned BuiltinID)
#define KF_FOR_EACH(FUNC, Item, Qt)
static constexpr llvm::StringLiteral InitESIMDMethodName
static void OutputStableNameChar(raw_ostream &O, char C)
static int64_t getIntExprValue(const Expr *E, ASTContext &Ctx)
Returns the signed constant integer value represented by given expression.
static std::pair< LangOptions::SubGroupSizeType, int64_t > CalcEffectiveSubGroup(ASTContext &Ctx, const LangOptions &LO, const FunctionDecl *FD)
static bool isSyclSpecialType(QualType Ty, SemaSYCL &S)
static std::pair< std::string, std::string > constructKernelName(SemaSYCL &S, const FunctionDecl *KernelCallerFunc, MangleContext &MC)
static bool isFreeFunction(SemaSYCL &SemaSYCLRef, const FunctionDecl *FD)
static bool isZeroSizedArray(SemaSYCL &S, QualType Ty)
static void checkSYCLType(SemaSYCL &S, QualType Ty, SourceRange Loc, llvm::DenseSet< QualType > Visited, SourceRange UsedAtLoc=SourceRange())
static CXXMethodDecl * getMethodByName(const CXXRecordDecl *CRD, StringRef MethodName)
Return method by name.
static void CheckSYCL2020Attributes(SemaSYCL &S, FunctionDecl *SYCLKernel, FunctionDecl *KernelBody, const llvm::SmallPtrSetImpl< FunctionDecl * > &CalledFuncs)
static bool isSYCLUndefinedAllowed(const FunctionDecl *Callee, const SourceManager &SrcMgr)
static bool isReadOnlyAccessor(const TemplateArgument &AccessModeArg)
static QualType calculateKernelNameType(ASTContext &Ctx, const FunctionDecl *KernelCallerFunc)
static void PropagateAndDiagnoseDeviceAttr(SemaSYCL &S, const SingleDeviceFunctionTracker &Tracker, Attr *A, FunctionDecl *SYCLKernel, FunctionDecl *KernelBody)
static const char * paramKind2Str(KernelParamKind K)
Returns a string ID of given parameter kind - used in header emission.
static void collectSYCLAttributes(SemaSYCL &S, FunctionDecl *FD, llvm::SmallVectorImpl< Attr * > &Attrs, bool DirectlyCalled)
static bool isDefaultSPIRArch(ASTContext &Context)
static bool isSYCLPrivateMemoryVar(VarDecl *VD)
static void addScopeAttrToLocalVars(CXXMethodDecl &F)
static std::pair< std::string, std::string > constructFreeFunctionKernelName(SemaSYCL &SemaSYCLRef, const FunctionDecl *FreeFunc, MangleContext &MC)
static QualType GetSYCLKernelObjectType(const FunctionDecl *KernelCaller)
static ParmVarDecl * getSyclKernelHandlerArg(FunctionDecl *KernelCallerFunc)
static target getAccessTarget(QualType FieldTy, const ClassTemplateSpecializationDecl *AccTy)
static std::string EmitShim(raw_ostream &OS, unsigned &ShimCounter, const std::string &LastShim, const NamespaceDecl *AnonNS)
static void unsupportedFreeFunctionParamType()
static ParamDesc makeParamDesc(const FieldDecl *Src, QualType Ty)
Creates a kernel parameter descriptor.
static void EmitShims(raw_ostream &OS, unsigned &ShimCounter, const DeclContext *DC, std::string &NameForLastShim, PrintingPolicy &Policy)
static constexpr llvm::StringLiteral LibstdcxxFailedAssertion
static void PrintNSClosingBraces(raw_ostream &OS, const DeclContext *DC)
static void PrintNamespaces(raw_ostream &OS, const DeclContext *DC)
static bool isAccessorPropertyType(QualType Ty, SYCLTypeAttr::SYCLType TypeName)
static constexpr llvm::StringLiteral FinalizeMethodName
static void reportConflictingAttrs(SemaSYCL &S, FunctionDecl *F, const Attr *A1, const Attr *A2)
static constexpr llvm::StringLiteral InitMethodName
This file declares semantic analysis for SYCL constructs.
Defines version macros and version-related utility functions for Clang.
DeviceFunctionTracker(SemaSYCL &S)
DiagDeviceFunction(SemaSYCL &S, const llvm::SmallPtrSetImpl< const FunctionDecl * > &RecursiveFuncs)
bool TraverseStaticAssertDecl(StaticAssertDecl *D)
bool VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E)
bool VisitCallExpr(CallExpr *e)
bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc)
bool TraverseConstantArrayTypeLoc(const ConstantArrayTypeLoc &ArrLoc)
void CheckBody(Stmt *ToBeDiagnosed)
bool TraverseVarDecl(VarDecl *VD)
bool TraverseIfStmt(IfStmt *S)
bool TraverseCaseStmt(CaseStmt *S)
bool VisitCXXTypeidExpr(CXXTypeidExpr *E)
ExprResult TransformDeclRefExpr(DeclRefExpr *DRE)
KernelBodyTransform(std::pair< DeclaratorDecl *, DeclaratorDecl * > &MPair, Sema &S)
bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call)
MarkWIScopeFnVisitor(ASTContext &Ctx)
void Visit(const TemplateArgument &TA)
void VisitPointerType(const PointerType *T)
void VisitTemplateTemplateArgument(const TemplateArgument &TA)
void VisitReferenceType(const ReferenceType *RT)
void VisitTypeTemplateArgument(const TemplateArgument &TA)
void VisitPackTemplateArgument(const TemplateArgument &TA)
SYCLFwdDeclEmitter(raw_ostream &OS, const LangOptions &LO)
void VisitTagType(const TagType *T)
void VisitIntegralTemplateArgument(const TemplateArgument &TA)
void VisitPackTemplateArgument(const TemplateArgument &TA)
void VisitTagType(const TagType *T)
void VisitTemplateArgument(const TemplateArgument &TA)
void VisitIntegralTemplateArgument(const TemplateArgument &TA)
void Visit(const TemplateArgument &TA)
SYCLKernelNameTypePrinter(raw_ostream &OS, PrintingPolicy &Policy)
void VisitType(const Type *T)
void VisitTemplateTemplateArgument(const TemplateArgument &TA)
void VisitTypeTemplateArgument(const TemplateArgument &TA)
void Visit(const TemplateArgument &TA)
void VisitIntegralTemplateArgument(const TemplateArgument &TA)
void VisitTemplateTemplateArgument(const TemplateArgument &TA)
void VisitBuiltinType(const BuiltinType *TT)
SYCLKernelNameTypeVisitor(SemaSYCL &S, SourceLocation KernelInvocationFuncLoc, QualType KernelNameType, bool IsUnnamedKernel)
void VisitTagType(const TagType *TT)
void VisitTypeTemplateArgument(const TemplateArgument &TA)
void VisitPackTemplateArgument(const TemplateArgument &TA)
void DiagnoseKernelNameType(const NamedDecl *DeclNamed)
~SingleDeviceFunctionTracker()
llvm::SmallPtrSetImpl< FunctionDecl * > & GetDeviceFunctions()
SingleDeviceFunctionTracker(DeviceFunctionTracker &P, Decl *Kernel)
FunctionDecl * GetKernelBody()
FunctionDecl * GetSYCLKernel()
llvm::SmallVectorImpl< Attr * > & GetCollectedAttributes()
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
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.
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.
Builtin::Context & BuiltinInfo
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
const LangOptions & getLangOpts() const
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>.
QualType getQualifiedType(SplitQualType split) const
Un-split a SplitQualType.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
const TargetInfo & getTargetInfo() const
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
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
unsigned getFieldCount() const
getFieldCount - Get the number of fields in the layout.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
ArraySizeModifier getSizeModifier() const
QualType getElementType() const
unsigned getIndexTypeCVRQualifiers() const
Attr - This represents one attribute.
attr::Kind getKind() const
SourceLocation getLocation() const
This class is used for builtin types like 'int'.
llvm::StringRef getName(unsigned ID) const
Return the identifier name for the specified builtin, e.g.
Represents a base class of a C++ class.
SourceLocation getBeginLoc() const LLVM_READONLY
bool isVirtual() const
Determines whether the base class is a virtual base class (or not).
QualType getType() const
Retrieves the type of the base class.
AccessSpecifier getAccessSpecifier() const
Returns the access specifier for this base specifier.
A C++ dynamic_cast expression (C++ [expr.dynamic.cast]).
Represents a call to a member function that may be written either with member call syntax (e....
static CXXMemberCallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RP, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0)
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Represents a C++ struct/union/class.
void setBases(CXXBaseSpecifier const *const *Bases, unsigned NumBases)
Sets the base classes of this struct or class.
void completeDefinition() override
Indicates that the definition of this class is now complete.
TypeSourceInfo * getLambdaTypeInfo() const
bool isLambda() const
Determine whether this class describes a lambda function object.
method_range methods() const
unsigned getNumBases() const
Retrieves the number of base classes of this class.
static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr, bool DelayTypeCreation=false)
base_class_iterator bases_begin()
capture_const_range captures() const
bool hasDefinition() const
llvm::iterator_range< base_class_const_iterator > base_class_const_range
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
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)
A C++ typeid expression (C++ [expr.typeid]), which gets the type_info that corresponds to the supplie...
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
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.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
llvm::iterator_range< iterator > callees()
Iterator access to callees/children of the node.
The AST-based call graph.
CallGraphNode * getRoot() const
Get the virtual root of the graph, all the functions available externally are represented as callees ...
void addToCallGraph(Decl *D)
Populate the call graph with the functions in the given declaration.
CallGraphNode * getNode(const Decl *) const
Lookup the node for the given declaration.
void setSkipConstantExpressions(ASTContext &Context)
CaseStmt - Represent a case statement.
SourceLocation getEnd() const
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
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 }.
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
A simple visitor class that helps create template argument visitors.
Represents the canonical version of C arrays with a specified constant size.
const Expr * getSizeExpr() const
Return a pointer to the size expression.
llvm::APInt getSize() const
Return the constant array size as an APInt.
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...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool isTranslationUnit() const
void addDecl(Decl *D)
Add the declaration D into this context.
DeclContext * getEnclosingNamespaceContext()
Retrieve the nearest enclosing namespace context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
A reference to a declared variable, function, enum, etc.
DeclarationNameInfo getNameInfo() const
SourceLocation getTemplateKeywordLoc() const
Retrieve the location of the template keyword preceding this name, if any.
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)
NestedNameSpecifierLoc getQualifierLoc() const
If the name was qualified, retrieves the nested-name-specifier that precedes the name,...
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Kind
Lists the kind of concrete classes of Decl.
static DeclContext * castToDeclContext(const Decl *)
bool isInvalidDecl() const
SourceLocation getLocation() const
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
void setIsUsed()
Set whether the declaration is used, in the sense of odr-use.
AccessSpecifier getAccess() const
bool isInAnonymousNamespace() const
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
DeclContext * getDeclContext()
The name of a declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
Concrete class used by the front-end to report problems and issues.
SyclOptReportHandler & getSYCLOptReport()
Retrieve the SyclOptReport info.
An instance of this object exists for each enum constant that is defined.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
This represents one expression.
bool isValueDependent() const
Determines whether the value of this expression depends on.
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Expr * IgnoreUnlessSpelledInSource()
Skip past any invisible AST nodes which might surround this statement, such as ExprWithCleanups or Im...
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
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.
static ExprValueKind getValueKindForType(QualType T)
getValueKindForType - Given a formal return or parameter type, give its value kind.
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.
Represents a member of a struct/union/class.
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)
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Represents a function declaration or definition.
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
param_iterator param_end()
bool isInlined() const
Determine whether this function should be inlined, because it is either marked "inline" or "constexpr...
QualType getReturnType() const
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
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)
void setImplicitlyInline(bool I=true)
Flag that this function is implicitly inline.
ArrayRef< ParmVarDecl * > parameters() const
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
FunctionDecl * getDefinition()
Get the definition for this declaration.
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
const ParmVarDecl * getParamDecl(unsigned i) const
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.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Describes an C or C++ initializer list.
unsigned getNumInits() const
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...
void reserveInits(const ASTContext &C, unsigned NumInits)
Reserve space for some number of initializers.
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.
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'.
Describes the capture of a variable or of this, or of a C++1y init-capture.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...
void mangleName(GlobalDecl GD, raw_ostream &)
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.
This represents a decl that may have a name.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
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...
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const
Appends a human-readable name for this declaration into the given stream.
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...
Represent a C++ namespace.
bool isAnonymousNamespace() const
Returns true if this is an anonymous namespace declaration.
bool isInline() const
Returns true if this is an inline namespace declaration.
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.
QualType getOriginalType() const
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
PointerType - C99 6.7.5.1 - Pointer Declarators.
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.
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
LangAS getAddressSpace() const
Return the address space of this type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
std::string getAsString() const
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
The collection of all-type qualifiers we support.
void print(raw_ostream &OS, const PrintingPolicy &Policy, bool appendSpaceIfNonEmpty=false) const
void setAddressSpace(LangAS space)
LangAS getAddressSpace() const
Represents a struct/union/class.
field_iterator field_end() const
field_range fields() const
virtual void completeDefinition()
Note that the definition of this type is now complete.
llvm::iterator_range< specific_decl_iterator< FieldDecl > > field_range
field_iterator field_begin() const
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.
Base for LValueReferenceType and RValueReferenceType.
QualType getPointeeType() const
Represents a __builtin_base_type expression.
Represents a __builtin_field_type expression.
Represents a __builtin_num_bases expression.
Represents a __builtin_num_fields expression.
std::string ComputeName(ASTContext &Context) const
static SYCLUniqueStableIdExpr * Create(const ASTContext &Ctx, SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, Expr *E)
static SYCLUniqueStableNameExpr * Create(const ASTContext &Ctx, SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, TypeSourceInfo *TSI)
std::string ComputeName(ASTContext &Context) const
A generic diagnostic builder for errors which may or may not be deferred.
@ K_Deferred
Create a deferred diagnostic, which is emitted only if the function it's attached to is codegen'ed.
@ K_ImmediateWithCallStack
Emit the diagnostic immediately, and, if it's a warning or error, also emit a call stack showing how ...
@ K_Nop
Emit no diagnostics.
bool isFDReachableFromSyclDevice(const FunctionDecl *Callee, const FunctionDecl *Caller)
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
DeviceDiagnosticReason
Bitmask to contain the list of reasons a single diagnostic should be emitted, based on its language.
@ Sycl
SYCL specific diagnostic.
@ None
Diagnostic doesn't apply to anything.
ASTContext & getASTContext() const
const LangOptions & getLangOpts() const
DiagnosticsEngine & getDiagnostics() const
void ConstructOpenCLKernel(FunctionDecl *KernelCallerFunc, MangleContext &MC)
bool isDeclAllowedInSYCLDeviceCode(const Decl *D)
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...
ExprResult BuildUniqueStableIdExpr(SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, Expr *E)
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...
void CheckSYCLKernelCall(FunctionDecl *CallerFunc, ArrayRef< const Expr * > Args)
ExprResult ActOnUniqueStableIdExpr(SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, Expr *E)
SYCLIntegrationFooter & getSyclIntegrationFooter()
SYCLIntegrationHeader & getSyclIntegrationHeader()
Lazily creates and returns SYCL integration header instance.
ExprResult BuildSYCLBuiltinFieldTypeExpr(SourceLocation Loc, QualType SourceTy, Expr *Idx)
@ KernelCallFunctionPointer
@ KernelCallVirtualFunction
@ KernelCallUndefinedFunction
@ KernelCallRecursiveFunction
@ KernelCallDllimportFunction
ExprResult ActOnSYCLBuiltinNumBasesExpr(ParsedType PT)
Get the number of base classes within the parsed type.
ExprResult ActOnSYCLBuiltinNumFieldsExpr(ParsedType PT)
Get the number of fields or captures within the parsed type.
void copySYCLKernelAttrs(CXXMethodDecl *CallOperator)
void checkSYCLDeviceVarDecl(VarDecl *Var)
ExprResult BuildUniqueStableNameExpr(SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, TypeSourceInfo *TSI)
void SetSYCLKernelNames()
llvm::SetVector< Decl * > & syclDeviceDecls()
ExprResult BuildSYCLBuiltinNumFieldsExpr(SourceLocation Loc, QualType SourceTy)
void addSyclDeviceDecl(Decl *d)
void deepTypeCheckForDevice(SourceLocation UsedAt, llvm::DenseSet< QualType > Visited, ValueDecl *DeclToCheck)
ExprResult BuildSYCLBuiltinNumBasesExpr(SourceLocation Loc, QualType SourceTy)
bool checkAllowedSYCLInitializer(VarDecl *VD)
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...
ExprResult BuildSYCLBuiltinBaseTypeExpr(SourceLocation Loc, QualType SourceTy, Expr *Idx)
void ProcessFreeFunction(FunctionDecl *FD)
static bool isSyclType(QualType Ty, SYCLTypeAttr::SYCLType TypeName)
Check whether Ty corresponds to a SYCL type of name TypeName.
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...
ExprResult ActOnUniqueStableNameExpr(SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, ParsedType ParsedTy)
Sema - This implements semantic analysis and AST building for C.
FPOptionsOverride CurFPFeatureOverrides()
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)
void PushFunctionScope()
Enter a new function scope.
DeviceDiagnosticReason getEmissionReason(const FunctionDecl *Decl)
const LangOptions & LangOpts
const LangOptions & getLangOpts() const
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)
bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, SourceLocation Loc, SourceRange Range, CXXCastPath *BasePath=nullptr, bool IgnoreAccess=false)
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
SourceManager & getSourceManager() const
ASTContext & getASTContext() const
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
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.
DeclContext * getCurLexicalContext() const
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)
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.
Stmt - This represents one statement.
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.
void startDefinition()
Starts the definition of this tag declaration.
void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override
Pretty-print the unqualified name of this declaration.
TagKind getTagKind() const
TagDecl * getDecl() const
IntType getInt64Type() const
virtual bool hasFloat128Type() const
Determine whether the __float128 type is supported on this target.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
A template argument list.
unsigned size() const
Retrieve the number of template arguments in this template argument list.
const TemplateArgument & get(unsigned Idx) const
Retrieve the template argument at a given index.
Location wrapper for a TemplateArgument.
Represents a template argument.
pack_iterator pack_end() const
Iterator referencing one past the last argument of a template argument pack.
pack_iterator pack_begin() const
Iterator referencing the first argument of a template argument pack.
QualType getAsType() const
Retrieve the type for a type template argument.
ArrayRef< TemplateArgument > getPackAsArray() const
Return the array of arguments in this template argument pack.
llvm::APSInt getAsIntegral() const
Retrieve the template argument as an integral value.
TemplateName getAsTemplate() const
Retrieve the template name for a template name argument.
bool isNull() const
Determine whether this template argument has no value.
unsigned pack_size() const
The number of template arguments in the given template argument pack.
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.
@ Pack
The template argument is actually a parameter pack.
ArgKind getKind() const
Return the kind of stored template argument.
The base class of all kinds of template declarations (e.g., class, function, etc.).
NamedDecl * getTemplatedDecl() const
Get the underlying, templated declaration.
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
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.
const Type * getTypeForDecl() const
Base wrapper for a particular "section" of type source info.
SourceLocation getBeginLoc() const
Get the begin source location.
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
bool isRValueReferenceType() const
bool isPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isScalarType() const
bool isVariableArrayType() const
const Type * getArrayElementTypeNoTypeQual() const
If this is an array type, return the element type of the array, potentially with type qualifiers miss...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isLValueReferenceType() const
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isUndeducedType() const
Determine whether this type is an undeduced type, meaning that it somehow involves a C++11 'auto' typ...
bool isFunctionType() const
bool isStructureOrClassType() const
bool isVectorType() const
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isNullPtrType() const
bool isRecordType() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
static UnaryOperator * Create(const ASTContext &C, Expr *input, Opcode opc, QualType type, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, bool CanOverflow, FPOptionsOverride FPFeatures)
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
void setType(QualType newType)
Represents a variable declaration or definition.
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
void setInitStyle(InitializationStyle Style)
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
@ CallInit
Call-style initialization (C++98)
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
const Expr * getInit() const
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
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.
bool Init(InterpState &S, CodePtr OpPC)
bool Cast(InterpState &S, CodePtr OpPC)
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.
@ OK_Ordinary
An ordinary object is located at an address in memory.
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...
@ SD_Automatic
Automatic storage duration (most local variables).
LangAS
Defines the address space values used by the address space qualifier of QualType.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_XValue
An x-value expression is a reference to an object with independent storage but which can be "moved",...
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
const FunctionProtoType * T
float __ovld __cnfn distance(float, float)
Returns the distance between p0 and p1.
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
Extra information about a function prototype.
Describes how types, statements, expressions, and declarations should be printed.
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.
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.