@@ -731,21 +731,6 @@ constructKernelName(Sema &S, FunctionDecl *KernelCallerFunc,
731
731
// anonymous namespace so these don't get linkage.
732
732
namespace {
733
733
734
- // These enable handler execution only when previous handlers succeed.
735
- template <typename ... Tn>
736
- static bool handleField (FieldDecl *FD, QualType FDTy, Tn &&... tn) {
737
- bool result = true ;
738
- std::initializer_list<int >{(result = result && tn (FD, FDTy), 0 )...};
739
- return result;
740
- }
741
- template <typename ... Tn>
742
- static bool handleField (const CXXBaseSpecifier &BD, QualType BDTy,
743
- Tn &&... tn) {
744
- bool result = true ;
745
- std::initializer_list<int >{(result = result && tn (BD, BDTy), 0 )...};
746
- return result;
747
- }
748
-
749
734
template <typename T> struct bind_param { using type = T; };
750
735
751
736
template <> struct bind_param <CXXBaseSpecifier &> {
@@ -758,6 +743,26 @@ template <> struct bind_param<FieldDecl *const &> { using type = FieldDecl *; };
758
743
759
744
template <typename T> using bind_param_t = typename bind_param<T>::type;
760
745
746
+ class KernelObjVisitor {
747
+ Sema &SemaRef;
748
+
749
+ public:
750
+ KernelObjVisitor (Sema &S) : SemaRef(S) {}
751
+
752
+ // These enable handler execution only when previous handlers succeed.
753
+ template <typename ... Tn>
754
+ bool handleField (FieldDecl *FD, QualType FDTy, Tn &&... tn) {
755
+ bool result = true ;
756
+ std::initializer_list<int >{(result = result && tn (FD, FDTy), 0 )...};
757
+ return result;
758
+ }
759
+ template <typename ... Tn>
760
+ bool handleField (const CXXBaseSpecifier &BD, QualType BDTy, Tn &&... tn) {
761
+ bool result = true ;
762
+ std::initializer_list<int >{(result = result && tn (BD, BDTy), 0 )...};
763
+ return result;
764
+ }
765
+
761
766
// This definition using std::bind is necessary because of a gcc 7.x bug.
762
767
#define KF_FOR_EACH (FUNC, Item, Qt ) \
763
768
handleField ( \
@@ -767,161 +772,167 @@ template <typename T> using bind_param_t = typename bind_param<T>::type;
767
772
&std::decay_t <decltype (handlers)>::FUNC), \
768
773
std::ref(handlers), _1, _2)...)
769
774
770
- // The following simpler definition works with gcc 8.x and later.
771
- // #define KF_FOR_EACH(FUNC) \
772
- // handleField(Field, FieldTy, ([&](FieldDecl *FD, QualType FDTy) { \
773
- // return handlers.f(FD, FDTy); \
775
+ // The following simpler definition works with gcc 8.x and later.
776
+ // #define KF_FOR_EACH(FUNC) \
777
+ // handleField(Field, FieldTy, ([&](FieldDecl *FD, QualType FDTy) { \
778
+ // return handlers.f(FD, FDTy); \
774
779
// })...)
775
780
776
- // Implements the 'for-each-visitor' pattern.
777
- template <typename... Handlers>
778
- static void VisitElement(CXXRecordDecl *Owner, FieldDecl *ArrayField,
779
- QualType ElementTy, Handlers &... handlers) {
780
- if (Util::isSyclAccessorType (ElementTy))
781
- KF_FOR_EACH (handleSyclAccessorType, ArrayField, ElementTy);
782
- else if (Util::isSyclStreamType (ElementTy))
783
- KF_FOR_EACH (handleSyclStreamType, ArrayField, ElementTy);
784
- else if (Util::isSyclSamplerType (ElementTy))
785
- KF_FOR_EACH (handleSyclSamplerType, ArrayField, ElementTy);
786
- else if (Util::isSyclHalfType (ElementTy))
787
- KF_FOR_EACH (handleSyclHalfType, ArrayField, ElementTy);
788
- else if (ElementTy->isStructureOrClassType ())
789
- VisitRecord (Owner, ArrayField, ElementTy->getAsCXXRecordDecl (),
790
- handlers...);
791
- else if (ElementTy->isArrayType ())
792
- VisitArrayElements (ArrayField, ElementTy, handlers...);
793
- else if (ElementTy->isScalarType ())
794
- KF_FOR_EACH (handleScalarType, ArrayField, ElementTy);
795
- }
781
+ // Implements the 'for-each-visitor' pattern.
782
+ template <typename... Handlers>
783
+ void VisitElement(CXXRecordDecl *Owner, FieldDecl *ArrayField,
784
+ QualType ElementTy, Handlers &... handlers) {
785
+ if (Util::isSyclAccessorType (ElementTy))
786
+ KF_FOR_EACH (handleSyclAccessorType, ArrayField, ElementTy);
787
+ else if (Util::isSyclStreamType (ElementTy))
788
+ KF_FOR_EACH (handleSyclStreamType, ArrayField, ElementTy);
789
+ else if (Util::isSyclSamplerType (ElementTy))
790
+ KF_FOR_EACH (handleSyclSamplerType, ArrayField, ElementTy);
791
+ else if (Util::isSyclHalfType (ElementTy))
792
+ KF_FOR_EACH (handleSyclHalfType, ArrayField, ElementTy);
793
+ else if (ElementTy->isStructureOrClassType ())
794
+ VisitRecord (Owner, ArrayField, ElementTy->getAsCXXRecordDecl (),
795
+ handlers...);
796
+ else if (ElementTy->isArrayType ())
797
+ VisitArrayElements (ArrayField, ElementTy, handlers...);
798
+ else if (ElementTy->isScalarType ())
799
+ KF_FOR_EACH (handleScalarType, ArrayField, ElementTy);
800
+ }
801
+
802
+ template <typename ... Handlers>
803
+ void VisitArrayElements (FieldDecl *FD, QualType FieldTy,
804
+ Handlers &... handlers) {
805
+ const ConstantArrayType *CAT = cast<ConstantArrayType>(FieldTy);
806
+ QualType ET = CAT->getElementType ();
807
+ int64_t ElemCount = CAT->getSize ().getSExtValue ();
808
+ std::initializer_list<int >{(handlers.enterArray (), 0 )...};
809
+ for (int64_t Count = 0 ; Count < ElemCount; Count++) {
810
+ VisitElement (nullptr , FD, ET, handlers...);
811
+ (void )std::initializer_list<int >{(handlers.nextElement (ET), 0 )...};
812
+ }
813
+ (void )std::initializer_list<int >{
814
+ (handlers.leaveArray (FD, ET, ElemCount), 0 )...};
815
+ }
796
816
797
- template <typename ... Handlers>
798
- static void VisitArrayElements (FieldDecl *FD, QualType FieldTy,
799
- Handlers &... handlers) {
800
- const ConstantArrayType *CAT = cast<ConstantArrayType>(FieldTy);
801
- QualType ET = CAT->getElementType ();
802
- int64_t ElemCount = CAT->getSize ().getSExtValue ();
803
- std::initializer_list<int >{(handlers.enterArray (), 0 )...};
804
- for (int64_t Count = 0 ; Count < ElemCount; Count++) {
805
- VisitElement (nullptr , FD, ET, handlers...);
806
- (void )std::initializer_list<int >{(handlers.nextElement (ET), 0 )...};
807
- }
808
- (void )std::initializer_list<int >{
809
- (handlers.leaveArray (FD, ET, ElemCount), 0 )...};
810
- }
817
+ template <typename ParentTy, typename ... Handlers>
818
+ void VisitRecord (CXXRecordDecl *Owner, ParentTy &Parent,
819
+ CXXRecordDecl *Wrapper, Handlers &... handlers);
811
820
812
- template <typename ParentTy, typename ... Handlers>
813
- static void VisitRecord (CXXRecordDecl *Owner, ParentTy &Parent,
814
- CXXRecordDecl *Wrapper, Handlers &... handlers);
815
-
816
- template <typename ... Handlers>
817
- static void VisitRecordHelper (CXXRecordDecl *Owner,
818
- clang::CXXRecordDecl::base_class_range Range,
819
- Handlers &... handlers) {
820
- for (const auto &Base : Range) {
821
- (void )std::initializer_list<int >{(handlers.enterField (Owner, Base), 0 )...};
822
- QualType BaseTy = Base.getType ();
823
- // Handle accessor class as base
824
- if (Util::isSyclAccessorType (BaseTy)) {
821
+ template <typename ... Handlers>
822
+ void VisitRecordHelper (CXXRecordDecl *Owner,
823
+ clang::CXXRecordDecl::base_class_range Range,
824
+ Handlers &... handlers) {
825
+ for (const auto &Base : Range) {
825
826
(void )std::initializer_list<int >{
826
- (handlers.handleSyclAccessorType (Base, BaseTy), 0 )...};
827
- } else if (Util::isSyclStreamType (BaseTy)) {
828
- // Handle stream class as base
827
+ (handlers.enterField (Owner, Base), 0 )...};
828
+ QualType BaseTy = Base.getType ();
829
+ // Handle accessor class as base
830
+ if (Util::isSyclAccessorType (BaseTy)) {
831
+ (void )std::initializer_list<int >{
832
+ (handlers.handleSyclAccessorType (Base, BaseTy), 0 )...};
833
+ } else if (Util::isSyclStreamType (BaseTy)) {
834
+ // Handle stream class as base
835
+ (void )std::initializer_list<int >{
836
+ (handlers.handleSyclStreamType (Base, BaseTy), 0 )...};
837
+ } else
838
+ // For all other bases, visit the record
839
+ VisitRecord (Owner, Base, BaseTy->getAsCXXRecordDecl (), handlers...);
829
840
(void )std::initializer_list<int >{
830
- (handlers.handleSyclStreamType (Base, BaseTy), 0 )...};
831
- } else
832
- // For all other bases, visit the record
833
- VisitRecord (Owner, Base, BaseTy->getAsCXXRecordDecl (), handlers...);
834
- (void )std::initializer_list<int >{(handlers.leaveField (Owner, Base), 0 )...};
841
+ (handlers.leaveField (Owner, Base), 0 )...};
842
+ }
835
843
}
836
- }
837
844
838
- template <typename ... Handlers>
839
- static void VisitRecordHelper (CXXRecordDecl *Owner,
840
- clang::RecordDecl::field_range Range,
841
- Handlers &... handlers) {
842
- VisitRecordFields (Owner, handlers...);
843
- }
845
+ template <typename ... Handlers>
846
+ void VisitRecordHelper (CXXRecordDecl *Owner,
847
+ clang::RecordDecl::field_range Range,
848
+ Handlers &... handlers) {
849
+ VisitRecordFields (Owner, handlers...);
850
+ }
851
+
852
+ // FIXME: Can this be refactored/handled some other way?
853
+ template <typename ParentTy, typename ... Handlers>
854
+ void VisitStreamRecord (CXXRecordDecl *Owner, ParentTy &Parent,
855
+ CXXRecordDecl *Wrapper, Handlers &... handlers) {
856
+ (void )std::initializer_list<int >{
857
+ (handlers.enterStruct (Owner, Parent), 0 )...};
858
+ for (const auto &Field : Wrapper->fields ()) {
859
+ QualType FieldTy = Field->getType ();
860
+ (void )std::initializer_list<int >{
861
+ (handlers.enterField (Wrapper, Field), 0 )...};
862
+ // Required to initialize accessors inside streams.
863
+ if (Util::isSyclAccessorType (FieldTy))
864
+ KF_FOR_EACH (handleSyclAccessorType, Field, FieldTy);
865
+ (void )std::initializer_list<int >{
866
+ (handlers.leaveField (Wrapper, Field), 0 )...};
867
+ }
868
+ (void )std::initializer_list<int >{
869
+ (handlers.leaveStruct (Owner, Parent), 0 )...};
870
+ }
844
871
872
+ template <typename ... Handlers>
873
+ void VisitRecordBases (CXXRecordDecl *KernelFunctor, Handlers &... handlers) {
874
+ VisitRecordHelper (KernelFunctor, KernelFunctor->bases (), handlers...);
875
+ }
876
+
877
+ // A visitor function that dispatches to functions as defined in
878
+ // SyclKernelFieldHandler for the purposes of kernel generation.
879
+ template <typename ... Handlers>
880
+ void VisitRecordFields (CXXRecordDecl *Owner, Handlers &... handlers) {
881
+
882
+ for (const auto Field : Owner->fields ()) {
883
+ (void )std::initializer_list<int >{
884
+ (handlers.enterField (Owner, Field), 0 )...};
885
+ QualType FieldTy = Field->getType ();
886
+
887
+ if (Util::isSyclAccessorType (FieldTy))
888
+ KF_FOR_EACH (handleSyclAccessorType, Field, FieldTy);
889
+ else if (Util::isSyclSamplerType (FieldTy))
890
+ KF_FOR_EACH (handleSyclSamplerType, Field, FieldTy);
891
+ else if (Util::isSyclHalfType (FieldTy))
892
+ KF_FOR_EACH (handleSyclHalfType, Field, FieldTy);
893
+ else if (Util::isSyclSpecConstantType (FieldTy))
894
+ KF_FOR_EACH (handleSyclSpecConstantType, Field, FieldTy);
895
+ else if (Util::isSyclStreamType (FieldTy)) {
896
+ CXXRecordDecl *RD = FieldTy->getAsCXXRecordDecl ();
897
+ // Handle accessors in stream class.
898
+ VisitStreamRecord (Owner, Field, RD, handlers...);
899
+ KF_FOR_EACH (handleSyclStreamType, Field, FieldTy);
900
+ } else if (FieldTy->isStructureOrClassType ()) {
901
+ if (KF_FOR_EACH (handleStructType, Field, FieldTy)) {
902
+ CXXRecordDecl *RD = FieldTy->getAsCXXRecordDecl ();
903
+ VisitRecord (Owner, Field, RD, handlers...);
904
+ }
905
+ } else if (FieldTy->isReferenceType ())
906
+ KF_FOR_EACH (handleReferenceType, Field, FieldTy);
907
+ else if (FieldTy->isPointerType ())
908
+ KF_FOR_EACH (handlePointerType, Field, FieldTy);
909
+ else if (FieldTy->isArrayType ()) {
910
+ if (KF_FOR_EACH (handleArrayType, Field, FieldTy))
911
+ VisitArrayElements (Field, FieldTy, handlers...);
912
+ } else if (FieldTy->isScalarType () || FieldTy->isVectorType ())
913
+ KF_FOR_EACH (handleScalarType, Field, FieldTy);
914
+ else
915
+ KF_FOR_EACH (handleOtherType, Field, FieldTy);
916
+ (void )std::initializer_list<int >{
917
+ (handlers.leaveField (Owner, Field), 0 )...};
918
+ }
919
+ }
920
+ #undef KF_FOR_EACH
921
+ };
845
922
// Parent contains the FieldDecl or CXXBaseSpecifier that was used to enter
846
923
// the Wrapper structure that we're currently visiting. Owner is the parent
847
924
// type (which doesn't exist in cases where it is a FieldDecl in the
848
925
// 'root'), and Wrapper is the current struct being unwrapped.
849
926
template <typename ParentTy, typename ... Handlers>
850
- static void VisitRecord (CXXRecordDecl *Owner, ParentTy &Parent,
851
- CXXRecordDecl *Wrapper, Handlers &... handlers) {
927
+ void KernelObjVisitor::VisitRecord (CXXRecordDecl *Owner, ParentTy &Parent,
928
+ CXXRecordDecl *Wrapper,
929
+ Handlers &... handlers) {
852
930
(void )std::initializer_list<int >{(handlers.enterStruct (Owner, Parent), 0 )...};
853
931
VisitRecordHelper (Wrapper, Wrapper->bases (), handlers...);
854
932
VisitRecordHelper (Wrapper, Wrapper->fields (), handlers...);
855
933
(void )std::initializer_list<int >{(handlers.leaveStruct (Owner, Parent), 0 )...};
856
934
}
857
935
858
- // FIXME: Can this be refactored/handled some other way?
859
- template <typename ParentTy, typename ... Handlers>
860
- static void VisitStreamRecord (CXXRecordDecl *Owner, ParentTy &Parent,
861
- CXXRecordDecl *Wrapper, Handlers &... handlers) {
862
- (void )std::initializer_list<int >{(handlers.enterStruct (Owner, Parent), 0 )...};
863
- for (const auto &Field : Wrapper->fields ()) {
864
- QualType FieldTy = Field->getType ();
865
- (void )std::initializer_list<int >{
866
- (handlers.enterField (Wrapper, Field), 0 )...};
867
- // Required to initialize accessors inside streams.
868
- if (Util::isSyclAccessorType (FieldTy))
869
- KF_FOR_EACH (handleSyclAccessorType, Field, FieldTy);
870
- (void )std::initializer_list<int >{
871
- (handlers.leaveField (Wrapper, Field), 0 )...};
872
- }
873
- (void )std::initializer_list<int >{(handlers.leaveStruct (Owner, Parent), 0 )...};
874
- }
875
-
876
- template <typename ... Handlers>
877
- static void VisitRecordBases (CXXRecordDecl *KernelFunctor,
878
- Handlers &... handlers) {
879
- VisitRecordHelper (KernelFunctor, KernelFunctor->bases (), handlers...);
880
- }
881
-
882
- // A visitor function that dispatches to functions as defined in
883
- // SyclKernelFieldHandler for the purposes of kernel generation.
884
- template <typename ... Handlers>
885
- static void VisitRecordFields (CXXRecordDecl *Owner, Handlers &... handlers) {
886
-
887
- for (const auto Field : Owner->fields ()) {
888
- (void )std::initializer_list<int >{(handlers.enterField (Owner, Field), 0 )...};
889
- QualType FieldTy = Field->getType ();
890
-
891
- if (Util::isSyclAccessorType (FieldTy))
892
- KF_FOR_EACH (handleSyclAccessorType, Field, FieldTy);
893
- else if (Util::isSyclSamplerType (FieldTy))
894
- KF_FOR_EACH (handleSyclSamplerType, Field, FieldTy);
895
- else if (Util::isSyclHalfType (FieldTy))
896
- KF_FOR_EACH (handleSyclHalfType, Field, FieldTy);
897
- else if (Util::isSyclSpecConstantType (FieldTy))
898
- KF_FOR_EACH (handleSyclSpecConstantType, Field, FieldTy);
899
- else if (Util::isSyclStreamType (FieldTy)) {
900
- CXXRecordDecl *RD = FieldTy->getAsCXXRecordDecl ();
901
- // Handle accessors in stream class.
902
- VisitStreamRecord (Owner, Field, RD, handlers...);
903
- KF_FOR_EACH (handleSyclStreamType, Field, FieldTy);
904
- } else if (FieldTy->isStructureOrClassType ()) {
905
- if (KF_FOR_EACH (handleStructType, Field, FieldTy)) {
906
- CXXRecordDecl *RD = FieldTy->getAsCXXRecordDecl ();
907
- VisitRecord (Owner, Field, RD, handlers...);
908
- }
909
- } else if (FieldTy->isReferenceType ())
910
- KF_FOR_EACH (handleReferenceType, Field, FieldTy);
911
- else if (FieldTy->isPointerType ())
912
- KF_FOR_EACH (handlePointerType, Field, FieldTy);
913
- else if (FieldTy->isArrayType ()) {
914
- if (KF_FOR_EACH (handleArrayType, Field, FieldTy))
915
- VisitArrayElements (Field, FieldTy, handlers...);
916
- } else if (FieldTy->isScalarType () || FieldTy->isVectorType ())
917
- KF_FOR_EACH (handleScalarType, Field, FieldTy);
918
- else
919
- KF_FOR_EACH (handleOtherType, Field, FieldTy);
920
- (void )std::initializer_list<int >{(handlers.leaveField (Owner, Field), 0 )...};
921
- }
922
- #undef KF_FOR_EACH
923
- } // namespace
924
-
925
936
// A base type that the SYCL OpenCL Kernel construction task uses to implement
926
937
// individual tasks.
927
938
template <typename Derived> class SyclKernelFieldHandler {
@@ -1887,8 +1898,11 @@ void Sema::ConstructOpenCLKernel(FunctionDecl *KernelCallerFunc,
1887
1898
StableName);
1888
1899
1889
1900
ConstructingOpenCLKernel = true ;
1890
- VisitRecordBases (KernelObj, checker, kernel_decl, kernel_body, int_header);
1891
- VisitRecordFields (KernelObj, checker, kernel_decl, kernel_body, int_header);
1901
+ KernelObjVisitor Visitor{*this };
1902
+ Visitor.VisitRecordBases (KernelObj, checker, kernel_decl, kernel_body,
1903
+ int_header);
1904
+ Visitor.VisitRecordFields (KernelObj, checker, kernel_decl, kernel_body,
1905
+ int_header);
1892
1906
ConstructingOpenCLKernel = false ;
1893
1907
}
1894
1908
0 commit comments