-
Notifications
You must be signed in to change notification settings - Fork 770
[LIBCLC] Generate FunctionDecl to remangle substituted entries #7220
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
@steffenlarsen you might find it interesting :) |
@bader Could you please help with review? |
Can I suggest someone from @intel/dpcpp-cfe-reviewers help for this ? This PR is mainly playing with the clang tooling so they would be the most relevant. |
@jchlanda, could you resolve merge conflicts, please? |
0ab248c
to
3d8d1b2
Compare
Done. |
Fixes: #6505 |
@intel/dpcpp-cfe-reviewers, ping. |
If you add this line to the PR description, GitHub will automatically link the PR with the referenced issue. |
I am not very familiar with the ClangTool. @premanandrao, @AaronBallman, could you please take a look at? |
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 don't have much expertise in this area, so a lot of my comments are more superficial.
Does existing test coverage suffice to test these changes?
// Fix up the template types in the original FD's arg tys and return ty. | ||
auto AreQTsEqual = [&](clang::QualType &LHS, clang::QualType &RHS) -> bool { | ||
return (LHS.getBaseTypeIdentifier() && RHS.getBaseTypeIdentifier() && | ||
LHS.getBaseTypeIdentifier()->isStr( | ||
RHS.getBaseTypeIdentifier()->getName())) || | ||
LHS == RHS; | ||
}; | ||
unsigned NumReplaced = 0; | ||
unsigned Idx = 0; | ||
for (auto &TemplateArgQT : TemplateArgTys) { | ||
if (AreQTsEqual(TemplateArgQT, RetTy)) { | ||
RetTy = TemplateTypeParamTys[Idx]; | ||
goto Found; | ||
} | ||
for (unsigned i = 0; i < ArgTys.size(); ++i) { | ||
if (AreQTsEqual(ArgTys[i], TemplateArgQT)) { | ||
ArgTys[i] = TemplateTypeParamTys[Idx]; | ||
goto Found; | ||
} | ||
} |
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.
Are you basically trying to instantiate the function 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.
Yeap, making sure that the template is fully specialized.
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.
Ooofda, I think you might need to use the usual template instantiation machinery to do this (you may have multiple levels of instantiation to perform for a type like foo<T<U>>
(think: template template parameters). CC @erichkeane
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 a bit of a tricky issue.
In principle you are right; the following, fictional, overload of image read would not be handled correctly:
template <typename T> class woof{};
template <>
int4 __spirv_ImageRead<int4 , ocl_image3d_ro, woof<int4>>(ocl_image3d_ro, woof<int4>) {}
However, this patch:
- does not deviate from the current status, the same failure could be observed in the mainline,
- we only need to be able to handle functions defined in libclc, all of which have to follow spir-v interface,
- I am concerned that if we wanted to make it complete, we would end up re-implementing huge chunks of clang for something that is a closed scope task,
- finally, remangler will hard fail should the interface changed.
With thte patch, the above sample would result in:
Unhandled type : woof<int vector[4]>
UNREACHABLE executed at /home/jakub/Projects/oneAPI/jchlanda/llvm/src/llvm/frontendaction/LibclcRemangler.cpp:479!
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.
Ooof, there are quite a lot of situations that'll get out of hand here, its not handling constraint overloading, template-template params, etc, but I don't have a good hold on it. BUT if the libclc owner is equally unconcerned as you about these, I've got no problems obviously.
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.
@steffenlarsen would you be able to weigh in on this?
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.
Use of templates in the current builtins are luckily limited and hopefully they stay this way. It would be nice to see handling of these improve in the future (hopefully in a way where it can again reuse some existing logic) but at least this doesn't seem to worsen the handling of these outliers compared to mainline.
Note that the builtins libclc attempts to mimic need to be handled correctly by the SPIR-V Translator too, so to my knowledge the subset of possible instantiations we support of the templated builtins are actually fairly limited too.
assert(false && "unhandled type name: decltype(auto)"); | ||
else if (Name == "std::nullptr_t") | ||
Res = ContextAST->NullPtrTy; | ||
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.
So if you don't know the type you assume it's an enumeration type? That seems dangerous. For example, this is missing a type for _BitInt, so that would turn into an enum here. I think the else case should be an assertion to help spot missing types.
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.
Although this matches what the previous code did.
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've added an assert for _BitInt
, the problem here is that we match on strings printed from itanium_demangle::Node
and having a generic else close that matches an invalid state is not possible (or hard to get?). FWIW handling a valid qualified type as an enum (falling to catch all else as it is now) would result in a mis-mangled name and would be spotted by the tests.
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.
Doesn't that presume we're testing every possible builtin type? (That sounds like it would get out of sync pretty quickly as we do add new builtin types, though somewhat uncommonly.)
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 similar to #7220 (comment), we only need to be able to handle what spir-v can throw at the remangler.
BlockMeta *NewMeta = reinterpret_cast<BlockMeta *>(std::malloc(NBytes)); | ||
if (NewMeta == nullptr) | ||
std::terminate(); | ||
BlockList->Next = new (NewMeta) BlockMeta{BlockList->Next, 0}; |
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.
@AaronBallman, does this statement have sequencing issues or is it well sequenced?
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.
Okay, so I am glad I was not the only person who looked at that code and went "is that right?"! :-D
There's no sequencing problem there because of: https://eel.is/c++draft/expr.ass#1
assert(false && "unhandled type name: decltype(auto)"); | ||
else if (Name == "std::nullptr_t") | ||
Res = ContextAST->NullPtrTy; | ||
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.
Although this matches what the previous code did.
|
||
bool remangleFunction(Function &Func, llvm::Module *M) { | ||
if (!Func.getName().startswith("_Z")) | ||
return true; |
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.
Should this return false instead?
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 don't think so, the bool here is used as a success/failure notion, and I'd say that a state where we don't need to remangle and can early exit from this function matches the success.
Sorry @smanna12, me neither. |
As it stands now we do not test remangler and discover the failures at runtime with |
Thank you for the explanation! Are there existing tests for |
I'm not sure if I follow exactly, but
|
I don't know about libclc, but at least in LLVM and Clang, adding untested code is generally not something we do. But I see now that the CMake changes also include an execution with |
Yeap, it is being build by default for the CI runs (see the buildbot script here: https://github.com/jchlanda/llvm/blob/jakub/remangling_action/buildbot/configure.py#L127), as well as for both CUDA and HIP. |
Fantastic, that alleviates my concerns about the testing! |
Is there anything else I could do for this PR? |
Co-authored-by: Aaron Ballman <aaron@aaronballman.com>
Co-authored-by: Aaron Ballman <aaron@aaronballman.com>
Co-authored-by: premanandrao <premanand.m.rao@intel.com>
Co-authored-by: premanandrao <premanand.m.rao@intel.com>
Co-authored-by: Steffen Larsen <steffen.larsen@intel.com>
Co-authored-by: Steffen Larsen <steffen.larsen@intel.com>
8e95ddc
to
e3bb16e
Compare
The failures are not related (assert tests in HIP) are we OK to merge this @intel/llvm-gatekeepers |
@premanandrao & @erichkeane & @AaronBallman - Have your concerns been addressed? |
My concerns were all addressed. |
@jchlanda, please address post-commit issue on Windows: https://github.com/intel/llvm/actions/runs/3634072977/jobs/6131787943 and on Linux in this mode: https://github.com/intel/llvm/actions/runs/3634072977/jobs/6131787547 |
@jchlanda, I'm going to revert it in a moment. Let me know if you have any other fix ready. |
@pvchupin I've fixed the issues you mentioned in #7220 (comment) (the last two commits): * shared libs build: e0f3a52 * windows mangling: b88627f The rest is as per #7220 Co-authored-by: Aaron Ballman <aaron@aaronballman.com> Co-authored-by: premanandrao <premanand.m.rao@intel.com> Co-authored-by: Steffen Larsen <steffen.larsen@intel.com>
The diffs are quite hard to follow, but in an essence this patch brings: * a new entry, implementing a generic address space for multiple `__CLC_NVVM_ATOMIC_XYZ_IMPL`, where `XYZ` stands for `CAS`, `INDEC`, `LOAD`, `MAX`, `MIN`, `STORE` and `SUB`, * fixes the name of mangled function that the IMPL uses, * the rest is just formatting to 80 chars. This patch supersedes: #5849 but it requires the fixes to the remangler from: #7220 Fixes: #7658
Retire the by hand mangling of substituted function in favor of constructing corresponding
FunctionDecls
and letting clang mangle it for us. This ensures that we never diverge from clang's mangling idiosyncrasies and bugfixes would likely be in the AST creation, not mangling itself.The tool has been rewritten as a
ClangTool
implementingFrontendAction
.Additionally, we provide the option to perform a test run, in which no substitutions are made, while checking that remangled name does not diverge from the original mangled name. The tests are added to
check-libclc
target.The diffs are a bit ugly, it might be easier to inspect the file mode, basically the change lives entirely in
Remangler
class, and if you followRemangler::remangle
it will lead you through what it does.Fixes: #6505