-
Notifications
You must be signed in to change notification settings - Fork 769
[SYCL] Changes to visitor model in preparation of array support. #1764
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Signed-off-by: rdeodhar <[email protected]>
clang/lib/Sema/SemaSYCL.cpp
Outdated
template <typename RangeTy, typename... Handlers> | ||
static void VisitField(CXXRecordDecl *Owner, RangeTy Item, QualType ItemTy, | ||
Handlers &... handlers) { | ||
if (Util::isSyclAccessorType(ItemTy)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't use curley brackets for single line if-statements
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
clang/lib/Sema/SemaSYCL.cpp
Outdated
} else if (Util::isSyclStreamType(ItemTy)) | ||
(void)std::initializer_list<int>{ | ||
(handlers.handleSyclStreamType(Item, ItemTy), 0)...}; | ||
else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This else body shouldn't be necessary, make the two checks top-level. Additionally, please leave the existing order (where structure/class type happens right after accessor/stream) and put the array at the end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
int64_t ElemCount = CAT->getSize().getSExtValue(); | ||
std::initializer_list<int>{(handlers.enterArray(), 0)...}; | ||
for (int64_t Count = 0; Count < ElemCount; Count++) { | ||
VisitField(nullptr, Item, ET, handlers...); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that 'visitField' could instead have its 'owner' be a generic declaration, so that the array type could pass that on instead. This would also allow offset-handling quite a bit more easily I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about this. Let's wait until the handleArrayType bodies are filled in.
clang/lib/Sema/SemaSYCL.cpp
Outdated
bool copyableToKernel(const FieldDecl *FD, const QualType &FieldTy) { | ||
// C++ lambda capture already flags non-constant array types. | ||
// Here, we check copyability. | ||
if (FieldTy->isConstantArrayType()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (FieldTy->isConstantArrayType()) { | |
if (const auto *CAT = dyn_cast<ConstantArrayType>(FieldTy)) { |
And so fourth, do the same elsewhere if you're going to use the type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
clang/lib/Sema/SemaSYCL.cpp
Outdated
@@ -801,6 +843,43 @@ class SyclKernelFieldChecker | |||
bool IsInvalid = false; | |||
DiagnosticsEngine &Diag; | |||
|
|||
// Check whether the object is bit-wise copyable | |||
bool copyableToKernel(const FieldDecl *FD, const QualType &FieldTy) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually a 'check' type function, and thus should be 'checkCopyableToKernel'. With that, please invert the 'bool' (false is successful). Then, all of the Diagnostics.report, followed by a return changes to "return Diagnostics.Report", since that is implicitly convertable to bool.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
clang/lib/Sema/SemaSYCL.cpp
Outdated
return false; | ||
} | ||
} | ||
if (!FieldTy->isStructureOrClassType()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no curleys for single liners.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
clang/lib/Sema/SemaSYCL.cpp
Outdated
} | ||
|
||
void handleArrayType(const CXXBaseSpecifier &, QualType) final { | ||
// FIXME |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add some text here, what do you intend this fixme to do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deleted.
template <typename RangeTy, typename... Handlers> | ||
static void VisitArrayElements(RangeTy Item, QualType FieldTy, | ||
Handlers &... handlers) { | ||
const ConstantArrayType *CAT = cast<ConstantArrayType>(FieldTy); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When you do cast
to ConstantArrayType
you expect that FieldTy
is ConstantArrayType
, otherwise assertion will be triggered, so, is it safe to do cast
here? I'm asking because VisitArrayElements
is called after check on isArrayType
, not on isConstantArrayType
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Later, he leaves this comment, which made me not comment on this. but it is still worth evaluating:
// C++ lambda capture already flags non-constant array types.
// Here, we check copyability.
There are 4 types of arrays:
Constant
This one is obvious.
DependentSized
I dont think we have to worry about this one, all instantiations are done before we get here, right?
Incomplete
You cannot actually capture an incomplete sized array type as far as I can tell. They aren't particularly easy to spell in C, and I think we prevent capturing them: https://godbolt.org/z/-oDsdz
Variable
This is the only one that I think is possible, but only as a reference type: https://godbolt.org/z/hEdiK-
Of course, VLAs in structs aren't supported in clang (with the pretty assertive message: fields must have a constant size: 'variable length array in structure' extension will never be supported)
That said, Do we prevent the reference case from making it here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK SYCL spec allows only "by value" ([=] this one) capture for kernels, AFAIK we just don't diagnose if someone tried to use "by reference" capture.
This comment didn't satisfy me because kernel object can be defined not only as lambda but as user-defined callable object as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, then the VariableArraytype isn't a concern, though we should probably diagnose that (should we diagnose ALL ReferenceType fields?).
I'd not thought about other object types. From that perspective, only the incomplete type is of concern, we should likely diagnose that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI: This is another great use of the 'have visit methods return the boolean value'. We could/should stop descending once we report failure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I just forgot, but it seems we already diagnose ReferenceType fields, don't we?
llvm/clang/lib/Sema/SemaSYCL.cpp
Line 810 in 08f8656
IsInvalid = Diag.Report(FD->getLocation(), diag::err_bad_kernel_param_type) |
From that perspective, only the incomplete type is of concern, we should likely diagnose that.
Agree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Non-constant arrays could slip through via function objects. I've added a check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know you emailed a separate implementation that you're working on, so I'll hold off on further review. That said, see my comment here:
We'd like this return value to propogate and happen everywhere, it doesn't make sense to continue looking into any handlers if the 'base' had failed, even struct descent.
clang/lib/Sema/SemaSYCL.cpp
Outdated
} | ||
template <typename T, typename... Tn> | ||
static bool handleField(FieldDecl *FD, QualType FDTy, T &t, Tn &... tn) { | ||
return (t.first->*t.second)(FD, FDTy) && handleField(FD, FDTy, tn...); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this "&&" logic needs to happen at every level here. All the way to the root fields, base classes, etc. As soon as we discover an error in attempting anything we need to give up. So the 'bool' needs to be propogated quite a bit more.
I would think it should cause us to stop descending as well.
clang/lib/Sema/SemaSYCL.cpp
Outdated
bool bad = Diag.Report(FD->getLocation(), diag::err_bad_kernel_param_type) | ||
<< FieldTy; | ||
IsInvalid |= bad; | ||
return !bad; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK bad
here is always true. @erichkeane , should we return true
in handler functions to continue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bad
is completely unnecessary here, I think 934 should just be: "IsInvalid = true", and return false.
You're right, Diag.Report ALWAYS returns true. I'd also suggest having each of these functions just return isValid().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, done.
clang/lib/Sema/SemaSYCL.cpp
Outdated
std::cerr << "isSyclAccessorType:Ty\n"; | ||
Ty->dump(); | ||
bool b = isSyclType(Ty, "accessor", true /*Tmpl*/) || isSyclType(Ty, "accessor_common", true /*Tmpl*/); | ||
std::cerr << (b ? "IS" | ||
: "NOT") | ||
<< " an accessor\n\n"; | ||
return b; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, it seems something wrong happened, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks fine to me too. However, @bader, it seems to fail in the merge step. Whats the best way to do this? SHould he commit a merge commit, or do a rebase/force-push, or what?
To avoid force-pushes it's re-commended to resolve conflict using |
I've merged in the latest intel/llvm. It should be mergeable now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
One minor style comment - please, apply in follow-up PR(s).
if (const auto *CAT = dyn_cast<ConstantArrayType>(FieldTy)) { | ||
QualType ET = CAT->getElementType(); | ||
return checkNotCopyableToKernel(FD, ET); | ||
} else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} else | |
} |
Please, don't use else after return.
Signed-off-by: rdeodhar [email protected]