@@ -832,8 +832,8 @@ class KernelObjVisitor {
832
832
833
833
// Implements the 'for-each-visitor' pattern.
834
834
template <typename... Handlers>
835
- void VisitElement (CXXRecordDecl *Owner, FieldDecl *ArrayField,
836
- QualType ElementTy, Handlers &... handlers) {
835
+ void VisitElementImpl (CXXRecordDecl *Owner, FieldDecl *ArrayField,
836
+ QualType ElementTy, Handlers &... handlers) {
837
837
if (Util::isSyclAccessorType (ElementTy))
838
838
KF_FOR_EACH (handleSyclAccessorType, ArrayField, ElementTy);
839
839
else if (Util::isSyclStreamType (ElementTy))
@@ -854,6 +854,16 @@ class KernelObjVisitor {
854
854
KF_FOR_EACH (handleScalarType, ArrayField, ElementTy);
855
855
}
856
856
857
+ template <typename ... Handlers>
858
+ void VisitFirstElement (CXXRecordDecl *Owner, FieldDecl *ArrayField,
859
+ QualType ElementTy, Handlers &... handlers) {
860
+ VisitElementImpl (Owner, ArrayField, ElementTy, handlers...);
861
+ }
862
+
863
+ template <typename ... Handlers>
864
+ void VisitNthElement (CXXRecordDecl *Owner, FieldDecl *ArrayField,
865
+ QualType ElementTy, Handlers &... handlers);
866
+
857
867
template <typename ... Handlers>
858
868
void VisitArrayElements (FieldDecl *FD, QualType FieldTy,
859
869
Handlers &... handlers) {
@@ -863,17 +873,35 @@ class KernelObjVisitor {
863
873
QualType ET = CAT->getElementType ();
864
874
int64_t ElemCount = CAT->getSize ().getSExtValue ();
865
875
std::initializer_list<int >{(handlers.enterArray (), 0 )...};
866
- for (int64_t Count = 0 ; Count < ElemCount; Count++) {
867
- VisitElement (nullptr , FD, ET, handlers...);
876
+
877
+ assert (ElemCount > 0 && " SYCL prohibits 0 sized arrays" );
878
+ VisitFirstElement (nullptr , FD, ET, handlers...);
879
+ (void )std::initializer_list<int >{(handlers.nextElement (ET), 0 )...};
880
+
881
+ for (int64_t Count = 1 ; Count < ElemCount; Count++) {
882
+ VisitNthElement (nullptr , FD, ET, handlers...);
868
883
(void )std::initializer_list<int >{(handlers.nextElement (ET), 0 )...};
869
884
}
885
+
870
886
(void )std::initializer_list<int >{
871
887
(handlers.leaveArray (FD, ET, ElemCount), 0 )...};
872
888
}
873
889
890
+ // Parent contains the FieldDecl or CXXBaseSpecifier that was used to enter
891
+ // the Wrapper structure that we're currently visiting. Owner is the parent
892
+ // type (which doesn't exist in cases where it is a FieldDecl in the
893
+ // 'root'), and Wrapper is the current struct being unwrapped.
874
894
template <typename ParentTy, typename ... Handlers>
875
895
void VisitRecord (const CXXRecordDecl *Owner, ParentTy &Parent,
876
- const CXXRecordDecl *Wrapper, Handlers &... handlers);
896
+ const CXXRecordDecl *Wrapper, Handlers &... handlers) {
897
+ (void )std::initializer_list<int >{
898
+ (handlers.enterStruct (Owner, Parent), 0 )...};
899
+ VisitRecordHelper (Wrapper, Wrapper->bases (), handlers...);
900
+ VisitRecordHelper (Wrapper, Wrapper->fields (), handlers...);
901
+ (void )std::initializer_list<int >{
902
+ (handlers.leaveStruct (Owner, Parent), 0 )...};
903
+ }
904
+
877
905
template <typename ParentTy, typename ... Handlers>
878
906
void VisitUnion (const CXXRecordDecl *Owner, ParentTy &Parent,
879
907
const CXXRecordDecl *Wrapper, Handlers &... handlers);
@@ -988,25 +1016,13 @@ class KernelObjVisitor {
988
1016
}
989
1017
#undef KF_FOR_EACH
990
1018
};
991
- // Parent contains the FieldDecl or CXXBaseSpecifier that was used to enter
992
- // the Wrapper structure that we're currently visiting. Owner is the parent
993
- // type (which doesn't exist in cases where it is a FieldDecl in the
994
- // 'root'), and Wrapper is the current struct being unwrapped.
995
- template <typename ParentTy, typename ... Handlers>
996
- void KernelObjVisitor::VisitRecord (const CXXRecordDecl *Owner, ParentTy &Parent,
997
- const CXXRecordDecl *Wrapper,
998
- Handlers &... handlers) {
999
- (void )std::initializer_list<int >{(handlers.enterStruct (Owner, Parent), 0 )...};
1000
- VisitRecordHelper (Wrapper, Wrapper->bases (), handlers...);
1001
- VisitRecordHelper (Wrapper, Wrapper->fields (), handlers...);
1002
- (void )std::initializer_list<int >{(handlers.leaveStruct (Owner, Parent), 0 )...};
1003
- }
1004
1019
1005
1020
// A base type that the SYCL OpenCL Kernel construction task uses to implement
1006
1021
// individual tasks.
1007
1022
class SyclKernelFieldHandlerBase {
1008
1023
public:
1009
1024
static constexpr const bool VisitUnionBody = false ;
1025
+ static constexpr const bool VisitNthElement = true ;
1010
1026
// Mark these virtual so that we can use override in the implementer classes,
1011
1027
// despite virtual dispatch never being used.
1012
1028
@@ -1115,6 +1131,21 @@ void KernelObjVisitor::VisitUnion(const CXXRecordDecl *Owner, ParentTy &Parent,
1115
1131
HandlerFilter<Handlers::VisitUnionBody, Handlers>(handlers).Handler ...);
1116
1132
}
1117
1133
1134
+ template <typename ... Handlers>
1135
+ void KernelObjVisitor::VisitNthElement (CXXRecordDecl *Owner,
1136
+ FieldDecl *ArrayField,
1137
+ QualType ElementTy,
1138
+ Handlers &... handlers) {
1139
+ // Don't continue descending if none of the handlers 'care'. This could be 'if
1140
+ // constexpr' starting in C++17. Until then, we have to count on the
1141
+ // optimizer to realize "if (false)" is a dead branch.
1142
+ if (AnyTrue<Handlers::VisitNthElement...>::Value)
1143
+ VisitElementImpl (
1144
+ Owner, ArrayField, ElementTy,
1145
+ HandlerFilter<Handlers::VisitNthElement, Handlers>(handlers)
1146
+ .Handler ...);
1147
+ }
1148
+
1118
1149
// A type to check the validity of all of the argument types.
1119
1150
class SyclKernelFieldChecker : public SyclKernelFieldHandler {
1120
1151
bool IsInvalid = false ;
@@ -1237,6 +1268,7 @@ class SyclKernelFieldChecker : public SyclKernelFieldHandler {
1237
1268
public:
1238
1269
SyclKernelFieldChecker (Sema &S)
1239
1270
: SyclKernelFieldHandler(S), Diag(S.getASTContext().getDiagnostics()) {}
1271
+ static constexpr const bool VisitNthElement = false ;
1240
1272
bool isValid () { return !IsInvalid; }
1241
1273
1242
1274
bool handleReferenceType (FieldDecl *FD, QualType FieldTy) final {
@@ -1285,6 +1317,7 @@ class SyclKernelUnionChecker : public SyclKernelFieldHandler {
1285
1317
: SyclKernelFieldHandler(S), Diag(S.getASTContext().getDiagnostics()) {}
1286
1318
bool isValid () { return !IsInvalid; }
1287
1319
static constexpr const bool VisitUnionBody = true ;
1320
+ static constexpr const bool VisitNthElement = false ;
1288
1321
1289
1322
bool checkType (SourceLocation Loc, QualType Ty) {
1290
1323
if (UnionCount) {
0 commit comments