Skip to content

Commit 07926eb

Browse files
author
Erich Keane
authored
[NFC][SYCL] Move visitors into their own class. (#2081)
A recent patch has shown there is good reason to have access to Sema/ASTContext when doing the visiting. This also makes it more consistent with the other visitors in Clang. Additionally, there was an odd bracket issue that I've fixed, seemingly a close/open namespace got lost along the way, so the 'close' namespace (with comment) bracket was ACTUALLY the end of the function.
1 parent a420e7a commit 07926eb

File tree

1 file changed

+166
-152
lines changed

1 file changed

+166
-152
lines changed

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 166 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -731,21 +731,6 @@ constructKernelName(Sema &S, FunctionDecl *KernelCallerFunc,
731731
// anonymous namespace so these don't get linkage.
732732
namespace {
733733

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-
749734
template <typename T> struct bind_param { using type = T; };
750735

751736
template <> struct bind_param<CXXBaseSpecifier &> {
@@ -758,6 +743,26 @@ template <> struct bind_param<FieldDecl *const &> { using type = FieldDecl *; };
758743

759744
template <typename T> using bind_param_t = typename bind_param<T>::type;
760745

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+
761766
// This definition using std::bind is necessary because of a gcc 7.x bug.
762767
#define KF_FOR_EACH(FUNC, Item, Qt) \
763768
handleField( \
@@ -767,161 +772,167 @@ template <typename T> using bind_param_t = typename bind_param<T>::type;
767772
&std::decay_t<decltype(handlers)>::FUNC), \
768773
std::ref(handlers), _1, _2)...)
769774

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); \
774779
// })...)
775780

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+
}
796816

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);
811820

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) {
825826
(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...);
829840
(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+
}
835843
}
836-
}
837844

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+
}
844871

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+
};
845922
// Parent contains the FieldDecl or CXXBaseSpecifier that was used to enter
846923
// the Wrapper structure that we're currently visiting. Owner is the parent
847924
// type (which doesn't exist in cases where it is a FieldDecl in the
848925
// 'root'), and Wrapper is the current struct being unwrapped.
849926
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) {
852930
(void)std::initializer_list<int>{(handlers.enterStruct(Owner, Parent), 0)...};
853931
VisitRecordHelper(Wrapper, Wrapper->bases(), handlers...);
854932
VisitRecordHelper(Wrapper, Wrapper->fields(), handlers...);
855933
(void)std::initializer_list<int>{(handlers.leaveStruct(Owner, Parent), 0)...};
856934
}
857935

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-
925936
// A base type that the SYCL OpenCL Kernel construction task uses to implement
926937
// individual tasks.
927938
template <typename Derived> class SyclKernelFieldHandler {
@@ -1887,8 +1898,11 @@ void Sema::ConstructOpenCLKernel(FunctionDecl *KernelCallerFunc,
18871898
StableName);
18881899

18891900
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);
18921906
ConstructingOpenCLKernel = false;
18931907
}
18941908

0 commit comments

Comments
 (0)